简体   繁体   English

Django 中的多字段外键

[英]Multiple field foreign key in django

I have two models in django with definitions below.我在 Django 中有两个模型,定义如下。 CreativeStatus model :创意状态模型:

class RtbdCreativeStatus(models.Model):
    creative_id = models.CharField(max_length=500, primary_key=True)
    advertiser_id = models.CharField(max_length=100, primary_key=True)
    exposure_level = models.CharField(max_length=125)
    modified_on = models.DateTimeField()
    modified_by = models.CharField(max_length=100)


class RtbdCreative(models.Model):
    id = models.AutoField(primary_key=True)
    advertiser_id = models.ForeignKey(RtbdCreativeStatus, on_delete=models.CASCADE)
    creative_id = models.ForeignKey(RtbdCreativeStatus, on_delete=models.CASCADE)
    country_id = models.IntegerField()
    adm = models.CharField(max_length=255, null=True, blank=True)
    sample_url = models.CharField(max_length=500)
    landing_page = models.CharField(max_length=500, null=True, blank=True)
    html = models.CharField(max_length=500)
    creative_attributes = models.CommaSeparatedIntegerField(max_length=150, null=True, blank=True)
    advertiser_domains = models.CharField(max_length=500)
    description = models.CharField(max_length=500, null=True, blank=True)
    created_on = models.DateTimeField(auto_now=True, auto_now_add=True)
    creative_type = models.CharField(max_length=50, null=True, blank=True)
    demand_source_type_id = models.IntegerField()
    revalidate = models.BooleanField(default=False)

(creative_id, advertiser_id ) combination is unique in my CreativeStatus table . (creative_id,adverter_id) 组合在我的 CreativeStatus 表中是唯一的。 I want that combination to be my foreign key for Creative table.我希望该组合成为我的 Creative 表的外键。 I tried adding it but i get this error .我尝试添加它,但出现此错误。 django 中的错误截图

1)How do i achieve this join with two key combination as my foreign key . 1)我如何使用两个组合键作为我的外键来实现这种连接。

2)What should be my query to fetch all the creatives with their status from CreativeStatus table . 2)从 CreativeStatus 表中获取所有广告及其状态的查询应该是什么。

UPDATE 1更新 1

on reading the answers below , i updated my model as mentioned below :在阅读下面的答案时,我更新了我的模型,如下所述:

class RtbdCreative(models.Model):
    id = models.AutoField(primary_key=True)
    advertiser_id = models.ForeignKey(RtbdCreativeStatus, to_field='advertiser_id', related_name='advertiser', db_column='advertiser_id', on_delete=models.CASCADE)
    creative_id = models.ForeignKey(RtbdCreativeStatus, to_field='creative_id', related_name='creative', db_column='creative_id', on_delete=models.CASCADE)
    country_id = models.IntegerField()
    adm = models.CharField(max_length=255, null=True, blank=True)
    sample_url = models.CharField(max_length=500)
    landing_page = models.CharField(max_length=500, null=True, blank=True)
    html = models.CharField(max_length=500)
    creative_attributes = models.CommaSeparatedIntegerField(max_length=150, null=True, blank=True)
    advertiser_domains = models.CharField(max_length=500)
    description = models.CharField(max_length=500, null=True, blank=True)
    created_on = models.DateTimeField(auto_now=True, auto_now_add=True)
    creative_type = models.CharField(max_length=50, null=True, blank=True)
    demand_source_type_id = models.IntegerField()
    revalidate = models.BooleanField(default=False)

Now i am getting this error现在我收到这个错误在此处输入图片说明 . . I have combination of advertiser_id , craetive_id as unique .我将 adser_id 、 craetive_id 组合为 unique 。 But django expects both to be unique.但是 django 期望两者都是独一无二的。 What can i do to make it work ?我该怎么做才能让它发挥作用?

I just saw a parameter as to_fields for models.ForeignObject , superclass of models.ForeignKey .我刚才看到一个参数作为to_fieldsmodels.ForeignObject,models.ForeignKey的超类。 It might be used in this case for defining foreign key for composite primary key or unique keys.在这种情况下,它可能用于为复合主键或唯一键定义外键。

    advertiser_creative_id = models.ForeignObject(RtbdCreativeStatus, to_fields=['advertiser_id', 'creative_id'], related_name='abc', on_delete=models.CASCADE)

There is a from_fields parameter as well.还有一个from_fields参数。 It can be used to map the fields with to_fields .它可用于使用to_fields映射字段。 Refer https://docs.djangoproject.com/en/2.2/_modules/django/db/models/fields/related/参考https://docs.djangoproject.com/en/2.2/_modules/django/db/models/fields/related/

As mentioned in ERRROS, you need to add related_name as argument, when you want to add more than one foreign key for same Model.如 ERRROS 中所述,当您想为同一模型添加多个外键时,您需要添加 related_name 作为参数。

class Creative(models.Model):
    id = models.AutoField(primary_key=True)
    advertiser_id = models.ForeignKey(RtbdCreativeStatus,
                                      related_name="Advertiser", on_delete=models.CASCADE)
    creative_id = models.ForeignKey(RtbdCreativeStatus,
                                    related_name="Creative",
                                    on_delete=models.CASCADE)
    country_id = models.IntegerField()
    adm = models.CharField(max_length=255, null=True, blank=True)
    sample_url = models.CharField(max_length=500)
    landing_page = models.CharField(max_length=500, null=True, blank=True)
    html = models.CharField(max_length=500)
    creative_attributes = models.CommaSeparatedIntegerField(
        max_length=150, null=True, blank=True)
    advertiser_domains = models.CharField(max_length=500)
    description = models.CharField(max_length=500, null=True, blank=True)
    created_on = models.DateTimeField(auto_now=True, auto_now_add=True)
    creative_type = models.CharField(max_length=50, null=True, blank=True)
    demand_source_type_id = models.IntegerField()
    revalidate = models.BooleanField(default=False)

When you add multiple ForeignKeys towards same table, you should override the related_name option of your fields, so that the fields could be distinguished easily.当您向同一个表添加多个外键时,您应该覆盖字段的related_name选项,以便可以轻松区分字段。

You could implement a custom validation for checking uniqueness of the creative_id and advertiser_id ,您可以实施自定义验证来检查creative_idadvertiser_id唯一性,

class Creative(models.Model):
    advertiser_id = models.ForeignKey(CreativeStatus,
                                  related_name="advertisers")
    creative_id = models.ForeignKey(CreativeStatus,
                                related_name="creatives")

    def clean(self):
        data = self.cleaned_data
        if not data['advertiser_id'] == data['creative_id']:
            raise ValidationError("Unique Constraint failed {}, {}".format(self.advertiser_id, self.creative_id))
        return data

You could query your creatives from CreativeStatus using the related name.您可以使用相关名称从CreativeStatus查询您的广告CreativeStatus

creative_status_obj = CreativeStatus.objects.get(pk=some_pk)#or any query.
#All creatives of the given object can be queried using reverse relation.
creatives = creative_status_obj.creatives.all()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM