在一个表单中编辑两个模型

时间:2014-10-03 18:03:02

标签: python django forms

我按照Django documentation中的说明扩展了Django的标准User模型,以添加一些字段。

from django.db import models
from django.contrib.auth.models import User

class Employee(models.Model):
    user = models.OneToOneField(User)
    company = models.CharField(max_length=200)

现在我想要一个表单来编辑两个模型中的字段 时间。我找到了this solution,但据我了解,这会产生 有两个提交按钮的两种形式。

是否可以使用基于通用类的视图(UpdateView)来组合两个模型 以一种形式?或者我可能必须使用基于功能的视图?什么会这样 视图看起来像?

修改

现在可以将数据保存到两个模型。但我无法弄清楚如何从数据库加载两种模型的数据。我的视图现在看起来像这样:

def UserSettingsUpdateView(request):
# if this is a POST request we need to process the form data

    user = request.user
    employee = user.employee

    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = UserSettingsForm(request.POST)

        # check whether it's valid:
        if form.is_valid():

            # Save User model fields
            user.first_name = request.POST['first_name']
            user.last_name = request.POST['last_name']
            user.save()

            # Save Employee model fields
            employee.company = request.POST['company']
            employee.news_notifications = request.POST['news_notifications']
            employee.save() 

            # redirect to the index page
            return HttpResponseRedirect('/')

    # if a GET (or any other method)
    else:
        form = UserSettingsForm(instance=user)

    return render(request, 'settings.html', {'form': form})

我的表格:

class UserSettingsForm(forms.ModelForm):

    # fields from User model
    first_name = forms.CharField(required=False, label='First Name')
    last_name = forms.CharField(required=False, label='Last Name')

    class Meta:
        model = Employee
        fields = ('first_name', 'last_name', 'company', 'news_notifications',)

我想我必须将实例correkt传递给表单。但是我怎么能为这两个模型做到这一点?

再次感谢!

第二次修改

我找到了解决方案:

def UserSettingsUpdateView(request):
    # if this is a POST request we need to process the form data

    user = request.user
    employee = user.employee

    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form_user = UserSettingsForm(request.POST)
        form_extended = UserSettingsExtendedForm(request.POST)

        # check whether it's valid:
        if form_user.is_valid() and form_extended.is_valid():

            # Save User model fields
            user.first_name = request.POST['first_name']
            user.last_name = request.POST['last_name']
            user.save()

            # Save Employee model fields
            employee.company = request.POST['company']
            if "news_notifications" in request.POST:
                employee.news_notifications = True
            else:
                employee.news_notifications = False
            employee.save() 

            # redirect to the index page
            return HttpResponseRedirect('/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form_user = UserSettingsForm(instance=user)
        form_extended = UserSettingsExtendedForm(instance=employee)

    return render(request, 'settings.html', {'form_user': form_user, 'form_extended': form_extended})

形式:

from django import forms
from django.contrib.auth.models import User
from usersettings.models import Employee


class UserSettingsForm(forms.ModelForm):

    class Meta:
        model = User
        fields = ('first_name', 'last_name',)


class UserSettingsExtendedForm(forms.ModelForm):

    class Meta:
        model = Employee
        fields = ('company', 'news_notifications',)

在模板中:

{% load crispy_forms_tags %}

<form action="" method="post">
    {% csrf_token %}

    {{ form_user|crispy }}
    {{ form_extended|crispy }}

    <input type="submit" value="Submit" class="btn btn-primary" />
</form>

3 个答案:

答案 0 :(得分:1)

您可以使用此解决方案:

混合两种形式:

class EmployeeEditForm(forms.ModelForm):
    #fields from User model that you want to edit
    first_name = forms.CharField(required=False, label=_('First Name'))
    last_name = forms.CharField(required=False, label=_('Last Name'))

    class Meta:
        model = Employee
        fields = ('first_name', 'last_name', 'company')

然后,在views.py中,您可以获得EmployeeUser这样的对象:

user = request.user
employee = user.employee

并像这样编辑User对象:

user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.save()

并像这样编辑Employee对象:

employee.company = request.POST['company']
employee.save() 

答案 1 :(得分:0)

我看到你的所有答案,我看到你解决了这个问题,但没有解决从数据库中设置自定义字段的值。

我有两个模型:默认django的用户和我的个人资料。 所以我需要以一种形式编辑它们。 这是我的代码:

view.py

def user_profile(request):
    profile_instance, created = Profile.objects.get_or_create(user=request.user) 
    profile_combined_form = ProfileCombinedForm(request.POST or None, instance=profile_instance)
    if request.POST:
        if profile_combined_form.is_valid():
                profile_combined_form.save_all_fields_from_request(request=request)
    return render(request, 'form-elements.html', {'form': profile_combined_form})

forms.py - 组合表单类

class ProfileCombinedForm(ModelForm):
    # fields from User model that you want to edit
    first_name = CharField(required=False, label='First Name')
    last_name = CharField(required=False, label='Last Name')

    def __init__(self, *args, **kwargs):
        super(ProfileCombinedForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        # You can dynamically adjust your layout
        self.helper.layout.append(Submit('save', 'Save'))
        self.fields['first_name'] = CharField(initial=self.instance.user.first_name)
        self.fields['last_name'] = CharField(initial=self.instance.user.last_name)

    class Meta:
        model = Profile
        fields = ('balance', 'first_name', 'last_name')

    def save_all_fields_from_request(self, request):
        self.save()
        user, created = User.objects.get_or_create(id=request.user.id)
        user.first_name = request.POST['first_name']
        user.last_name = request.POST['last_name']
        user.save()

models.py

class Profile(models.Model):
    user = models.ForeignKey(User)
    balance = models.IntegerField( default=0, blank=False, null=False)
    status = models.IntegerField(default=1, blank=False, null=False)
    enabled = models.BooleanField(default=True, blank=False, null=False)

    def __str__(self):
        return self.user.first_name + " " + self.user.last_name

现在first_name和last_name从数据库正确加载并正确保存到数据库。来自Profile的其他字段(如“balance”)加载并正确保存。

答案 2 :(得分:-1)

在此project template处尝试用户模型。一旦了解了它的工作原理,就可以更轻松地交付用户。该模板已经附带了您想要做的表单。