django加入2个表,其中有2个外键

时间:2012-10-18 03:03:26

标签: django django-models

我有2个表说TableA和TableB

   class A(models.Model)
      A_name = models.CharField(max_length=48,primary_key=True)
      A_version = models.DecimalField(max_digits=3, decimal_places=0,null=False,blank=False)
      A_type = models.CharField(max_length=32, blank=True)
      class Meta:
             unique_together = ("A_name", "A_version") 

   class B(models.Model)
     B_number = models.CharField(max_length=32 ,primary_key=True)
     A_name = models.ForeignKey(A,related_name="AA_name",on_delete=models.DO_NOTHING)
     A_version = models.ForeignKey(A,related_name="AA_version",on_delete=models.DO_NOTHING)
         class Meta:
             unique_together = ("B_number","A_name", "A_version") 

现在我想做这样的事情:         从A,B中选择*,其中B.B_name = A.A_name和B.B_version = A.A_version和A.A_type =“type_name”。我无法执行get,因为A_type不是唯一的,它可以返回多个对象。 Plz帮助

2 个答案:

答案 0 :(得分:0)

不确定这是否回答了您的问题,但如果您想通过使用联接获得只有一个查询的所有对象,则可以使用select_related

all_b = B.objects.all().select_related('A_name', 'A_version')
some_b = all_b[0]
some_b.A_name # does not incur extra db query

如果您想要更多地控制查询,可以随时添加过滤器:

B.objects.filter(A_name__A_type='type_name').select_related('A_name', 'A_version')

答案 1 :(得分:0)

我认为模型的设计不是很好。 A模型将A_name和A_version一起作为唯一。这意味着总会有一个对象具有A_name和A_version的唯一组合。

在模型B中,您可以引用ID字段,因为这将为您提供唯一的组合A_name和A_version。

你需要在B中做什么:保存方法是确保没有新记录或现有记录获得与DB中已存在的相同的B_number和A引用

 class B(models.Model)
     B_number = models.CharField(max_length=32, unique=True) #Don't use as primary key
     A        = models.ForeignKey(A,on_delete=models.DO_NOTHING)

    def save(self, *args, **kvargs):
        if self.id:
            try:
                b_s = B.objects.get(B_number=self.B_number, A=self.A).exclude(pk=self.id)

                #The existing combination already exists:
                raise ValueError('The combination of B_number and A already exists')

            except B.DoesNotExist:
                #No existing records violates the rule
                pass
        else:
            try:
                b_s = B.objects.get(B_number=self.B_number, A=self.A)

                #The existing combination already exists:
                raise ValueError('The combination of B_number and A already exists')

            except B.DoesNotExist:
                #No existing records violates the rule
                pass

         #All is good, no violation
         super(B, self).save(*args, **kvargs)

一旦确定,您确定当您在A_type上运行查询时,底层B:s是唯一的

示例数据:

ID        A_name        A_version    A_type
 1        "name1"       1.0          "type1"
 2        "name2"       1.1          "type1"
 3        "name2"       1.2          "type2"

 Model B
 ID  B_number  A
 1    "10"     1
 2    "20"     1
 3    "30"     2
 4    "40"     3

#Will return A.id=1 and A.id=2
a_s = A.objects.filter(A_type="type1")

for a in a_s:
    for b in a.b.all():
        print b.number, a.A_number, a.A_version

因为我没有时间自己测试错误而预订错别字。