django-tastypie:将ModelResource链接到资源 [英] django-tastypie: linking a ModelResource to a Resource

查看:156
本文介绍了django-tastypie:将ModelResource链接到资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试django-tastypie来设计一个RESTful api。我正面临一个问题:

 #RevisionObject通过pysvn 
提交信息#资源完全是functionnal RevisionObject代码不在这里)
class RevisionResource(Resource):
id = fields.CharField(attribute ='revision')
description = fields.CharField(attribute ='message')
author = fields.CharField(attribute ='author')
changed_pa​​th = fields.ListField(attribute ='changed_pa​​ths')

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

class RevisionToApplyResource(ModelResource):
####这里的问题
revision = fields .ToManyField(RevisionResource,'revision')
####
class Meta:
queryset = RevisionToApply.objects.all()
pre>

在我的models.py中,我有:

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

我的问题是RevisionToApply模型(对于django)使用一个int进行修订。



如何告诉Tastypie将RevisionToApplyResource的修订字段用作指向RevisionResource的指针?如果ToXxxxField仅用于与django模型链接,那么插入ResourceObject的完美时刻是什么?



谢谢。



$ $ $ $ $ $ $ $ $ $ $ $


$ b $ obj_key = getattr(bundle.obj,self。属性)
foreign_obj = self.to_class()。obj_get(pk = obj_key)
除了ObjectDoesNotExist:
foreign_obj =无

如果不是foreign_obj:
如果不是self.null:
raise ApiFieldError(模型'%r'有一个空属性
'%s',不允许空值%(bundle.obj,
self.attribute))
返回无

self.fk_resource = self.get_related_resource(foreign_obj)
fk_bundle = Bundle(obj = foreign_obj,request = bundle.request)
return self.hydrate_related(fk_bundle,self.fk_reso urce)


解决方案

我将如何做。看看 ToOneField 类如何工作,你会注意到,水合物/脱水方法对负责获取和设置实际的相关实例。通过将 ToOneField 进行子类化,并覆盖这两种方法,您可以获得Tastypie的自动资源处理的好处,而无需实际的外键。



(我指的是 ToOneField 而不是 ToManyField ,因为在您的模型中,给定的 RevisionToApply 只能指向一个版本,似乎。)



它看起来像这样:

  class NoForeignKeyToOneField(ToOneField):

def dehydrate(self,bundle):
#手动查找相关对象
try:
obj_key = getattr(bundle.obj,self.attribute)
###
#在此处获取修订对象。如果你想让它通用,
#可能会传递一个可调用__init__可以在这里调用
###
foreign_obj = revision_object
除了ObjectDoesNotExist:
foreign_obj =无
#其余的仍然是相同的
如果不是foreign_obj:
如果不是self.null:
raise ApiFieldError(模型'%r'有一个空属性'% s',并且不允许空值。%(bundle.obj,self.attribute))
返回无

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

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

如果值为None:
返回值

#这里不要返回e全资源,只有主键
related_resource = self.build_related_resource(value,request = bundle.request)
return related_resource.pk

然后在您的资源中使用此字段类型,而不是基本的 ToOneField 。我没有测试过,但我相信这种方法是健全,简单的,它会完成工作。


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)

解决方案

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.

这篇关于django-tastypie:将ModelResource链接到资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆