【问题标题】:Django Duplicate Values in ChoiceFieldChoiceField中的Django重复值
【发布时间】:2021-02-15 15:24:27
【问题描述】:

我是 Django 新手,但遇到了 forms.py 的问题。我通过 Models.Py 从数据库中提取值,然后将这些对象用作我的 Django 页面上的下拉列表。

例如,我将汽车数据存储在数据库中:

本田 |雅阁 |黑色 | 2016

丰田 |凯美瑞 |红色 | 2014

福特 |融合 |白色 | 2018

本田 |思域 |银 | 2020

丰田 |卡罗拉 |黑色 | 2010

等等。在models.py中,我有:

class MyCars(models.Model):

    make_name = models.CharField(max_length=50, blank=True, null=True)
    model_name = models.CharField(max_length=50, blank=True, null=True)
    color = models.CharField(max_length=15, blank=True, null=True)
    year = models.CharField(max_length=15, blank=True, null=True)


    def __str__(self):
        all_cars = []
        return self.make_name

    class Meta:
        managed = False
        db_table = 'my_cars'

然后在我的 form.py 中,我按照以下方式做一些事情:

all_cars = forms.ModelChoiceField(queryset=MyCars.objects.all())

问题是,当我只需要本田在下拉列表中出现一次时,我将获得本田、丰田等的重复值。有什么建议/想法可以通过这个过滤吗?

【问题讨论】:

  • 您只想选择make_name?或者<make_name> <model_name> 是正确的吗?
  • 否 - 我想将品牌和型号分开

标签: python django


【解决方案1】:

您的表格似乎没有被规范化。考虑到许多汽车可能具有相同的品牌,并且随着时间的推移可能会出现新品牌,您确实应该有一个 Model 用于品牌,并有一个从 MyCarsMake 的外键。

class Make(models.Model):
    name = models.CharField(max_length=50, blank=True, null=True)
    
    def __str__(self):
        return self.name

class MyCars(models.Model):
    make = models.ForeignKey(Make, on_delete=models.CASCADE, related_name="cars")
    model_name = models.CharField(max_length=50, blank=True, null=True)
    color = models.CharField(max_length=15, blank=True, null=True)
    year = models.CharField(max_length=15, blank=True, null=True)


    def __str__(self):
        all_cars = []
        return self.make_name

    class Meta:
        managed = False
        db_table = 'my_cars'

现在是你的形式:

all_cars = forms.ModelChoiceField(queryset=Make.objects.all())

此外,名称 MyCars 应该是单数(MyCar),因为型号名称是单数(检查 verbose_nameverbose_name_plural 在您的情况下 verbose_name_plural 最终是 my carss)。

【讨论】:

  • 感谢您的提示。如果我理解正确,这将需要一个新的汽车制造数据库,以便在表单中向“all_cars”添加值?否则会返回空值?
  • @MC2020 新数据库?不。 同一个数据库中的新表?是的。此外,您还需要为 Make model / make form 输入条目以供用户制作。在最终确定一个模型之前,应该始终对它们进行规范化(搜索数据库规范化)。您还可以根据我的建议做出一些明显的改进,例如在Make 模型中的name 字段上设置unique=True,等等。
  • 对 - 我的意思是一张新桌子。感谢您的帮助!
  • @MC2020 请注意,上述实现仍未标准化。例如,可以将 model_name(可能会有重复的值)拆分到单独的表中。
【解决方案2】:

如果您使用的是PostgreSQL,请更改

all_cars = forms.ModelChoiceField(queryset=MyCars.objects.all())

all_cars = forms.ModelChoiceField(queryset=MyCars.objects.distinct("model_name"))

【讨论】:

  • 谢谢 - 这至少为我指明了正确的方向。不幸的是,MySQL 似乎不支持。还有其他想法吗?
  • raw sql or annotate by Count and filter by less than 2.
【解决方案3】:

您必须在 forms.py 中过滤您的查询。目前,您只是使用 MyCars.objects.all() 获取所有内容。不确定确切的语法,但 Django 文档是一个很好的地方。 https://docs.djangoproject.com/en/3.1/

如果我没记错的话,它是不同的,但不是 100% 肯定。 https://books.agiliq.com/projects/django-orm-cookbook/en/latest/distinct.html

【讨论】:

    【解决方案4】:

    你没有重复,你的问题是你的 str 函数返回 self.make_name,所以,你的查询集是汽车的完整列表,就像丰田凯美瑞和丰田卡罗拉一样相同的 make_name 您看到它们具有相同的名称,但在背面您只是显示该属性。您可以对查询使用 distinct 函数来更改属性,也可以直接更改汽车模型上的 str 函数以适应您的需要(您可以连接多个属性)。举个例子:

    def __str__(self):
        all_cars = []
        return f"${self.make_name} - {self.model_name}"
    

    【讨论】:

      猜你喜欢
      • 2011-12-13
      • 1970-01-01
      • 2011-12-26
      • 2021-10-18
      • 2011-04-10
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多