Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django tastypie和GenericForeignKey_Django_Rest_Django Models_Tastypie - Fatal编程技术网

Django tastypie和GenericForeignKey

Django tastypie和GenericForeignKey,django,rest,django-models,tastypie,Django,Rest,Django Models,Tastypie,我有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 = generi

我有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')

我做Page.objects.get(pk=1).content\u对象,我得到了它

请帮助我显示一个链接(或JSON输出),该链接将对象锚定在REST中

class PageResource(ModelResource):
    content_object = fields.?????

    class Meta:
        queryset = Page.objects.all()
        resource_name = 'page'
如何做对

谢谢


Vitaliy

目前,在tastypie中使用泛型关系并不容易。在上提交了一些修补程序,但截至撰写本文时,这些修补程序尚未合并

最简单的方法是定义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'
希望这能有所帮助。

我的资源就是包含ContentTypeResource的应用程序。如果它与您的其他资源在同一个应用程序中,您不需要对其进行限定。在下面的代码中删除

“contrib/contenttype”是资源的名称。设置您自己的名称是可选的。如果您不指定,Tastypie将为您创建一个。我已经在下面的更新代码中删除了它

fields=['model']
部分限制此资源表示的模型中的可访问字段。如果查看Django代码中ContentType模型的定义,您将看到它有一个名为“model”的字段

我认为最初的答案混淆了字段名。您正在尝试为content\u类型创建新资源,并将其连接到模型中的content\u类型外键。上面的代码对其进行了分类

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'
您还需要在URL.py中注册ContentTypeResource,就像在所有其他资源中一样:

from myapp.api import ContentTypeResource

v1_api = Api(api_name='v1')
v1_api.register(ContentTypeResource())
“myapp”位同样是api代码包含ContentTypeResource的应用程序


我希望这能把事情弄清楚。我自己刚开始工作…

这将为您提供内容对象字段作为嵌套对象。它很简单,很有效,而且(不幸的是)它的效率与技术所允许的一样高

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

如果内容对象具有相应的ModelResource,则我们设法获取其uri:

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 ''
我们破解了密码

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": ""
},

看起来这是一个月前正式添加到Tastypie的,请查看这里的示例


事实上,正如马里奥所建议的那样,他们增加了对这一点的支持。因为我花了很长时间才弄明白,我想这可能会帮助一些人。下面是一个使用Django内置注释模型的示例,其中我从注释对象获得与注释相反的关系:

将此添加到注释附加到的模型中:

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

我现在正试图实现这一点。你能提供一点更多的上下文来帮助我理解吗。我有一个加法,它与属性有一个通用关系。我想得到给定加法的所有属性。在您的示例中,“myresources”、“contrib/contenttype”、“model”指的是什么。谢谢。我在实现这一点时遇到了一些困扰:如果您使用的是反向泛型关系,您不能忘记在访问泛型资源的模型上使用fields.ToManyField。在没有将修补程序应用于tastypie的情况下,您是否可以正常工作?但这需要知道您将要将关系指向哪些模型。这种做法首先违背了拥有通用外键的目的。
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