假设我使用的是默认auth.models.User
以及我的自定义Profile
和Address
模型,如下所示:
class Profile(models.Model):
user = models.OneToOneField(User)
primary_phone = models.CharField(max_length=20)
address = models.ForeignKey("Address")
class Address(models.Model):
country = CountryField(default='CA')
province = CAProvinceField(default='BC')
city = models.CharField(max_length=80)
postal_code = models.CharField(max_length=6)
street1 = models.CharField(max_length=80)
street2 = models.CharField(max_length=80, blank=True, null=True)
street3 = models.CharField(max_length=80, blank=True, null=True)
现在我想创建一个注册表单。我可以根据ModelForm
创建User
,但不会包含Profile
和Address
的字段(这是必需的)。那么建立这种形式的最佳方式是什么?我应该甚至使用ModelForm
吗?
此外,我如何使用相同的表单编辑复杂对象?我可以轻松地将一个Profile实例传回给它,它保存对必要的Address和Profile对象的引用,但是如何让它为我填写字段?
答案 0 :(得分:8)
如何使用3个单独的ModelForm
。一个用于Address
,一个用于User
,一个用于Profile
,但有:{/ p>
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ('user', 'address',)
然后,在您的视图中分别处理这3个表单。具体而言,ProfileForm
使用save
commit=False
更新实例上的user
和address
字段:
# ...
profile_form = ProfileForm(request.POST)
if profile_form.is_valid():
profile = profile_form.save(commit=False)
# `user` and `address` have been created previously
# by saving the other forms
profile.user = user
profile.address = address
请不要犹豫,在此处使用交易,以确保只有在3个表单有效时才会插入行。
答案 1 :(得分:3)
您应该首先考虑官方推荐的扩展用户模型的方式as seen in the docs,我认为这直接来自项目经理的个人博客about the subject。 (实际的博客文章相当陈旧,现在)
至于您对表单的实际问题,请查看项目经理自己的可重用 django-profiles 应用,看看是否仔细阅读代码可以解决您的问题。特别是使用它们的these functions和the views。
编辑添加:
我已经对它进行了一些调查(因为我需要自己这样做)。似乎这样就足够了:
# apps.profiles.models
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
...
birth_date = models.DateField(blank=True, null=True)
joined = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'user profile'
verbose_name_plural = 'user profiles'
db_table = 'user_profiles'
class Address(models.Model):
user = models.ForeignKey(UserProfile)
...
# apps.profiles.forms
from django import forms
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from django.contrib.auth.models import User
from apps.profiles.models import UserProfile, Address
class UserForm(ModelForm):
class Meta:
model = User
...
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
...
AddressFormSet = inlineformset_factory(UserProfile, Address)
我使用“...”来剪切上面代码中的内容。我还没有对此进行测试,但是通过查看示例和表单上的文档,我认为这是正确的。
注意我将FK从Address模型放到UserProfile而不是相反,就像你的问题一样。我相信内联表单集需要它才能正常工作。
然后当然在您的视图和模板中,您将最终单独处理UserForm,UserProfileForm和AddressFormSet,但它们都可以插入到同一个表单中。
答案 2 :(得分:1)
我认为您正在寻找带有模型表单的inline formsets。这有助于您在一个页面上处理多个表单,并且还可以处理外键关系。
<强>更新强>
也许这个问题对你有帮助:Django: multiple models in one template using forms