Campo vacío de Django

Tengo un modelo que tiene la dirección de usuario. Este modelo debe tener los campos nombre primero y último nombre, ya que uno desea establecer la dirección de un destinatario (como su compañía, etc.). Lo que estoy tratando de lograr es:

  • Si el campo fist_name / last_name en la dirección se llena, devuelva simplemente ese campo
  • Si el campo fist_name / last_name en la dirección está vacío, busque los datos del campo correspondiente desde una clave foránea que apunte a un django.auth.models adecuado. Usuario
  • Me gustaría que esto se tratara como un campo django normal que estaría presente en los campos de búsqueda
  • No quiero crear un método, ya que es una refactorización y Address.first_name / last_name se usan en varios lugares de la aplicación (también en formas de modelo, etc.), por lo que necesito esto lo más fácil posible o si no Tendré que juguetear en muchos lugares.

Gracias por la ayuda 🙂

Aquí hay dos opciones. La primera es crear un método para buscarlo dinámicamente, pero use el decorador de property para que otros códigos puedan usar el acceso directo a los atributos.

 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 

Esto siempre se referirá al último valor de first_name, incluso si se cambia el Usuario relacionado. Puede obtener / establecer la propiedad exactamente como lo haría con un atributo: myinstance.first_name = 'daniel'

La otra opción es anular el método save() del modelo para que realice la búsqueda al guardar:

 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) 

De esta manera, no tiene que cambiar su base de datos, pero solo se actualiza al guardar, por lo tanto, si el objeto Usuario relacionado se cambia pero este objeto no, se referirá al valor anterior del Usuario.

Aunque esto no cumple con todos los requisitos del OP, en algunos casos de uso donde se necesita el repliegue en los filtros queryset (en el nivel de la base de datos) puede ser posible usar la clase Coalesce() Django ().

La solución más simple en tal caso podría ser la anotación queryset (usando el ejemplo de la respuesta de @ daniel-roseman):

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

Cada elemento obtenido del conjunto de consultas obtendrá un atributo first_name , que tiene el valor de _first_name con un _first_name (en caso de que el valor sea null ) para user.first_name .

Es decir, asumiendo que su modelo tiene como relación de user .

Esto se puede implementar, por ejemplo, en un administrador personalizado y también podría usarse junto con un enfoque de property .

En esta respuesta SO se proporciona un ejemplo detallado para un caso similar (anulación en lugar de reserva).