Django沒有註冊用戶的視圖函數和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'), ]
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 進行保護。