2011-04-29 20 views
11

Tengo un modelo y excluí dos campos, los campos create_date y created_by. Ahora aparece el error "No nulo" cuando se usa el método save() porque el created_by está vacío.Django, agregando propiedades excluidas al modelo presentado

He intentado agregar la identificación del usuario al formulario antes del save() método como este: form.cleaned_data['created_by'] = 1 y form.cleaned_data['created_by_id'] = 1. Pero nada de esto funciona.

¿Puede alguien explicarme cómo puedo 'agregar' cosas adicionales al formulario del modelo enviado para que se guarde?

class Location(models.Model): 
    name = models.CharField(max_length = 100) 
    created_by = models.ForeignKey(User) 
    create_date = models.DateTimeField(auto_now=True) 

class LocationForm(forms.ModelForm): 
    class Meta: 
     model = Location 
     exclude = ('created_by', 'create_date',) 

Respuesta

17

Puesto que usted ha excluido los campos created_by y create_date en su forma, tratando de asignarlos a través form.cleaned_data no tiene ningún sentido.

Esto es lo que puede hacer:

Si se tiene una vista, sólo tiene que utilizar form.save(commit=False) y luego establecer el valor de created_by

def my_view(request): 
    if request.method == "POST": 
     form = LocationForm(request.POST) 
     if form.is_valid(): 
      obj = form.save(commit=False) 
      obj.created_by = request.user 
      obj.save() 
     ... 
     ... 

`

Si está utilizando el Administrador, puede anular el método save_model() para obtener el resultado deseado.

class LocationAdmin(admin.ModelAdmin): 
    def save_model(self, request, obj, form, change): 
     obj.created_by = request.user 
     obj.save() 
+1

gracias hombre! Tan simple ... –

+1

En serio, el Pony estaría orgulloso. – Civilian

+0

Lo anterior no funcionaba para mí. En mi Meta ModelForm, estaba especificando los campos para incluir, en lugar de excluir. Resultó que el problema era que estaba usando la variable de clase "incluir", cuando debería haber estado usando "campos". Por lo tanto, se incluyeron los campos que quería excluir y el formulario no se validaría. – Chuck

4

pasa un usuario como un parámetro para formar constructor, a continuación, utilizarla para configurar campo created_by de una instancia de modelo:

def add_location(request): 
    ... 
    form = LocationForm(user=request.user) 
    ... 

class LocationForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     user = kwargs.pop('user') 
     super(forms.ModelForm, self).__init__(*args, **kwargs) 
     self.instance.created_by = user 
0

Una forma de hacer esto es mediante el uso form.save (commit = False) (doc)

Eso devolverá una instancia de objeto de la clase de modelo sin comprometerlo con la base de datos.

lo tanto, su procesamiento podría ser algo como esto:

form = some_form(request.POST) 
location = form.save(commit=False) 
user = User(pk=1) 
location.created_by = user 
location.create_date = datetime.now() 
location.save() 
+0

tenga en cuenta que también tiene que realizar una llamada al método save_m2m() del formulario –

+0

Es cierto, si hay relaciones de muchos a muchos asociados al modelo. – Brant

1

La solución correcta es pasar una instancia del objeto con campos rellenos previamente al constructor del formulario modelo. De esa forma, los campos se completarán en el momento de la validación. La asignación de valores después de form.save() puede dar como resultado errores de validación si se requieren campos.

LocationForm(request.POST or None, instance=Location(
    created_by=request.user, 
    create_date=datetime.now(), 
)) 

en cuenta que una instancia es un objeto no guardado, por lo que no se le asignará el identificador hasta que se formen los guarda.

+0

Personalmente creo que este es un mejor enfoque –

Cuestiones relacionadas