Django空字段回退

Posted

技术标签:

【中文标题】Django空字段回退【英文标题】:Django empty field fallback 【发布时间】:2010-11-23 11:34:31 【问题描述】:

我有一个保存用户地址的模型。该模型必须具有first_namelast_name 字段,因为人们想为收件人(如他的公司等)设置地址。我想要实现的是:

如果地址中的first_name/last_name 字段已填写 - 只需返回该字段 如果地址中的first_name/last_name 字段为空 - 从指向正确django.auth.models.User 的外键中获取相应的字段数据 我希望将其视为将出现在字段查找中的普通 Django 字段 我不想创建一个方法,因为它是一种重构,Address.first_name/last_name 在应用程序的各个地方(也以模型形式等)使用,所以我需要这个尽可能顺利,否则我将不得不在很多地方修补。

【问题讨论】:

【参考方案1】:

这里有两个选项。第一种是创建一个动态查找的方法,但使用property 装饰器,以便其他代码仍然可以使用直接属性访问。

class MyModel(models.Model):
    _first_name = models.CharField(max_length=100, db_column='first_name')

    @property
    def first_name(self):
        return self._first_name or self.user.first_name

    @first_name.setter
    def first_name(self, value):
       self._first_name = value

这将始终引用 first_name 的最新值,即使相关用户已更改。您可以像获取属性一样获取/设置属性:myinstance.first_name = 'daniel'

另一种选择是覆盖模型的 save() 方法,以便在您保存时进行查找:

def save(self, *args, **kwargs):
    if not self.first_name:
        self.first_name = self.user.first_name
    # now call the default save() method
    super(MyModel, self).save(*args, **kwargs)

这样您不必更改数据库,但它只会在保存时刷新 - 因此,如果相关的用户对象已更改但此对象未更改,它将引用旧的用户值。

【讨论】:

您可以指定 db_column='first_name' 以防止架构更改:docs.djangoproject.com/en/dev/ref/models/fields/#db-column 所以在 @first_name.setter 之后添加 first_name.db_column="first_name" ?我能做到:address = Address.objects.get(first_name="blah") 吗? 我已根据 piquadrat 的评论更新了代码和解释。 感谢您的帮助 :) 它可以完美运行(属性方法),我唯一担心的是 - 我有一个模型表单,它不会用 self.user 填充空白字段。名。设置属性和获取是完美的。 还有一个小问题 - 在进行查找时 django orm 无法解析属性信息字段,它需要原始的 _first_name 字段。【参考方案2】:

虽然这不能满足所有 OP 的要求,但在某些需要在查询集过滤器(数据库级别)中回退的用例中,可以使用 Django 的 Coalesce() 类 (docs)。

在这种情况下,最简单的解决方案可能是查询集注释(使用来自@daniel-roseman 的answer 的示例):

queryset = MyModel.objects.annotate(first_name=Coalesce('_first_name', 'user__first_name'))

从查询集中获得的每个项目将获得一个first_name 属性,其值为_first_name,并回退(如果值为null)到user.first_name

也就是说,假设您的模型具有 user 关系。

这可以实现,例如在自定义管理器中,也可以与property 方法结合使用。

this SO answer 中提供了类似情况的详细示例(覆盖而不是回退)。

【讨论】:

以上是关于Django空字段回退的主要内容,如果未能解决你的问题,请参考以下文章

Django Newbie - 使用多字段表单,如何消除查询集中的空字段

Django 模型:可空字段

Python Django:从空模型字段获取无值

选择字段中的 Django 空标签 - 没有查询集

如果空值传递给Django中的表单字段,如何验证表单?

django - 如何在选择字段中取回一个空的选择?