Python 相关模型上的django rest框架过滤器
我有一个国家模型和一个在某一年到某个国家度假的人模型。我想有一个国家的Api,在其中我可以只过滤某些人在某一年有假期的国家 Models.pyPython 相关模型上的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
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)