【Wagtail】マイグレート済み＆編集中のプロジェクトのUserモデルをカスタマイズする

wagtailでユーザーモデルに独自のフィールドを追加したいと思ったことはありませんか？
また、すでにマイグレート＆マイグレーションやアプリやファイルを追加し編集してしまったwagtailプロジェクトで
後からユーザーモデルに独自のフィールドを追加したいと思ったことはありませんか？

自分もそういう状況になり、実装にかなり苦労してしまったのでメモします。

## 前提条件
これからwagtailでプロジェクト作る場合は簡単です。
ただし、ユーザーモデルのカスタマイズに関する設定などが終わるまではマイグレートしてはいけません。

また、すでにマイグレート＆マイグレーションや編集を行ったプロジェクトでもユーザーモデルのカスタマイズは可能ですが
ただし現在のDB丸ごと消して削除する必要があります。(DBを消したくない場合は私が知る限りではできそうにないようです)


## 参考
一応、wagtailの公式ドキュメントにも手順はありますが、どのファイルを編集するのか
以後詳しく説明しますが、アプリ名を決まった名前で命名する必要があるのにその辺に触れてなくて分かりづらいです。

wagtail公式：Custom user models
https://docs.wagtail.org/en/stable/advanced_topics/customisation/custom_user_models.html

ChatGPTに聞くもうまくいかず、色々とサイトを探っていたら海外のこのサイトがかなり有能でわかりやすく一発で解決しました。
(ただしimportするものに不備があり、そこは公式のドキュメントが参考になりました)
Add Custom User Model to django or wagtail sites
https://medium.com/@altaf008bd/wagtail-add-custom-fields-including-image-to-custom-user-model-1c976ddbc24

これらを参考に解説していきます。

今回は例として、ユーザーモデルに電話番号を追加したいとう想定で"phone"というフィールドを追加するという流れで解説します。

## 手順について
これからプロジェクト作る場合でも、既存のプロジェクトに後からカスタマイズする場合でも手順はほぼ同じです。
後からカスタマイズする場合は特殊な手順を挟むので、その時になったら別途解説します。

## 1."users"アプリケーションの作成
ユーザーモデルのカスタマイズをする専用のアプリケーションを作成します。
ここで、<font color="Red">名前は必ず"users"にしてください。</font>そうでなければうまくいかないようです。
```
python manage.py startapp users
```
これでusers"アプリケーション(ディレクトリ)が生成されますので、この中身を以後編集します。

## 2.models.pyの編集
usersアプリケーションのmodels.pyをこのように編集します。
```python:models.py
from django.contrib.auth.models import AbstractUser
from django.db import models


# extend user model

class User(AbstractUser):

    phone = models.CharField(verbose_name='phone', max_length=30)

```
今回はphoneというフィールドが１つだけですが、もちろんフィールド名前はあなたのプロジェクトに合わせて
自由にしてOKです。フィールドの種類も変えてOKです。数もフィールドを複数作ってOKです。

## 3.admin.pyの編集
usersアプリケーションのadmin.pyをこのように編集します。
```python:admin.py
from django import forms
from django.utils.translation import gettext_lazy as _
from wagtail.users.forms import UserEditForm, UserCreationForm


class CustomUserEditForm(UserEditForm):
    phone = forms.CharField(max_length=30, required=True, label=_("Phone"))
    

class CustomUserCreationForm(UserCreationForm):
    phone = forms.CharField(max_length=30, required=True, label=_("Phone"))
```
ポイントは、フィールド名を間違えないことです。
<font color="Red">先ほどmodels.pyで設定したフィールド名と同じになるようにしてください。
フィールドの種類もmodels.pyでの設定と一致させてください。(この例だとCharField)</font>
また、label=_("Phone")の部分が管理画面で表示されます。

## 4.create.htmlとedit.htmlの作成
create.htmlとedit.htmlが必要らしいです。
おそらくこれが、管理画面を拡張してユーザーの作成や編集の画面で出てくるようにするみたいです。
作成する場所がかなり重要です。
まず、usersアプリケーションの直下にtemplatesディレクトリを作成します。(ここまではテンプレート作成でお馴染みの手順ですね。)
ここからが重要ですが、この<font color="Red">templatesディレクトリの中にwagtailusersディレクトリを作り、さらにその中にusersディレクトリを作ります。このusersディレクトリにcreate.htmlとedit.htmlを配置します。</font>
![で.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/4ca4db25-5537-fe1c-cc0c-f132b0aea068.png)
こんな感じですね。この通りのフォルダ名、階層構想、htmlファイル名にしないとダメなようです。
create.htmlとedit.htmlをそれぞれ下記のように編集します。

```html:create.html
{% extends "wagtailusers/users/create.html" %}
{% block extra_fields %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.phone %}
{% endblock extra_fields %}
```


```html:create.edit.html
{% extends "wagtailusers/users/edit.html" %}
{% block extra_fields %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.phone %}
{% endblock extra_fields %}
```

<font color="Red">field=form.〇〇〇〇の部分が重要です。models.pyで設定したフィールド名と一致させてください。今回は〇〇〇〇の部分がmodels.pyで設定したphoneになります。</font>


## 5.base.pyの設定
プロジェクトディレクトリのbase.pyに設定を追加します。
プロジェクトディレクトリ(名称が正しくないかもしれません)とは、wgtailのプロジェクトのビルドでで初期に作成している
ベース？的なディレクトリです。wagtail公式のチュートリアルだと"mysite"という名前です。
![名称未設ms定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/56e65972-65cd-761a-52fa-d01ede0c1392.png)
このディレクトリの中に"setting"ディレクトリがありその中にbase.pyがあるのでこれを編集します。
下記を追記します。
```python:base.py
##省略##

AUTH_USER_MODEL = 'users.User'##追加
WAGTAIL_USER_EDIT_FORM = 'users.admin.CustomUserEditForm'##追加
WAGTAIL_USER_CREATION_FORM = 'users.admin.CustomUserCreationForm'##追加
WAGTAIL_USER_CUSTOM_FIELDS = ['phone']##追加

##省略##

# Application definition

INSTALLED_APPS = [
    "users",##追加
    "search",
    ##省略##
    "wagtail.contrib.forms",
    "wagtail.contrib.redirects",
    "wagtail.embeds",
    "wagtail.sites",
    "wagtail.users",
    "wagtail.snippets",
    ##省略##

]

##省略##
```
<font color="Red">ここで、WAGTAIL_USER_CUSTOM_FIELDS = ['phone']の['phone']の部分は
models.pyで設定した値と一致させてください。
フィールドを複数作った場合は、['フィールド名1','フィールド名2','フィールド名3']とい感じにしてください。
また、設定したフィールドは全て書かないとエラーになります。
</font>

追加にあたり、書く場所が重要なようです。
<font color="Red">"users"はINSTALLED_APPSの中にある"wagtail.users"よりも上の位置に書いてください</font>
![名称未設っっd定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/47d918db-1a18-064f-8a2b-e49010e7c73d.png)


また、特に指定はなかったですが、<font color="Red">
AUTH_USER_MODEL = 'users.User'
WAGTAIL_USER_EDIT_FORM = 'users.admin.CustomUserEditForm'
WAGTAIL_USER_CREATION_FORM = 'users.admin.CustomUserCreationForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['phone']
はINSTALLED_APPS[]より上に書くと私の場合うまくいきました。
</font>

ユーザーモデルのカスタムの設定はこれで完了です。

## 6.マイグレート
ここで、これからプロジェクトを作り始める場合はここでマイグレートしてください
```
python manage.py migrate
```
これで、userモデルにphoneフィールドが使いされます。
以上で完了です。

## 7.DBの削除(既存プロジェクト後からカスタマイズする場合)
すでにマイグレートや他の編集をしてしまっている方はDBの削除が必要です。
仮に**python manage.py migrate**を実行してもエラーが出ます。

エラー：
(django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency users.0001_initial on database 'default'.)

プロジェクト内の、"db.sqlite3"を手動で削除してください。
![名称未設でl定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/1b5b3d1a-6452-96b1-dd2c-e3ea1f168039.png)
削除したら、マイグレートします。
```
python manage.py migrate
```
これで、DBは全て消えてしまいますが後からでもユーザーモデルがカスタマイズできました。

## 8.確認
マイグレート後はスーパーユーザーのアカウント作成して、管理画面に行ってみましょう。
今回紹介した例とは異なる写真で申し訳ないですが、赤枠で囲った部分のようにカスタムしたフィールドが表示され
編集ができるようになっています。
![名称未っっっs設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/bb125328-372b-3914-0187-57c6fd7cf682.png)
(この写真では、UserIdとUserTypeがカスタムで追加したものになります)

以上で終わりになります。