Django REST框架外键和过滤
Posted
技术标签:
【中文标题】Django REST框架外键和过滤【英文标题】:Django REST framework foreign keys and filtering 【发布时间】:2014-09-11 17:33:13 【问题描述】:我在 django 应用中有以下模型:
models.py:
class Make(BaseModel):
slug = models.CharField(max_length=32) #alfa-romeo
name = models.CharField(max_length=32) #Alfa Romeo
def __unicode__(self):
return self.name
class Model(BaseModel):
make = models.ForeignKey(Make) #Alfa Romeo
name = models.CharField(max_length=64) # line[2]
engine_capacity = models.IntegerField()
trim = models.CharField(max_length=128) # line[4]
还有serializers.py:
from .models import Make,Model
from rest_framework import serializers
class MakeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Make
fields = ('url', 'slug', 'name')
class ModelSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Model
fields = ('url', 'make', 'name', 'trim', 'engine_capacity')
还有 views.py:
from rest_framework import viewsets
from rest_framework import filters
from rest_framework import generics
from .models import Make, Model
from .serializers import MakeSerializer, ModelSerializer
class MakeViewSet(viewsets.ModelViewSet):
queryset = Make.objects.all()
serializer_class = MakeSerializer
filter_backends = (filters.DjangoFilterBackend,)
class ModelViewSet(viewsets.ModelViewSet):
make = MakeSerializer
queryset = Model.objects.all()
serializer_class = ModelSerializer
filter_backends = (filters.DjangoFilterBackend,)
我需要做什么,我想获取由特定品牌制造的所有模型。 如何使用查询参数获取具有特定外键的所有模型?我的第二个问题 - 我可以使用 queryparams 过滤结果以获取具有特定 engine_capacity 的模型吗?
一条评论:如果我可以在 url 中使用类似这样的内容来查询结果,那将是完美的:/api/models/?make=ford
where make is slug
field in Make
model
【问题讨论】:
【参考方案1】:您可以在视图集中指定filter_fields = ('make__slug', )
。不要忘记也包括filter_backends = (DjangoFilterBackend, )
。您还需要添加 django-filter
依赖项。
class ModelViewSet(viewsets.ModelViewSet):
queryset = Model.objects.all()
serializer_class = ModelSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_fields = ('make__slug',)
然后你像/api/models/?make__slug=ford
一样查询。注意双下划线符号。
Docs.
如果你不喜欢 URL 中的make__slug
关键字参数,那么你可以创建一个过滤器类:
import django_filters
from myapp.models import Make
class ModelFilter(django_filters.FilterSet):
make = django_filters.ModelChoiceFilter(field_name="make__slug",
queryset=Make.objects.all())
class Meta:
model = Model
fields = ('make',)
然后
class ModelViewSet(viewsets.ModelViewSet):
make = MakeSerializer
queryset = Model.objects.all()
serializer_class = ModelSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_class = ModelFilter
/api/models/?make=ford
应该可以工作。
【讨论】:
我尝试使用您的解决方案,该解决方案看起来简单明了,但name
参数一直给我错误。
如果您指的是django_filters.ModelsChoiceFilter(name="make_slug")
中的name 属性,那么它应该是“field_name”。自从发布了我的原始答案以来,它在django_filters
的最新版本中被重命名。我会更新我的答案。【参考方案2】:
扩展@vladimir-prudnikov 的answer:
最近版本的 django-filter 发生了一些变化。你可能想要:
class ModelFilter(django_filters.FilterSet):
make = django_filters.ModelChoiceFilter(field_name='make__slug',
to_field_name='slug',
queryset=Make.objects.all())
class Meta:
model = Model
fields = ('make',)
见https://django-filter.readthedocs.io/en/master/ref/filters.html#field-name和https://django-filter.readthedocs.io/en/master/ref/filters.html#to-field-name
【讨论】:
【参考方案3】:urls.py
url('^model/by/(?P<make>\w+)/$', ModelByMakerList.as_view()),
views.py
class ModelByMakerList(generics.ListAPIView):
serializer_class = ModelSerializer
def get_queryset(self):
"""
This view should return a list of all models by
the maker passed in the URL
"""
maker = self.kwargs['make']
return Model.objects.filter(make=maker)
欲了解更多信息checkout the docs。
您也可以使用 QUERY_PARAMS 过滤,但恕我直言,这看起来更好。
【讨论】:
【参考方案4】:在你的视图中你需要做的事情是这样的: 它被称为“跨越关系的查找”
queryset = Model.objects.filter(make__name__exact='Alfa Romeo')
具有特定发动机容量的模型的过滤类似
queryset = Model.objects.filter(engine_capacity__exact=5)
如果您想组合两个过滤器,您可以将它们链接起来:
queryset = Model.objects.filter(make__name__exact='Alfa Romeo').filter(engine_capacity__exact=5)
更多示例可以在这里找到django query making
【讨论】:
我知道如何查询标准 Django 模型,我需要对 Django Rest Framework 做同样的事情以上是关于Django REST框架外键和过滤的主要内容,如果未能解决你的问题,请参考以下文章