【发布时间】:2020-08-22 00:08:43
【问题描述】:
我是 Django 新手,我正在尝试创建一条路线,可以调用该路线从我的数据库中检索车辆数组,但我希望用户能够在 url 中提供多个查询参数(一些喜欢:http://127.0.0.1:8000/vehicles/?year=2020&make=Toyota)。我遇到的问题是我的车辆模型包含对 make 和 v_model 的外键的引用(这样命名是为了避免与 Django“模型”发生冲突)。我有一个看起来不太优雅的解决方案。每个搜索字段都有三个嵌套条件语句,这一事实让我感到怀疑。我尝试使用“filters.SearchFilter”,但我只能提供一个作为搜索基础的值。所以像这样的请求:http://127.0.0.1:8000/vehicles/?search=2020&search=Toyota 只会搜索“丰田”品牌的车辆,而忽略“年份”参数。
还有其他更简洁或更“经 Django 认可”的方法吗?
这是我的代码:
models.py:
class Make(models.Model):
name = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.name
class VModel(models.Model):
name = models.CharField(max_length=200, unique=True)
make = models.ForeignKey(Make, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Vehicle(models.Model):
make = models.ForeignKey(Make, on_delete=models.CASCADE)
v_model = models.ForeignKey(VModel, on_delete=models.CASCADE)
year = models.CharField(max_length=5)
def __str__(self):
return self.year + " " + self.v_model.name
views.py:
这是我对 filters.SearchFilter 的尝试:
queryset = Vehicle.objects.all()
serializer_class = VehicleSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['year', 'v_model__name','make__name']
这是我的“工作”解决方案,看起来很老套:
(注意:我使用的是name__icontains,所以如果用户输入“Toyot”,它仍然会得到所有丰田品牌的汽车)。
class VehicleListViewSet(viewsets.ModelViewSet):
serializer_class = VehicleSerializer
queryset = Vehicle.objects.all()
pagination_class = CustomPagination
def get_queryset(self):
qs = super().get_queryset()
selected_make = self.request.query_params.get('make', None)
if selected_make:
try:
found_make = Make.objects.get(name__icontains=selected_make)
except:
return []
if found_make:
if found_make.id:
qs = qs.filter(make=found_make.id)
selected_v_model = self.request.query_params.get('v_model', None)
if selected_v_model:
try:
found_v_model = VModel.objects.get(name__icontains=selected_v_model)
except:
return []
if found_v_model:
if found_v_model.id:
qs = qs.filter(v_model=found_v_model.id)
selected_year = self.request.query_params.get('year', None)
if selected_year:
qs = qs.filter(year=selected_year)
return qs
【问题讨论】:
-
你见过这个库吗:github.com/AltSchool/dynamic-rest?
-
我检查过了。我无法使过滤正常工作,当我尝试克隆演示存储库时出现错误。您是否能够成功实施?
-
嗯嗯,是的。您应该将其安装为 pip 包,然后从中导入视图集类。我让它在几个项目上工作。如果您不需要速度,它几乎适用于所有情况。
标签: python django django-rest-framework filtering