对于我的应用程序,我有以下(简化)模型给出的位置和事件:
class Location(models.Model):
name = models.CharField(max_length=64)
class Event(models.Model):
location = models.ForeignKey(Location)
date = models.DateField()
在我的API中,我有一个端点:/api/locations/
,它返回所有位置,每个位置都有嵌入其中的事件,例如:
[
{
'id': 1,
'name': 'Location 1',
'events': [
{'id': 1, 'date': '2018-01-01'},
{'id': 2, 'date': '2018-01-14'}
]
},
{
'id': 2,
'name': 'Location 2',
'events': [
{'id': 3, 'date': '2017-12-28'},
{'id': 4, 'date': '2018-01-10'}
]
}
]
我的序列化工具看起来像:
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = ('id', 'date',)
read_only_fields = ('id',)
class LocationSerializer(serializers.ModelSerializer):
events = EventSerializer(many=True)
class Meta:
model = Location
fields = ('id', 'name', 'events',)
read_only_fields = ('id',)
使用ViewSets,我想在此调用中添加一个过滤器,其中包含max_date
和min_date
参数,例如:/api/locations/?min_date=2018-01-01&max_date=2018-01-15
。哪个应该只返回在这两个日期之间有事件的位置,AND应该只返回这两个日期之间每个位置的事件。
在上面的示例数据中,两个位置都会返回,位置1会列出两个事件,但位置2只会在其列表中包含第二个事件。在我的ViewSet中,我可以获取这些参数并将它们作为查询集过滤器附加:
class LocationViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
serializer_class = LocationSerializer
def get_queryset(self):
queryset = Location.objects.all()
min_date = self.request.query_params.get('min_date', None)
max_date = self.request.query_params.get('max_date', None)
if min_date is not None and max_date is not None:
queryset = queryset.filter(event__date__lte=max_date, event__date__gte=min_date)
return queryset
这将过滤掉两个日期之间没有任何事件的所有位置,但是这些返回的位置会显示所有事件,而不仅仅是min_date
和max_date
之间的事件。我假设我必须以某种方式将查询参数传递给EventSerializer
中嵌入的LocationSerializer
,但我不确定如何执行此操作。
答案 0 :(得分:2)
尝试在视图中预取过滤的事件:
from django.db.models import Prefetch
class LocationViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
serializer_class = LocationSerializer
def get_queryset(self):
queryset = Location.objects.all()
min_date = self.request.query_params.get('min_date', None)
max_date = self.request.query_params.get('max_date', None)
if min_date is not None and max_date is not None:
queryset = queryset.filter(event__date__lte=max_date, event__date__gte=min_date).prefetch_related(Prefetch('events', queryset=Event.objects.filter(date__lte=max_date, date__gte=min_date))
return queryset
您还可以使用serializerMethodField
过滤事件:
class LocationSerializer(serializers.ModelSerializer):
events = SerializerMethodField()
class Meta:
model = Location
fields = ('id', 'name', 'events',)
read_only_fields = ('id',)
get_events(self, obj):
min_date = self.context['request'].query_params.get('min_date', None)
max_date = self.context['request'].query_params.get('max_date', None)
events = obj.events.filter(date__lte=max_date, date__gte=min_date)
return LocationSerializer(events, many=True).data
使用self.context['request']
,您可以获取请求数据,但是系列化程序。