我有GFK的页面模型。
class Page(models.Model):
title = models.CharField(max_length=200)
content_type = models.ForeignKey(ContentType,null=True,blank=True)
object_id = models.CharField(max_length=255,null=True,blank=True)
content_object = generic.GenericForeignKey('content_type', 'object_id')
和
class TextContent(models.Model):
content = models.TextField(null=True, blank=True)
pages = generic.GenericRelation(Page)
我做了Page.objects.get(pk = 1).content_object,我明白了。
请帮我看一下REST中锚定对象的链接(或输出到JSON)。
class PageResource(ModelResource):
content_object = fields.?????
class Meta:
queryset = Page.objects.all()
resource_name = 'page'
怎么做对了?
谢谢!
的Vitaliy
答案 0 :(得分:7)
目前在tastypie中使用泛型关系并不容易。在tastypie github page提交了一些补丁,但截至本文撰写时尚未合并。
最简单的方法是,定义contenttype资源并将其用于具有通用关系的资源。有点像:
class ContentTypeResource(ModelResource):
class Meta:
queryset = ContentType.objects.all()
resource_name = "contrib/contenttype"
fields = ['model']
detail_allowed_methods = ['get',]
list_allowed_methods = ['get']
class PageResource(ModelResource):
content_object = fields.ToOneField('myresources.ContentTypeResource', 'content_object')
class Meta:
queryset = Page.objects.all()
resource_name = 'page'
希望这有帮助。
答案 1 :(得分:5)
“myresources”是包含ContentTypeResource的应用程序。如果它与您的其他资源位于同一个应用程序中,则无需限定它。在下面的代码中删除。
“contrib / contenttype”是资源的名称。设置您自己的名称是可选的。如果您没有指定,Tastypie将为您创建一个。我已在下面的更新代码中将其删除。
fields = ['model']
部分限制此资源所代表的模型中的可访问字段。如果你看一下Django代码中ContentType模型的定义,你会发现它有一个名为'model'的字段。
我认为最初的答案是其字段名称混淆了。您正在尝试为content_type创建新资源,并将其挂钩到模型中的content_type外键。上面的代码对此进行了排序。
class ContentTypeResource(ModelResource):
class Meta:
queryset = ContentType.objects.all()
fields = ['model']
detail_allowed_methods = ['get',]
list_allowed_methods = ['get']
class PageResource(ModelResource):
content_type = fields.ToOneField('ContentTypeResource', 'content_type')
class Meta:
queryset = Page.objects.all()
resource_name = 'page'
您还需要在urls.py中注册ContentTypeResource,就像您拥有所有其他资源一样:
from myapp.api import ContentTypeResource
v1_api = Api(api_name='v1')
v1_api.register(ContentTypeResource())
“myapp”位再次是包含ContentTypeResource的api代码的应用程序。
我希望这可以解决问题。我只是让它自己工作......
答案 2 :(得分:3)
看起来这个月被正式添加到Tastypie,请查看此处的示例。
https://github.com/toastdriven/django-tastypie/blob/master/docs/content_types.rst
答案 3 :(得分:2)
我们破解了代码!
class ContentTypeResource(ModelResource):
class Meta:
queryset = ContentType.objects.all()
resource_name = 'content_type'
allowed_methods = ['get',]
class PageObjectResource(ModelResource):
content_object = fields.CharField()
content_type = fields.ToOneField(
ContentTypeResource,
attribute = 'content_type',
full=True)
class Meta:
queryset = models.PageObject.objects.all()
resource_name = 'page_object'
allowed_methods = ['get',]
def dehydrate_content_object(self, bundle):
for resource in api._registry.values():
if resource._meta.object_class == bundle.obj.content_object.__class__:
return resource.full_dehydrate(resource.build_bundle(obj=bundle.obj.content_object, request=bundle.request)).data
return ''
结果如下:
"page_objects": [
{
"content_object": {
"id": "186",
"look_stills": [
{
"_image": "/static/media/uploads/looks/DSC_0903_PR_MEDIUM_QUALITY_RGB_FA.jpg",
"aspect": "front",
"id": "186",
"look_still_icons": [
{
"colour_code": "58",
"enabled": true,
"id": "186",
"in_stock_only": true,
"look_product": {
"colour_code": "58",
"enabled": true,
"id": "186",
"resource_uri": "/api/look_product/186/",
"style_code": "420215"
},
"resource_uri": "/api/look_still_icon/186/",
"x_coord": 76,
"y_coord": 5
}
],
"ordering": 1,
"resource_uri": "/api/look_still/186/"
}
],
"resource_uri": "/api/look_still_set/186/",
"slug": ""
},
"content_type": {
"app_label": "looks_beta",
"id": "97",
"model": "lookstillset",
"name": "look still set",
"resource_uri": "/api/content_type/97/"
},
"id": "2",
"object_id": 186,
"resource_uri": "/api/page_object/2/"
}
],
"page_order": 3,
"page_template": "look_still",
"resource_uri": "/api/page/2/",
"slug": "",
"spread_number": 2,
"title": ""
},
答案 4 :(得分:1)
这为您提供了content_object字段作为嵌套对象。这很简单,很有效,并且(不幸的是)技术可以实现高效率。
class PageResource(ModelResource):
def full_dehydrate(self, bundle):
new_bundle = super(PageResource, self).full_dehydrate(bundle)
new_bundle.data['content_object'] = get_serializable(bundle.obj.content_object)
return new_bundle
class Meta:
queryset = Page.objects.all()
def get_serializable(model):
data = {'type': model.__class__.__name__}
for field in model._meta.fields:
data[field.name] = getattr(model, field.name)
return data
答案 5 :(得分:0)
我们设法获取内容对象的uri,如果它有相应的ModelResource:
class ContentTypeResource(ModelResource):
class Meta:
queryset = ContentType.objects.all()
resource_name = 'content_type'
allowed_methods = ['get',]
class PageObjectResource(ModelResource):
content_object_uri = fields.CharField()
content_type = fields.ToOneField(
ContentTypeResource,
attribute = 'content_type',
full=True)
class Meta:
queryset = models.PageObject.objects.all()
resource_name = 'page_object'
allowed_methods = ['get',]
def dehydrate_content_object_uri(self, bundle):
for resource in api._registry.values():
if resource._meta.object_class == bundle.obj.content_object.__class__:
return resource.get_resource_uri(bundle.obj.content_object)
return ''
答案 6 :(得分:0)
将此添加到注释附加到的模型:
class CmntedObject(models.Model):
comments = generic.GenericRelation(Comment,
content_type_field='content_type',
object_id_field='object_pk')
并且资源看起来像这样:
class UserResource(ModelResource):
what ever you need here....
class CmntedObjectResource(ModelResource):
comments = fields.ToManyField('path.to.api.CmntedObjectResource', 'comments', full=True, null=True)
class Meta:
queryset = CmntedObject.objects.all()
resource_name = 'cmntedobject'
allowed_methods = ['get', 'post', 'delete']
authorization = DjangoAuthorization()
class CommentResource(ModelResource):
user = fields.ToOneField('path.to.api.UserResource', 'user', full=True)
content_type_id = fields.CharField(attribute = 'content_type_id')
site_id = fields.CharField(attribute = 'site_id')
content_object = GenericForeignKeyField({
CmntedObject: CmntedObjectResource, #shown above
OtherCmntedObject: OtherCmntedObjectResource, #optional
}, 'content_object', null=True)
class Meta:
queryset = Comment.objects.all()
resource_name = 'cmnt'
allowed_methods = ['get', 'post', 'delete']
authorization = DjangoAuthorization()
def obj_create(self, bundle, **kwargs):
#here we get the current authenticated user as the comment user.
bundle = super(CmntResource, self).obj_create(bundle, user=bundle.request.user)
return bundle