Django形式与两个不同模型的字段

时间:2022-01-19 12:08:05

I need to display one form, with multiple fields from 2 different models. Form will contain only part of fields from models, and layout will be made using the crispy forms.

我需要显示一个表单,其中包含来自2个不同模型的多个字段。表单将仅包含模型中的部分字段,并且将使用松散表单进行布局。

My models:

class Company(BaseModel):
    title = models.CharField(_('Company'), max_length=128)
    domain = models.CharField(_('Domain'), max_length=128)
class Account(BaseModel):
    company = models.ForeignKey(Company)
    user = models.OneToOneField(User)
    role = models.CharField(_('Role'), choices=ROLES, default='member', max_length=32)

Fields which I want to show in form: company title, user first name, user last name, user email

我想在表单中显示的字段:公司标题,用户名,用户姓,用户电子邮件

Is it even possible? How can I do this?

它甚至可能吗?我怎样才能做到这一点?

2 个解决方案

#1


5  

The other answers on this page involve tossing away the benefits of model forms and possibly needing to duplicate some of the functionality you get for free.

此页面上的其他答案涉及抛弃模型表单的好处,并可能需要复制您免费获得的一些功能。

The real key is to remember that one html form != one django form. You can have multiple forms wrapped in a single html form tag.

真正的关键是要记住一个html表单!=一个django表单。您可以将多个表单包装在单个html表单标记中。

So you can just create two model forms and render them both in your template. Django will handle working out which POST parameters belong to each unless some field names * - in which case give each form a unique prefix when you instantiate it.

因此,您只需创建两个模型表单并在模板中进行渲染。 Django将处理哪些POST参数属于每个POST参数,除非某些字段名称发生冲突 - 在这种情况下,在实例化时为每个表单赋予唯一的前缀。

Forms:

class CompanyForm(forms.ModelForm):
    class Meta:
        fields = [...]
        model = Company

class AccountForm(forms.ModelForm):
    class Meta:
        fields = [...]
        model = Account

View:

if request.method == 'POST':

    company_form = CompanyForm(request.POST)
    account_form = AccountForm(request.POST)

    if company_form.is_valid() and account_form.is_valid():

        company_form.save()
        account_form.save()
        return HttpResponseRedirect('/success')        

    else:
        context = {
            'company_form': company_form,
            'account_form': account_form,
        }

else:
    context = {
        'company_form': CompanyForm(),
        'account_form': AccountForm(),
    }

return TemplateResponse(request, 'your_template.html', context)

Template:

<form action="." method="POST">
    {% csrf_token %}
    {{ company_form.as_p }}
    {{ account_form.as_p }}
    <button type="submit">
</form>

#2


1  

In your forms.py

在你的forms.py中

from django import forms


class YourForm(forms.Form):
    title = forms.CharField()
    first_name = forms.CharField()
    last_name = ...

In your views.py

在你的views.py中

from forms import YourForm
from django import views
from models import Company, Account

class YourFormView(views.FormView)
    template_name = 'some_template.html'
    form_class = YourForm
    success_url = '/thanks/'

    def form_valid(self, form):
        title = form.cleaned_data['title']
        ...
        # do your processing here using Company and Account
        # i.e. company = Company.objects.create(title=title, ...)
        #      account = Account.objects.get_or_create(
        #      user=..., company=company ...)
        #      ... more processing
        #
        # Call company.save() and account.save() after adding
        # your processed details to the relevant instances
        #  and return a HttpResponseRedirect(self.success_url)

    def is_valid(self):
        # don't forget to validate your fields if need be here

As usual the docs are pretty helpful. https://docs.djangoproject.com/en/1.7/topics/forms/

像往常一样,文档非常有用。 https://docs.djangoproject.com/en/1.7/topics/forms/

#1


5  

The other answers on this page involve tossing away the benefits of model forms and possibly needing to duplicate some of the functionality you get for free.

此页面上的其他答案涉及抛弃模型表单的好处,并可能需要复制您免费获得的一些功能。

The real key is to remember that one html form != one django form. You can have multiple forms wrapped in a single html form tag.

真正的关键是要记住一个html表单!=一个django表单。您可以将多个表单包装在单个html表单标记中。

So you can just create two model forms and render them both in your template. Django will handle working out which POST parameters belong to each unless some field names * - in which case give each form a unique prefix when you instantiate it.

因此,您只需创建两个模型表单并在模板中进行渲染。 Django将处理哪些POST参数属于每个POST参数,除非某些字段名称发生冲突 - 在这种情况下,在实例化时为每个表单赋予唯一的前缀。

Forms:

class CompanyForm(forms.ModelForm):
    class Meta:
        fields = [...]
        model = Company

class AccountForm(forms.ModelForm):
    class Meta:
        fields = [...]
        model = Account

View:

if request.method == 'POST':

    company_form = CompanyForm(request.POST)
    account_form = AccountForm(request.POST)

    if company_form.is_valid() and account_form.is_valid():

        company_form.save()
        account_form.save()
        return HttpResponseRedirect('/success')        

    else:
        context = {
            'company_form': company_form,
            'account_form': account_form,
        }

else:
    context = {
        'company_form': CompanyForm(),
        'account_form': AccountForm(),
    }

return TemplateResponse(request, 'your_template.html', context)

Template:

<form action="." method="POST">
    {% csrf_token %}
    {{ company_form.as_p }}
    {{ account_form.as_p }}
    <button type="submit">
</form>

#2


1  

In your forms.py

在你的forms.py中

from django import forms


class YourForm(forms.Form):
    title = forms.CharField()
    first_name = forms.CharField()
    last_name = ...

In your views.py

在你的views.py中

from forms import YourForm
from django import views
from models import Company, Account

class YourFormView(views.FormView)
    template_name = 'some_template.html'
    form_class = YourForm
    success_url = '/thanks/'

    def form_valid(self, form):
        title = form.cleaned_data['title']
        ...
        # do your processing here using Company and Account
        # i.e. company = Company.objects.create(title=title, ...)
        #      account = Account.objects.get_or_create(
        #      user=..., company=company ...)
        #      ... more processing
        #
        # Call company.save() and account.save() after adding
        # your processed details to the relevant instances
        #  and return a HttpResponseRedirect(self.success_url)

    def is_valid(self):
        # don't forget to validate your fields if need be here

As usual the docs are pretty helpful. https://docs.djangoproject.com/en/1.7/topics/forms/

像往常一样,文档非常有用。 https://docs.djangoproject.com/en/1.7/topics/forms/