Djangoにおける共通モデルフィールドの設定と継承(監査モデル、承認モデル)

auto_now_addauto_nowの活用方法

Djangoフレームワークでは、オブジェクトの作成日時と更新日時を自動で管理するためにauto_now_add=Trueauto_now=Trueという便利な機能が提供されています。これらの具体的な使用方法と相違点について以下に説明します。

auto_now_add=Trueの特性

  • 動作: オブジェクトが初めて作成される際に、そのフィールドに現在の日時を自動的に設定します。
  • 適用場面: オブジェクトの作成日時を記録する必要があるが、その後は変更されないようにしたいフィールドに適しています。

auto_now=Trueの特性

  • 動作: オブジェクトが保存されるたびに、そのフィールドに現在の日時を自動的に設定します。
  • 適用場面: オブジェクトの最終更新日時を追跡する必要があるフィールドに適しており、オブジェクトが変更されるたびにタイムスタンプが更新されます。

比較と違い

  • auto_now_add=True:
  • オブジェクト作成時にのみ自動で値が設定されます。
  • 作成後はフォームや管理画面から変更できず、作成時刻の正確性が保証されます。
  • 作成日時フィールドの処理を簡素化します。
  • default=now:
  • より柔軟性があり、オブジェクトインスタンス化時に初期値を手動で設定できます。
  • editable=Falseと組み合わせることで、フォームからの手動編集を防ぎます。
  • 初期時刻を手動で設定する必要がある場合に有用ですが、通常はauto_now_addほどシンプルではありません。

推奨される使用方法

ほとんどの場合、作成日時と更新日時の管理にはauto_now_add=Trueauto_now=Trueを使用することが推奨されます。これらは意図が明確で使いやすいためです。

実装例

以下にAuditBaseModelでこれらの属性を使用する方法を示します。

監査モデルと承認モデルの定義

from django.conf import settings
from django.db import models
from core.models import MasterModel

class ApprovalBaseModel(models.Model):
    reference_no = models.ForeignKey(MasterModel, null=True, blank=True, to_field='reference_number',
                                    on_delete=models.PROTECT, related_name='%(class)s_reference',
                                    verbose_name="承認番号")
    approval_status = models.BooleanField(default=False, verbose_name='承認状態')
    reviewer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True,
                                 to_field='username', related_name='%(class)s_reviewer', verbose_name='レビュアー')
    review_time = models.DateTimeField(null=True, editable=False, blank=True, verbose_name="承認日時")

    class Meta:
        abstract = True
from django.utils.timezone import now

class AuditBaseModel(models.Model):
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True,
                                to_field='username', related_name='%(class)s_creator', verbose_name='作成者')
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="作成日時")
    modifier = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True, blank=True,
                                to_field='username', related_name='%(class)s_modifier', verbose_name="更新者")
    modified_time = models.DateTimeField(auto_now=True, verbose_name="更新日時")

    class Meta:
        abstract = True
class SalesOrderClosureModel(ApprovalBaseModel, AuditBaseModel):
    """
    売上注文クローズモデルヘッダー
    未出荷または部分出荷の場合、この注文をクローズし、実際に出荷された数量を計上します
    """
    closure_no = models.CharField(unique=True, max_length=20, editable=False, verbose_name="クローズ番号")
    closure_date = models.DateField(default=date.today, editable=False, verbose_name="クローズ日")
    factory = models.ForeignKey(FactoryModel, on_delete=models.PROTECT, related_name='sales_factory',
                              to_field='factory_code', verbose_name="工場")
    customer = models.ForeignKey(CustomerModel, on_delete=models.PROTECT, related_name='sales_customer', 
                              to_field='customer_code', verbose_name="顧客")
    representative = models.ForeignKey(RepresentativeModel, on_delete=models.PROTECT, 
                                     related_name='sales_rep', to_field='rep_code',
                                     verbose_name="担当者")
    reason = models.CharField(null=True, blank=True, max_length=100, verbose_name="クローズ理由")
    is_confirmed = models.BooleanField(default=False, verbose_name="確認状態")
    confirm_user = models.CharField(max_length=20, editable=False, null=True, blank=True, 
                                   verbose_name="確認ユーザー")
    confirm_time = models.DateTimeField(null=True, editable=False, blank=True, verbose_name="確認日時")

    class Meta:
        db_table = 'sales_closure'
        verbose_name = '売上注文クローズヘッダー'
        verbose_name_plural = verbose_name

タグ: Django モデル継承 タイムスタンプ 抽象モデル フィールド設定

7月11日 21:23 投稿