如何在django tastypie中使用向后关系

时间:2013-02-02 13:43:12

标签: django reverse tastypie

这是我的模特

class Nisit(models.Model):

和这个

class Page(models.Model):
followingNisit = models.ManyToManyField(Nisit,blank=True)

这是我的资源

class NisitResource(ModelResource):
    page = fields.ToManyField('chula.api.PageResource','page_set',null=True)
class Meta:
    queryset = Nisit.objects.all()      
    resource_name = 'nisit'
    filtering = {
        'page' : ALL_WITH_RELATIONS,
        'id' : ALL,
    }

class PageResource(ModelResource):
    followingNisit = fields.ToManyField(NisitResource, 'followingNisit',null=True)
    reporter = fields.ManyToManyField(ReporterResource,'reporter')
    followers_count = fields.CharField(attribute='followers_count')

class Meta:
    queryset = Page.objects.all()
    resource_name = 'page'
    authorization= Authorization()
    filtering = {
        'id':ALL,
        'followingNisit': ALL_WITH_RELATIONS,
    }

我请求时可以------- 127.0.0.1:8000/api/v2/page/?format=json&followingNisit__id=1

但是反过来,当我要求--------- 127.0.0.1:8000/api/v2/nisit/?format=json&page__id=1时,我会收到此错误

{"error_message": "Cannot resolve keyword 'page_set' into field. Choices are: displayName, facebook, faculty, friend, id, major, n_id, name, page, password, picture, reporter, year_in_school", "traceback": "Traceback (most recent call last):\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 202, in wrapper\n    response = callback(request, *args, **kwargs)\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 441, in dispatch_list\n    return self.dispatch('list', request, **kwargs)\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 474, in dispatch\n    response = method(request, **kwargs)\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 1127, in get_list\n    objects = self.obj_get_list(request=request, **self.remove_api_resource_names(kwargs))\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 1890, in obj_get_list\n    base_object_list = self.apply_filters(request, applicable_filters)\n\n  File \"D:\\Study\\SeniorProject\\Code\\mysite\\tastypie\\resources.py\", line 1862, in apply_filters\n    return self.get_object_list(request).filter(**applicable_filters)\n\n  File \"C:\\Python27\\lib\\site-packages\\django\\db\\models\\query.py\", line 624, in filter\n    return self._filter_or_exclude(False, *args, **kwargs)\n\n  File \"C:\\Python27\\lib\\site-packages\\django\\db\\models\\query.py\", line 642, in _filter_or_exclude\n    clone.query.add_q(Q(*args, **kwargs))\n\n  File \"C:\\Python27\\lib\\site-packages\\django\\db\\models\\sql\\query.py\", line 1250, in add_q\n    can_reuse=used_aliases, force_having=force_having)\n\n  File \"C:\\Python27\\lib\\site-packages\\django\\db\\models\\sql\\query.py\", line 1122, in add_filter\n    process_extras=process_extras)\n\n  File \"C:\\Python27\\lib\\site-packages\\django\\db\\models\\sql\\query.py\", line 1316, in setup_joins\n    \"Choices are: %s\" % (name, \", \".join(names)))\n\nFieldError: Cannot resolve keyword 'page_set' into field. Choices are: displayName, facebook, faculty, friend, id, major, n_id, name, page, password, picture, reporter, year_in_school\n"}

2 个答案:

答案 0 :(得分:1)

我一直在努力解决从setup_joins抛出的同一个FieldError,我想我刚刚解决了我的问题。我试图通过多对多关系来过滤,并且永远无法获得" _set"在fields.ToManyField()工作。在错误案例和工作简单过滤器中调试TastyPie代码之后,我意识到可以完全绕过对中间资源的需求。

这对我有用,我希望它对你的情况有所帮助。由于我不了解您的模型设置,我将构成一个类似的例子。

首先,模特:

### models.py ###
from django.db import models

class Ingredient(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()

    def __unicode__(self):
        return '%s' % (self.name)

class RecipeIngredient(models.Model):
    recipe = models.ForeignKey('Recipe')
    ingredient = models.ForeignKey('Ingredient')
    weight = models.IntegerField(null = True, blank = True)

    def __unicode__(self):
        return '%s: %s' % (self.recipe, self.ingredient)

class Recipe(models.Model):
    title = models.CharField(max_length=100)
    ingredients = models.ManyToManyField(Ingredient, through='RecipeIngredient')

    def __unicode__(self):
        return '%s' % (self.title)

以下是ModelResources:

### api.py ###
from tastypie.resources import ModelResource, ALL, ALL_WITH_RELATIONS
from tastypie import fields
from some_app.models import Ingredient, Recipe

class IngredientResource(ModelResource):

    class Meta:
        queryset = Ingredient.objects.all()
        resource_name = 'ingredient'
        filtering = {
            'name': ALL,
        }

class RecipeResource(ModelResource):
    ingredients = fields.ToManyField(
        'some_app.api.IngredientResource',
        'ingredients',
        full=True)

    class Meta:
        queryset = Recipe.objects.all()
        resource_name = 'recipe'
        filtering = {
            'title': ALL,
            'ingredients': ALL_WITH_RELATIONS,
        }

注意我没有RecipeIngredientResource,我直接挂钩到IngredientResource,因为Recipe模型包含带有选项ingredients的ManyToManyField through='RecipeIngredient'

过滤特定成分的所有配方的示例网址如下所示:

http://localhost:8000/api/recipes/recipe/?ingredients__name=blueberry

而且,为了完整起见,这里有一个名为' some_app'的Django应用程序。为任何想要实现此示例的人节省输入数据的时间:

[
    {
        "pk": 1, 
        "model": "some_app.ingredient", 
        "fields": {
            "name": "apple", 
            "description": "a tempting fruit"
        }
    }, 
    {
        "pk": 2, 
        "model": "some_app.ingredient", 
        "fields": {
            "name": "cherry", 
            "description": "a red fruit"
        }
    }, 
    {
        "pk": 3, 
        "model": "some_app.ingredient", 
        "fields": {
            "name": "blueberry", 
            "description": "a blue fruit"
        }
    }, 
    {
        "pk": 4, 
        "model": "some_app.ingredient", 
        "fields": {
            "name": "flour", 
            "description": "used for baking and stuff"
        }
    }, 
    {
        "pk": 5, 
        "model": "some_app.ingredient", 
        "fields": {
            "name": "sugar", 
            "description": "makes stuff sweet"
        }
    }, 
    {
        "pk": 1, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 1, 
            "weight": 3, 
            "ingredient": 1
        }
    }, 
    {
        "pk": 2, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 1, 
            "weight": 2, 
            "ingredient": 4
        }
    }, 
    {
        "pk": 3, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 1, 
            "weight": 4, 
            "ingredient": 5
        }
    }, 
    {
        "pk": 4, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 2, 
            "weight": 8, 
            "ingredient": 2
        }
    }, 
    {
        "pk": 5, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 2, 
            "weight": 4, 
            "ingredient": 4
        }
    }, 
    {
        "pk": 6, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 2, 
            "weight": 6, 
            "ingredient": 5
        }
    }, 
    {
        "pk": 7, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 3, 
            "weight": 15, 
            "ingredient": 3
        }
    }, 
    {
        "pk": 8, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 3, 
            "weight": 5, 
            "ingredient": 4
        }
    }, 
    {
        "pk": 9, 
        "model": "some_app.recipeingredient", 
        "fields": {
            "recipe": 3, 
            "weight": 6, 
            "ingredient": 5
        }
    }, 
    {
        "pk": 1, 
        "model": "some_app.recipe", 
        "fields": {
            "title": "Apple Pie"
        }
    }, 
    {
        "pk": 2, 
        "model": "some_app.recipe", 
        "fields": {
            "title": "Cherry Pie"
        }
    }, 
    {
        "pk": 3, 
        "model": "some_app.recipe", 
        "fields": {
            "title": "Blueberry Pie"
        }
    }
]

答案 1 :(得分:-1)

这是事情,如果django tastypie与django非常相似(正如任何人所料)你使用了错误的关键字,在你的情况下,它不会是page_set,只使用{ {1}}相反,它会起作用。

我建议你在字段名称中使用复数

page

因此前向关系为pages = fields.ToManyField('chula.api.PageResource','page_set',null=True) ,后向关系为pages我现在无法记住。但无论如何它会看起来更好。