Django学习5-用户账户:注册
创建用户账户
注册
Django没有注册用户的视图函数和URL模式,自定义URL模式,编写视图函数和模板。
注册URL模式
在users/urls.py中导入注册函数register
from django.urls import path, include
from django.contrib.auth import views as auth_views
from .views import register
app_name = 'users'
urlpatterns = [
# path('', include('django.contrib.auth.urls')),
path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'),
path('logout/',auth_views.LogoutView.as_view(template_name='index.html'), name='logout'),
path('register/', register, name='register'),
]
注册视图函数register
Django提供了注册用的表单django.contrib.auth.forms.UserCreationForm
包含2个密码输入字段,内嵌元类指定Django的用户模型User
。
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given username and
password.
"""
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
password1 = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
help_text=password_validation.password_validators_help_text_html(),
)
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput,
strip=False,
help_text=_("Enter the same password as before, for verification."),
)
class Meta:
model = User
fields = ("username",)
field_classes = {'username': UsernameField}
注册函数的调用形式与之前的表单类似:POST请求时,根据表单提交的数据创建用户对象,并直接登录创建的用户,接着重定向到learning_logs的首页;GET请求时,生成空表单,不会有任何数据。
def register(request):
"""注册用户"""
if request.method != 'POST':
# 显示空的注册表单
form = UserCreationForm()
else:
# 提交填好的注册表
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
# 注册后的用户 直接登录, 重定向到首页
authenticated_user = authenticate(username=new_user.username,
password=request.POST.get('password1', ""))
login(request, authenticated_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'register.html', context)
这里使用用户验证函数authenticate
验证用户的身份,一般情况下接受用户名username和密码password。验证通过后,返回一个user对象,使用login
登录这个用户。
注册模板
{% extends 'base.html' %}
{% block title %}Register{% endblock %}
{% block content %}
<form action="{% url 'users:register' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Register"/>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}"/>
</form>
{% endblock %}
注册成功后,返回到首页。
Django默认的注册表单类生成表单,输入注册的用户名后要输入2次同哟的密码。
在登录界面添加注册的链接
{% block content %}
...
<form action="{% url 'users:login' %} " method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Login"/>
<input type="hidden" name='next' value="{% url 'learning_logs:index' %}"/>
</form>
<p><a href="{% url 'users:register' %}">register</a></p>
{% endblock %}
注册时添加邮箱字段
Django默认的注册表单类没有邮箱(email)字段,自定义一个表单类继承它,并添加email字段。
在users/forms.py创建注册表单类RegisterForm
from django.forms import Form, CharField, PasswordInput, EmailField
from django.contrib.auth.forms import UserCreationForm, UsernameField
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
email = EmailField()
class Meta:
model = User
fields = ("username", "email")
field_classes = {'username': UsernameField}
添加了EmailField
字段,其余继承了UserCreationForm
。并在视图函数中使用新的注册表单类。结果如下
尝试登录到admin site
查看创建的用户:
新创建的用户都没有赋予其staff
属性,这些账户都不能访问管理界面。
使用超级用户进行访问,查看当前的User。
用户与数据
修改Topic和Post模型的属性,让每个post和topic都有其创建者。对页面也进行限制,普通用户只能访问自己创建的数据。
限制访问
使用@login_required
装饰器能限制只有验证过的用户才能访问被其装饰的视图函数。当用户没有登录,访问被其装饰的视图函数时,会重定向到settings.LOGIN_URL
指定的URL。使用方法:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
使用@login_required
对项目内的视图函数进行装饰,并设置LOGIN_URL
为用户登录的URL。在用户没有进行登录验证时,访问topic时会提示先进行登录。
登录之后根据LOGIN_URL的设置返回到首页。
数据与用户关联
需要将数据关联到提交它们的用户。只需要将高层数据关联到用户,这样低层的数据将自动关联到用户。只要所有的topic都有其特定的用户,那么都能从数据库中找到每条post的拥有者。
在 learning_logs/models.py 中为Topic模型添加所有者字段。接着进行数据迁移, Django提示模型被修改了,而owner
这个字段是必不可少的,且没有默认值。
(venv) [email protected]:~/PycharmProjects/django_ulysses$ python3 manage.py makemigrations learning_logs
You are trying to add a non-nullable field 'owner' to topic without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
按照提示选择提供一个默认的user用户
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> 3
Migrations for 'learning_logs':
learning_logs/migrations/0004_auto_20181025_0850.py
- Add field owner to topic
- Alter field id on post
- Alter field id on topic
输入用户的id(user.id)Django会使用这个用户来迁移数据库,生成迁移文件,之后执行数据迁移,可以查询每个topic对于的用户了。
>>> from learning_logs.models import Topic
>>> t = Topic.objects.get(id=10)
>>> print(t, t.owner)
Answer suffer leader public bad. Perhaps general resource perform perform enjoy system. Treatment soon green must least Democrat too.
When manage office state we best capital charge. Hanabi
用户访问自己的数据
将topic设置为当前用户为自己的创建者时,才能被访问。
@login_required
def topics(request):
"""全部的topics"""
topics = Topic.objects.filter(owner=request.user).order_by('-date_added')
从数据库中筛选出所有者为当前登录用户的topics(目前所有topics的所有者为同一个),用其他用户登录时,没有任何主题。
类似的方法对topic,new_post, edit_post 进行保护。