Djangoで指定したfieldだけ表示する(クラスベース汎用ビューのDetailViewを使う)

概要

  • Djangoのテンプレートで、あらかじめ指定したフィールドだけ表示したい
    • Userモデルで、is_activeなど不要なフィールドは見せたくない
    • django.views.generic.DetailView で表示する想定
  • フィールドを後から増減させたときに、なるべく一箇所だけの変更で済ませたい

対応

  • modelクラスに、指定したフィールドだけを抽出する関数を追加する
    • viewごとに表示するフィールドを変えたい場合は、下記のviewable_field_listを上書きする

ソースコード

models.py

class CustomUser(AbstractUser):

    # get viewable fields with order.
    viewable_field_list = ('userType', 'username', 'email', 'companyName', 'nearestStation')
    editable_field_list = ('username', 'companyName', 'nearestStation')
    def get_selected_fields(self):
        """Returns a list of selected field names on the instance."""
        fields = []
        for vf in self.viewable_field_list:
            for f in self._meta.fields:
                fname = f.name
                if vf != fname:
                    continue
                # resolve picklists/choices, with get_xyz_display() function
                get_choice = 'get_'+fname+'_display'
                if hasattr(self, get_choice):
                    value = getattr(self, get_choice)()
                else:
                    try:
                        value = getattr(self, fname)
                    except AttributeError:
                        value = None

                # only display fields with values and skip some fields entirely
                if f.editable:  # and value:
                    fields.append(
                    {
                    'label':f.verbose_name,
                    'name':f.name,
                    'value':value,
                    'is_editable': f.name in self.editable_field_list
                    }
                    )
        return fields

template

<ul>
  {% for f in object.get_selected_fields %}
    <li>{{ f.label|capfirst }} ( {{ f.name }} ) : {{ f.value|escape|urlize }} (editable={{ f.is_editable }})</li>
  {% endfor %}
</ul>

必要に応じて、viewの記述も変更

views.py

class UserDetailView(OnlyYouMixin, DetailView):
    model = CustomUser

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if int(context["object"].userType.id) == USERTYPE_SUPPLIER:
            self.model.viewable_field_list = ('userType', 'username', 'email', 'companyName',)
        elif int(context["object"].userType.id) == USERTYPE_BUYER:
            self.model.viewable_field_list = ('userType', 'username', 'email', 'nearestStation')
        return context

参考

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です