代码之家  ›  专栏  ›  技术社区  ›  Mike Shultz

如何在django中连接两个非唯一列?

  •  1
  • Mike Shultz  · 技术社区  · 15 年前

    我希望能够通过一个列连接两个模型,这两个列都不是唯一的。

    class Ctystate(models.Model):
        ctystate_id = models.IntegerField(primary_key=True)
        zip5 = models.IntegerField()
        [...]
    
    class Addr2zip(models.Model):
        addr2zip_id = models.IntegerField(primary_key=True)
        ctystate = models.ForeignKey(Ctystate, db_column='zip5', to_field='zip5')
        zip5 = models.IntegerField()
        [...]
    

    使用ForeignKey字段只会导致模型验证错误:

    模型“Addr2zip”下的字段“zip5”必须具有unique=True约束。

    有没有什么方法可以使用两个模型中的“zip5”字段来连接这两个模型?我知道这可能会导致重复的结果,但也有其他的保护措施,将用于过滤器。

    我也不希望有中间的桌子。如果必须的话,我可以编写自己的SQL,但我会尽可能地坚持使用ORM。谢谢。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Evgeny    15 年前

    在美国,一个邮政编码可能包含1个城市。一个城市绝对可以有一个邮政编码,所以你需要一个多人的关系。

    此外,邮政编码可以跨州线,也有跨州线的城市(例如堪萨斯城),但实际上每个城市只属于一个州。

    数据模型将取决于您想如何解释它。

    很可能您甚至不需要使用合理的模型运行这样的连接。

    但是,如果您希望保持模型不变(您需要检查真实的表名),这种方法可能会起作用:

    addr_list = Ctystate.objects.extra(
        select = {
            'city_name': 'ctystate.name',
            'addr': 'addr2zip.address'
        },
        where = ['ctystate.zip5 = addr2zip.zip5'],
        tables = ['ctystate', 'addr2zip']#assuming that those are names in your table
    )
    
        2
  •  0
  •   Bernhard Vallant    15 年前

    我认为你应该这样解决:

    class Ctystate(models.Model):
        ctystate_id = models.IntegerField(primary_key=True)
        zip5 = models.IntegerField(unique=True)
    
    class Addr2zip(models.Model):
        addr2zip_id = models.IntegerField(primary_key=True)
        ctystate = models.ForeignKey(Ctystate, db_column='zip5', to_field='zip5')
    

    如果你想那样做 ForeignKey ctystate 将由 zip5 在名为 zip5型 . 如果要使用外键不动产,必须设置 to_field unique=True 因为否则就不再是1:n(外键)关系了 Addr2zip 对象可以与多个 Ctystate 对象,这将是一个m:n关系-如果需要,必须使用 ManyToManyField !).

    推荐文章