【问题标题】:Django: Replace foreign key attribute name (as well as column name) “_id” suffix with “_code” or other suffixDjango:将外键属性名(以及列名)“_id”后缀替换为“_code”或其他后缀
【发布时间】:2020-07-20 23:42:26
【问题描述】:

我的问题与this question 密切相关,但又略有不同。

给定以下 Django 模型:

class Country(models.Model):
    code = models.CharField(primary_key=True)


class Person(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)

请注意,我在 Country 上指定了一个名为 code 的自定义主键字段。 Country 类应该没有 id 字段或属性。这工作正常。

当然,我希望Person 类的Country 外键使用code 字段。这也很好。到目前为止一切顺利。

但是,我也真的希望Person 表中的基础列名 正好是country_code。 不 country_id。所以我添加了db_column 字段参数:

class Person(models.Model):
    country = models.ForeignKey(
        Country, 
        on_delete=models.CASCADE,
        db_column='country_code',
    )

现在列名正确命名为country_code,而不是country_id。到目前为止一切顺利。


现在。在我的python代码中,我希望能够通过一个人以正常方式访问一个国家:

person = Person.objects.get(...)
country = person.country

但是,我希望能够通过使用country_code 的人访问国家代码pk,不是 country_id,如下所示:

person = Person.objects.get(...)
country_code = person.country_code

而且我还希望能够创建带有country_code 参数的Person 对象,而不是country_id:

person = Person(country_code='foo')

而且我还希望能够查询带有country_code 参数的Person 对象,而不是country_id:

people = Person.objects.filter(country_code='foo')

应该有没有 person.country_id 属性、字段或列。只有person.country 和person.country_code。是的,我希望准确地调用该字段/属性/列person.country_code,NOTperson.country_id,即使它具有相同的值。这正是我想要在 Python 和 RDBMS 中使用的确切名称。


到目前为止,我还没有做到这一点。我尝试过将to_field 参数添加到Person.country 字段声明中,如下所示:

class Person(models.Model):
    country = models.ForeignKey(
        Country, 
        on_delete=models.CASCADE,
        to_field='code',
        db_column='country_code',
    )

这似乎没有达到预期的效果。

是否可以在 Django 中更改模型的外键字段属性名称(以及基础列名称)?

在我看来,这不像是一件奇怪的事情。也许我错了。这可能吗?这是否太难/不标准而不值得?我是在自找麻烦吗?

【问题讨论】:

    标签: python django


    【解决方案1】:

    自定义外键子类

    class NamedForeignKey(models.ForeignKey):
        suffix_idname = 'id'
        def __init__(self, *args, **kwargs):
            suffix_idname = kwargs.pop('suffix_idname', None)
            if suffix_idname:
                self.suffix_idname = suffix_idname
            super().__init__(*args, **kwargs)
    
        def get_attname(self):
            return '%s_%s' % (self.name, self.suffix_idname)
    
    class Person(models.Model):
        country = NamedForeignKey(
            Country, 
            on_delete=models.CASCADE,
            suffix_idname='code',
        )
    

    【讨论】:

    • 这似乎正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    相关资源
    最近更新 更多