且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Django用户注册AttributeError

更新时间:2023-12-02 09:46:34

你需要返回clean_data而不是password1上的表单验证。



你的清洁应该如下所示:

  def clean自我):
#运行超级方法清理数据来验证表单(确保必填字段填写而不是超出最大镜头)
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#返回清理数据
/ pre>

编辑



我还想添加,你应该绝对与模型中的表单,我知道你可以把它们捆绑在一起,但你应该把这个逻辑分开成一个单独的控制器。



您的表单验证应该非常轻巧,任何额外的验证都应该在单独的控制器中发生,这样可以使代码更加可重复使用。



还有,我不记得了,但我很积极,你的额外的清洁方法永远不会被调用。坚持在主要的 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.