从Django中的现有对象设置表单的默认值

时间:2013-12-26 20:58:53

标签: django django-forms

我正在尝试创建我的Django 1.5项目的页面,用户可以在其中更改其预先信息。我写了一个表格:

class UserModify(forms.Form):
    middleschool = 'MS'
    highschool = 'HS'
    university = 'U'
    blank = ''
    male = 'M'
    female = 'F'
    mastercard = 'MC'
    maestro = 'M'
    visa = 'V'
    americanexpress = 'A'

    school_choices = ((middleschool, 'Middle School'), (highschool, 'High school'), (university, 'University'), (blank, 'Not Defined'),)
    sex = ((male, 'Male'), (female, 'Female'), (blank, 'Not defined'),)
    card_choices = ((mastercard, 'MasterCard'), (maestro, 'Mestro'), (visa, 'Visa/Visa Electron'), (americanexpress, 'American Express'),(blank, 'Not Defined'))

    password = forms.CharField(label = 'Password', widget=forms.PasswordInput)
    repassword = forms.CharField(label = ' Reinstert password', widget=forms.PasswordInput)
    name = forms.CharField(label = 'Name', required=False)
    surname = forms.CharField(label = 'Surname', required=False)
    school = forms.ChoiceField(choices = school_choices, required=False, label='What school are you enrolled?', initial = blank) 
    birthdate = forms.DateField(label = 'Birth date', required=False, widget=forms.extras.SelectDateWidget(years=range(1950, 2015)))
    sex = forms.ChoiceField(choices = sex, required=False, label='Sex', initial = blank)
    city = forms.CharField(label = 'City', required=False)
    paypal_info = forms.EmailField(required=False,)
    card_type = forms.ChoiceField(choices = card_choices, label='Card type', required=False)
    card_info = forms.CharField(min_length = 16, max_length = 16, label = 'Your card number', required=False,)
    def clean_repassword(self):
        repassword = self.cleaned_data['repassword']
        password = self.cleaned_data['password']
        if repassword != password:
            raise forms.ValidationError("Verification password different from original password!")
    widgets = {
            'password': forms.PasswordInput(),
            'birthdate': forms.extras.SelectDateWidget(years=range(1950, 2014))
    }

这是相对观点:

def usermodify(request, user):
    mod_user = User.objects.get(username = user)
    if request.method == 'POST':
        form = UserModify(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            mod_user.password = cd['password']
            mod_user.first_name = cd['name']
            mod_user.last_name = cd['surname']
            mod_user.save()
            profile = mod_user.get_profile()
            profile.school = cd['school']
            profile.birthdate = cd['birthdate']
            profile.sex = cd['sex']
            profile.city = cd['city']
            profile.save()
            return render(request, 'user.html', {'request':request, 'view_user': mod_user, 'view_user_profile': profile})
    else:
        form = UserModify()
    return render(request, 'user_modify.html', {'form': form, 'request': request, 'modify_user': mod_user})

表单的渲染就像现在一样简单:

<form action="" method="post">
{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Modify">
    <input type="reset" value="Reset">
</form>

我想要做的是默认使用对象中的当前值填充表单,以便用户只需要更改感兴趣的那个并保留其他值。

3 个答案:

答案 0 :(得分:1)

使用ModelForm代替常规FormModelForm可以与实例关联,该实例用于预填充表单。如果您要同时更新User和个人资料,则可以在一个视图中使用两个ModelForm。例如:

class UserModelForm(forms.ModelForm):
    repassword = ... # additional fields that have no represenation in the model

    class Meta:
        model = User
        fields = ["username", "password", ]  # ...

    def clean(self):
        # ... your validation logic

class ProfileForm(forms.ModelForm):
    class Meta:
        model = YourProfileModel
        fields = []  # ...

然后在视图中使用两者:

def usermodify(request, user):
    # mod_user = ...

    user_form = UserModelForm(request.POST or None, instance=mod_user)
    profile_form = ProfileForm(request.POST or None, instance=mod_user.get_profile())
    if user_form.is_valid() and profile_form.is_valid():
        user_form.save()  # this saves to the associated mod_user, as passed via the `instance` argument
        profile_form.save() 
        # ... redirect etc.
    return render(..., {'user_form': user_form, 'profile_form': profile_form})  # pass both forms to the template

在模板中,将两个表单放在一个<form>标记中。确保它们没有冲突的字段名称,或use a prefix.

答案 1 :(得分:0)

  1. 如果您尝试在对象中获取默认值。您可以在模型中设置它,这些将转移到您的表单,并填充。例如:

    school_choices = models.CharField(空白=真,默认='HS')

  2. 结合使用Django的CBV(基于类的视图)和UdpdateView:

    https://docs.djangoproject.com/en/dev/ref/class-based-views/generic-editing/#updateview

  3. UpdateView将为您预先填写表单。

答案 2 :(得分:0)

供将来参考:我在渲染表格时使用Initial解决了here