Django用户注册AttributeError [英] Django User Registration AttributeError
问题描述
当尝试注册与django用户类具有OneToOneField关系的自定义内置用户类时,会引发异常,没有文件或行#信息。
异常值:'str'对象没有属性'get'
django错误页面指向views.py行'if form.is_valid()''虽然我不明白这是如何导致列出的例外。
我的models.py用户类:
User Model
class ShedUser(models。模型):
类名称:ShedUser
属性:
用户 - 与django的OneToOne关系用户
zipcode - 用户的Zipcode
社区 - 社区与用户的邮政编码相关
user = models.OneToOneField(User)
zipcode = models.CharField(max_length = 5)
community = mod els.ForeignKey('Community',related_name ='community')
#返回用户的用户名
def __str __(self):
return self.user.username
我的views.py UserRegistration:
code>UserRegistration
注册新用户帐户
def UserRegistration(request):
如果request.user.is_authenticated():
返回HttpResponseRedirect('/')
如果request.method =='POST':
form = UserRegistrationForm(request.POST)
如果form.is_valid():
#空启动对象
community = Community()
sheduser = ShedUser()
#完整社区列表
communities = Community.objects.all()
#新用户社区存在的布尔值
community_exists = False
#通过现有社区解析为向社区签署新用户
for社区中的current_community:
#如果新用户的邮政编码与现有的邮政编码匹配
如果current_community.zipcode == form.cleaned_data ['zipcode']:
community = current_community
community_exists = True
#如果没有社区存在此邮政编码:
如果不是community_exists:
#为新的生成一个新的stat对象社区
new_stats = Stats(user_count = 0,tool_count = 0,machinery_count = 0,electronic_count = 0,borrow_count = 0)
new_stats.save()
#创建新社区
community.zipcode = form.cleaned_data ['zipcode']
community.stats = new_stats
community.save()
#创建django用户对象
用户= User.objects.create_user(username = form.cleaned_data ['username'],email = form.cleaned_data ['email'],password = form.cleaned_data ['password'],first_name = form.cleaned_data ['first_name'] ,last_name = form.cleaned_data ['last_name'])
user.save()
#创建ShedUser对象
sheduser.user = user
sheduser.zipcode = form.cleaned_data ['zipcode']
sheduser.community = community
sheduser.community.stats.user_count + = 1
sheduser.community.save()
sheduser.save ()
return HttpResponseRedirect('/ login')
else:
返回render_to_response('register.html',{'form':form},context_instance = RequestContext ))
else:
form = UserRegistrationForm()
context = {'form :form}
return render_to_response('register.html',context,context_instance = RequestContext(request))
,最后我的forms.py:
UserRegistrationForm
class UserRegistrationForm(ModelForm )
username = forms.CharField(label =('User Name'))
email = forms.EmailField(label =('Email Address'))
password = forms.CharField( label =('Password'),widget = forms.PasswordInput(render_value = False))
password1 = forms.CharField(label =('Verify Password'),widget = forms.PasswordInput(render_value = False) b $ b first_name = forms.CharField(label =('First Name'))
last_name = forms.CharField(label =('Last Name'))
class Meta:
model = ShedUser
exclude =('user','community')
#清理用户名
def clea n_username(self):
username = self.cleaned_data ['username']
#确保用户名不存在
try:
User.objects.get(username = username)
除了User.DoesNotExist:
返回用户名
raise forms.ValidationError(该用户名已被占用)
#清理表单密码
def clean(self):
#验证密码匹配
password = self.cleaned_data ['password']
password1 = self.cleaned_data ['password1']
如果没有password1:
raise forms.ValidationError(你必须确认你的密码!)
如果password!= password1:
raise forms.ValidationError(你的密码不匹配)
返回密码1
完整追溯:
环境:
请求方法:POST
请求URL:http:// 127.0.0.1:8000/register/
Django版本:1.5.4
Python版本:3.2.3
安装的应用程序:
('django.contrib.auth ',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages'
'django.contrib.staticfiles',
'django.contrib.admin',
'models')
安装的中间件:
('django.middleware.common .CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware'
'django.contrib.messages.middleware.MessageMiddleware')
追溯:
文件C:\Python32\lib\site- packages\\ \\ django\core\handlers\base.pyin get_response
115. response = callback(request,* callback_args,** callback_kwargs)
文件C:\Tool UserRegistration
中共享\\\Code\Release-2\toolshare\models\views.py104.如果form.is_valid():
文件C:\Python32 is_valid
中的\lib\site- packages\django\forms\forms.py返回self.is_bound而不是bool(self.errors)
文件C:\ _get_errors中的Python32\lib\site-packages\django\forms\forms.py
117. self.full_clean()
文件C:\Python32\lib\在__django\forms\forms.py在full_clean
274. self._post_clean()
文件C:\Python32\lib\site-packages\django \forms\models.py在_post_clean
317. exclude = self._get_validation_exclusions()
文件C:\Python32\lib\site- packages\django\forms\\ _models.py_get_validation_exclusions
303. field_value = self.cleaned_data.get(field,None)
E xception类型:/ register中的AttributeError /
异常值:'str'对象没有属性'get'
请让我知道是否需要更多的代码,或者需要更多的信息。
你需要返回clean_data而不是password1上的表单验证。
你的清洁应该如下所示:
def clean自我):
/ pre>
#运行超级方法清理数据来验证表单(确保必填字段填写而不是超出最大镜头)
cleaning_data = super(UserRegistrationForm,self).clean()
#验证密码匹配
password = clean_data ['password']
password1 = clean_data ['password1']
如果不是password1:
#raise forms.ValidationError (你必须确认你的密码!)
#而不是提出异常,你应该在表单本身上出错。
self._errors ['password1'] = self.error_class(['你必须确认你的密码'])
如果密码!= password1:
#raise forms.ValidationError(你的密码没有匹配。)
#而不是提出异常,你应该在表单本身上出错。
self._errors ['password1'] = self.error_class(['您的密码不匹配'])
返回clean_data#返回清理数据
编辑
我还想添加,你应该绝对与模型中的表单,我知道你可以把它们捆绑在一起,但你应该把这个逻辑分开成一个单独的控制器。
您的表单验证应该非常轻巧,任何额外的验证都应该在单独的控制器中发生,这样可以使代码更加可重复使用。
还有,我不记得了,但我很积极,你的额外的清洁方法永远不会被调用。坚持在主要的
def clean
defition和单独的调用以获取对象...等到用户对象控制器。When attempting to register a custom built user class, which has a OneToOneField relationship with a django user class, an exception is raised, with no file or line # information.
Exception Value: 'str' object has no attribute 'get'
The django error page points this to the views.py line 'if form.is_valid(),' although I don't understand how this causes the exception listed.
my models.py user class:
""" User Model """ class ShedUser( models.Model ): """ Class Name: ShedUser Attributes: user - OneToOne relation with django User zipcode - User's Zipcode community - community related to user's zipcode """ user = models.OneToOneField( User ) zipcode = models.CharField( max_length = 5 ) community = models.ForeignKey( 'Community', related_name='community' ) # Returns user's username def __str__(self): return self.user.username
my views.py UserRegistration:
""" UserRegistration to Register a new User account """ def UserRegistration(request): if request.user.is_authenticated(): return HttpResponseRedirect('/') if request.method == 'POST': form = UserRegistrationForm( request.POST ) if form.is_valid(): # empty initiated objects community = Community() sheduser = ShedUser() # Full community list communities = Community.objects.all() # Boolean for new user's community existence community_exists = False # Parse through existing communities to assign new user to a community for current_community in communities: # If the new user's zipcode matches an existing zipcode if current_community.zipcode == form.cleaned_data['zipcode']: community = current_community community_exists = True # If no community exists with this zipcode: if not community_exists: # Generate a new stat object for the new community new_stats = Stats( user_count=0, tool_count=0, machinery_count=0, electronic_count=0, borrow_count=0 ) new_stats.save() # Create the new community community.zipcode = form.cleaned_data['zipcode'] community.stats = new_stats community.save() # Create the django user object user = User.objects.create_user( username = form.cleaned_data['username'], email = form.cleaned_data['email'], password = form.cleaned_data['password'], first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name']) user.save() # Create the ShedUser object sheduser.user = user sheduser.zipcode = form.cleaned_data['zipcode'] sheduser.community = community sheduser.community.stats.user_count += 1 sheduser.community.save() sheduser.save() return HttpResponseRedirect('/login') else: return render_to_response('register.html', {'form':form}, context_instance=RequestContext(request)) else: form = UserRegistrationForm() context = {'form': form} return render_to_response('register.html', context, context_instance=RequestContext(request))
and finally my forms.py :
""" UserRegistrationForm """ class UserRegistrationForm( ModelForm ): username = forms.CharField( label=('User Name')) email = forms.EmailField( label=('Email Address')) password = forms.CharField( label=('Password'), widget = forms.PasswordInput( render_value=False ) ) password1 = forms.CharField( label=('Verify Password'), widget = forms.PasswordInput( render_value=False ) ) first_name = forms.CharField( label=('First Name')) last_name = forms.CharField( label=('Last Name')) class Meta: model = ShedUser exclude = ('user', 'community') # Clean the Username def clean_username(self): username = self.cleaned_data['username'] # Ensure username doesn't exist try: User.objects.get( username=username ) except User.DoesNotExist: return username raise forms.ValidationError("That username is already taken.") # Clean the form passwords def clean(self): # verify passwords match password = self.cleaned_data['password'] password1 = self.cleaned_data['password1'] if not password1: raise forms.ValidationError("You must confirm your password!") if password != password1: raise forms.ValidationError("Your passwords did not match.") return password1
Full traceback:
Environment: Request Method: POST Request URL: http://127.0.0.1:8000/register/ Django Version: 1.5.4 Python Version: 3.2.3 Installed Applications: ('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', 'models') Installed Middleware: ('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware') Traceback: File "C:\Python32\lib\site-packages\django\core\handlers\base.py" in get_response 115. response = callback(request, *callback_args, **callback_kwargs) File "C:\ToolShare\R2\Code\Release-2\toolshare\models\views.py" in UserRegistration 104. if form.is_valid(): File "C:\Python32\lib\site-packages\django\forms\forms.py" in is_valid 126. return self.is_bound and not bool(self.errors) File "C:\Python32\lib\site-packages\django\forms\forms.py" in _get_errors 117. self.full_clean() File "C:\Python32\lib\site-packages\django\forms\forms.py" in full_clean 274. self._post_clean() File "C:\Python32\lib\site-packages\django\forms\models.py" in _post_clean 317. exclude = self._get_validation_exclusions() File "C:\Python32\lib\site-packages\django\forms\models.py" in _get_validation_exclusions 303. field_value = self.cleaned_data.get(field, None) Exception Type: AttributeError at /register/ Exception Value: 'str' object has no attribute 'get'
Please let me know whether more code is required, or you need any more information.
解决方案you need to return the cleaned_data and not the password1 on the form validation.
your clean should look like the following:
def clean(self): # Runs the super methods clean data to validate the form (ensure required fields are filled out and not beyond max lens) cleaned_data = super(UserRegistrationForm, self).clean() # verify passwords match password = cleaned_data['password'] password1 = cleaned_data['password1'] if not password1: # raise forms.ValidationError("You must confirm your password!") # instead of raising exceptions you should put an error on the form itself. self._errors['password1'] = self.error_class(['you must confirm your password']) if password != password1: # raise forms.ValidationError("Your passwords did not match.") # instead of raising exceptions you should put an error on the form itself. self._errors['password1'] = self.error_class(['Your passwords did not match']) return cleaned_data # return that cleaned data
EDIT
I also want to add, you should absolutely de-couple the form from the models, i know you can tie them in together as you have, but you should separate that logic out into a separate controller.
Your form validations should be pretty lightweight, any additional validations should happen in a separate controller - it makes the code much more re-usable.
also, i can't remember, but i'm positive your additional clean method will never be called. Stick that in the main
def clean
defition and separate calls out to obtain objects...etc into a User object controller.这篇关于Django用户注册AttributeError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!