Help us understand the problem. What is going on with this article?

Django の ModelChoiceField で option タグに属性を追加したい

環境

django 2.2
python 3.6.8

やりたい事

forms.Select の option タグに value 以外の属性も追加したい。

これを

<select name="persons" required="" id="id_persons">
  <option value="" selected="">---------</option>
  <option value="1">山田 太郎</option>
  <option value="2">山田 花子</option>
</select>

↓みたいにしたい

<select name="persons" required="" id="id_persons">
  <option value="" selected="">---------</option>
  <option value="1" age="10">山田 太郎</option>
  <option value="2" age="20">山田 花子</option>
</select>

やってみた

modelsの定義はこんな感じ

models.py
class Person(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    age = models.IntegerField()

    def __str__(self):
        return f"{self.last_name} {self.first_name}" 

forms.Select を継承した SelectPersonWidget を作成

custom_widget.py
class SelectPersonWidget(forms.Select):

__init__ で queryset を渡しておく

custom_widget.py
class SelectPersonWidget(forms.Select):
    def __init__(self, attrs=None, choices=(), queryset=None):
        self.queryset = queryset
        super().__init__(attrs, choices)

create_option で queryset から必要な情報を取得して attrs に追加する

custom_widget.py
class SelectPersonWidget(forms.Select):
    def __init__(self, queryset, attrs=None, choices=()):
        self.queryset = queryset
        super().__init__(attrs, choices)

    def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
        option = super().create_option(name, value, label, selected, index, subindex, attrs)
        if value:
            person = self.queryset.get(pk=value)
            option['attrs'].update({'age': person.age}) # ここで attrs に追加
        return option

作成した SelectPersonWidget を ModelChoiceField の widget に指定する

forms.py
from django. import forms

from .models import Person
from .custom_widget import SelectPersonWidget


class SampleForm(forms.Form):
    all_person = Person.objects.all()

    persons = forms.ModelChoiceField(
        queryset=all_person,
        widget=SelectPersonWidget(queryset=all_person) # ここで指定する
    )

描画してみる。
option タグに age属性 が追加された

image.png

他に方法があれば知りたい

参考

https://docs.djangoproject.com/ja/2.2/ref/forms/widgets/

myname6c7c2
東京都 フリーランスエンジニア Python+Django C#
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした