前言:上一篇:django-allauth(一)小试牛刀 介绍了django-allauth的安装及基本使用(如用户的注册,登录,邮箱验证和密码重置),然而allauth并没有提供展示和修改用户资料的功能,也没有对用户资料进行扩展。那么本篇就来介绍如何拓展用户个人资料和修改个人资料。一个在用户登录后跳转到个人信息页面(/accounts/profile/),一个允许登录用户编辑个人资料/accounts/profile/update/)。
1.创建一个APP,叫做myaccount
这里教大家一个便捷使用 python manage.py shell 的方法。 首先打开manage.py文件,然后在pycharm中找到菜单栏的工具,如图:
点击后,会出现 这样就可以不用每次在terminal中输入python manage.py ... 比如createsuperuser, startapp, migrate,makemigrations 其次呢我创建一个源码目录apps/,用来放自己的APP, 再创建一个源码目录extra_apps/,用来存放额外添加的APP,比如百度的富文本编辑器UEditor,xadmin等 将其加入到settings.py配置文件INSTALLED_APP里去,同时把urls也加入到项目的urls里去,如下图所示。 House_website/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.github',
'myaccount',
]
为了方便国内开发者,我建议在settings.py里添加
LANGUAGE_CODE = 'zh-hans' # 中文支持,时区为中国上海
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
2.编写模型
由于Django自带的User模型字段邮箱,所以我们需要对其扩展,最便捷的方式就是创建UserProfile的模型,如下所示。我们添加了需要拓展的字段。
myaccount/models.py
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)
birthday = models.DateField(null=True, blank=True, verbose_name='出生日期')
gender = models.CharField(max_length=6, choices=(('male', u'男'), ('female', u'女')), default='female',
verbose_name='性别')
age = models.IntegerField(verbose_name='年龄', null=True)
QQ = models.CharField(max_length=20, null=True, blank=True, verbose_name='QQ', default='')
telephone = models.CharField(max_length=50, null=True, blank=True, verbose_name='电话', default='')
signature = models.TextField(max_length=500, verbose_name='个性签名',default='',null=True)
mod_date = models.DateTimeField('Last modified', auto_now=True, )
is_delete = models.BooleanField(default=False, verbose_name='是否删除')
class Meta:
verbose_name = 'User Profile'
def __str__(self):
return "{}'s profile".format(self.user.__str__())
# models.py中新定义一个account_verified方法,来提醒邮箱是否验证
def account_verified(self):
if self.user.is_authenticated:
result = EmailAddress.objects.filter(email=self.user.email)
if len(result):
return result[0].verified
else:
return False
else:
return False
3.编写urls
House_website/House_website/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('accounts/', include('myaccount.urls')),
]
4.编写视图函数
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.birthday = form.cleaned_data['birthday']
user_profile.age = form.cleaned_data['age']
user_profile.gender = form.cleaned_data['gender']
user_profile.QQ = form.cleaned_data['QQ']
user_profile.telephone = form.cleaned_data['telephone']
user_profile.signature = form.cleaned_data['signature']
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})
5.编写表单
在myaccount/下新建一个forms.py 我们用户更新资料需要用到表单,所以我们把表单单独放在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)
birthday = forms.DateField(label="birthday", required=False)
age = forms.IntegerField(label='age', required=False)
gender = forms.CharField(label="gender", widget=forms.RadioSelect(
choices=(('female', '女'), ('male', '男'))), initial=('female', '女'), required=False)
QQ = forms.CharField(label='QQ', required=False, max_length=20)
signature = forms.CharField(label='signature', required=False, max_length=500)
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'
6.编写模板
因为django-allauth默认会在templates/account/文件夹下寻找模板文件,为方便后续集中美化模板,我们也把模板文件放在这个文件夹中。 templates/account/profile.html
{% load account %}
{% 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 }}.
{% if not user.profile.account_verified %}
(Unverified email.)
{% endif %}
</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>
<li>birthday: {{ user.profile.birthday }} </li>
<li>age: {{ user.profile.age }} </li>
<li>gender: {{ user.profile.gender }} </li>
<li>QQ: {{ user.profile.QQ }} </li>
<li>signature: {{ user.profile.signature }}</li>
</ul>
{% endblock %}
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 %}
7.查看效果
在Terminal输入以下命令:
python manage.py makemigrations # 生成映射文件
# 如果之前生成过映射文件,那就把之前的映射文件删除
# \House_website\apps\myaccount\migrations\0001_initial.py
python manage.py migrate # 执行映射文件,创建数据表
python manage.py runserver # 运行服务
下面是django_allauth所有内置的URLs,均可以访问的。
/accounts/login/(URL名account_login): 登录
/accounts/signup/ (URL名account_signup): 注册
/accounts/password/reset/(URL名: account_reset_password) :重置密码
/accounts/logout/ (URL名account_logout): 退出登录
/accounts/password/set/ (URL名:account_set_password): 设置密码
/accounts/password/change/ (URL名: account_change_password): 改变密码(需登录)
/accounts/email/(URL名: account_email) 用户可以添加和移除email,并验证
/accounts/social/connections/(URL名:socialaccount_connections): 管理第三方账户
如果没账号,先注册一个,我就不演示了,
登录之后会进入profile页面:
点击上方Update Profile,进入个人信息修改页面:
输入信息后点击下方的Update 按钮就可以完后修改,重定向到/accounts/profile/ ,个人信息就修改完成了!
到这里本篇久写完了,希望大家点个赞支持一下!
特别鸣谢:大江狗前辈 声明:我写博客只是记录自己的学习进度和总结并分享给大家,并不保证原创,如有引用您的博文,请您理解!