【问题标题】:Show distinct values in dropdown menu with django-select2使用 django-select2 在下拉菜单中显示不同的值
【发布时间】:2019-11-18 10:48:30
【问题描述】:

我正在使用 django-select2 和表单来创建下拉列表,使用 ModelSelect2Widget。

我的问题是我在“名称”字段上进行过滤,并且多个对象可以具有相同的“名称”但不同的“值”(请参阅​​下面的模型描述)。这会导致下拉菜单中多次出现相同的名称。

我想删除这些重复项。我尝试使用 .distinct('name') 来选择查询集,但它似乎不起作用。 example of result obtained with ModelSelect2Widget

下面是我使用的代码的描述:

我有两个通过外键链接的模型

models.py

class Who(models.Model):
    name = models.CharField(max_length=256)
    value = models.CharField(max_length=256)

    def __str__(self);
        return str(self.name)

class Data(models.Model):
    who = models.ForeignKey(Who)

我使用这里描述的形式:

forms.py

from django_select2.forms import ModelSelect2Widget
...

class CreateDataForm(ModelForm):
    class Meta:
        model = Data
        fields = ('who',)
        widgets = {'who': ModelSelect2Widget(
            queryset=Who.objects.all().distinct('name'),
            search_fields=['name_icontains']
        )}

有谁知道如何删除这些重复项?

【问题讨论】:

  • 您需要什么Who 型号?选择一个的标准是什么?为什么他们不止一个Station to depart同名?
  • 有几个车站 de 出发(出发站)同名,因为几个巴士站可以有相同的名称但被放置在不同的位置(例如一个在马路的一侧,另一个在另一边)
  • 你有没有考虑过,也许,你有一个糟糕的设计?看来您需要将Depart 拆分为两个模型:DepartDepartLocation。然后引用Depart 而不是DepartLocation。看着你的post,你似乎“不碍事”并且在你的代码上写了反模式。
  • 是的,这显然是可能的! (但是,这些不是真正的模型,我尽量简化以直入问题)我仍然需要学习如何构建干净的模型架构

标签: django jquery-select2 django-select2


【解决方案1】:

我终于找到了问题的根源。

在django_select2 ModelSelect2Mixin中,用于过滤下拉菜单中显示的值的函数filter_queryset以“return queryset.filter(select).distinct()”结尾。这个问题是这个 .distinct() 优于查询集中的那个 (.distinct("name"))

为了解决我的问题,我不得不重写过滤器查询集函数,并删除 .distinct():

class ModelSelect2WidgetWithoutDistinct(ModelSelect2Widget):
    """In dropdown list, shows objects from queryset without the initial .distinct()."""

    def filter_queryset(self, request, term, queryset=None, **dependent_fields):
        """Same function as in select2 ModelSelect2Mixin except last line."""
        if queryset is None:
            queryset = self.get_queryset()
        search_fields = self.get_search_fields()
        select = Q()
        term = term.replace('\t', ' ')
        term = term.replace('\n', ' ')
        for t in [t for t in term.split(' ') if not t == '']:
            select &= reduce(lambda x, y: x | Q(**{y: t}), search_fields,
                                Q(**{search_fields[0]: t}))
        if dependent_fields:
            select &= Q(**dependent_fields)

        return queryset.filter(select)  # initially queryset.filter(select).distinct()

【讨论】:

    【解决方案2】:
    # You can define queryset like this
    
    class CreateDataForm(ModelForm):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['who'].queryset = Who.objects.distinct()
    
        class Meta:
            model = Data
            fields = ('who',)
    

    【讨论】:

    • 感谢您的回答。但是,我也无法使此解决方案起作用。我刚刚发现问题是在 django_select2 ModelSelect2Mixin 中,用于过滤要在下拉菜单上显示的值的函数 filter_queryset 以“return queryset.filter(select).distinct()”结尾。这个“.distinct()”覆盖了用于定义查询集的那个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2018-03-28
    • 2020-10-02
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多