接續上一篇 這次要講的是我研究中途試過的另一個方法 Substituting
這其實是我一開始的想法
我本來的想法是在auth_user table內新增一個filed 叫做phone_number 如下示意圖
在網路上查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欄位
這種自行創建的方法好處是可以自行定義user表內要有那些欄位 可以新增可以變動
但是如果本來的資料庫就有資料除非你會用SQL語言把資料庫備份到新建立的資料庫內 不燃你要全部重建資料很麻煩
所以我才會選用上一篇那種擴充的方式來新增table
未來如果要新增我也可以直接用對應的方式去寫 更有彈性