当我创建一个具有外部关系的新资源时,例如,{"pk": 20}
,我创建了一个新的不需要的FK项。在
我有一个与Language
模型相关的Order
模型类,因此在创建Order实例时,我可能必须指定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
资源:
我试图用jQuery创建一个新的Order
:
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
设置为src_lang_id
字段,而是为src_lang
创建一个新的带有空字段的Language
,并为dst_lang
设置一个正确的值。但是空字段受Language
模型定义的限制。它是如何拯救它的?在
另外,这很奇怪,因为我直接为语言模型指定了readonly访问,并且只指定了访问支持的语言列表的get
方法。在
如果我将OrderResource
类的语言字段声明为,即: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()
我发现没有比使字段只读并重写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()
您应该以与
pk=20
对应的/api/v2/languages/72/
格式指定src_lang
。在第二,什么是{}?documentation列出了对您可能有用的
ReadOnlyAuthorization
。在此外,授权应用资源,而不是底层模型。为
fk
创建新对象时,它不使用restapi,而是使用django.db.models
及其权限。因此,授权可能不会通过外键约束应用。在正如this对您的问题的回答中所述,
src_lang
应该对应于一个资源,而不是其他值。我怀疑,当POST发生并且没有找到资源pk=20
时,它会创建一个新的Language
对象并调用save
而没有Django模型验证,从而允许在创建的Language
中存在一个空白字段。在强制只读类型资源的一种方法是创建不允许
obj_create
的资源。在然后从您的
^{pr2}$Order
资源引用此资源,只覆盖src_lang
字段以指向只读资源。在任何引用现有资源的请求都将按正常方式完成(但您需要正确引用该资源,而不是使用
pk=20
)。任何引用未知语言的请求都将失败,因为无法创建新的Language
对象。在相关问题 更多 >
编程相关推荐