当我创建具有外部关系的新资源时,指定为,即,{"pk": 20}
我创建了一个新的不需要的 FK 项。
我有Order
与模型有关系的模型类Language
,因此在创建 Order 实例时,我可能必须指定订单的语言。语言列表应该是恒定的,用户不能修改现有语言或创建新语言。
Order
资源:
class OrderResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user', null=True, full=True)
src_lang = fields.ForeignKey(LanguageResource, 'src_lang', null=True, full=True)
dst_lang = fields.ForeignKey(LanguageResource, 'dst_lang', null=True, full=True)
def obj_create(self, bundle, request=None, **kwargs):
return super(OrderResource, self).obj_create(bundle, request, user=request.user)
class Meta:
resource_name = 'orders'
queryset = Order.objects.all()
serializer = Serializer(['json'])
authentication = MultiAuthentication(SessionAuthentication(), ApiKeyAuthentication())
authorization = ResourceAuthorization()
这是一个Language
资源:
class Language(models.Model):
name = models.CharField(max_length=100)
code = models.CharField(max_length=100)
class LanguageResource(ModelResource):
class Meta:
resource_name = 'languages'
queryset = Language.objects.all()
allowed_methods = ['get']
authorization = ReadOnlyAuthorization()
serializer = Serializer(['json'])
我正在尝试Order
使用 jQuery 创建一个新的:
var data = JSON.stringify({
"comment": "Something random",
"src_lang": {"pk": "20"},
"dst_lang": "/api/v2/languages/72/"
});
$.ajax({
type: 'POST',
url: '/api/v2/orders/',
data: data,
dataType: "json",
contentType: "application/json"
});
它没有设置pk:20
tosrc_lang_id
字段,而是创建一个Language
带有空字段的新 forsrc_lang
并为 设置正确的值dst_lang
。但是空字段受Language
模型定义的限制。它是如何保存的?
这也很奇怪,因为我直接指定了语言模型的只读访问权限,以及get
访问受支持语言列表的唯一方法。
如果我将类的语言字段声明OrderResource
为 ie: src_lang = fields.ForeignKey(LanguageResource, 'src_lang', null=True, full=True, readonly=True)
,它不会创建任何内容,但也不会为外键设置任何值。
所以,我只需要指定一种现有的语言,我不需要创建它。
更新
ResourceAuthorization
:
class ResourceAuthorization(Authorization):
def is_authorized(self, request, object=None):
user = getattr(request, 'user', None)
if not user:
return False
return user.is_authenticated()
def apply_limits(self, request, object_list):
if request and hasattr(request, 'user'):
if request.user.is_superuser:
return object_list
return object_list.filter(user=request.user)
return object_list.none()
更新 2
我发现没有什么比让字段只读和覆盖obj_create
方法更聪明的了:
class OrderResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user', null=True, full=True)
src_lang = fields.ForeignKey(LanguageResource, 'src_lang', null=True, full=True, blank=True, readonly=True)
dst_lang = fields.ForeignKey(LanguageResource, 'dst_lang', null=True, full=True, blank=True, readonly=True)
def obj_create(self, bundle, request=None, **kwargs):
src_lang_id, dst_lang_id = bundle.data.get('src_lang', None), bundle.data.get('dst_lang', None)
if not all([src_lang_id, dst_lang_id]):
raise BadRequest('You should specify both source and destination language codes')
src_lang, dst_lang = Language.objects.guess(src_lang_id), Language.objects.guess(dst_lang_id)
if not all([src_lang, dst_lang]):
raise BadRequest('You should specify both source and destination language codes')
return super(OrderResource, self).obj_create(
bundle, request, user=request.user, src_lang=src_lang, dst_lang=dst_lang
)
class Meta:
resource_name = 'orders'
queryset = Order.objects.all()
serializer = Serializer(['json'])
authentication = MultiAuthentication(SessionAuthentication(), ApiKeyAuthentication())
authorization = ResourceAuthorization()