Django define valores de formulário padrão

241

Eu tenho um modelo da seguinte maneira:

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()

Eu também tenho um formulário de modelo para o modelo acima, da seguinte maneira:

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

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

Quero saber como definir o valor padrão para esse campo oculto do tanque. Aqui está minha função de mostrar / salvar o formulário até o momento:

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/')
Mike
fonte

Respostas:

401

Você pode usar inicial, que é explicado aqui

Você tem duas opções para preencher o valor ao chamar o construtor de formulários:

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

ou defina o valor na definição do formulário:

tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 
Sergey Golovchenko
fonte
E como essa variável é initialpassada para a forma real? No modelo de formulário real, precisamos escrever como um parâmetro / argumento?
mgPePe
2
@bharal É mágico. ;-) (Ou melhor, os construtores de formulários do Django entendem a variável "inicial" especial e interagem com seu conteúdo sem que você precise fazer algo extra). Pessoalmente, prefiro especificar valores padrão na definição do formulário e usar apenas o mecanismo inicial = ... se o padrão desejado for um valor dinâmico (por exemplo, algo inserido por um usuário ou com base em seu login, localização geográfica etc.)
Richard J Foster
66
inicial não é o padrão. O valor inicial não se aplica se o formulário tiver sido vinculado :(.
clime
4
Comentando aqui para mencionar outro caso de uso em que esta solução de parâmetros iniciais ajudará: Ao enviar um link de registro para alguém, se você deseja preencher previamente o email / id ou qualquer outra credencial no formulário de registro, nesse caso, você não pode escrever isso em o modelo em si é dinâmico, e você precisa chamar o construtor com o parâmetro inicial, como mencionado por @ umnik700. Funciona bem!
Keshav Agrawal
1
@ Phillip: Não substitua View.get_formpara definir os dados iniciais. Qualquer CBV com um FormMixin (basicamente todos os CBVs que criam ou editam dados) pode usar uma initialvariável em nível de classe (para padrões inalteráveis) ou você pode substituir FormMixin.get_initial()para retornar um ditado de valores iniciais a serem passados ​​ao construtor do formulário (para padrões dinâmicos .)
GDorn
29

Outra solução: defina inicial após criar o formulário:

form.fields['tank'].initial = 123
Andreas Zwerger
fonte
Este trabalho para minha necessidade, apenas inicia um campo no formulário. obrigado.
precisa saber é o seguinte
11

Eu tive essa outra solução (estou publicando-a no caso de alguém como eu estar usando o seguinte método do 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',

            })
        }

A inicial é desativada na __init__função comoself.fields['is_active'].initial = False

Izuzvo
fonte
0

Espero que isso possa ajudá-lo:

form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id
Code47
fonte
0

Como explicado nos documentos do Django , initialnão é default.

  • O valor inicial de um campo deve ser exibido em um HTML. Mas se o usuário excluir esse valor e finalmente enviar um valor em branco para esse campo, o initialvalor será perdido. Portanto, você não obtém o que é esperado por um comportamento padrão .

  • O comportamento padrão é: o valor que o processo de validação assumirá se o dataargumento não contiver nenhum valor para o campo.

Para implementar isso, uma maneira direta é combinar initiale 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
fonte