iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Modern Web

Python x Django 網站實作&學習記錄系列 第 7

D7 allauth 採坑日記 Extending & Substituting User model (2)

接續上一篇 這次要講的是我研究中途試過的另一個方法 Substituting
這其實是我一開始的想法
我本來的想法是在auth_user table內新增一個filed 叫做phone_number 如下示意圖
Imgur

在網路上查how to customize user form 會給你很多不同的答案而我每一樣都是過 但都出現問題
剛好下面這篇列舉了3種我遇過的失敗
https://stackoverflow.com/questions/64396391/how-am-i-supposed-to-add-a-field-to-a-signup-form-in-django-allauth-docs-vs-sta
第1個失敗的原文網址在這
https://dev.to/danielfeldroy/customizing-django-allauth-signup-forms-2o1m
他在setting中把原本allauth的signup form從 allauth/account/forms.py 改成 app/user/forms.py中的SpyBookSignupForm類別
在SpyBookSignupForm類別繼承allauth本來的signup form然後再去修改
但是這種方法前提是你要存的type這個欄位已經在auth_user table裡面
但他也沒有講model怎麼改才能讓auth_user table新增欄位
第2個失敗是django作者pennersr給的方法
https://stackoverflow.com/questions/12303478/how-to-customize-user-profile-when-using-django-allauth
這方法其實沒錯 只是 first_name & last_name本來就是在auth_user table裡面有的欄位所以你用以下的code去處理會真的看到資料庫有新增first_name & last_name

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Voornaam')
    last_name = forms.CharField(max_length=30, label='Achternaam')

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.save()

但如果你改成要增加phone_number如下
你確實會在註冊畫面跳出讓你填寫Phone number的地方
但當你送出之後資料庫裏面不會存到phone_number 原因也是auth_user沒有phone_number這個欄位(user.phone_number這行就存不到東西)

class SignupForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Voornaam')
    last_name = forms.CharField(max_length=30, label='Achternaam')
    phone_number = forms.CharField(max_length=30, label='Phone Number')
    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.phone_number = self.cleaned_data['phone_number']
        user.save()

第3個失敗也一樣追根究柢是沒有phone_number欄位

追來追去我找到這篇
https://stackoverflow.com/questions/54242325/django-all-auth-custom-signup-form-with-custom-user-model
他用繼承AbstractUser的方法自行創建一個新的user表 這方法確實有用但是....你的資料庫要完全重建才行
因此我開了一個新的專案docsystem_4 新增user_infos app
從現在開始一直到最後都不要執行makemigrations, migrate

因為上一篇講很多設定了 重複的不分我就不講 我講差異點
docsystem_4/settings.py
除了allauth需要的基本參數以及installed_app要改成user_infos之外還要新增一個
他這個會去抓user_infos/models內的User類別

AUTH_USER_MODEL = 'user_infos.User'

docsystem_4/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('allauth.urls')),
]

user_infos/models.py 改成如下

from django.db import models
from django.contrib.auth.models import User, AbstractUser
from django.utils.translation import gettext_lazy as _

# Custom Usermodel 
class User(AbstractUser):
    phonenumber = models.CharField(_('phonenumber'), max_length=8, blank=True, default="")
    pass

user_infos/forms.py 改成如下

from django import forms

class GuestSignUpForm(forms.Form):
    first_name = forms.CharField(
        max_length=30,
        label="First Name",
        widget=forms.TextInput(
            attrs={"placeholder":"小明"}
        ),
    )
    last_name = forms.CharField(
        max_length=30,
        label="Last Name",
        widget=forms.TextInput(
            attrs={"placeholder":"王"}
        ),
    )
    phonenumber = forms.CharField(
        max_length=10,
        label="Phone number",
        widget=forms.TextInput(
            attrs={"placeholder":"0987654321"}
        ),
        required=False,
    )

    def signup(self, request, user):
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.phonenumber = self.cleaned_data['phonenumber']
        user.save()
        return user

改動其實比上一篇的少
然後執行創建table的步驟

python manage.py makemigrations #告訴django依據model跟installed_app要該棟那些table
python manage.py migrate        #執行以上的變動
python manage.py runserver      #執行server

完成後你的資料表架構變成這樣
原本的auth_user變成的user_infos_user 並且出現了phone_number欄位
Imgur
Imgur

這種自行創建的方法好處是可以自行定義user表內要有那些欄位 可以新增可以變動
但是如果本來的資料庫就有資料除非你會用SQL語言把資料庫備份到新建立的資料庫內 不燃你要全部重建資料很麻煩
所以我才會選用上一篇那種擴充的方式來新增table
未來如果要新增我也可以直接用對應的方式去寫 更有彈性


上一篇
D6 allauth 採坑日記 Extending & Substituting User model (1)
下一篇
D8 新增使用google account 登入的功能
系列文
Python x Django 網站實作&學習記錄30

尚未有邦友留言

立即登入留言