【図解あり】django モデル メソッドとMetaオプション
モデル内のメソッドがよくわからない…
Metaオプションの使い方がよくわからない…
djangoを勉強する中で、一度はdef __str__等のメソッドやMetaオプションを見かけたことがあると思います。初学者にとって、これらのオプションについて理解するのはなかなか難しいと思いますし、筆者も最初は全く理解できませんでした。
本記事では、モデル内のフィールド以外のオプション設定について解説していきます。
では早速解説していきます。
1. モデルメソッド
まずモデルメソッドとは以下のようにモデル内で使われるメソッドを表しています。主な使われ方としては、管理画面の表示内容を調整したり、データを保存した時にアクションを追加することができます。
class Post(models.Model):
#フィールド
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
#メソッド
def __str__(self):
return self.title
def~の部分がメソッドです。代表的なメソッドが「str」、「get_absolute_url」、「save」ですので以降で詳細について解説していきます。
1.1 strメソッド
pythonのstrメソッドと同じ使い方であり、 文字列を返すためのメソッドです。
サンプルコードと管理画面を確認しながら理解を深めましょう。
サンプルコード
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
#文字列を返すメソッド追加
def __str__(self):
return self.title + ' | ' + self.author.username
サンプルコードのような文字列を返すためのメソッドを追加します。まだイメージ沸かないと思うので管理画面を確認しながら解説していきます。
管理画面
strメソッド設定しない場合…
object…と表示されます。
strメソッド設定する場合…
strメソッド内で返した「self.title + ' | ' + self.author.username」の文字列が管理画面に表示されているのがわかるかと思います。
Djnagoでstrメソッドを使った場合、管理画面等に表示されるオブジェクト名が変更されるということを頭に入れておきましょう。
1.2 get_absolute_urlメソッド
get_absolute_urlメソッドはurlを取得するためのメソッドです。
サンプルコード
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
#url取得するためのメソッド
def get_absolute_url(self, **kwargs):
#ブログ詳細ページへ遷移するためのurl
return reverse("blog_detail", kwargs={"pk": pk})
上記のようget_absolute_urlを設定することで、簡単にurlを取得できリンクを作成することができます。
実際どのように使うかはテンプレートファイルで確認していきます。
なお今回ブログのリストページから詳細ページへのリンクを作成する前提で解説していきます。
templates/list.html
<h1 class="text-danger">投稿リスト</h1>
<ul>
{% for post in object_list %}
<li><a href="{{post.get_absolute_url}}">{{ post.title }}</a></li>
{% endfor%}
</ul>
通常ならリンクの部分を、{% url 'blog_detail' post.pk %}と表記することが通常かと思いますが、get_abolute_urlを使用すればより簡単にリンク作成できます。
その他メリットとしては、仮にurlを変更した場合でも、templateファイルを変更する必要がないためコードの管理が楽になります。
また{{...get_absolute_url}}のリンクは、{% url... %}と比べて、他のtemplateファイルでコードの再利用がしやすいのもメリットです。
1.3 saveメソッド
saveメソッドは、データを保存する際にアクションを追加できます。
サンプルコード
from django.db import models
from django.contrib.auth.models import User
#slugifyを使うためにimport要
from django.utils.text import slugify
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(null=True, blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
#保存時にアクション追加
def save(self, *args, **kwargs):
#スラッグが存在しない場合
if not self.slug:
#タイトルをスラッグに変換
self.slug = slugify(self.title, allow_unicode=True)
super().save(*args, **kwargs)
def save以降で保存時のアクションを追加します。
今回スラッグが存在しない場合、タイトルをスラッグに変換するアクションを追加します。
またslugifyは中々便利です。例えばタイトルが「how to study django」であれば、「how-to-study-django」のようにハイフンを補ってくれて、slugフィールドに適応する形に変換してくれます。
以下の管理画面のイメージです。
またslugify(…, allow_unicode=True)とすることで和文でも対応可能になります。ただ和文のurlは、SNSでシェアされた時等「%E3%82%B5%E3%83%BC」のように文字化けする可能性があるので、スラッグは英文にするのが無難かと思います。
2. Metaオプション
Metaオプションはフィールド以外で設定できるオプションで様々な設定ができます。今回はよく使うMetaオプションを解説していきます。
2.1 よく使うMetaオプション
サンプルコード
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
#Metaオプション設定
class Meta:
ordering = ["-created_at"]
verbose_name_plural = "投稿"
Metaの使い方は、モデルのクラス内に"class Meta:"と定義し、そのクラス内にオプション設定していきます。
ではサンプルコードで使用されているオプションを解説していきます。
◆ordering
orderingは、その言葉通り順序を調整するために使用します。
ordering=["〇〇"]にすれば昇順、ordering=["-〇〇"]にすれば降順になります。
したがってordering=['-created_αt']とすることで、管理画面等で日付の新しい順(新着順)にオブジェクトを並べることができます。
なお、昇順と降順についてわからない方は以下のサイトをご参考ください。
◆verbose_name/verbose_name_plural
今回サンプルコードではverbose_name_plural="投稿"としています。
管理画面でどのようになるか確認していきましょう。
見ての通り赤枠の部分に”投稿”と反映されているのがわかるかと思います。
ちなみにverbose_name="投稿"とすると以下の通り、"投稿s"となります。
お好みの方を使えば良いかと思います。
2.2 Metaオプションを使ったモデルの継承
モデルの継承方法について解説していきます。abstractとproxyについて解説していきます。サンプルコードを使いながら解説していきます。
◆abstract=Trueの設定
サンプルコード
from django.db import models
#抽象クラス
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
#Meta内で設定
class Meta:
#デフォルトはFalse設定
abstract = True
#CommonInfoを継承
class Student(CommonInfo):
group = models.CharField(max_length=20)
abstract = Trueと設定することで、抽象クラスに設定でき他クラスで継承することができます。抽象クラスを設定し継承することで、継承したクラス内(Student)で、抽象クラスで定義したフィールド(name、age)を継承することができます。
また特徴として、抽象化設定されたクラス(CommonInfo)のDBテーブルは作成されずに、継承したクラス(Student)のみDBテーブルが作成されます。この作成されたDBテーブル内に抽象クラスで定義したフィールド(name、age)のカラムが追加されます。
上記のサンプルコード以外にも下記のような使い方もできるので結構便利です。よく使用する日時に関するフィールドをTimeStampとまとめることで、よりコードを短くまとめることができます。
サンプルコード
from django.db import models
class TimeStamp(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Post(TimeStamp):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
body = models.TextField()
◆proxy=Trueの設定
サンプルコード
from django.db import models
class MyModel(models.Model):
name = models.CharFiel d(max_length=100)
class UpperModel(MyModel):
#Meta内で設定
class Meta:
#デフォルトはFalse
proxy = True
#メソッド追加
def __str__(self):
#大文字にする
return self.name.upper()
メソッドだけ変更したい時 or 追加したい時に使用します。
MyModelの方は、DBテーブルが作成されますが、UpperModelの方は DBテーブルが作成されません。つまりUpperModelでは、MyModelで作成されるDBテーブルを継承してるということです。
管理画面は、以下のようになります。
管理画面(UpperModel)
データを保存すると…
3. 関連リンク
今回よく使うメソッドやMetaオプションを紹介しましたが、特にMetaオプションについては、他にも色々種類があります。ぜひ一度公式ドキュメントを確認してみてください。
4. 最後に
いかがでしたか?
次回は、モデルクラスより作成したDBからどのようにデータを取得するかについて解説していきます。
ぜひご期待ください!
この記事が気に入ったらサポートをしてみませんか?