在django-allauth教程(1)我们讲解了django-allauth的安装及基本使用(如用户的注册,登录,邮箱验证和密码重置)。我们也提到了allauth并没有提供展示和修改用户资料的功能,也没有对用户资料进行扩展,今天我们就来补上这块。在本文里,我们将会开发两个功能页面,一个在用户登录后跳转到个人信息页面(/accounts/profile/),一个允许登录用户编辑个人资料/accounts/profile/update/)。
我们的教程会一共分4部分,欢迎关注我们微信公众号。本文是第2部分。
安装与基本使用(注册,登录, 邮箱验证,密码重置) - 已完结
用户资料扩展及修改
实现第三方auth登录
美化登录与注册表单
第一步 创建应用及配置
由于django-allauth已经占用了account这个app名,所以我们需要先创建一个叫myaccount的app,并将其加入到settings.py配置文件INSTALLED_APP里去,同时把urls也加入到项目的urls里去,如下图所示。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myaccount',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.weibo',
]
项目的urls.py文件如下所示:
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('accounts/', include('myaccount.urls')),
]
因为我们希望用户在登录或注册后自动跳转到/accounts/profile/, 我们可以加入以下代码。
LOGIN_REDIRECT_URL = '/accounts/profile/'
第二步 编写模型
由于Django自带的User模型字段邮箱,所以我们需要对其扩展,最便捷的方式就是创建UserProfile的模型,如下所示。我们添加了org和telephone两个字段。
# myaccount/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
org = models.CharField(
'Organization', max_length=128, blank=True)
telephone = models.CharField(
'Telephone', max_length=50, blank=True)
mod_date = models.DateTimeField('Last modified', auto_now=True)
class Meta:
verbose_name = 'User Profile'
def __str__(self):
return "{}'s profile".format(self.user.__str__())
第三步 编写URLs和视图
我们需要编写2个URLs和对应视图来实现我们的功能。
# myaccount/urls.py
from django.urls import re_path
from . import views
app_name = "myaccount"
urlpatterns = [
re_path(r'^profile/$', views.profile, name='profile'),
re_path(r'^profile/update/$', views.profile_update, name='profile_update'),
]
2个对应视图处理方法如下所示。这段代码是如何工作的请参加我们之前文章【Django用户资料扩展与编辑】
# myaccount/views.py
from django.shortcuts import render, get_object_or_404
from .models import UserProfile
from .forms import ProfileForm
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.decorators import login_required
@login_required
def profile(request):
user = request.user
return render(request, 'account/profile.html', {'user': user})
@login_required
def profile_update(request):
user = request.user
user_profile = get_object_or_404(UserProfile, user=user)
if request.method == "POST":
form = ProfileForm(request.POST)
if form.is_valid():
user.first_name = form.cleaned_data['first_name'] user.last_name = form.cleaned_data['last_name']
user.save()
user_profile.org = form.cleaned_data['org']
user_profile.telephone = form.cleaned_data['telephone']
user_profile.save()
return HttpResponseRedirect(reverse('myaccount:profile'))
else:
default_data = {'first_name': user.first_name, 'last_name': user.last_name,
'org': user_profile.org, 'telephone': user_profile.telephone, }
form = ProfileForm(default_data)
return render(request, 'account/profile_update.html', {'form': form, 'user': user})
我们用户更新资料需要用到表单,所以我们把表单单独放在forms.py, 代码如下所示。我们创建了两个表单:一个是更新用户资料时使用,一个是重写用户登录表单。
# myaccount/forms.py
from django import forms
from .models import UserProfile
class ProfileForm(forms.Form):
first_name = forms.CharField(label='First Name', max_length=50, required=False)
last_name = forms.CharField(label='Last Name', max_length=50, required=False)
org = forms.CharField(label='Organization', max_length=50, required=False)
telephone = forms.CharField(label='Telephone', max_length=50, required=False)
class SignupForm(forms.Form):
def signup(self, request, user):
user_profile = UserProfile()
user_profile.user = user
user.save()
user_profile.save()
为什么我们需要重写用户登录表单?因为django-allauth在用户注册只会创建User对象,不会创建与之关联的UserProfile对象,我们希望用户在注册时两个对象一起被创建,并存储到数据库中。这点非常重要。通过重写表单,你还可以很容易添加其它字段。
要告诉django-allauth使用我们自定义的登录表单,我们只需要在settings.py里加入一行。
ACCOUNT_SIGNUP_FORM_CLASS = 'myaccount.forms.SignupForm'
第四步 编写模板
因为django-allauth默认会在templates/account/文件夹下寻找模板文件,为方便后续集中美化模板,我们也把模板文件放在这个文件夹中。
#myaccount/templates/account/profile.html
{% block content %}
{% if user.is_authenticated %}
<a href="{% url 'myaccount:profile_update' %}">Update Profile</a> | <a href="{% url 'account_email' %}">Manage Email</a> | <a href="{% url 'account_change_password' %}">Change Password</a> |
<a href="{% url 'account_logout' %}">Logout</a>
{% endif %}
<p>Welcome, {{ user.username }}.</p>
<h2>My Profile</h2>
<ul>
<li>First Name: {{ user.first_name }} </li>
<li>Last Name: {{ user.last_name }} </li>
<li>Organization: {{ user.profile.org }} </li>
<li>Telephone: {{ user.profile.telephone }} </li>
</ul>
{% endblock %}
#myaccount/templates/account/profile_update.html
{% block content %}
{% if user.is_authenticated %}
<a href="{% url 'myaccount:profile_update' %}">Update Profile</a> | <a href="{% url 'account_email' %}">Manage Email</a> | <a href="{% url 'account_change_password' %}">Change Password</a> |
<a href="{% url 'account_logout' %}">Logout</a>
{% endif %}
<h2>Update My Profile</h2>
<div class="form-wrapper">
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<div class="button-wrapper submit">
<input type="submit" value="Update" />
</div>
</form>
</div>
{% endblock %}
第五步 查看效果
在terminal里面连续输入以下命令启动服务器,就可以查看效果了。
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
访问以下用户注册链接你就可以看到如下注册页面。
http://127.0.0.1:8000/accounts/signup/
在你完成注册或登录后你可以看到个人信息页了。
点击Update Profile, 你就可以更新个人资料了,如下图所示。
第六步 思考与改进
我们如何显示用户的邮箱是否验证过,并提醒他们去验证邮箱?Django实现这个也非常容易。我们只需要在模型models.py中新定义一个account_verified方法。
from django.db import models
from django.contrib.auth.models import User
from allauth.account.models import EmailAddress
# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
org = models.CharField(
'Organization', max_length=128, blank=True)
telephone = models.CharField(
'Telephone', max_length=50, blank=True)
mod_date = models.DateTimeField('Last modified', auto_now=True)
class Meta:
verbose_name = 'User Profile'
def __str__(self):
return "{}'s profile".format(self.user.username)
def account_verified(self):
if self.user.is_authenticated:
result = EmailAddress.objects.filter(email=self.user.email)
if len(result):
return result[0].verified
return False
模板改为如下即可。
<p>Welcome, {{ user.username }}.
{% if not user.profile.account_verified %}
(Unverified email.)
{% endif %}
</p>
如果用户登录但邮箱未验证就会看到下面效果。
用户点击管理邮箱可以更改邮箱或重新发验证邮件,如下所示。
我们的教程会一共分4部分,欢迎关注我们微信公众号。本文是第2部分。
安装与基本使用(注册,登录, 邮箱验证,密码重置) - 已完结
用户资料扩展及修改 - 已完结
实现第三方auth登录
美化登录与注册表单