1. 程式人生 > >django-allauth教程(2): 使用者個人資料UserProfile擴充套件與編輯

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登入

  • 美化登入與登錄檔單