2010-02-09 30 views
21

he hecho un ModelForm la adición de algunos campos adicionales que no son en el modelo. Utilizo estos campos para algunas calcualciones al guardar el formulario.Django ModelForm con campos adicionales que no se encuentran en el modelo

Los campos adicionales aparecen en el formulario y que se envían en la solicitud POST al cargar el formulario. El problema es que no se agregan al diccionario cleaned_data cuando valido el formulario. ¿Cómo puedo acceder a ellos?

+0

Se deben agregar a la dicción de datos limpios. Por favor, publique su código de formulario, para que podamos echarle un vistazo. – gruszczy

+0

Te aconsejo que no almacenes la información en el campo Formulario. Una solución más limpia es: almacenarlo en sesiones. – sergzach

+0

Si el código que ha publicado en su respuesta de seguimiento es una copia exacta y pegar, entonces hay un problema de sangría con la última línea, debe ser de un nivel. –

Respuesta

1

Ok he resuelto él. Parece que acceder a los campos adicionales con cleaned_data ['field_name'] genera un KeyError pero funciona clean_data.get ('field_name'). Eso es extraño porque se puede acceder a los campos normales para el modelo a través de la función clean_data ['field_name'].

Actualización: No, no funciona. Con get() no genera un KeyError pero establece un valor de None porque los campos adicionales no están en el diccionario de clean_data.

Aquí está el código. En las plantillas hay una función de autocompletar, por lo que en el formulario hay un campo "artista" representado como un CharField y un IntegerField oculto que se autopolará con la identificación del artista dada. En el método clean_artist, quiero seleccionar el objeto del artista y almacenarlo en el campo del artista del formulario.

models.py

class Music(models.Model): 
    artist = models.ForeignKey(Artist, related_name='music', blank=True, null=True) 
    # other fields... 

forms.py

class MusicForm(forms.ModelForm): 
    artist_id = forms.IntegerField(label="", widget=forms.HiddenInput(), required=False) 
    artist = forms.CharField(required=False) 
    # other fields ... 

    class Meta: 
     model = Music 

    def clean_artist(self): 
     if self.cleaned_data.get('artist') == '': 
      artist = None 
     else: 
      artist_id = self.cleaned_data.get('artist_id') # this returns always None because artist_id is not in cleaned_fields (this seemed to work with previous django versions but not with current SVN version) 
      if artist_id != None: 
       artist = Artist.objects.get(id=artist_id) 
      else: 
       artist = None 

    return artist 
+0

Esto es extraño, porque obtener no es diferente de []. Publique su código y será más fácil encontrar un problema subyacente. – gruszczy

+4

el artista que regresa necesita una sangría adicional. no está en el método clean_artist. –

+1

¿el guión solucionó el problema? – Anentropic

5

En primer lugar, usted no debe tener campos artist_id y artista. Se construyen a partir del modelo. Si necesita un nombre de artista, agregue el campo de nombre de artista, que es CharField.

Por otra parte, usted está tratando de recuperar algo de valor dentro cleaned_data limpio. Puede que no haya datos que necesita: debe usar valores de self.data, donde se encuentran los datos directamente de POST.

+0

en realidad es correcto usar datos limpios dentro de los métodos individuales de clean_X: http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute – Anentropic

+0

Gracias por la edición, @Martin – Cartucho

11

Es posible extender Django ModelForm con campos adicionales. Imagine que tiene un modelo de usuario personalizada y esto ModelForm:

class ProfileForm(forms.ModelForm): 

    class Meta: 
     model = User 
     fields = ['username', 'country', 'website', 'biography'] 

Ahora, imagine que desea incluir un campo adicional (no presente en su modelo de usuario, que permite decir un avatar imagen). Ampliar su forma de hacer esto:

from django import forms 

class AvatarProfileForm(ProfileForm): 

    profile_avatar = forms.ImageField() 

    class Meta(ProfileForm.Meta): 
     fields = ProfileForm.Meta.fields + ('profile_avatar',) 

último (dado que la forma tiene un ImageField), recuerde incluir request.FILES cuando una instancia de la forma en su opinión:

# (view.py) 

def edit_profile(request): 
    ... 
    form = AvatarProfileForm(
     request.POST or None, 
     request.FILES or None, 
     instance=request.user 
    ) 
    ... 

espero que ayude. ¡Buena suerte!

EDIT:

que era conseguir una "sólo puede concatenar tuplas (no "lista") a tupla" error en el atributo AvatarProfileForm.Meta.fields. Lo cambió a una tupla y funcionó.

+2

Obtengo 'django.core.exceptions.FieldError: campo (s) desconocido (my_new_field) especificado para MyModel' cuando agrego' my_new_field' a la lista 'fields'. Django 1.10 – CpILL

4

Esta respuesta puede ser demasiado tarde para que el creador original, pero pensé que podría ayudar a los demás. Tuve el mismo problema y me di cuenta de que se puede acceder a self.cleaned_data ('artist_id') en el método clean(), pero no en clean_artist().

Cuando agregué los campos adicionales en la declaración de 'campos' de Meta, funcionó.

class Meta: 
     model = Music 
     fields=[..., 'artist_id'] 

Usted debe ser capaz de acceder a la self.cleaned_data ('artist_id') en clean_artist().

Cuestiones relacionadas