我有一个包含用户地址的模型。此模型必须具有first_name和last_name字段,因为有人希望将地址设置为收件人(如他的公司等)。我想要实现的是:
感谢您的帮助:)
答案 0 :(得分:6)
这里有两种选择。第一个是创建一个动态查找的方法,但使用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)
这样您就不必更改数据库,但只在保存时刷新 - 因此,如果相关的User对象被更改但此对象不是,则它将引用旧的User值。
答案 1 :(得分:0)
尽管这不能满足所有OP的要求,但在某些用例中,在查询集过滤器中需要回退(在数据库级别),可以使用Django的Coalesce()
类({{3} }。
在这种情况下,最简单的解决方案可能是查询集注释(使用@ daniel-roseman的docs中的示例):
queryset = MyModel.objects.annotate(first_name=Coalesce('_first_name', 'user__first_name'))
从查询集中获得的每个项目都将获得一个first_name
属性,该属性的值为_first_name
,其备用项(如果值为null
,则退回到{{1} }。
也就是说,假设您的模型具有user.first_name
关系。
例如,可以实现在自定义管理器中,也可以与user
方法结合使用。
answer中提供了类似情况的详细示例(覆盖而不是后备)。