EDITADO:
¿Cómo puedo establecer el valor predeterminado de un campo de Django en una función que se evalúa cada vez que se crea un nuevo objeto de modelo?
Quiero hacer algo como lo siguiente, excepto que en este código, el código se evalúa una vez y establece el valor predeterminado en la misma fecha para cada objeto modelo creado, en lugar de evaluar el código cada vez que se crea un objeto modelo:
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
ORIGINAL:
Quiero crear un valor predeterminado para un parámetro de función de modo que sea dinámico y se llame y configure cada vez que se llame a la función. ¿Cómo puedo hacer eso? p.ej,
from datetime import datetime
def mydate(date=datetime.now()):
print date
mydate()
mydate() # prints the same thing as the previous call; but I want it to be a newer value
Específicamente, quiero hacerlo en Django, por ejemplo,
from datetime import datetime, timedelta
class MyModel(models.Model):
# default to 1 day from now
my_date = models.DateTimeField(default=datetime.now() + timedelta(days=1))
django
django-models
parameters
lambda
default
Rob Bednark
fuente
fuente
Respuestas:
La pregunta está equivocada. Al crear un campo de modelo en Django, no está definiendo una función, por lo que los valores predeterminados de la función son irrelevantes:
Esta última línea no define una función; está invocando una función para crear un campo en la clase.
PRE Django 1.7
Django le permite pasar un invocable como predeterminado , y lo invocará cada vez, tal como desee:
Django 1.7+
Tenga en cuenta que desde Django 1.7, no se recomienda el uso de lambda como valor predeterminado (consulte el comentario de @stvnw). La forma correcta de hacer esto es declarar una función antes del campo y usarla como invocable en valor_predeterminado llamado arg:
Más información en la respuesta de @simanas a continuación
fuente
get_default_my_date
?¡Hacer esto
default=datetime.now()+timedelta(days=1)
está absolutamente mal!Se evalúa cuando inicia su instancia de django. Si está bajo apache, probablemente funcionará, porque en algunas configuraciones apache revoca su aplicación django en cada solicitud, pero aún puede encontrarse algún día revisando su código y tratando de descubrir por qué esto no se calcula como esperaba .
La forma correcta de hacer esto es pasar un objeto invocable al argumento predeterminado. Puede ser una función datetime.today o su función personalizada. Luego, se evalúa cada vez que solicita un nuevo valor predeterminado.
fuente
get_deadline(my_parameter)
?deadline
volver a eliminar el campo y al mismo tiempo eliminar laget_deadline
función? He eliminado un campo con una función para un valor predeterminado, pero ahora Django se bloquea al iniciar después de eliminar la función. Podría editar manualmente la migración, lo que estaría bien en este caso, pero ¿qué pasa si simplemente cambia la función predeterminada y desea eliminar la función anterior?Hay una distinción importante entre los siguientes dos constructores DateTimeField:
Si utiliza
auto_now_add=True
en el constructor, la fecha y hora a la que hace referencia my_date es "inmutable" (solo se establece una vez cuando la fila se inserta en la tabla).Con
auto_now=True
embargo, con el valor de fecha y hora se actualizará cada vez que se guarde el objeto.Esto definitivamente fue un problema para mí en un momento. Como referencia, los documentos están aquí:
https://docs.djangoproject.com/en/dev/ref/models/fields/#datetimefield
fuente
A veces, es posible que deba acceder a los datos del modelo después de crear un nuevo modelo de usuario.
Así es como genero un token para cada nuevo perfil de usuario usando los primeros 4 caracteres de su nombre de usuario:
fuente
No puedes hacer eso directamente; el valor predeterminado se evalúa cuando se evalúa la definición de la función. Pero hay dos formas de evitarlo.
Primero, puede crear (y luego llamar) una nueva función cada vez.
O, más simplemente, use un valor especial para marcar el predeterminado. Por ejemplo:
Si
None
es un valor de parámetro perfectamente razonable, y no hay otro valor razonable que pueda usar en su lugar, puede crear un nuevo valor que definitivamente está fuera del dominio de su función:En algunos casos raros, se está escribiendo meta-código que realmente hace falta ser capaz de tomar absolutamente nada, ni siquiera, por ejemplo,
mydate.func_defaults[0]
. En ese caso, debe hacer algo como esto:fuente
myfunc
función está hecha para tomar (e imprimir) adatetime
; lo ha cambiado para que no se pueda utilizar de esa forma.Pase la función como parámetro en lugar de pasar el resultado de la llamada a la función.
Es decir, en lugar de esto:
Prueba esto:
fuente
print datetime.now()
incondicionalmente.datetime.now
función. Pero cualquier usuario que pase un valor no predeterminado pasará una fecha y hora, no una función.foo = datetime.now(); myfunc(foo)
levantaráTypeError: 'datetime.datetime' object is not callable
. Si realmente quisiera usar su función, tendría que hacer algo comomyfunc(lambda: foo)
, que no es una interfaz razonable.