保存扩展用户模型的问题
Posted
技术标签:
【中文标题】保存扩展用户模型的问题【英文标题】:Issue with saving extended User model 【发布时间】:2012-09-06 20:39:15 【问题描述】:在用户向 Django-Register 注册后,我在提交创建从 auth.User 扩展的用户配置文件的表单时遇到问题。
我从模板中的一串代码中得到错误:Please correct the following fields:
:
% if form.errors %<p>Please correct the following fields:</p>% endif %
告诉我表单中是否有错误,其余的表单模板如下所示:
<div class='register_div'>
% if form.first_name.errors %
<p class='error'> form.first_name.errors </p>
% endif %
<p>
<label for='first_name'% if form.first_name.errors %class='error'% endif %>
First Name:
</label>
</p>
<p> form.first_name </p>
</div>
我的模型.py
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
role = models.CharField(max_length=14, choices=role, verbose_name='Role', blank=True, null=True)
job_description = models.TextField(max_length=100, verbose_name='Job Description', blank=True)
# Basic Information
first_name = models.CharField(max_length=30, verbose_name='First Name')
last_name = models.CharField(max_length=30, verbose_name='Last Name')
dob = models.DateField(verbose_name='Date of Birth')
stud_id = models.BigIntegerField(verbose_name='Student ID',)
mob_num = models.CharField(max_length=30, verbose_name='Mobile Number')
home_num = models.CharField(max_length=30, verbose_name='Home Number')
term_add = models.TextField(verbose_name='Term Time Address')
perm_add = models.TextField(verbose_name='Permanent Address')
au_status = models.NullBooleanField(verbose_name='Are you a member of the AU?')
# Next of Kin Details
nok_first_name = models.CharField(max_length=30, verbose_name='First Name (Next of Kin) ')
nok_last_name = models.CharField(max_length=30, verbose_name='Last Name (Next of Kin)')
relationship = models.CharField(max_length=30, verbose_name='Relationship (with Next of Kin)')
nok_mob_num = models.CharField(max_length=30, verbose_name='Mobile Number (Next of Kin)')
nok_home_num = models.CharField(max_length=30, verbose_name='Home Number (Next of Kin)')
nok_add = models.TextField(verbose_name='Address (Next of Kin)')
# Health and Safety
diet = models.TextField(verbose_name='Dietary Requirements', blank=True)
med_cond = models.TextField(verbose_name='Medical Conditions', blank=True)
fear = models.TextField(verbose_name='Greatest Fears', blank=True)
swim = models.NullBooleanField(verbose_name='Can you swim more than 100m?')
# Equipment:
sleeping_bag = models.NullBooleanField(verbose_name='Do you have a warm sleeping bag')
waterproof = models.NullBooleanField(verbose_name='Do you have waterproof clothing?')
shoes = models.NullBooleanField(verbose_name='Do you have a pair of climbing shoes?')
shoe_size = models.DecimalField(verbose_name='What is your athletic shoe size (in UK sizes)?', max_digits=3, decimal_places=1, blank=True, null=True)
harness = models.NullBooleanField(verbose_name='Do you have a harness?')
belay_device = models.NullBooleanField(verbose_name='Do you have a belay plate and a screwgate?')
helmet = models.NullBooleanField(verbose_name='Do you have a helmet?')
nut = models.NullBooleanField(verbose_name='Do you have a set of nuts?')
hex = models.NullBooleanField(verbose_name='Do you have a set of hexes?')
# Misc.:
minibus = models.NullBooleanField(verbose_name='Can you drive the SU minibus?')
我的表单.py
class RegistrationForm(ModelForm):
# Basic Information
first_name = forms.RegexField(label='First Name', regex=r'^[A-Z][a-zA-Z\s]+$',
error_messages = 'invalid': "A name starts with a capital letter,
and may contain only alphabetical characters.")
last_name = forms.RegexField(label='Last Name', regex=r'^[A-Z][a-zA-Z\s]+$',
error_messages = 'invalid': "A name starts with a capital letter,
and may contain only alphabetical characters." )
# Details
au_status = forms.TypedChoiceField(label='Are you a member of the AU?', required=False, choices=choices, coerce=int)
# Next of Kin Details
nok_first_name = forms.RegexField(label='First Name (Next of Kin)', regex=r'^[A-Z][a-zA-Z\s]+$',
error_messages = 'invalid': "A name starts with a capital letter,
and may contain only alphabetical characters.")
nok_last_name = forms.RegexField(label='Last Name (Next of Kin)',
regex=r'^[A-Z][a-zA-Z\s]+$',
error_messages = 'invalid': "A name starts with a capital
letter, and may contain only alphabetical characters.")
# Health and Safety
swim = forms.TypedChoiceField(label='Can you swim more than 100m?',
required=False, choices=choices, coerce=int)
# Equipment:
sleeping_bag = forms.TypedChoiceField(label='Do you have a warm sleeping bag', required=False, choices=choices, coerce=int)
waterproof = forms.TypedChoiceField(label='Do you have waterproof clothing?', required=False, choices=choices, coerce=int)
shoes = forms.TypedChoiceField(label='Do you have a pair of climbing shoes?', required=False, choices=choices, coerce=int)
harness = forms.TypedChoiceField(label='Do you have a harness?', required=False, choices=choices, coerce=int)
belay_device = forms.TypedChoiceField(label='Do you have a belay plate and a screwgate?', required=False, choices=choices, coerce=int)
helmet = forms.TypedChoiceField(label='Do you have a helmet?', required=False, choices=choices, coerce=int)
nut = forms.TypedChoiceField(label='Do you have a set of nuts?', required=False, choices=choices, coerce=int)
hex = forms.TypedChoiceField(label='Do you have a set of hexes?', required=False, choices=choices, coerce=int)
# Misc.:
minibus = forms.TypedChoiceField(label='Can you drive the SU minibus?', required=False, choices=choices, coerce=int)
class Meta:
model = UserProfile
我的意见.py
def MemberRegistration(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/accounts/login/')
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.get(username=request.user)
profile = UserProfile(user=user)
profile.first_name = form.cleaned_data['first_name']
profile.last_name = form.cleaned_data['last_name']
profile.dob = form.cleaned_data['dob']
profile.stud_id = form.cleaned_data['stud_id']
profile.mob_num = form.cleaned_data['mob_num']
profile.home_num = form.cleaned_data['home_num']
profile.term_add = form.cleaned_data['term_add']
profile.perm_add = form.cleaned_data['perm_add']
profile.au_status = form.cleaned_data['au_status']
profile.nok_first_name = form.cleaned_data['nok_first_name']
profile.nok_last_name = form.cleaned_data['nok_last_name']
profile.relationship = form.clenaed_data['relationship']
profile.nok_mob_num = form.cleaned_data['nok_mob_num']
profile.nok_home_num = form.cleaned_data['nok_home_num']
profile.nok_add = form.cleaned_data['nok_add']
profile.diet = form.cleaned_data['diet']
profile.med_cond = form.cleaned_data['med_cond']
profile.fear = form.cleaned_data['fear']
profile.swim = form.cleaned_data['swim']
profile.sleeping_bag = form.cleaned_data['sleeping_bag']
profile.waterproof = form.cleaned_data['waterproof']
profile.shoes = form.cleaned_data['shoes']
profile.shoe_size = form.cleaned_data['shoe_size']
profile.harness = form.cleaned_data['harness']
profile.belay_device = form.cleaned_data['belay_device']
profile.helmet = form.cleaned_data['helmet']
profile.nut = form.cleaned_data['nut']
profile.hex = form.cleaned_data['hex']
profile.minibus = form.cleaned_data['minibus']
profile.save()
return render_to_response('base_profile.html', context_instance=RequestContext(request))
else:
return render_to_response('base_registration.html', 'form': form, context_instance=RequestContext(request))
else:
form = RegistrationForm()
context = 'form': form
return render_to_response('base_registration.html', context, context_instance=RequestContext(request))`
非常感谢任何帮助!如果有人能告诉我如何减少代码以及我发现过多的代码,那就太好了。感谢您的所有帮助:)
更新:
我知道错误是什么! Refer to this!我没有填写模型的用户字段。谁能帮我解决这个问题并减少我使用的代码量?
更新 2:
表单现在通过了,但总是有错误。
当我使用此版本的views.py 时,profile.save()
行得到IntegrityError at /register/ - accounts_userprofile.first_name may not be NULL
`if form.is_valid():
user = User.objects.get(username=request.user)
user.first_name = form.cleaned_data['first_name']
user.last_name = form.cleaned_data['last_name']
user.save()
profile = UserProfile(user=user,
dob = form.cleaned_data['dob'],
stud_id = form.cleaned_data['stud_id'],
mob_num = form.cleaned_data['mob_num'],
home_num = form.cleaned_data['home_num'],
term_add = form.cleaned_data['term_add'],
perm_add = form.cleaned_data['perm_add'],
au_status = form.cleaned_data['au_status'],
nok_first_name = form.cleaned_data['nok_first_name'],
nok_last_name = form.cleaned_data['nok_last_name'],
relationship = form.cleaned_data['relationship'],
nok_mob_num = form.cleaned_data['nok_mob_num'],
nok_home_num = form.cleaned_data['nok_home_num'],
nok_add = form.cleaned_data['nok_add'],
diet = form.cleaned_data['diet'],
med_cond = form.cleaned_data['med_cond'],
fear = form.cleaned_data['fear'],
swim = form.cleaned_data['swim'],
sleeping_bag = form.cleaned_data['sleeping_bag'],
waterproof = form.cleaned_data['waterproof'],
shoes = form.cleaned_data['shoes'],
shoe_size = form.cleaned_data['shoe_size'],
harness = form.cleaned_data['harness'],
belay_device = form.cleaned_data['belay_device'],
helmet = form.cleaned_data['helmet'],
nut = form.cleaned_data['nut'],
hex = form.cleaned_data['hex'],
minibus = form.cleaned_data['minibus'],
)
profile.save()`
如果我改用这个版本的views.py:
if form.is_valid():
profile = User.objects.get(username=request.user)
for key in UserProfileForm.base_fields.keys():
for val in form.cleaned_data.values():
setattr(profile, key, val)
profile.save()
return render_to_response('base_profile.html', context_instance=RequestContext(request))`
我被传递到 base_profile.html,只有 first_name 和 last_name 填充了 term_add/perm_add/nok_add/diet/med_cond/fears 字段。任何人都可以帮忙吗?对不起,我是个菜鸟>.
用于一次注册用户和用户配置文件的旧views.py 看起来像这样:
def MemberRegistration(request):
if request.user.is_authenticated():
return render_to_response('base_profile.html', context_instance=RequestContext(request))
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(username = form.cleaned_data['username'],
email = form.cleaned_data['email'],
password = form.cleaned_data['password'],
)
user.first_name = form.cleaned_data['first_name']
user.last_name = form.cleaned_data['last_name']
member = user.save()
member = Member(user=user, first_name = form.cleaned_data['first_name'],
last_name = form.cleaned_data['last_name'],
date_of_birth = form.cleaned_data['date_of_birth'],
email = form.cleaned_data['email'],
student_id = form.cleaned_data['student_id'],
au_status = form.cleaned_data['au_status'],
mob_num = form.cleaned_data['mob_num'],
home_num = form.cleaned_data['home_num'],
term_time_add = form.cleaned_data['term_time_add'],
permanent_add = form.cleaned_data['permanent_add'],
diet = form.cleaned_data['diet'],
med_condition = form.cleaned_data['med_condition'],
fear = form.cleaned_data['fear'],
swim = form.cleaned_data['swim'],
sleeping_bag = form.cleaned_data['sleeping_bag'],
waterproof = form.cleaned_data['waterproof'],
shoes = form.cleaned_data['shoes'],
shoe_size = form.cleaned_data['shoe_size'],
harness = form.cleaned_data['harness'],
belay_device = form.cleaned_data['belay_device'],
helmet = form.cleaned_data['helmet'],
nuts_set = form.cleaned_data['nuts_set'],
hexes_set = form.cleaned_data['hexes_set'],
minibus_driver = form.cleaned_data['minibus_driver'],
)
member.save()
return render_to_response('base_profile.html', context_instance=RequestContext(request))
else:
return render_to_response('base_registration.html', 'form': form, context_instance=RequestContext(request))
else:
form = RegistrationForm()
context = 'form': form
return render_to_response('base_registration.html', context, context_instance=RequestContext(request))
【问题讨论】:
'request.user' 中已经有用户了,为什么还要再找呢? 【参考方案1】:对于视图,您可以通过以下方式减少它:
if form.is_valid():
profile = UserProfile(user=request.user) # you already have the user in the request.
for key, val in form.cleaned_data.values():
setattr(profile, key, val)
profile.save()
在这里,您正在遍历字典并将所有键和值设置为配置文件对象。请检查是否需要所有密钥,如果不需要,您将不得不以某种方式删除它们或尝试不同的方法,例如:
my_keys = ('key1', 'key2', 'key3', ...)
for key in my_keys:
profile[key] = form.cleaned_data.get(key, "")
profile.save()
你也应该使用模型形式:
class RegistrationForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ('user',)
此外,来自 django 的用户模型已经有一个 first_name、last_name 字段,因此您无需再次添加这些字段。
我可以看到你的模型上也有很多字段,我建议你创建一个这样的模型:
class UserDetails(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=255)
value = models.CharField(max_length=255)
通过这种方式,您可以以更灵活的方式保存所有详细信息和更多信息,而不是为用户提供大量字段。你可以让它变得更有趣,并添加一个类型和一个函数来转换它(例如,如果你需要将值设为整数)。
因此,例如,您可以这样做:
for key, value in form.cleaned_data.values():
UserDetails(user=request.user, name=key, value=value).save()
然后访问任何:
print request.user.user_details_set.all()
它应该打印所有这些细节。我可以从这种方法中看到的唯一不好的事情是ModelForms
不会那么容易工作,但我向你保证迁移会更加零星:)
【讨论】:
问题是我之前已经创建了用户,我不应该让他/她再次输入用户名等。有什么解决方法吗? 好的,刚刚更新了答案,问题是你正在做一个错误的查询来获取@möter 所说的用户 我还需要在表单中添加用户字段吗? 我仍然收到同样的错误,提示用户字段是必需的>。 哦,您应该在那里使用模型表单,您需要从元数据中排除该字段。刚刚更新以上是关于保存扩展用户模型的问题的主要内容,如果未能解决你的问题,请参考以下文章
保存自定义用户模型时 Django ManyToMany 覆盖
如何在将密码保存到用户模型 Django 之前对其进行加密?
使用覆盖保存为抽象模型扩展 Django ModelForm