Django用户帐户:从模型创建视图

时间:2015-05-09 20:35:21

标签: python django

我正在尝试为我正在处理的Django应用实施用户帐户。我目前能够以管理员身份创建用户帐户,但我希望有一个表单,以便用户可以为自己创建一个帐户。我确实有一个表单视图来尝试这样做,但是当我点击提交时,数据不会写入数据库。我得到类似"[09/May/2015 20:41:00] "POST /createuser/ HTTP/1.1" 200 3175"的东西......似乎应该发布。

我在Django 1.7.6中。我的工作基于this博客。

我的问题:当我尝试从公共视图创建用户帐户时,为什么我的数据不会写入数据库?

以下是相关部分:

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>

2 个答案:

答案 0 :(得分:0)

正如我在评论中所说,您的表单无效,因此永远不会达到表单保存。但是在你的模板中,你已经避免了当表单无效时Django给你显示错误和重新显示值的所有东西,所以你无法看到它。您应该使用Django变量:

,而不是将字段写为原始HTML
<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>

......等等。

请注意,您的视图也过于复杂,并尝试保存原始密码。你应该这样做:

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})

因为ModelForm无论如何都要从清理过的数据中创建一个实例;特别是UserCreationForm您从新用户的呼叫set_password继承,以确保保存散列密码。

答案 1 :(得分:0)

实际答案是我正在创建一个错误模型的视图。实际的用户创建发生在admin.py中,上面没有显示,但是从AuthUser继承。参考我为整个代码提供的链接。模板完全相同,除了我将其重命名为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})