Python Django空字段回退
我有一个保存用户地址的模型。这个模型必须有Python Django空字段回退,python,django,django-models,model,field,Python,Django,Django Models,Model,Field,我有一个保存用户地址的模型。这个模型必须有名字和姓氏字段,因为人们希望设置收件人的地址(比如他的公司等)。我想要实现的是: 如果地址中的first\u name/last\u name字段已填充,只需返回该字段即可 如果地址中的first\u name/last\u name字段为空,则从指向正确django.auth.models.User的外键获取相应字段数据 我希望这个被视为正常的Django字段,它将出现在字段查找中 我不想创建一个方法,因为它是一个重构和地址。first_name/l
名字
和姓氏
字段,因为人们希望设置收件人的地址(比如他的公司等)。我想要实现的是:
- 如果地址中的
/first\u name
字段已填充,只需返回该字段即可last\u name
- 如果地址中的
/first\u name
字段为空,则从指向正确last\u name
django.auth.models.User的外键获取相应字段数据
- 我希望这个被视为正常的Django字段,它将出现在字段查找中
- 我不想创建一个方法,因为它是一个重构和
/地址。first_name
在应用程序中的不同位置使用(也在模型表单中,等等),所以我需要尽可能平滑地使用它,否则,我将不得不在很多地方进行修补last_name
- 这里有两个选项。第一种方法是创建一个动态查找它的方法,但是使用
属性
装饰器,以便其他代码仍然可以使用直接属性访问
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\u 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)
通过这种方式,您不必更改数据库,但它仅在保存时刷新-因此,如果相关的用户对象已更改,但此对象未更改,它将引用旧的用户值。尽管这不满足OP的所有要求,但在某些情况下,queryset筛选器(在数据库级别)中需要回退可以使用Django的
Coalesce()
class()
这种情况下最简单的解决方案可能是queryset注释(使用@daniel roseman的示例):
queryset=MyModel.objects.annotate(first\u name=Coalesce(“\u first\u name”,“user\u first\u name”))
然后,从查询集获得的每个项将获得一个first\u name
属性,该属性的值为\u first\u name
,并向user.first\u name
回退(如果该值为null
)
也就是说,假设您的模型具有asuser
关系
这可以在自定义管理器中实现,也可以与属性
方法结合使用
类似情况的详细示例(覆盖而不是回退)如所示。您可以指定db\u column='first\u name'以防止架构更改:因此在@first\u name.setter thingy之后只需添加first\u name.db\u column=“first\u name”?我能做什么:address=address.objects.get(first_name=“blah”)?我已经更新了代码和解释,以回应Piquard的评论。感谢帮助:)它工作完美(属性方法),我唯一关心的是-我有一个模型表单,它不会用self.user.first_名称填充空字段。设置属性和获取是完美的。还有一个小问题——在查找时,django orm无法解析属性信息字段,它需要原始的_first_name字段。