简体   繁体   中英

Django user accounts: creating view from model

I'm trying to implement user accounts for a Django app I'm working on. I am currently able to create user accounts as an admin, but I would like to have a form so that users can create an account for themselves. I do actually have a form view to attempt to do this, but when I hit submit the data doesn't write to the database. I get something like "[09/May/2015 20:41:00] "POST /createuser/ HTTP/1.1" 200 3175" ... which seems like it should be posting.

I'm in Django 1.7.6. I'm basing my work off of this blog.

My question : Why does my data not write to the database when I attempt to make a user account from the public view?

Here are the relevant pieces:

models.py
    class AuthUserManager(BaseUserManager):
    def create_user(self, username, email, password=None):
        if not email:
            raise ValueError('Users must have an email address')
        if not username:
            raise ValueError('Users must have a username')

        user = self.model(username=username, email=self.normalize_email(email),
                          )
        user.is_active = True
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, email, password):
        user = self.create_user(username=username, email=email, password=password)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class AuthUser(AbstractBaseUser, PermissionsMixin):
    alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', message='Only alphanumeric characters are allowed.')

    ### Redefine the basic fields that would normally be defined in User ###
    username = models.CharField(unique=True, max_length=20, validators=[alphanumeric])
    email = models.EmailField(verbose_name='email address', unique=True, max_length=255)
    first_name = models.CharField(max_length=30, null=True, blank=True)
    last_name = models.CharField(max_length=50, null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    is_active = models.BooleanField(default=True, null=False)
    is_staff = models.BooleanField(default=False, null=False)

    ### Our own fields ###
    profile_image = models.ImageField(upload_to="uploads", blank=False, null=False, default="/static/images/defaultuserimage.png")
    user_bio = models.CharField(max_length=600, blank=True)

    objects = AuthUserManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    def get_full_name(self):
        fullname = self.first_name+" "+self.last_name
        return fullname

    def get_short_name(self):
        return self.username

    def __unicode__(self):
        return self.email


forms.py
class AuthUserForm(UserCreationForm):
    class Meta:
        model = AuthUser
        fields = ['username', 'email', 'first_name', 'last_name', \
              'password','user_bio']



views.py
def AuthUserView(request):
    if request.method == 'POST':
        form = AuthUserForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            email = form.cleaned_data['email']
            first_name = form.cleaned_data['first_name']
            last_name = form.cleaned_data['last_name']
            password1 = form.cleaned_data['password1']
            password2 = form.cleaned_data['password2']
            user_bio = form.cleaned_data['user_bio']

            authuser_obj = AuthUser(username = username,
                                    email = email,
                                    first_name = first_name,
                                    last_name = last_name,
                                    password1 = password1,
                                    password2 = password2,
                                    user_bio = user_bio
                                    )
            authuser_obj.save()
            return render_to_response('recipes/name.html', RequestContext(request))
    else:
        form = AuthUserForm()
    return render(request, 'recipes/name.html',
                  {'form' : form})




name.html
<form action="/createuser/" method="post">
      {% csrf_token %}

<h2>Create your account here!</h2>

<div class="form-group">
    <div class="col-sm-8">

        <label for="first_name" class="col-sm-6">First Name</label>
        <input type="text"  class="form-control" name="first_name" id="first_name"
               placeholder="First Name">
    </br>
        <label for="last_name" class="col-sm-6">Last Name</label>
        <input type="text"  class="form-control" name="last_name" id="last_name"
               placeholder="Last Name">

    </br>
        <label for="username" class="col-sm-6">Username</label>
        <input type="text"  class="form-control" name="username" id="username"
               placeholder="User Name">
    </br>
        <label for="email" class="col-sm-6">Email</label>
        <input type="text"  class="form-control" name="email" id="email"
               placeholder="Email">
    </br>
        <label for="password1" class="col-sm-6">Password</label>
        <input type="text"  class="form-control" name="password1" id="password1"
               placeholder="Keep it to just numbers and letters">
    </br>
        <label for="password2" class="col-sm-6">Enter your password again</label>
        <input type="text"  class="form-control" name="password2" id="password2"
               placeholder="Just to double check">
    </br>
        <label for="user_bio" class="col-sm-6">Care to share a bio?</label>
        <input type="text"  class="form-control" name="user_bio" id="user_bio"
               placeholder="Write a bit about yourself!">
    </br>
    <div class="col-sm-offset-3 col-sm-1">
        <button type="submit" class="btn btn-warning" name="submit" id="submit">Submit</button>
    </div>

</div>
    <a><img src="/static/recipes/images/beet4flipped.png" align="right" ></a>

    </div>

</div>


</form>

As I stated in the comment, your form is not valid, so the form save is never reached. But in your template you have avoided all the things Django gives you to show errors and redisplay values when the form is not valid, so you have no way of seeing that. Instead of writing the fields as raw HTML, you should use the Django variables:

<div>{{ form.non_form_errors %}</div>

<div class="form-group">
    <div class="col-sm-8">
        {{ form.first_name.label }}
        {{ form.first_name }}
        {{ form.first_name.errors }}
    </div>

    <div class="col-sm-8">
        {{ form.last_name.label }}
        {{ form.last_name }}
        {{ form.last_name.errors }}
    </div>

... and so on.

Note that your view is also over-complicated and tries to save the raw password. You should do this:

def AuthUserView(request):
    if request.method == 'POST':
        form = AuthUserForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('some-destination-url-name')
    else:
        form = AuthUserForm()
    return render(request, 'recipes/name.html', {'form' : form})

since a ModelForm takes care of creating an instance from the cleaned data anyway; and in particular the UserCreationForm you're inheriting from calls set_password on the new user to ensure the hashed password is saved.

The actual answer was that I was creating a view off of the wrong model. The actual user creation happens in admin.py, which was not shown above but inherits from AuthUser. Reference the link I provided for the entirety of the code. The template is exactly the same except I renamed it signup.html.

admin.py
class CustomUserCreationForm(UserCreationForm):
    """ A form for creating new users. Includes all the required fields, plus a repeated password. """
    password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
    password2 = forms.CharField(label='Password Confirmation', widget=forms.PasswordInput)

    class Meta(UserCreationForm.Meta):
        model = AuthUser
        fields = ('username', 'email', 'first_name', 'last_name', 'user_bio')

    def clean_username(self):
        username = self.cleaned_data["username"]

        try:
            AuthUser._default_manager.get(username=username)
        except AuthUser.DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])

    def clean_password2(self):
        #Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")

        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Passwords do not match.")
        return password2

    def save(self, commit=True):
        #Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

class CustomUserChangeForm(UserChangeForm):
    password = ReadOnlyPasswordHashField(label="password",
                                         help_text="""Raw passwords are not stored, so there is no way to see this
                                         user's password, but you can change the password using <a href=\"password/\">
                                         this form</a>.""")

    class Meta(UserChangeForm.Meta):
        model = AuthUser
        fields = ('username', 'email', 'password', 'is_active', 'is_staff', 'is_superuser', 'user_permissions')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]


views.py
def CustomUserCreationView(request):
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect("/recipes/")
    else:
        form = CustomUserCreationForm()
    return render(request, 'recipes/signup.html',
                  {'form' : form})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM