Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django tastypie and GenericForeignKey

I have Page model with 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')

and

class TextContent(models.Model):
    content = models.TextField(null=True, blank=True)
    pages = generic.GenericRelation(Page)

I do Page.objects.get(pk=1).content_object and I got it.

Help me please to show a link (or output to JSON) that anchored object in REST.

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

    class Meta:
        queryset = Page.objects.all()
        resource_name = 'page'

How to do it right?

Thanks!

Vitaliy

like image 550
moskrc Avatar asked Nov 18 '11 18:11

moskrc


3 Answers

There's currently no easy way using generic relations in tastypie. There have been some patches submitted at tastypie github page but these have not been merged as of this writing.

The easiest way to do this, define a contenttype resource and use that for the resources having a generic relation. Something along the lines of:

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'

Hope this helps.

like image 177
tayfun Avatar answered Nov 18 '22 09:11

tayfun


The "myresources" thing is the app that contains the ContentTypeResource. If it's in the same app as your other resources, you don't need to qualify it. Deleted in the code below.

The "contrib/contenttype" is the name of the resource. Setting your own name is optional. Tastypie will create one for you if you don't specify it. I've deleted it in the update code below.

The fields = ['model'] section limits the accessible fields from the model that this resource represents. If you look at the definition of the ContentType model in the Django code, you'll see it has a field called 'model'.

I think the original answer had its field names mixed up. You're trying to create a new resource for content_type, and hook that up to the content_type foreign key in your model. The code above sorts this out.

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'

You're also going to need to register ContentTypeResource in your urls.py as you have with all your other resources:

from myapp.api import ContentTypeResource

v1_api = Api(api_name='v1')
v1_api.register(ContentTypeResource())

The "myapp" bit is again the app with the api code containing ContentTypeResource.

I hope this clears things up. I just got it working myself...

like image 5
CaptainThrowup Avatar answered Nov 18 '22 10:11

CaptainThrowup


It looks like this was officially added to Tastypie a month ago, check out the example here.

https://github.com/toastdriven/django-tastypie/blob/master/docs/content_types.rst

like image 3
Mario Avatar answered Nov 18 '22 09:11

Mario