Tastypie accessing fields from inherited models

此生再无相见时 提交于 2019-12-06 02:36:26

问题


Is it possible to include fields on related models, using tastypie?

As per my models below: if I persist one VideoContent and one TextContent instance to the DB, I can then get 2 objects back from my Content resource, however none of the additional fields are available.

Is it possible to include fields from related models (in this instance, the video url and the text content) and will that cater for adding more Content types in the future without having to rewrite the Content Resource, or am I coming at this from the wrong direction?

The goal is to be able to extend this with more ContentTypes without having to make changes to the Content resource (assuming it's possible to get it working in the first place)

Models.py:

class Content(models.Model):
    parent = models.ForeignKey('Content', related_name='children', null=True, blank=True)

class TextContent(Content):
    text = models.CharField(max_length=100)

class VideoContent(Content):
    url = models.CharField(max_length=1000)

And then my resources:

class ContentResource(ModelResource):
    children = fields.ToManyField('myapp.api.resources.ContentResource', 'children', null=True, full=True)

    class Meta:
        resource_name = 'content'
        queryset = ContentResource.objects.all()
        authorization = Authorization()
        always_return_data = True

回答1:


I found a good solution in another answer

Populating a tastypie resource for a multi-table inheritance Django model


I've run into the same problem - although I'm still in the middle of solving it. Two things that I've figured out so far:

django-model-utils provides an inheritence manager that lets you use the abstract base class to query it's table and can automatically downcast the query results.

One thing to look at is the dehydrate/rehydrate methods available to Resource classes.

This is what I did:

class CommandResource(ModelResource):

   class Meta:
        queryset = Command.objects.select_subclasses().all()

That only gets you half way - the resource must also include the dehydrate/rehydrate stuff because you have to manually package the object up for transmission (or recieving) from the user.

The thing I'm realizing now is that this is super hacky and there's gotta be a better/cleaner way provided by tastypie - they can't expect you to have to do this type of manual repackaging in these types of situations - but, maybe they do. I've only got about 8 hours of experience with tastypie @ this point so if I'm explaining this all wrong perhaps some nice stackoverflow user can set me straight. :D :D :D




回答2:


I had the same requirement and finally solved it.

I didn't like the answer given in the above link because I didn't like the idea of combining queryset and re-sorting.

Apparently, you can inherit multiple resources.

By subclassing multiple resources, you include the fields of the resources.
And since those fields are unique to each resource, I made them nullable in the init.

wonder if there's a way to list the parents only once. (There are two now. One for subclassing, and one in meta)

class SudaThreadResource(ThreadResource):

    def __init__(self, *args, **kwargs):
        super(SudaThreadResource, self).__init__(*args, **kwargs)

        for field_name, field_object in self.fields.items():
            # inherited_fields  can be null                                                                                                                                                                                                                                     
            if field_name in self.Meta.inherited_fields:
                field_object.null=True

    class Meta(ThreadResource.Meta):
        resource_name = 'thread_suda'
        usedgoodthread_fields = UsedgoodThreadResource.Meta.fields[:]
        userdiscountinfothread_fields = UserDiscountinfoThreadResource.Meta.fields[:]
        staffdiscountinfothread_fields = StaffDiscountinfoThreadResource.Meta.fields[:]
        bitem_checklistthread_fields = BitemChecklistThreadResource.Meta.fields[:]

        parent_field_set = set(ThreadResource.Meta.fields[:])

        field_set = set(
            set(usedgoodthread_fields) |
            set(userdiscountinfothread_fields) |
            set(staffdiscountinfothread_fields) |
            set(bitem_checklistthread_fields)
        )

        fields = list(field_set)
        inherited_fields = list(field_set - parent_field_set)


        queryset = forum_models.Thread.objects.not_deleted().exclude(
            thread_type__in=(forum_const.THREAD_TYPE_MOMSDIARY, forum_const.THREAD_TYPE_SOCIAL_DISCOUNTINFO)
        ).select_subclasses()


来源:https://stackoverflow.com/questions/12753113/tastypie-accessing-fields-from-inherited-models

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!