django-allauth教程(2): 用户个人资料UserProfile扩展与编辑

在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登录

  • 美化登录与注册表单

猜你喜欢

转载自blog.csdn.net/weixin_42134789/article/details/80656289