【发布时间】:2021-12-20 08:22:05
【问题描述】:
我已经使用 Django Rest Framework 构建了一个简单的 API
两种模型:Person 和 Hike(人为 FK)
我已经安装了这些 PIP 包:
| package | version |
|---|---|
| Django | 3.2.7 |
| django-filter | 21.1 |
| django-mathfilters | 1.0.0 |
| djangorestframework | 3.12.4 |
| djangorestframework-api-key | 2.1.0 |
models.py
...
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Hike(models.Model):
hiker = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='hikes')
hike_date = models.DateField(max_length=100, blank=False)
distance_mi = models.FloatField(blank=False)
views.py
...
class PersonViewSet(viewsets.ModelViewSet):
queryset = Person.objects.all()
serializer_class = PersonSerializer
serializers.py
class PersonSerializer(serializers.ModelSerializer):
hikes = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
all_hikes = Hike.objects.all()
def total_mi(self, obj):
result = self.all_hikes.filter(hiker__id=obj.id).aggregate(Sum('distance_mi'))
return round(result['distance_mi__sum'], 2)
...
total_miles = serializers.SerializerMethodField('total_mi')
...
class Meta:
model = Person
fields = ('id','first_name','last_name','hikes','total_miles')
filters.py
class HikerFilter(django_filters.FilterSet):
hiker = django_filters.ModelChoiceFilter(field_name="hiker",
queryset=Person.objects.all())
class Meta:
model = Hike
fields = {
'hiker': ['exact'],
'hike_date': ['gte', 'lte', 'exact', 'gt', 'lt'],
'distance_mi': ['gte', 'lte', 'exact', 'gt', 'lt'],
}
样本数据:远足
| id | hike_date | distance_mi |
|---|---|---|
| 2 | 2020-11-02 | 4.5 |
| 3 | 2021-03-16 | 3.3 |
| 5 | 2021-08-11 | 5.3 |
| 7 | 2021-10-29 | 4.3 |
Person 视图包括通过 Serializer (total_mi) 添加的“total_miles”统计数据。
个人端点 http://localhost:8000/persons/2/
{
"id": 2,
"first_name": "Miles",
"last_name": "Marmot",
"hikes": [
2,
3,
5,
7
],
"total_miles": 17.4,
},
目前,“total_miles”适用于所有年份。
我的问题:如何通过传递 URL 参数按特定年份在“个人”视图中过滤“total_miles”(浮动)和“hikes”(列表)?
例如http://localhost:8000/persons/2/?year=2020 > "total_miles": 4.5,
例如http://localhost:8000/persons/2/?year=2021 > "total_miles": 12.9,
--
我能够在Serializer.py 中按年限制“total_miles”
all_hikes = Hike.objects.filter(hike_date__year='2020') 但年份是硬编码的,仅用于测试。
我可以将参数/var 传递给 Serializer 函数吗?
或者这可以通过自定义过滤器来实现吗?
可选/奖励:
Person 视图中的“hikes”(id 列表)也可以按 Year 过滤吗?
例如http://localhost:8000/persons/2/?year=2020 > "total_miles": 4.5, "hikes": [2]
例如http://localhost:8000/persons/2/?year=2021 > "total_miles": 12.9, "hikes": [3, 5, 7]
提前致谢!最好的~
【问题讨论】:
-
我只是想记下这个问题的辅助。我可以通过 URL 参数获取一个人一年(或任何日期范围)的所有远足: localhost:8000/hikes/?hiker=2&hike_date__gte=2021-01-01&hike_date__lt=2022-01-01 按人返回所有远足(id =2) 表示“2021”
标签: python django django-rest-framework django-filter django-filters