Python 相关模型上的django rest框架过滤器

Python 相关模型上的django rest框架过滤器,python,django,django-rest-framework,Python,Django,Django Rest Framework,我有一个国家模型和一个在某一年到某个国家度假的人模型。我想有一个国家的Api,在其中我可以只过滤某些人在某一年有假期的国家 Models.py from django.db import models class Country(models.Model): id = models.CharField(max_length=50,primary_key=True) country = models.CharField(max_length=255,null=True) class P

我有一个国家模型和一个在某一年到某个国家度假的人模型。我想有一个国家的Api,在其中我可以只过滤某些人在某一年有假期的国家

Models.py

from django.db import models

class Country(models.Model):
  id = models.CharField(max_length=50,primary_key=True)
  country = models.CharField(max_length=255,null=True)

class PersonYear(models.Model):
  id = models.IntegerField(primary_key=True)
  person = models.CharField(max_length=255,null=True)
  year = models.IntegerField(null=True)
  country = models.ForeignKey(Country, related_name='personyears')
示范国的内容

id|country
1|France
2|Italy
3|Spain
模范人物的内容

id|person|year|country_id
1|John|2014|1
2|John|2015|1
3|Mary|2014|1
序列化程序.py

from apiapp.models import PersonYear,Country
from rest_framework import serializers

class PersonyearSerializer(serializers.HyperlinkedModelSerializer):

   class Meta:
      model = PersonYear
      fields = ('id','person','year')

class CountrySerializer(serializers.HyperlinkedModelSerializer):
   personyears = PersonyearSerializer(many=True)

   class Meta:
      model = Country
      fields = ('id','country','personyears')
Views.py

import rest_framework_filters as filters

class PersonyearFilter(filters.FilterSet):
   id = filters.AllLookupsFilter(name='id')
   person = filters.AllLookupsFilter(name='person')
   year = filters.AllLookupsFilter(name='year')

   class Meta:
      model = PersonYear

class PersonyearViewSet(viewsets.ModelViewSet):
   queryset = PersonYear.objects.all()
   serializer_class = PersonyearSerializer
   filter_backends = (filters.backends.DjangoFilterBackend,)
   filter_fields =  ['id','person','year']
   filter_class = PersonyearFilter

class CountryFilter(filters.FilterSet):
   id = filters.AllLookupsFilter(name='id')
   nm = filters.AllLookupsFilter(name='country')
   personyears = filters.RelatedFilter(PersonyearFilter,name='personyears') 

   class Meta:
      model = Country 

class CountryViewSet(viewsets.ModelViewSet):
   queryset = Country.objects.all()
   serializer_class = CountrySerializer
   filter_backends = (filters.backends.DjangoFilterBackend,)
   filter_fields = ['id','country','personyears']
   filter_class = CountryFilter
我想选择2014年John度假的所有国家:

我希望得到一张唱片:

{"id": "1", "country": "France",
   "personyears": [
    {   "id": 1,
        "person": "John"
        "year": 2014
    }
]
}
但是我把这张唱片重复了4次。你能解释一下我做错了什么以及如何得到我想要的吗

更新1:

我不想在2014年只为John提供一个特殊的解决方案。我想要一个解决任何人在任何一年的所有实例。例如,我还希望以下筛选器为我提供一个结果:

更新2:

我试着替换:

 queryset = Country.objects.all()
作者:

这有助于获得以下预期(1项记录)结果:

本地主机:8000/国家/地区/?个人=约翰和个人=2014年

但我现在得到了person='Mary'/year='2015'的意外/不想要的结果

本地主机:8000/国家/地区/?人员=玛丽和人员=2015年

我没想到会有结果(2015年玛丽没有去任何国家度假)。但是我有

  {"id": "1","country": "France",
   "personyears": [
            {
                "id": 1,
                "person": "John",
                "year": 2014
            },
            {
                "id": 2,
                "person": "John",
                "year": 2015
            },
            {
                "id": 3,
                "person": "Mary",
                "year": 2014
            }
   ]
   }

您的
查询集应该是:

Country.objects.filter(personyears__year='your_year', person='your_person').values_list('country', flat=True)
这将返回所有国家的列表


注意:这将根据不同用户可能相同的人名进行过滤。应该还有一个模型作为
Person
,其
外键
应该映射到
PersonYear

那么,2014年约翰多久在法国一次?这似乎在最后一个查询集上缺少了一个
.distinct()
。它看起来确实像是将CountryViewSet中的
queryset=Country.objects.all()
替换为
queryset=Country.objects.all().distinct()
,这样做很简单。但我们会做更多的测试,但结果并不是这样。如果我现在筛选person=Mary和year=2015,结果告诉我Mary在2015年去了法国,而她在2015年没有去任何地方。因此我将CountryView中的queryset替换为
queryset=Country.objects.filter(Personyear\uu year='2014',Personyear\uu person='John')。values\u list('Country',flat=True)
我首先在它工作的shell中测试了它。但是在views.py中,当试图获取序列化程序“CountrySerializer”上字段“id”的值时,它给出了错误
AttributeError:get AttributeError。序列化程序字段的名称可能不正确,并且与“unicode”实例上的任何属性或键都不匹配。
还尝试用此
queryset=Country.objects.filter(personyears\uuuuu year='2014',personyears\uuuu person='John')
替换,但结果相同(4条相同的记录)。我还想知道你的建议是否有效,如何以通用的方式使用它(例如:2015年玛丽度假的所有国家)
Country.objects.filter(personyears\uuu year='2014',personyears_‌​_瓦卢先生‌​es_列表(“国家”,佛罗里达州)‌​at=True).values('country').distinct()
这就是您需要的吗?或者,您可以执行以下操作:
countries\u id=set(country.objects.filter(personyear\u year='your\u year',person='your\u person')。values\u list('id',flat=True))
。然后:
country=country.objects.filter(id\u in=countries\u id)
。将
country
传递到序列化程序中,它就会工作。顺便说一句,我认为您并不真正需要序列化程序。您只需要国家的名称,直接调用我在答案中提到的查询,返回国家列表。从视图中返回该列表,而不是clalling serlizer,然后返回值
Country.objects.filter(personyears__year='your_year', person='your_person').values_list('country', flat=True)