¿Es posible agregar un valor predeterminado a ArrayField?
Traté de hacer esto para el campo de correo electrónico, pero esto no funcionó:
constantes.py:
ORDER_STATUS_CHANGED = 'order_status_changed' NEW_SIGNAL = 'new_signal' NOTIFICATION_SOURCE = ( (ORDER_STATUS_CHANGED, 'Order Status Changed'), (NEW_SIGNAL, 'New Signal'), )modelos.py:
from notifications import constants from django.contrib.postgres.fields import ArrayField class NotificationSetting(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='notification_setting') telegram = ArrayField(models.CharField( choices= constants.NOTIFICATION_SOURCE, max_length=30 ), default=list) email = ArrayField(models.CharField( choices= constants.NOTIFICATION_SOURCE, max_length=16 ), default=list(dict(constants.NOTIFICATION_SOURCE).keys())) class Meta: db_table = 'notification_settings' def __str__(self): return f'Notification setting for user {self.user}'Y anular el método de guardado del modelo sería una mala práctica, creo.
El problema es que en el sitio de administración de django veo que los valores predeterminados no cuentan cuando se crea el objeto. (UPD. Maibe tengo un problema con mi ChoiseArrayField personalizado)
Y recibo este mensaje: WARNINGS: notifications.NotificationSetting.email: (postgres.E003) ArrayField default should be a callable instead of an instance so that it's not shared between all field instances. HINT: Use a callable instead, eg, use list instead of []``
La propiedad default en un ArrayField debe ser invocable. Puede leer más sobre eso aquí: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/ .
Lo que obtiene al colocar directamente allí list(dict(constants.NOTIFICATION_SOURCE).keys()) es solo una advertencia, por lo que aún debe agregar los valores predeterminados al campo. Al colocar este valor predeterminado directamente allí, pondrá en las migraciones lo siguiente y los valores se compartirán en todas las instancias de campo:
default=['order_status_changed', 'new_signal']Para deshacerse de la advertencia, debe crear una función que devuelva el valor predeterminado:
def get_email_default(): return list(dict(constants.NOTIFICATION_SOURCE).keys())y poner la función por defecto en el campo:
email = ArrayField(models.CharField( choices= constants.NOTIFICATION_SOURCE, max_length=16 ), default=get_email_default)Al hacer esto, la advertencia desaparecerá y desde la función puede tener lógica para elegir el valor predeterminado.
Después de hacer esto, en las migraciones el valor predeterminado se verá así:
default=my_model.models.get_email_default