Django 已经为我们写好了登录功能的全部代码。
我们不必像之前处理注册流程那样费劲了。
只需几分钟的简单配置,就可为用户提供登录功能。
引入内置的 URL 模型
Django 内置的登录、修改密码、找回密码等视图函数对应的 URL 模式位于django.contrib.auth.urls.py 中。首先在工程的 urls.py 文件里包含这些 URL 模式。 url(r'^users/', include('django.contrib.auth.urls')),
设置模板路径
默认的登录视图函数渲染的是 registration/login.html 模板。因此需要在 templates/ 目录下新建一个 registration 文件夹。再在 registration/ 目录下新建 login.html 模板文件。
编写登录模板
登录模板的代码和注册模板的代码十分类似。已提供模板。关注表单部分的代码:
<form class="form" action="{% url 'login' %}" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{{ field.errors }}
{% if field.help_text %}
<p class="help text-small text-muted">{{ field.help_text|safe }}</p>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary btn-block">登录</button>
</form>需要特别说明的是{{ form.non_field_errors }}。
这显示的同样是表单错误,但是显示的表单错误是和具体的某个表单字段无关的。
相对 {{ field.errors }}显示的是具体某个字段的错误。
比如对于字段 username,如果用户输入的 username 不
符合要求,比如太长了或者太短了,表单会在 username
下方渲染这个错误。
但有些表单错误不和任何具体的字段相关,比如用户输入的
用户名和密码无法通过验证,这可能是用户输入的用户名不
存在,也可能是用户输入的密码错误,因此这个错误信息将
通过 {{ form.non_field_errors }} 渲染。
设置登录登出的跳转 URL
在settings中设置以下参数:
LOGOUT_REDIRECT_URL = '/blog/index/'
LOGIN_REDIRECT_URL = '/blog/index/'
表示登录后跳转到index页面。
页面跳转
对于一个网站来说,比较好的用户体验是登录、注册和注销后跳转回用户之前访问的页面。
在登录和注销的视图函数中,Django 已经为我们处理了跳转回用户之前访问页面的流程。
其实现的原理是,在登录和注销的流程中,始终传递一个 next 参数记录用户之前访问页面的 URL。
我们需要做的就是在用户访问登录或者注销的页面时,在 URL 中传递一个 next 参数给视图函数,具体做法如下:
<button class="btn btn-default">
<a href="{% url 'logout' %}?next={{ request.path }}">注销登录</a>
</button>
<button class="btn btn-default">
<a href="{% url 'login' %}?next={{ request.path }}">登录</a>
</button>
可以看到,我们在登录和注销的 URL 后加了 next 参数,其值为 {{ request.path }}。request.path 是用户当前访问页面的 URL。
为了在整个登录流程中记录 next 的值,还需要在登录表单中增加一个表单控件,用于传递 next 值。
registration/login.html<form class="form" action="{% url 'login' %}" method="post">
...
<button type="submit" class="btn btn-primary btn-block">登录</button>
<input type="hidden" name="next" value="{{ next }}"/>
</form>
即在表单中增加了一个隐藏的 input 控件,其值为 {{ next }},即之前通过 URL 参数传递给登录视图函数的,然后登录视图函数又将该值传递给了 login.html 模板。
这样在整个登录流程中,始终有一个记录着用户在登录前页面 URL 的变量 next 在视图和模板间来回传递,直到用户登录成功后再跳转回 next 记录的页面。
类似的,我们也希望用户注册后返回注册前页面。
不过由于注册视图函数是我们自己写的,所以需要我们自己去获取跳转的地址。
需要修改一下注册视图函数:
def register(request):
redirect_to = request.POST.get('next', request.GET.get('next', ''))
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
if redirect_to:
return redirect(redirect_to)
else:
return redirect(reverse('blog:index'))
else:
form = RegisterForm()
return render(request, 'users/register.html', {'form':form,'next':redirect_to})
然后修改模板
base.html
<a href="{% url 'users:register' %}?next={{ request.path }}">注册</a>
使用modelform上传头像。
服务器端安装pillowpip install pillow
添加图片字段到文章models.pyheadshot = models.ImageField(upload_to='avatar/%Y/%m/%d/',default='default.jpg', verbose_name='头像')
settings.py 增加图片存储路径,同时创建目录。MEDIA_URL = '/uploads/' MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
项目urls.py添加如下staticfrom django.conf import settingsfrom django.conf.urls.static import static
urlpatterns = [ ........ ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
form表单提交方法为post,且含有enctype="multipart/form-data"属性
view函数接收:form = RegisterForm(request.POST, request.FILES)
{% if user.is_authenticated %} <li class="cl-effect-11"><a href="#">{{ user.username }} <img src="{{ user.avatar.url }}" alt="{{ user.username }}" height="40" width="40"></a></li> <li class="cl-effect-11"><a href="{% url 'logout' %}" data-hover="退出">退出</a></li> {# <li class="cl-effect-11"><a href="{% url 'users:edit' %}" data-hover="修改密码">修改密码</a></li>#} <li class="cl-effect-11"><a href="{% url 'password_change' %}" data-hover="修改密码">修改密码</a></li> {% else %} <li class="cl-effect-11"><a href="{% url 'login' %}?next={{ request.path }}" data-hover="登陆">登陆</a></li> <li class="cl-effect-11"><a href="{% url 'users:register' %}?next={{ request.path }}" data-hover="注册">注册</a></li> {% endif %}