django-tastypie: linking a ModelResource to a Resource

浪尽此生 提交于 2019-12-22 15:04:10

问题


I'm currently trying django-tastypie to design a RESTful api. I'm facing a problem:

# the RevisionObject retrieve commits info through pysvn
# This Resource is fully functionnal (RevisionObject code is not here)
class RevisionResource(Resource):
    id = fields.CharField(attribute='revision')
    description = fields.CharField(attribute='message')
    author = fields.CharField(attribute='author')
    changed_path = fields.ListField(attribute='changed_paths')

    class Meta:
        object_class = RevisionObject
        allowed_methods = ['get']
        resource_name = 'revision'

class RevisionToApplyResource(ModelResource):
    #### here's the problem
    revision = fields.ToManyField(RevisionResource, 'revision')
    ####
    class Meta:
        queryset = RevisionToApply.objects.all()

In my models.py I have:

class RevisionToApply(models.Model):
    patch = models.ForeignKey(PatchRequest)
    revision = models.PositiveIntegerField()
    applied = models.BooleanField(default = False)

My problem is that the RevisionToApply models (for django) uses an int to the revision.

How can I tell tastypie to use the revision field of RevisionToApplyResource as a pointer to a RevisionResource? If the ToXxxxField are only for linking with django models, what is the perfect moment to insert the ResourceObject?

thanks.

class NoForeignKeyToOneField(ToOneField):
    def dehydrate(self, bundle):
        try:
            obj_key = getattr(bundle.obj, self.attribute)
            foreign_obj = self.to_class().obj_get(pk=obj_key)
        except ObjectDoesNotExist:
            foreign_obj= None

        if not foreign_obj:
            if not self.null:
                raise ApiFieldError("The model '%r' has an empty attribute"
                   "'%s' and doesn't allow null value." % (bundle.obj,
                   self.attribute))
            return None

        self.fk_resource = self.get_related_resource(foreign_obj)
        fk_bundle = Bundle(obj=foreign_obj, request=bundle.request)
        return self.dehydrate_related(fk_bundle, self.fk_resource)

回答1:


Here's how I would do it. Taking a look at how the ToOneField class works, you'll notice that the hydrate/dehydrate method pair takes care of getting and setting the actual related instance. By subclassing ToOneField and overriding these two methods, you can get the benefit of Tastypie's automated resource handling without an actual foreign key.

(I'm referring to ToOneField rather than ToManyField because in your model, a given RevisionToApply can only point to one revision, it seems.)

It would look something like this:

class NoForeignKeyToOneField(ToOneField):

    def dehydrate(self, bundle):
        # Look up the related object manually
        try:
            obj_key = getattr(bundle.obj, self.attribute)
            ###
            # Get the revision object here. If you want to make it generic,
            # maybe pass a callable on __init__ that can be invoked here
            ###
            foreign_obj = revision_object
        except ObjectDoesNotExist:
            foreign_obj = None
        # The rest remains the same
        if not foreign_obj:
            if not self.null:
                raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (bundle.obj, self.attribute))
            return None

        self.fk_resource = self.get_related_resource(foreign_obj)
        fk_bundle = Bundle(obj=foreign_obj, request=bundle.request)
        return self.dehydrate_related(fk_bundle, self.fk_resource)

    def hydrate(self, bundle):
        value = super(NoForeignKeyToOneField, self).hydrate(bundle)

        if value is None:
            return value

        # Here, don't return the full resource, only the primary key
        related_resource = self.build_related_resource(value, request=bundle.request)
        return related_resource.pk

And then use this field type in your resource rather than the basic ToOneField. I haven't tested it , but I believe the approach is sound, simple and it'll get the job done.



来源:https://stackoverflow.com/questions/7672452/django-tastypie-linking-a-modelresource-to-a-resource

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