如何在 Django 查询中处理可变数量的参数
how to handle a variable number of arguments in django query
我当前的项目让我构建一个页面,可以在其中按类别过滤输出。这意味着默认情况下您会获得完整的项目列表,但您可以通过单击(多个或单个)复选框来缩小输出范围。这个想法是,如果您只想查看两个类别的结果,您可以选择这两个类别,然后只查看这两个类别的项目。 (想像一个亚马逊页面,您可以在其中搜索商品但过滤结果)
这通过使用 get 方法的表单来实现。所以 url 看起来像:
ip/?family=category_one&family=category_two
我的代码如下:
请注意,固件模型通过 ManyToManyField 与 ProductModel 相关,而 ProductModel 通过 ForeignKey 关系与 Family 相关
*型号
class Family(models.Model):
family_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
slug = models.SlugField(null=False, unique=True)
family_name = models.CharField(max_length=50, editable=True, unique=True)
class ProductModel(models.Model):
model_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
model_number = models.CharField(max_length=25, editable=True, unique=True)
family_id = models.ForeignKey(Family, on_delete=models.DO_NOTHING, editable=True, null=False, blank=False)
class Firmware(models.Model):
firmware_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
version = models.CharField(max_length=50, help_text='The \'version number\' of the firmware',
editable=True)
model_id = models.ManyToManyField(ProductModel, editable=True)
*查看:
class FirmwareListView(ListView):
model = Firmware
context_object_name = 'firmwares'
qs = QuerySet()
def get(self, request, *args, **kwargs):
requested_families = request.GET.getlist("family")
if requested_families:
query = Q(model_id__family_id__family_name__iexact=requested_families[0])
for f in range(1, len(requested_families)):
query = query | Q(model_id__family_id__family_name__iexact=requested_families[f])
self.qs = Firmware.objects.filter(query)
else:
self.qs = Firmware.objects.all()
return super().get(request, *args, **kwargs)
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data()
context['firmware_list'] = self.qs
return context
这里最重要的部分是:
requested_families = request.GET.getlist("family")
if requested_families:
query = Q(model_id__family_id__family_name__iexact=requested_families[0])
for f in range(1, len(requested_families)):
query = query | Q(model_id__family_id__family_name__iexact=requested_families[f])
self.qs = Firmware.objects.filter(query)
这个查询会工作(因为它 运行s 和 returns 结果但是结果是错误的。结果似乎忽略了 exact requirement and only 运行 a contains query.换句话说,如果我按类别过滤 foo 我会得到结果对于 food 和 foo。如果我 运行 通过执行以下查询:
self.qs = Firmware.objects.filter(Q(model_id__family_id__family_name__iexact=requested_families[0]) | Q(model_id__family_id__family_name__iexact=requested_families[1]))
我选择了两个类别,结果很完美。当然,我不能在生产中使用上述方法,因为我永远不知道用户会选择多少类别。
我看过这个 post ( Django query with variable number of filter arguments ) 并尝试了那里的所有建议,但没有成功。
我认为问题是我正在尝试从一个模型中过滤一个字段,该模型 运行 通过多对多字段然后是外键。没有办法解决这个问题(至少我能想到)
非常感谢您提供的任何帮助。我有点卡在这个上,但必须有办法做到这一点。目前我能想到的唯一方法是对每个term单独查询,然后在最后合并结果。
我不得不做类似的事情。我最终使用了一个将 .exclude() 链接到那些未被选中的查询集。我在表单中使用了一点 javascript 来传递正确的(我不想要的)值。
费了好大劲才弄明白这一点。好吧,我造成了我自己的问题。首先,我通过另一种方法传递我的查询结果(我没有在我原来的问题中提到它,因为我认为它是不相关的)改变了查询。
第二种方法以独特的方式对输出进行排序。当我开始仔细研究该方法时,我注意到查询集在其中突然发生了变化。我发现我在哪里犯了错误,瞧!现在可以正常使用了。
最重要的是使用上述方法(并在下面重新显示)创建可变数量的查询参数的方法非常完美。
要在 Django 中创建可变数量的查询参数,您可以使用:
class ViewName():
qs = QuerySet()
def get(self, request, *args, **kwargs):
get_queries = request.GET.getlist('named_get')
if get_queries:
query = Q(query_type=get_queries[0])
for t in range(1, len(filtered_types)):
query = query | Q(query_type=get_queries[t]) #obviously if you need an and here just substitute in & where | currently is
Model.objects.filter(query)
我当前的项目让我构建一个页面,可以在其中按类别过滤输出。这意味着默认情况下您会获得完整的项目列表,但您可以通过单击(多个或单个)复选框来缩小输出范围。这个想法是,如果您只想查看两个类别的结果,您可以选择这两个类别,然后只查看这两个类别的项目。 (想像一个亚马逊页面,您可以在其中搜索商品但过滤结果)
这通过使用 get 方法的表单来实现。所以 url 看起来像:
ip/?family=category_one&family=category_two
我的代码如下:
请注意,固件模型通过 ManyToManyField 与 ProductModel 相关,而 ProductModel 通过 ForeignKey 关系与 Family 相关
*型号
class Family(models.Model):
family_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
slug = models.SlugField(null=False, unique=True)
family_name = models.CharField(max_length=50, editable=True, unique=True)
class ProductModel(models.Model):
model_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
model_number = models.CharField(max_length=25, editable=True, unique=True)
family_id = models.ForeignKey(Family, on_delete=models.DO_NOTHING, editable=True, null=False, blank=False)
class Firmware(models.Model):
firmware_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
version = models.CharField(max_length=50, help_text='The \'version number\' of the firmware',
editable=True)
model_id = models.ManyToManyField(ProductModel, editable=True)
*查看:
class FirmwareListView(ListView):
model = Firmware
context_object_name = 'firmwares'
qs = QuerySet()
def get(self, request, *args, **kwargs):
requested_families = request.GET.getlist("family")
if requested_families:
query = Q(model_id__family_id__family_name__iexact=requested_families[0])
for f in range(1, len(requested_families)):
query = query | Q(model_id__family_id__family_name__iexact=requested_families[f])
self.qs = Firmware.objects.filter(query)
else:
self.qs = Firmware.objects.all()
return super().get(request, *args, **kwargs)
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data()
context['firmware_list'] = self.qs
return context
这里最重要的部分是:
requested_families = request.GET.getlist("family")
if requested_families:
query = Q(model_id__family_id__family_name__iexact=requested_families[0])
for f in range(1, len(requested_families)):
query = query | Q(model_id__family_id__family_name__iexact=requested_families[f])
self.qs = Firmware.objects.filter(query)
这个查询会工作(因为它 运行s 和 returns 结果但是结果是错误的。结果似乎忽略了 exact requirement and only 运行 a contains query.换句话说,如果我按类别过滤 foo 我会得到结果对于 food 和 foo。如果我 运行 通过执行以下查询:
self.qs = Firmware.objects.filter(Q(model_id__family_id__family_name__iexact=requested_families[0]) | Q(model_id__family_id__family_name__iexact=requested_families[1]))
我选择了两个类别,结果很完美。当然,我不能在生产中使用上述方法,因为我永远不知道用户会选择多少类别。
我看过这个 post ( Django query with variable number of filter arguments ) 并尝试了那里的所有建议,但没有成功。
我认为问题是我正在尝试从一个模型中过滤一个字段,该模型 运行 通过多对多字段然后是外键。没有办法解决这个问题(至少我能想到)
非常感谢您提供的任何帮助。我有点卡在这个上,但必须有办法做到这一点。目前我能想到的唯一方法是对每个term单独查询,然后在最后合并结果。
我不得不做类似的事情。我最终使用了一个将 .exclude() 链接到那些未被选中的查询集。我在表单中使用了一点 javascript 来传递正确的(我不想要的)值。
费了好大劲才弄明白这一点。好吧,我造成了我自己的问题。首先,我通过另一种方法传递我的查询结果(我没有在我原来的问题中提到它,因为我认为它是不相关的)改变了查询。
第二种方法以独特的方式对输出进行排序。当我开始仔细研究该方法时,我注意到查询集在其中突然发生了变化。我发现我在哪里犯了错误,瞧!现在可以正常使用了。
最重要的是使用上述方法(并在下面重新显示)创建可变数量的查询参数的方法非常完美。
要在 Django 中创建可变数量的查询参数,您可以使用:
class ViewName():
qs = QuerySet()
def get(self, request, *args, **kwargs):
get_queries = request.GET.getlist('named_get')
if get_queries:
query = Q(query_type=get_queries[0])
for t in range(1, len(filtered_types)):
query = query | Q(query_type=get_queries[t]) #obviously if you need an and here just substitute in & where | currently is
Model.objects.filter(query)