Tengo un modelo que me gustaría que contenga el nombre de un sujeto y sus iniciales (los datos son algo anonimizados y se rastrean por iniciales).
Ahora mismo, escribí
class Subject(models.Model):
name = models.CharField("Name", max_length=30)
def subject_initials(self):
return ''.join(map(lambda x: '' if len(x)==0 else x[0],
self.name.split(' ')))
# Next line is what I want to do (or something equivalent), but doesn't work with
# NameError: name 'self' is not defined
subject_init = models.CharField("Subject Initials", max_length=5, default=self.subject_initials)
Como se indica en la última línea, preferiría poder tener las iniciales realmente almacenadas en la base de datos como un campo (independiente del nombre), pero eso se inicializa con un valor predeterminado basado en el campo de nombre. Sin embargo, estoy teniendo problemas ya que los modelos de django no parecen tener un "yo".
Si cambio la línea a subject_init = models.CharField("Subject initials", max_length=2, default=subject_initials)
, puedo hacer syncdb, pero no puedo crear nuevos sujetos.
¿Es esto posible en Django, tener una función invocable que dé un valor predeterminado a algún campo en función del valor de otro campo?
(Para los curiosos, la razón por la que quiero separar las iniciales de mi tienda por separado es en casos excepcionales en los que los apellidos extraños pueden tener diferentes a los que estoy rastreando. Por ejemplo, alguien más decidió que las iniciales del Sujeto 1 llamado "John O'Mallory" son "JM" en lugar de "JO" y desea corregirlo, editarlo como administrador).
fuente
super().save(*args, **kwargs)
(sin losSubject, self
argumentos) como en el ejemplo en la documentación referenciada.No sé si hay una mejor manera de hacer esto, pero puede usar un controlador de señal para la
pre_save
señal :fuente
post_save
lugar depre_save
.**kwargs
argumento que deberían tener todas las funciones del receptor de acuerdo con docs.djangoproject.com/en/2.0/topics/signals/… ?save()
, quizás cambiada a anular__init__
, es mejor porque es más explícita.Usando señales de Django , esto se puede hacer bastante temprano, recibiendo la
post_init
señal del modelo.La
post_init
clase envía la señal una vez que ha realizado la inicialización en la instancia. De esta forma, la instancia obtiene un valorname
antes de probar si sus campos que no aceptan valores NULL están configurados.fuente
save()
, quizás cambiada a anular__init__
, es mejor porque es más explícita.Como implementación alternativa de la respuesta de Gabi Purcaru , también puede conectarse a la
pre_save
señal usando elreceiver
decorador :Esta función de receptor también toma los
**kwargs
argumentos de palabras clave comodín que todos los manejadores de señales deben tomar de acuerdo con https://docs.djangoproject.com/en/2.0/topics/signals/#receiver-functions .fuente