🕌

Djangoのモデルの利用例

2024/04/24に公開

Djangoのモデルの利用例

モデルクラスとフォームクラスの利用パターンの備忘録

モデルクラスのフィールドクラスのオプション

オプション名 説明 デフォルト
null Trueの場合、DEFAULT NULL、Falseの場合、NOT NULL False
balnk Trueの場合、空が許容される False
choises 選択肢を設定する。ウィジェットがセレクトボックスになる
db_column テーブルのカラム名になる 変数名がカラム名
db_index テーブルのカラム名にインデックスを張る
default デフォルト値、フィールドを設定しない場合の値
editable Trueの場合、編集可能。Falseの場合、編集できない True
error_messages エラーメッセージ文字列、フォームで利用
help_text フォームの説明用文字列、フォームで利用
primary_key Trueの場合、モデルの主キーになる。重複はダメ
unique ユニーク制約を張る
verbose_name フォームでの表記名
validators 倍でーしょんの設定。リストで行う

UUIDの主キー

主キーは自動的に設定されるので、特に設定は不要。UUIDにする場合、以下のようにする

from django.db import models
import uuid

class Player(models.Model):
    id = models.UUIDField(
        primary_key=True, 
        default=uuid.uuid4, 
        editable=False,
    )

MySQLの場合、テーブルのカラムは以下のようにchar(32)になっている

`id` char(32) NOT NULL,

CharField

文字列のフィールドの設定例です。NULLを許容している。空を許容している。フィールドを省略すると空文字が入る

フォームのデフォルトはTextInputになる

class Player(models.Model):
    name = models.CharField(
        verbose_name='名前', # フォームの表示名
        max_length=255, # 桁数、必須オプション
        blank=True, # 空を許容する
        null=True, # NULLを許容する DEFAULT NULL
        default='', # デフォルトが空文字
        validators=[validators.RegexValidator(
            regex=u'^[ぁ-んァ-ヶー一-龠]+$',
            message='全角のひらがな・カタカナ・漢字で入力してください',
        )],
    )

テーブルのカラムの設定は以下のようになる。DEFAULT NULLになっている

`name` varchar(255) DEFAULT NULL,

NULLを許容しない

NULLを許容しないなら、これだけでよい。

class Player(models.Model):
    name = models.CharField(
        verbose_name='名前', # フォームの表示名
        max_length=255, # 桁数、必須オプション
    )

IntegerField

整数のフィールドです

class Player(models.Model):
    age = models.IntegerField(
        verbose_name='年齢', # 表示名
        default=0, # 初期値
        validators=[
            validators.MinValueValidator(0), # 最小値
            validators.MaxValueValidator(150) # 最大値
        ],
    )

フォームはNumberInputになる。デフォルトでは、type="number"を表示する

choicesを設定する

choicesを設定するとフォーム側に選択肢を設定する。ウィジェットがNumberInputからSelectになる。テーブルのカラム定義には影響しない。あくまでもフォームのウィジェットが変更されるだけ

class Player(models.Model):
    age = models.IntegerField(
        verbose_name='年齢',
        default=0,
        validators=[
            validators.MinValueValidator(0),
            validators.MaxValueValidator(100)
        ],
        choices=(
            (10, '10才'),
            (20, '20才'),
            (30, '30才'),
        )
    )

BooleanField

True/Falseを設定するフィールド。ON/OFFを制御するカラムになる。要するに、Trueなら「1」、Falseなら「0」を登録する

class Player(models.Model):
    isActive = models.BooleanField(
        verbose_name='有効フラグ',
        default=True,
    )

MySQLでは、テーブルのカラムはtinyintになる

`isActive` tinyint(1) NOT NULL,

フォームはデフォルトでは、チェックボックスになる

Nullを許容する

null=TrueにするとNullを許容する。default=Noneにすることで、初期値が「NULL」になる。フィールドに値を代入しない場合、初期値「NULL」で登録される

class Player(models.Model):
    isActive = models.BooleanField(
        verbose_name='有効フラグ',
        null=True,
        default=None,
    )

テーブル定義はDEFAULT NULLになる

`isActive` tinyint(1) DEFAULT NULL,

フォームはデフォルトでは、SELECTになる。選択肢は「はい」「いいえ」「不明」。「不明」の場合、pythonでは、「None」になる。テーブルには「NULL」で代入される

DateTimeField

DateTimeでのフィールド。DateTimeの利用に利用可能。

from django.utils import timezone

class Player(models.Model):
    startTime = models.DateTimeField(
        verbose_name='開始時刻',
        default=timezone.now
    )

テーブルの定義は以下のようになる

`startTime` datetime(6) NOT NULL,

フォームでのウィジェットはDateTimeInputだが、実際にはただのテキストボックスになる。管理画面では、JSを含めた2個の入力パーツになる

登録日時と更新日時

登録日時、更新日時に利用可能。auto_now_add=Trueにすると登録日時になる。auto_now=Trueにすると更新日時になる。この場合、フォームには表示されない

class Player(models.Model):
    created_at = models.DateTimeField(
        verbose_name='新規登録日時',
        auto_now_add=True
    )
    modified_at = models.DateTimeField(
        verbose_name='更新日時',
        auto_now=True
    )

テーブルのカラムは以下のようになる

  `created_at` datetime(6) NOT NULL,
  `modified_at` datetime(6) NOT NULL,

DateField

Dateでのフィールド。Dateの利用に利用可能。

from datetime import date

class Player(models.Model):
    birthday = models.DateField(
        verbose_name='誕生日',
        default=date.today,
    )

テーブルのカラムは以下のようになる

`birthday` date NOT NULL,

フォームのデフォルトはTextInputなので、ただのtype="text"になる

モデルフォームでのウィジェットの変更

モデルフォームで、フィールドのウィジェットを変更する。type="date"に変更する

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['birthday']
        widgets = {
            'birthday': forms.TextInput(attrs={"type": "date"}),
        }

複数の選択肢

フォーム上での選択肢の設定を行う。choicesを設定することで選択肢を表示する。ただし、これはフォームクラスと連動した場合のみ。モデルを単体で利用する場合、自由に値が代入される可能性がある

セレクトボックス

CharFiledでも、IntegerFieldでもchoicesを設定することでフォーム側では自動的にセレクトボックスになる。フォームでウィジェットの設定は不要

class Player(models.Model):
    job = models.CharField(
        verbose_name="職業",
        max_length=255,
        choices=(
            ('hero', '勇者'),
            ('fighter', '戦士'),
            ('magician', '魔法使い'),
            ('dancer', '踊り子'),
        )
    )

フォームクラスは設定しなくても構わないが、あえて設定するから、以下のようになる

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['job']
        widgets = {
            'job':forms.Select(),
        }

ラジオボタン

フォームクラスで変更する。モデルクラスの設定は、セレクトボックスの設定と同じでも構わない。フォームクラスのウィジェットを変更することで対応可能

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['job']
        widgets = {
            'job':forms.RadioSelect(),
        }

デフォルトの「-----」をなくすためには、モデル側でdefault='XXX'を設定する

class Player(models.Model):
    job = models.CharField(
        verbose_name="職業",
        max_length=255,
        choices=(
            ('hero', '勇者'),
            ('fighter', '戦士'),
            ('magician', '魔法使い'),
            ('dancer', '踊り子'),
        ),
        default='hero',
    )

横に並べるならCSSを変更する

チェックボックス

True/False、つまり、ON/OFFだけのチェックボックスなら、BooleanFieldを定義することで1個のチェックボックスを作ることが可能

class Player(models.Model):
    isActive = models.BooleanField(
        verbose_name='有効フラグ',
        default=True,
    )

BooleanFieldのデフォルトウィジェットはチェックボックスなので、ON/OFFのチェックボックスになる。フォームの設定は不要

複数選択可能なチェックボックス

チェックボックスで複数をチェック可能にする場合、多対多を構築する。これで、多対多を利用したチェックボックスの登録が可能になる

class PlayerType(models.Model):
    name = models.CharField(
        verbose_name='タイプ名',
        max_length=255,
    )
    
    def __str__(self):
        return self.name
class Player(models.Model):
    type = models.ManyToManyField(
        PlayerType,
        verbose_name='タイプ')

この場合、フォームではウィジェットの設定をしなくても複数選択可能なSELECTになる。あえて、設定するならSelectMultipleを設定する。設定しなくても自動的に服須選択可能なセレクトボックスになる

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['type']
        widgets = {
            'type':forms.SelectMultiple(),
        }

チェックボックスにするなら以下のように、CheckboxSelectMultipleのウィジェットを設定する

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['type']
        widgets = {
            'type':forms.CheckboxSelectMultiple(),
        }

複数を選択するチェックボックス

多対多ではなく、1カラムにチェックボックスで複数の値を代入する場合の例です。モデルのフィールドでJSONFieldを利用します。これにより、テーブルに格納されるデータはJSON化された状態でデータを保持します

class Player(models.Model):
    job = models.JSONField(
        verbose_name="職業",
        default='',
    )

フォーム側では、複数選択可能なチェックボックスにします

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = ['job']
    job = forms.MultipleChoiceField(
        label="職業",
        widget=forms.CheckboxSelectMultiple(),
        choices=(
            ('hero', '勇者'),
            ('fighter', '戦士'),
            ('magician', '魔法使い'),
            ('dancer', '踊り子'),
        ),
    )

テーブルのレコードには、リストをJSON化した状態で保存されます。ビュー処理のCreateViewでも、UpdateViewでもJSONデータを取り出して、チェックボックスに正しく反映します。CreateViewでも、UpdateViewでも、特別な手続きは不要

フォームクラスでのセレクト、ラジオ、チェックボックス

モデルと連動しないフォームパーツを作る場合の例です

セレクトボックス

普通のフォームクラスになる。継承元が、Modelformではなく、ただのFormになる。フォームのフィールドクラスをChoiceFieldにする。ウィジェットはなくてもよいが、デフォルトでSelectになる。あえて設定するなら以下のようになる

class PlayerForm (forms.Form):
    music = forms.ChoiceField(
        label="好きな音楽",
        choices=(
            ('jpop','JPOP'),
            ('rock','ロック'),
            ('anime','アニソン'),
            ('vocaloid','ボーカロイド'),
        ),
        initial = "",
        widget=forms.Select(),
    )

ラジオボタン

ウィジェットをRadioSelectにする

class PlayerForm (forms.Form):
    music = forms.ChoiceField(
        label="好きな音楽",
        choices=(
            ('jpop','JPOP'),
            ('rock','ロック'),
            ('anime','アニソン'),
            ('vocaloid','ボーカロイド'),
        ),
        initial = "",
        widget=forms.RadioSelect(),
    )

複数選択可能なチェックボックス

ウィジェットをCheckboxSelectMultipleにする

class PlayerForm (forms.Form):
    music = forms.ChoiceField(
        label="好きな音楽",
        choices=(
            ('jpop','JPOP'),
            ('rock','ロック'),
            ('anime','アニソン'),
            ('vocaloid','ボーカロイド'),
        ),
        initial = "",
        widget=forms.CheckboxSelectMultiple(),
    )

Discussion