实战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,你会看到下面这样的页面:
【未完待续】
本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
作者:舍得
首发:舍得学苑@博客园