Django從零搭建個人博客 | 使用allauth插件管理用戶登錄與注冊


原文章地址: EOSONES博客

django-allauth是最受歡迎的管理用戶登錄與注冊的第三方Django安裝包,可以大大簡化我們用戶注冊,登錄及賬戶管理,其核心功能包括用戶注冊、忘記密碼、登錄(微信,微博等第三方登錄;郵箱驗證)、登錄后密碼重置、郵箱發送密碼重置鏈接、退出等。

安裝與設置

運行CMD,打開虛擬環境

pip install django-allauth

安裝好后設置Myblog / settings.py,將allauth相關APP加入到INSTALLED_APP里去。對於第三方的providers,根據需要添加。 官網Providers文檔

INSTALLED_APPS = [
    ...,
    #django-allauth必須安裝的app
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    #第三方賬號相關,根據需求添加
    'allauth.socialaccount.providers.weibo',
    'allauth.socialaccount.providers.github',
]

同時還需要一些設置

 # django-allauth相關設置
AUTHENTICATION_BACKENDS = (
      # django admin所使用的用戶登錄與django-allauth無關 
      'django.contrib.auth.backends.ModelBackend',
      # allauth 身份驗證 
      'allauth.account.auth_backends.AuthenticationBackend',
)

#app django.contrib.sites需要的設置
SITE_ID = 1
# 指定要使用的登錄方法(用戶名、電子郵件地址兩者之一)
ACCOUNT_AUTHENTICATION_METHOD = 'username_email'
# 要求用戶注冊時必須填寫email
ACCOUNT_EMAIL_REQUIRED = True

配置郵箱:allauth 在注冊用戶時,會給用戶填寫的郵箱發送一封激活郵件,在重置密碼時也可通過郵箱進行重置。如果你沒有郵件服務器,可以設置成自己的QQ或163郵箱,localhost環境下一樣可以使用。[ 如何獲取郵箱授權碼 ](https://mp.weixin.qq.com/s?__biz=MjM5OTMyODA4Nw==&mid=2247483732&idx=1&sn=b022e3c3b789c09ae1d856cd49ed0764&chksm=a73c616c904be87a84821da1a3f79d3d548da67c36a011ef1c914203694444c4f003b265520e&scene=21#wechat_redirect" 如何獲取郵箱授權碼 ")

# smtp 服務器地址
EMAIL_HOST = "smtp.qq.com"
# 默認端口25,若請求超時可嘗試465
EMAIL_PORT = 25
# 用戶名
EMAIL_HOST_USER = "374542101@qq.com"
# 郵箱代理授權碼(不是郵箱密碼)
EMAIL_HOST_PASSWORD = "password" 
# 是否使用了SSL 或者TLS(兩者選其一)
# EMAIL_USE_TLS = True  
EMAIL_USE_SSL = True
# 發送人
EMAIL_FROM = "374542101@qq.com" # 
# 默認顯示的發送人,(郵箱地址必須與發送人一致),不設置的話django默認使用的webmaster@localhost
DEFAULT_FROM_EMAIL = "EOSONES 博客 <374542101@qq.com>" 

修改時區

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

將 allauth 添加加到總項目的 urls.py 中

# Myblog/urls.py
from django.conf.urls import re_path,include

urlpatterns = [
    ...,
    #django-allauth插件
    re_path(r'^accounts/', include('allauth.urls')),
]

django-allauth 常見設置選項

# 要求用戶注冊時必須填寫email
ACCOUNT_EMAIL_REQUIRED = True 
# 注冊中郵件驗證方法: "強制(mandatory)"、 "可選(optional)" 或 "否(none)" 之一
(注冊成功后,會發送一封驗證郵件,用戶必須驗證郵箱后,才能登陸)
ACCOUNT_EMAIL_VERIFICATION (="optional") 
# 作用於第三方賬號的注冊
SOCIALACCOUNT_EMAIL_VERIFICATION = 'optional' / 'mandatory' / 'none'
# 郵件發送后的冷卻時間(以秒為單位)
ACCOUNT_EMAIL_CONFIRMATION_COOLDOWN (=180) 
# 郵箱確認郵件的截止日期(天數)
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS (=3) 

# 指定要使用的登錄方法(用戶名、電子郵件地址或兩者之一)
ACCOUNT_AUTHENTICATION_METHOD (="username" | "email" | "username_email") 
# 登錄嘗試失敗的次數
ACCOUNT_LOGIN_ATTEMPTS_LIMIT (=5) 
# 從上次失敗的登錄嘗試,用戶被禁止嘗試登錄的持續時間
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT (=300) 
# 更改為True,用戶一旦確認他們的電子郵件地址,就會自動登錄
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION (=False) 

# 更改或設置密碼后是否自動退出
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE (=False) 
# 更改為True,用戶將在重置密碼后自動登錄
ACCOUNT_LOGIN_ON_PASSWORD_RESET (=False) 
# 控制會話的生命周期,可選項還有: "False" 和 "True"
ACCOUNT_SESSION_REMEMBER (=None) 

# 用戶注冊時是否需要輸入郵箱兩遍
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE (=False) 
# 用戶注冊時是否需要用戶輸入兩遍密碼
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE (=True) 
# 用戶不能使用的用戶名列表
ACCOUNT_USERNAME_BLACKLIST (=[]) 
# 加強電子郵件地址的唯一性
ACCOUNT_UNIQUE_EMAIL (=True) 
# 用戶名允許的最小長度的整數
ACCOUNT_USERNAME_MIN_LENGTH (=1) 
# 使用從社交賬號提供者檢索的字段(如用戶名、郵件)來繞過注冊表單
SOCIALACCOUNT_AUTO_SIGNUP (=True) 

# 設置登錄后跳轉鏈接
LOGIN_REDIRECT_URL (="/") 
# 設置退出登錄后跳轉鏈接
ACCOUNT_LOGOUT_REDIRECT_URL (="/")
# 用戶登出是否需要確認確認(True表示直接退出,不用確認;False表示需要確認)
ACCOUNT_LOGOUT_ON_GET (=True)

測試效果

首先生成數據庫

python manage.py makemigrations
python manage.py migrate

登錄 admin,將 example.com 改為我們博客的域名,在開發環境下,我們用127.0.0.1:8000,並設置好 site 名字(郵箱中顯示)再退出登錄。現在你就可以訪問以下鏈接查看allauth的效果了。由於我們已經設置好了郵箱,所以涉及郵箱驗證和密碼重置部分都可以正常進行的。注冊:http://127.0.0.1:8000/accounts/signup/登錄:http://127.0.0.1:8000/accounts/login/

django-allauth表單會自帶驗證,檢查用戶名和email是否已經注冊,同時檢查密碼強度是否夠以及用戶輸入的兩次密碼是不是一致。當注冊成功后,用戶會收到一封郵件來驗證郵箱,如果ACCOUNT_EMAIL_VERIFICATION = 'mandatory' ,用戶必須通過郵箱驗證后才能登陸。如果你不需要郵箱驗證,只需要設置 ACCOUNT_EMAIL_VERIFICATION = 'none' 就可以了。

1、內置的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): 管理第三方賬戶

擴展用戶模型

django-allauth 並沒有提供展示和修改用戶資料的功能,也沒有對用戶資料進行擴展,所以我們需要自定義用戶模型來進行擴展。

1、創建 app 及配置

由於 django-allauth 已經占用了 account 這個 app,所以我們可以創建一個叫 Myaccount 的 app,並將其加入 settings.py 配置文件的 INSTALL_APPS 中,同時把 url 也加入到項目 settings.py 中。

python manage.py startapp Myaccount
# Myblog/settings.py
INSTALLED_APPS = [
    ...,
    'Myaccount',
     #django-allauth必須安裝的app
    ...,
]
# Myblog/urls.py
from django.conf.urls import re_path,include

urlpatterns = [
    ...,
    #django-allauth插件
    re_path(r'^accounts/', include('allauth.urls')),
    #django-allauth用戶自定義信息擴展
    re_path(r'^accounts/', include('Myaccount.urls',namespace='accounts')),
]

因為我們希望用戶在登錄或注冊成功后,自動跳轉到個人信息頁 "/accounts/profile/",所以在前面的配置中加入了如下代碼

# Myblog/settings.py

LOGIN_REDIRECT_URL = "/accounts/profile/"

2、創建用戶模型及表單

 首先自定義的 User 模型繼承了 AbstractUser ,AbstractUser 是 django 自帶用戶類,可擴展用戶個人信息,AbstractUser 模塊下有:password、username、first_name、last_name、email、last_loginl、is_superuserl、is_staffl、is_activel、date_joined 字段,自定義用戶User擴展了 nickname、link 及頭像 avatar 字段,此處重寫了User的 save() 方法以便上傳的頭像以用戶名為文件夾分類。

# Myaccount/models.py

from django.db import models
#from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser  

#用pillow、django-imagekit模塊設置圖片,可以處理圖片,生成指定大小的縮略圖,前端顯示src="{{ user.avatar.url }}
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill

#擴展Django自帶的User模型字
class User(AbstractUser):
    nickname = models.CharField(max_length=30, blank=True, null=True, verbose_name='昵稱')
    # 擴展用戶個人網站字段
    link = models.URLField('個人網址', blank=True, help_text='提示:網址必須填寫以http開頭的完整形式')
    # 擴展用戶頭像字段,upload_to后必須是相對路徑,上傳路徑已設置為media,因此upto不需要media/avatar,數據庫中avatar/...,前端用avatar.url為media/avatar/...
    avatar = ProcessedImageField(upload_to='avatar',default='avatar/default.png',verbose_name='頭像',
                                processors=[ResizeToFill(100, 100)], # 處理后的圖像大小
                                format='JPEG', # 處理后的圖片格式
                                options={'quality': 95} # 處理后的圖片質量
                                )

    #重寫User的save()方法保存上傳的頭像目錄
    def save(self, *args, **kwargs):
    # 當用戶更改頭像的時候,avatar.name = '文件名',其他情況下avatar.name = 'upload_to/文件名'
    if len(self.avatar.name.split('/')) == 1:
      self.avatar.name = self.username + '/' + self.avatar.name
    #調用父類的save()方法后,avatar.name就變成了'upload_to/用戶名/文件名'
    super(User, self).save()

    # 定義網站管理后台表名
    class Meta:
      verbose_name = '用戶信息' 
      verbose_name_plural = verbose_name #指定模型的復數形式是什么,如果不指定Django會自動在模型名稱后加一個’s’
      ordering = ['-id']
      #admin后台顯示名字關聯到此表的字段的后天顯示名字
    def __str__(self):
      return self.username

 為了讓 Django 能夠識別自定義的用戶模型,需要在 settings.py 中需配置AUTH_USER_MODEL='Myaccount.User',注冊的用戶就會基於自定義User模型創建,並一同創建account中與自定義User關聯的模型。

# Myaccount/forms.py
from django import forms
from .models import User

class ProfileForm(forms.Form):
 class Meta:
  # 關聯的數據庫模型,這里是用戶模型
  model = User
  # 前端顯示、可以修改的字段(admin中)
  fields = ['nickname''link', 'avatar']

3、創建視圖並配置URLs

 我們需要創建2個URLs和對應的視圖來實現用戶資料展示和用戶資料編輯頁面。

# Myaccount/urls.py
from django.conf.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'),
]

因為我們希望用戶在登錄或注冊后自動跳轉到/accounts/profile/, 需要在 settings.py 中需配置

LOGIN_REDIRECT_URL = '/accounts/profile/'

視圖函數根據需求自定義,本博客前端用的是Ajax請求修改網站link與頭像avatar供參考

#Myaccount/views.py

from django.shortcuts import render
from django.http import HttpResponse

from Myaccount import models
# Create your views here.

#auth中用戶權限有關的類。auth可以設置每個用戶的權限。
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt

# 使用login_required裝飾器,用戶只有登錄了才能訪問其用戶資料
@login_required
#個人信息
def profile(request):
    # AUTH_USER_MODEL 類型的對象,表示當前登錄的用戶。
    user = request.user
    return render(request, 'account/profile.html', {'user': user})

import json
import base64
@login_required # 使用login_required裝飾器,用戶只有登錄了才能訪問其用戶資料
@csrf_exempt #取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。
def profile_update(request):
    #request.is_ajax(): #判斷請求頭中是否含有X-Requested-With的值
    if request.is_ajax():
      key=request.POST.get('key')#request.POST.get('')不存在默認為空,request.POST[]不存在報錯
    if key=='link':
      link=request.POST['link']
      username=request.POST['username']
      models.User.objects.filter(username=username).update(link=link)
      link=models.User.objects.filter(username=username).first().link
      linkJson={'link':link}
      return HttpResponse(json.dumps(linkJson))
    elif key=='avatar':
      username=request.POST['username']
      #用ModelForm可代替手動編寫代碼存儲上傳文件
      user_profile=models.User.objects.filter(username=username).first()
      user_profile.avatar=request.FILES.get('avatar')
      user_profile.save()
      url=user_profile.avatar.url
      dataJson={'url':url}
    return HttpResponse(json.dumps(dataJson))

4、設計前端模板

前端根據需求自定義設計,本博中客個人信息只允許更改頭像與個人網站,參考請到Github查看源碼。


需要注意前后端的交互信息,通過View中傳來的當前用戶模型User,可通過Django的模板語言顯示用戶名:{{ user.username }},用戶郵箱:{{ user.link }}、用戶頭像鏈接:{{ user.avatar.url }}、以及用戶郵箱:{{ user.emailaddress_set .0}}(django-allauth在注冊用戶時創建的ACCOUNTS表,關聯自定義模型User,包含用戶的郵箱信息及各種方法)、Django-allauth判斷郵箱是否驗證:{% if user.emailaddress_set .0.verified %} 、Django判斷用戶是否登錄:{% if user.is_authenticated %}等等。

美化頁面模板

django-allauth自帶的頁面很簡陋,我們需要進行美化。如果你是通過pip安裝的django-allauth,模板位置一般在python安裝位置或者虛擬環境下的blog_env\Lib\site-packages中,找到\allauth\templates下的整個account文件夾,或者從github上( allauth項目地址 )將allauth的/templates/accounts/文件夾整個拷貝到你的本地項目中的templates目錄下,因為django-allauth總是會在templates/accounts/文件夾中尋找模板。

1、美化base.html

不管是注冊,登錄還是重置密碼頁面,html模板主要內容都是表單。我們將使用bootstrap迅速美化模板和表單。最快速的方式就是修改base.html(如果沒有該文件,你需要創建一個),加入boostrap樣式和js。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{% block head_title %} {% endblock %}</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >
</head>
<body>

  <main>
      <div class="container">
      {% block content %}
      {% endblock %}
    </div>
  </main>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

</body>
</html>

我們以注冊頁面為例,教你如何美化 django-allauth 的表單。注冊頁面默認的 signup.html 代碼如下,我們先不做任何修改。

{% extends "account/base.html" %}

{% load i18n %}

{% block head_title %}{% trans "Signup" %}{% endblock %}

{% block content %}
<h1>{% trans "Sign Up" %}</h1>

<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>

<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {{ form.as_p }}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>

{% endblock %}

2、美化注冊表單

一個標准的 Boostrap 表單代碼如下,每個輸入字段 field 都是包圍在div里的class="form-group",同時每個 input 的 css 都有 form-control 這個屬性。而我們django的表單渲染 form.as_p 或則 form.as_table 顯然滿足不了我們的要求,因為我們沒法將 css 類名加進去。

<form>
  <div class="form-group">
    <label for="id_email">Email address</label>
    <input type="email" class="form-control" id="id_email" name="email">
  </div>
  <div class="form-group">
    <label for="id_password">Password</label>
    <input type="password" class="form-control" id="id_password" name="password">
  </div>
  <button type="submit" class="btn btn-default">Submit</button>
</form>

當然可以使用自定義widge的屬性來給各個字段添加css,或者直接使用django-crispy-forms表單,這兩種相對耦合度較高,此處推薦使用插件django-widget-teaks,在前端模板中不僅可以為字段添加樣式,還提供了強大的render_field方法,可以自定義某個字段的css和提示詞placeholder。
進入CMD,打開虛擬環境

pip install django-widget-tweaks

安裝成功后,需要把它加到 INSTALLED_APP 中,這時在模板中{% load widget_tweaks %},你就可以給你想要的字段添加css了。以signup.html,我們給每個輸入字段都加入了form-control屬性。

{% extends "account/base.html" %}

{% load i18n %}
{% load widget_tweaks %}

{% block head_title %}{% trans "Signup" %}{% endblock %}

{% block content %}
<h1>{% trans "Sign Up" %}</h1>

<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>

<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}

     {% for hidden in form.hidden_fields %}
      {{ hidden }}
    {% endfor %}

    {% for field in form.visible_fields %}
      <div class="form-group">
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
        {{ field|add_class:'form-control' }}
        {% for error in field.errors %}
          <span class="help-block">{{ error }}</span>
        {% endfor %}
      </div>
    {% endfor %}
  

  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}

    <div class="form-group">
  <button type="submit" class="btn btn-success"">{% trans "Sign Up" %}</button>
    </div>
</form>

{% endblock %}

根據頁面自定義功能,美化表單后,添加到頁面中。本博客設計如下圖所示,參考前端代碼請到 Github 查看。(第三方登錄方式添加到INSTALLED_APP中后,便會出現在Login模板中,第三方列表模板位置在插件包中的allauth\templates\socialaccount\snippets\provider_list.html 中,可進行自定義美化)。安照此方法,可依次將需要的模板進行美化。

3、修改郵件信息

注冊修改密碼的過程中,都會收到郵件信息,在我們復制到templates\account\mail文件中的txt文件即是我們郵件中的提示信息,根據需求自定義修改

第三方賬號登錄

1、Github

1、首先在Github中申請 OAuth Github OAuth注冊頁面,要注意將回調地址callback URL設置為 http://127.0.0.1:8000/accounts/github/login/callback/,設置完成后可在賬號的 Settings / Developer settings / OAuth Apps 中查找更新,上線需要將127.0.0.1:8000更新為我們的博客域名


2、進入admin后台,更新站點,將example.com改為我們博客的域名,在開發環境下,我們用127.0.0.1:8000,然后點擊 SOCIAL ACCOUNTS 下的 Social application,增加一個application,如下圖所示

Provider選Github,這里的Provider就是我們在INSTALLED_APP里增加的第三方socialaccount.provider,client id 和 secret key 我們在github注冊應用里獲得了,將 sites 加入到右邊 選中的 sites。
完成以上設置后,注銷,然后回到登錄頁面,選中 Github 登錄,授權應用即可,成功登錄后,郵箱里也會收到一份激活郵件,這是因為 django-allauth 會自動為我們添加一個本地賬號,根據你的 social account 用戶名和 email 。

2、微信

1、 首先注冊微信開放平台賬號,登錄后在管理中心—網站應用—創建網站應用,填寫網站相關信息進行申請,一般會在7個工作日內完成審核。


需注意的是,注冊信息需要公章,目前沒有發現個人注冊的方法,卒。

參考:大江狗 | django-allauth教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM