Django establece valores de formulario predeterminados

241

Tengo un modelo de la siguiente manera:

class TankJournal(models.Model):
    user = models.ForeignKey(User)
    tank = models.ForeignKey(TankProfile)
    ts = models.IntegerField(max_length=15)
    title = models.CharField(max_length=50)
    body = models.TextField()

También tengo un modelo de formulario para el modelo anterior de la siguiente manera:

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput()) 

    class Meta:
        model = TankJournal
        exclude = ('user','ts')

Quiero saber cómo establecer el valor predeterminado para ese campo oculto del tanque. Aquí está mi función para mostrar / guardar el formulario hasta ahora:

def addJournal(request, id=0):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')

    # checking if they own the tank
    from django.contrib.auth.models import User
    user = User.objects.get(pk=request.session['id'])

    if request.method == 'POST':
        form = JournalForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)

            # setting the user and ts
            from time import time
            obj.ts = int(time())
            obj.user = user

            obj.tank = TankProfile.objects.get(pk=form.cleaned_data['tank_id'])

            # saving the test
            obj.save()

    else:
        form = JournalForm()

    try:
        tank = TankProfile.objects.get(user=user, id=id)
    except TankProfile.DoesNotExist:
        return HttpResponseRedirect('/error/')
Miguel
fuente

Respuestas:

402

Puede usar la inicial que se explica aquí

Tiene dos opciones: completar el valor al llamar al constructor de formularios:

form = JournalForm(initial={'tank': 123})

o establezca el valor en la definición del formulario:

tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 
Sergey Golovchenko
fuente
¿Y cómo se pasa esa variable initiala la forma real? En el modelo de formulario real, ¿tenemos que escribir como parámetro / argumento?
mgPePe
2
@bharal Es mágico. ;-) (O más bien, los constructores de formularios de Django entienden la variable "inicial" especial e iteran a través de su contenido sin que tenga que hacer nada extra). Personalmente, prefiero especificar valores predeterminados en la definición del formulario y solo usar el mecanismo inicial = ... si el valor predeterminado deseado es un valor dinámico (por ejemplo, algo ingresado por un usuario, o basado en su inicio de sesión, ubicación geográfica, etc.)
Richard J Foster
66
inicial no es el predeterminado. El valor inicial no se aplica si el formulario se ha vinculado :(.
clima
44
Comentando aquí para mencionar otro caso de uso en el que esta solución del parámetro inicial ayudará: al enviar un enlace de registro a alguien si desea rellenar previamente el correo electrónico / ID o cualquier otra credencial en el formulario de registro, en ese caso no puede escribir eso en el modelo en sí es dinámico, en lugar de llamar al constructor con el parámetro inicial mencionado por @ umnik700. ¡Funciona genial!
Keshav Agrawal
1
@Phlip: no anule View.get_formpara establecer los datos iniciales. Cualquier CBV con un FormMixin (básicamente todos los CBV que crean o editan datos) puede usar una initialvariable de nivel de clase (para valores predeterminados sin cambios) o puede anular FormMixin.get_initial()para devolver un dictado de valores iniciales para pasar al constructor del formulario (para valores predeterminados dinámicos .)
GDorn
29

Otra solución: Establecer inicial después de crear el formulario:

form.fields['tank'].initial = 123
Andreas Zwerger
fuente
Esto funciona para mi necesidad, solo inicia un campo en el formulario. gracias.
bl4ckb1rd
11

Tuve esta otra solución (la estoy publicando en caso de que alguien más como yo esté usando el siguiente método del modelo):

class onlyUserIsActiveField(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(onlyUserIsActiveField, self).__init__(*args, **kwargs)
        self.fields['is_active'].initial = False

    class Meta:
        model = User
        fields = ['is_active']
        labels = {'is_active': 'Is Active'}
        widgets = {
            'is_active': forms.CheckboxInput( attrs={
                            'class':          'form-control bootstrap-switch',
                            'data-size':      'mini',
                            'data-on-color':  'success',
                            'data-on-text':   'Active',
                            'data-off-color': 'danger',
                            'data-off-text':  'Inactive',
                            'name':           'is_active',

            })
        }

La inicial se define en la __init__función comoself.fields['is_active'].initial = False

Izuzvo
fuente
0

Espero que esto pueda ayudarte:

form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id
Código47
fuente
0

Como se explica en los documentos de Django , initialno lo es default.

  • El valor inicial de un campo está destinado a mostrarse en un HTML. Pero si el usuario elimina este valor y finalmente devuelve un valor en blanco para este campo, el initialvalor se pierde. Por lo tanto, no obtiene lo que se espera de un comportamiento predeterminado .

  • El comportamiento predeterminado es: el valor que tomará el proceso de validación si el dataargumento no contiene ningún valor para el campo.

Para implementar eso, una forma sencilla es combinar initialy clean_<field>():

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 

    (...)

    def clean_tank(self):
        if not self['tank'].html_name in self.data:
            return self.fields['tank'].initial
        return self.cleaned_data['tank']
Timothé Delion
fuente