用户注册登陆是一个网站的基本功能,django对这部分进行了很好的封装,咱们只须要在django的基础上作些简单的修改就能够达到咱们想要的效果。在本讲中,咱们会用到user中的用户受权方面的一些函数,还会对django中的user进行扩展,以及django中的form验证。html
注册页面 前端
登陆页面 python
django的设计哲学是,一个应用只提供一种功能,好比users应用只提供用户相关功能,comment应用只提供评论相关功能,这能提升代码的重复利用率。git
在django中,只须要下面一条命令,便可创建users应用github
python3 manage.py startapp users
复制代码
咱们须要一个用户表,用来实现登陆注册功能,虽然django已经自带来用户登陆注册功能,也有相应的表,可是不符合中国人习惯,须要咱们对user模型进行自定义。实现自定义User模型最简单的方式就是继承AbstractBaseUser,AbstractBaseUser实现了User的核心功能,咱们只需加一些额外的字段进行补充便可。django
User模型原有的字段有:bash
这些都是最基本的字段,并不能知足咱们的需求。app
根据网站自身业务,咱们又添加了下面的字段ide
咱们只需在users/models.py中写入代码函数
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
GENDER_CHOICES = (
('M', '男'),
('F', '女'),
)
nickname = models.CharField(blank=True, null=True, max_length=20)
avatar = models.FileField(upload_to='avatar/')
mobile = models.CharField(blank=True, null=True, max_length=13)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES,blank=True, null=True)
subscribe = models.BooleanField(default=False)
class Meta:
db_table = "v_user"
复制代码
gender是性别字段,其中用到了choices=GENDER_CHOICES。这种方式经常用在下拉框或单多选框,例如 M对应男 F对应女。
在user文件夹下面,新建url.py文件,写入登陆、注册和退出的url信息。app_name是命名空间,咱们命名为'users'。
from django.urls import path
from . import views
app_name = 'users'
urlpatterns = [
path('login/', views.login, name='login'),
path('signup/', views.signup, name='signup'),
path('logout/', views.logout, name='logout'),
]
复制代码
url路由配置好了,咱们下面就开始写视图函数代码了
咱们先来写注册函数,写注册,固然得有注册表单了,幸运的是,在django中,能够用代码来生成表单。咱们只需在users下新建forms.py文件,而后写入注册表单的代码。
class SignUpForm(UserCreationForm):
username = forms.CharField(min_length=4,max_length=30,
error_messages={
'min_length': '用户名很多于4个字符',
'max_length': '用户名不能多于30个字符',
'required': '用户名不能为空',
},
widget=forms.TextInput(attrs={'placeholder': '请输入用户名'}))
password1 = forms.CharField(min_length=8, max_length=30,
error_messages={
'min_length': '密码很多于8个字符',
'max_length': '密码不能多于30个字符',
'required': '密码不能为空',
},
widget=forms.PasswordInput(attrs={'placeholder': '请输入密码'}))
password2 = forms.CharField(min_length=8,max_length=30,
error_messages={
'min_length': '密码很多于8个字符',
'max_length': '密码不能多于30个字符',
'required': '密码不能为空',
},
widget=forms.PasswordInput(attrs={'placeholder': '请确认密码'}))
class Meta:
model = User
fields = ('username', 'password1', 'password2',)
error_messages = {'password_mismatch': '两次密码不一致', }
复制代码
咱们的表单一共有三个字段:username、password一、password2,它们都是CharField类型,widget分别是TextInput和PasswordInput。并且django是自带验证的,只须要咱们配置好error_messages字典,当form验证的时候,就会显示咱们自定义的错误信息。 有了注册表单后,就能够在前端模板和视图函数中使用它。
下面是注册视图函数。
...
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password1 = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password1)
auth_login(request, user)
return redirect('home')
else:
print(form.errors)
else:
form = SignUpForm()
return render(request, 'registration/signup.html', {'form': form})
复制代码
在signup函数中,咱们经过form = SignUpForm初始化一个表单,并在render函数中传递给模板。
注册模板文件写在了templates/registration/signup.html
关键代码是
<form class="ui large form" novalidate method="post" action="{% url 'users:signup' %}" enctype="multipart/form-data" >
{% csrf_token %}
<div class="ui stacked segment">
<div class="field">
{{form.username}}
</div>
<div class="field">
{{form.password1}}
</div>
<div class="field">
{{form.password2}}
</div>
<button class="ui submit button" type="submit">注册</button>
</div>
{% include "base/form_errors.html" %}
</form>
复制代码
form的action为
{% url 'users:signup' %}
复制代码
即在url.py中定义的signup函数。 经过post请求传递给signup,在signup中,经过以下四行代码来实现注册,并自动登陆的。
username = form.cleaned_data.get('username')
raw_password1 = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password1)
auth_login(request, user)
复制代码
登陆函数与注册函数的模式是同样的,都是先写form,写模板,最后写视图函数。 因为form和模板的代码和注册功能相似,这里就不贴了,你们能够上github查看。
重点讲一下login视图函数
def login(request):
if request.method == 'POST':
next = request.POST.get('next', '/')
form = UserLoginForm(request=request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
auth_login(request, user)
return redirect(next)
else:
print(form.errors)
else:
next = request.GET.get('next', '/')
form = UserLoginForm()
print(next)
return render(request, 'registration/login.html', {'form': form, 'next':next})
复制代码
在login函数中,咱们多了一个next变量,next对应的是登陆后要跳转的url,其实这是一种场景,假如你在购物网站买东西,最后付款的时候,会跳转到付款页,假如你没有登陆,网站会提示你登陆,登陆后,会再次跳转到付款页。
固然了,跳转到登陆页的时候,须要你在url后追加next参数,如 aaa. com/login/?next=bbb. com 这样用户登陆后就会跳到bbb. com
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
def logout(request):
auth_logout(request)
return redirect('home')
复制代码
退出功能,仅须要一行代码 auth_logout(request) 就ok了。