Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django空字段回退_Python_Django_Django Models_Model_Field - Fatal编程技术网

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

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

      这可以在自定义管理器中实现,也可以与
      属性
      方法结合使用


      类似情况的详细示例(覆盖而不是回退)如所示。

      您可以指定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字段。