Mar*_*rkD 6 django django-rest-framework
对于我的应用程序,我有以下(简化的)模型给出的位置和事件:
class Location(models.Model):
name = models.CharField(max_length=64)
class Event(models.Model):
location = models.ForeignKey(Location)
date = models.DateField()
Run Code Online (Sandbox Code Playgroud)
在我的 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'}
]
}
]
Run Code Online (Sandbox Code Playgroud)
我的序列化程序看起来像:
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',)
Run Code Online (Sandbox Code Playgroud)
使用 ViewSets,我想向这个调用添加一个过滤器,带有一个max_date, 和min_date参数,例如:/api/locations/?min_date=2018-01-01&max_date=2018-01-15。哪个应该只返回在这两个日期之间有事件的位置,并且应该只返回这两个日期之间每个位置的事件。
在上面的示例数据中,两个位置都会返回,位置 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
Run Code Online (Sandbox Code Playgroud)
这将过滤掉那些没有这两个日期之间的任何事件的任何位置,但是那些返回位置展示其所有的事件,不只是之间的那些min_date和max_date。我假设我必须以某种方式将我的查询参数传递给EventSerializer嵌入在LocationSerializer.
尝试在视图中预取过滤事件:
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
Run Code Online (Sandbox Code Playgroud)
您还可以使用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
Run Code Online (Sandbox Code Playgroud)
您可以在self.context['request']序列化器中获取请求数据。
| 归档时间: |
|
| 查看次数: |
6970 次 |
| 最近记录: |