【Django】モデルのフィールド名は_アンダースコアから始めない方が良い

モデルのフィールド名は アンダースコアから初めない

こんばんはエンジニアの眠れない夜です。

Djangoで開発をしていてモデルのフィールド名に_アンダースコアをつけて後悔した話です。

結論から言うとタイトルの通りで、「モデルのフィールド名は_アンダースコアから始めない方が良い」です。

_アンダースコアで始めないほうがいい理由

それを話していく前にまずはどんなものを作ってしまったかをご紹介します。

開発をしていて私はこんなフィールドを作りました。

class Message(models.Model):
    create_at = models.DateTimeField(default=timezone.now)
    _from = models.ForeignKey(User)
    to = models.ForeignKey(User)
    body = models.TextField()

(読みづらいので細かい設定は省略しています)

何をしたいかというとMessageモデルにfromとtoというフィールドをもたせてUserモデルに関連付けてメッセージをやり取りをする機能を作りたかったのです。

そこでfromはpythonの予約ごと重複するので_fromというpythonでローカル変数を指定するときなどに使う方法で名前をつけてみました。

しかし、これだとテンプレートで呼び出す時に

Message._from

とやると下記のエラーが出て怒られます。

Variables and attributes may not begin with underscores django template

アンダースコアから始まる変数と属性はダメ。ってことですね。

そこで、調べてみるとテンプレートフィルターを使えば回避できるよ的なことが紹介されていました。

ただ、この方法だとdict型から取り出す分にはいいのですが、Modelに対して実行すると取ってきたモデルのフィールドにはアクセスできません。

message|get:"_from".email # エラーが出る

キーを使って返ってくるフィールドを選択できるようにテンプレートタグを作ってみました。

@register.filter(name='from')
def get(message,key):
    if key=='pk' or key=='id':return message._from.id
    if key=='email':return message._from.email
    return message._from.username

しかし、毎回こんなふうに書くのは面倒です。

message|from:"email"

UserがImageFiledを持っていてその先のフィールドにアクセスしたい時はこんな書き方ではアクセスさせてくれません。

message|from:"image".url

こんなことをするくらいなら初めからモデルのフィールド名にアンダースコアから始まる名前をつけない方がメンテが楽です。

ちなみに、アンダースコアをフィールド名の後ろにつけると
from_

base.Message.from_: (fields.E001) Field names must not end with an underscore.

フィールド名はアンダースコアで終わるのはダメ。と怒られます。

と、いうことで、、、

まとめと妥協案

「Djangoのモデルのフィールド名は_アンダースコアから始めない方が良い」ということです。

回避策としていいなと思ったのは関連モデルの名前を接尾語として足すのが今のところ一番いい方法ではないかと思います。

from_user

これなら予約ごとぶつかる心配もないですし、フィールドの意味も分かりやすい!

`from_user.id`
`from_user.email`
`from_user.username`

うん。わかりやすい。いっそのことtoto_userにしてしまった方がいいのではないかという気がしてきました。

`to_user.id`
`to_user.email`
`to_user.username`

他にもいい方法があれば是非コメントを頂けると嬉しいです。

※ 間違っているところなどありましたらご指摘いただけますと幸いです。

1 Comment

【Django】related_nameの設定でエラーが出たら | エンジニアの眠れない夜 へ返信するコメントをキャンセル

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください