2011-10-06 94 views
2

我目前正在尝试django-tastypie来设计一个RESTful api。我现在面临一个问题:django-tastypie:将ModelResource链接到资源

# 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() 

在我的models.py我:

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

我的问题是,RevisionToApply模型(Django的)使用的int版本。

如何告诉tastypie使用RevisionToApplyResource的修订字段作为指向RevisionResource的指针?如果ToXxxxField仅用于链接django模型,那么插入ResourceObject的最佳时机是什么?

谢谢。

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) 

回答

2

下面是我该怎么做。看看ToOneField类是如何工作的,你会注意到水合物/脱水方法对负责获取和设置实际的相关实例。通过继承ToOneField并重写这两个方法,您可以获得Tastypie的自动化资源处理的好处,而无需实际的外键。

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

这将是这个样子:

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 

然后在您的资源中使用此字段类型而不是基本的ToOneField。我没有对它进行测试,但我相信这种方法是合理的,简单的,它可以完成工作。

+0

它适用于脱水方法。感谢您的小费。我仍然遇到水合物问题。 – piir