在一个窗体中编辑两个模型



我扩展了Django的标准User模型,如Django中所述文档中添加一些字段。

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)

现在我想要一个单一的表单来同时编辑两个模型中的字段时间我找到了这个解决方案,但据我所知,这将导致有两个提交按钮的两个表单。

是否可以使用基于泛型类的视图(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',)

我想我必须传递与表单相对应的实例。但是我如何才能为两个模型都这样做呢?

再次感谢!

第二次编辑

我找到了一个解决方案:

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>

您可以使用此解决方案:

混合两种形式如下:

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

在此项目模板中尝试用户模型。一旦你了解了它的工作原理,就更容易交给用户了。该模板已经为您想要做的事情提供了一个表单。

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

我有两个模型:默认django的User和我的Profile。所以我需要把它们都编辑成一种形式。这是我的代码:

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

型号.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正确地从数据库加载并正确地保存到数据库。配置文件中的其他字段(如"balance")也可以正确加载和保存。

最新更新