实战Django:Rango Part4

 

在这个部分,我们将要开始学习如何设计用户系统,Django提供了一个叫“django.contrib.auth”的应用,我们可以用它来做出用户注册、登录、注销等一系列功能。

17.用户模型


在Django自带的用户系统中,用户模型里已经包含了如下数据:

  • 用户名
  • 密码
  • 电子邮箱
  • 姓名

我们想在用户模型中增加一些额外的字段,如:

  • 链接字段:允许用户展示他们自己的个人网站
  • 图片字段:让用户可以给自己设置一个头像

我们只要更新模型就可以实现上述的需求,编辑rango/models.py文件,先在头部加入一行:

rango/models.py:

from django.contrib.auth.models import User
然后在文件尾部加入如下内容:

rango/models.py:

class UserProfile(models.Model):
    # 这一句是必须的,链接UserProfile到Django的用户模型
    user = models.OneToOneField(User)

    # 我们想要增加的额外字段
    website = models.URLField(blank=True)
    picture = models.ImageField(upload_to='profile_images', blank=True)

    # 重写__str__方法,让它在被调用时显示用户名
    def __str__(self):
        return self.user.username

在这两个字段中,我们设置了“blank=True”,正如字面意思显示,这是允许该字段为空的节奏。

注意在“ImageField”字段中有一个“upload_to”属性,它指定了储存用户头像的文件夹,这个叫“profile_images”的文件夹将放在settings.py中指定的MEDIA_ROOT文件夹下,换句话说,它的路径将是:

rangoproject/media/profile_images/

模型做好后,我们需要更新一下数据库,然后在dos命令提示符下运行如下命令:

$ python manage.py makemigrations rango

继续在dos命令提示符下运行命令:

$ python manage.py migrate

 

18.安装PIL

Django的ImageField使用Python的图像库PIL,如果你没有安装PIL,那么需要先安装它。

在Windows平台的Python 3.2环境下,舍得推荐安装这个版本:

https://pypi.python.org/pypi/Pillow/2.6.0

找到其中的Pillow-2.6.0.win32-py3.2.exe (md5) ,下载下来之后,直接安装就可以了。注意,这是适用于Python 32位的版本。

 

19.在管理界面注册UserProfile

编辑rango/admin.py 文件,让它变成下面这个样子:

rango/admin.py

from django.contrib import admin
from rango.models import Category, Page
from rango.models import UserProfile

class PageAdmin(admin.ModelAdmin):
    list_display = ('title', 'category', 'url')

class CategoryAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug':('name',)}

admin.site.register(Category, CategoryAdmin)
admin.site.register(Page, PageAdmin)
admin.site.register(UserProfile)

 

20.创建用户注册视图和模板

“用户注册”功能将允许用户在我们的网站上创建账号,我们需要为这个功能添加视图和相应的模板。下面是要完成的工作:

  • 创建UserForm和UserProfileForm两个表单;
  • 添加视图,负责处理新建用户;
  • 创建模板,用来显示UserForm和UserProfileForm这俩表单;
  • 将URL映射到上面创建的视图;
  • 在首页中加入注册页面的链接;

让我们一步步来实现这些内容吧!编辑rango/forms.py 文件,让它变成下面这个样子:

rango/forms.py

class UserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = User
        fields = ('username', 'email', 'password')

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('website', 'picture')

 

你会发现我们在UserForm和UserProfileForm这俩表单中加入了两个Meta类,每个Meta类都带有一个model字段,它会告诉程序这个表单将要关联到数据库中的哪个表,比如UserForm关联到的是User表。

最后,别忘了将forms.py头部改成下面这样:

rango/forms.py

from django import forms
from django.contrib.auth.models import User
from rango.models import Category, Page, UserProfile

搞完上面这些,让我们来创建用户注册视图。

编辑rango/views.py,添加以下内容:

rango/views.py(注意将第一行代码放到文件头部)

from rango.forms import UserForm, UserProfileForm

def register(request):

    # registered:注册成功与否的信号.
    # 先默认为False,等注册成功后程序会将其改为True
    registered = False

    # 如果是一个HTTP POST请求, 就意味着将要处理表单数据.
    if request.method == 'POST':
        # 尝试从提交的信息中获取数据。
        # 注意UserForm和UserProfileForm都会用到这些数据.
        user_form = UserForm(data=request.POST)
        profile_form = UserProfileForm(data=request.POST)

        # 如果表单有效...
        if user_form.is_valid() and profile_form.is_valid():
            # 将用户表单数据储存到数据库.
            user = user_form.save()

            # 用set_password方法处理密码.
            # 然后储存用户数据.
            user.set_password(user.password)
            user.save()

            # 现在来处理UserProfile表单.
            # 先设置commit为False.
            # 这个信号用来延迟数据储存动作,直至我们将数据准备好。
            profile.user = user

            # 用户是否提供图片(头像)?
            # 如果有,则要将其储存进数据库.
            if 'picture' in request.FILES:
                profile.picture = request.FILES['picture']

            #储存UserProfile数据.
            profile.save()

            # 更新registered信号,将其改为True,此信号将通知模板系统用户已完成注册.
            registered = True

        # 表单无效或出错
        # 将故障代码显示给终端及用户.
        else:
            print(user_form.errors, profile_form.errors)

    # 非HTTP POST请求, 那我们就仅仅渲染一下两个空白表单,以供用户输入.
    else:
        user_form = UserForm()
        profile_form = UserProfileForm()

    # 根据内容渲染模板.
    return render(request,
            'rango/register.html',
            {'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )

接下来创建注册模板,创建templates/rango/register.html,加入如下内容:

templates/rango/register.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Rango</title>
    </head>

    <body>
        <h1>注册Rango</h1>

        {% if registered %}
        Rango说: <strong>非常感谢您的注册!</strong>
        <a href="/rango/">返回到首页.</a><br />
        {% else %}
        Rango说: <strong>注册请点这里!</strong><br />

        <form id="user_form" method="post" action="/rango/register/"
                enctype="multipart/form-data">

            {% csrf_token %}

            <!-- 显示每个表单,as_p方法会将每个元素处理为段落。这样可确保每个元素显示为一个新行,看起来很整洁]-->
            {{ user_form.as_p }}
            {{ profile_form.as_p }}

            <!-- 提供一个可点击的按钮,用来提交表单. -->
            <input type="submit" name="submit" value="注册" />
        </form>
        {% endif %}
    </body>
</html>

视图和模板都好了,下面我们该处理URL映射,将它们都连到一起。编辑rango/urls.py,改成下面这样:

rango/urls.py:

urlpatterns = patterns('',
    url(r'^$', views.index, name='index'),
    url(r'^about/$', views.about, name='about'),
    url(r'^category/(?P<category_name_slug>\w+)$', views.category, name='category'),
    url(r'^add_category/$', views.add_category, name='add_category'),
    url(r'^category/(?P<category_name_slug>\w+)/add_page/$', views.add_page, name='add_page'),
    url(r'^register/$', views.register, name='register'), # 新增内容在这里!
    )

最后,我们要修改首页模板(templates/rango/index.html),把“注册”链接放到首页中。请在</body>标签前添加以下内容:

templates/rango/index.html:

<a href="/rango/register/">注册</a><br />

我们来看检查一下工作成果,在浏览器中输入:http://127.0.0.1:8000/rango/register,你会看到下面这样的页面:

1

 

【未完待续】

本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
作者:舍得
首发:舍得学苑@博客园

 

posted on 2015-04-30 16:15  舍得学苑  阅读(598)  评论(0编辑  收藏  举报

导航