Как показать raw_id значение отношения ManyToMany в администраторе Django?

У меня есть приложение с помощью raw_id и на ForeignKeyField и на ManyToManyField. Администратор отображает значение внешнего ключа справа от окна редактирования.

Unfortunatey, это не работает с ManyToMany. Я проверил код, и я думаю, что это - нормальное поведение. Однако я хотел бы знать, есть ли у кого-то легкая подсказка для изменения этого поведения?

Заранее спасибо

Обновление: я попытался разделить ManyToManyRawIdWidget на подклассы, но я не знаю, как сказать, что raw_id_fields должен использовать мой пользовательский виджет. formfield_overrides, кажется, не работает с raw_id полями

5
задан luc 8 June 2010 в 11:27
поделиться

1 ответ

Наконец мне удалось заставить его работать. Вот обновленная версия Django2.0

from django.contrib.admin.widgets import ManyToManyRawIdWidget
from django.utils.encoding import smart_str
from django.urls import reverse
from django.utils.html import escape, mark_safe


class VerboseManyToManyRawIdWidget(ManyToManyRawIdWidget):
    """
    A Widget for displaying ManyToMany ids in the "raw_id" interface rather 
    than in a <select multiple> box. Display user-friendly value like the ForeignKeyRawId widget
    """

    def __init__(self, remote_field, attrs=None, *args, **kwargs):
        super().__init__(remote_field, attrs, *args, **kwargs)

    def label_and_url_for_value(self, value):
        values = value
        str_values = []
        field = self.rel.get_related_field()
        key = field.name
        fk_model = self.rel.model
        app_label = fk_model._meta.app_label
        class_name = fk_model._meta.object_name.lower()
        for the_value in values:
            try:
                obj = fk_model._default_manager.using(self.db).get(**{key: the_value})
                url = reverse('admin:{0}_{1}_change'.format(app_label, class_name), args=[obj.id])
                label = escape(smart_str(obj))
                elt = '<a href="{0}" {1}>{2}</a>'.format(
                    url,
                    'onclick="return showAddAnotherPopup(this);" target="_blank"',
                    label
                )
                str_values += [elt]
            except fk_model.DoesNotExist:
                str_values += [u'???']
        return mark_safe(', '.join(str_values)), ''


class MyAdmin(admin.ModelAdmin):
     ...
     def formfield_for_dbfield(self, db_field, **kwargs):
         if db_field.name in ('groups', ):
             kwargs['widget'] = VerboseManyToManyRawIdWidget(db_field.remote_field, self.admin_site)
         else:
             return super().formfield_for_dbfield(db_field, **kwargs)
         kwargs.pop('request')
         return db_field.formfield(**kwargs)

К сожалению, я зря потратил вознаграждение; -)

ОБНОВЛЕНИЕ: этот фрагмент теперь совместим с Django 2.0. См. Также http://djangosnippets.org/snippets/2108/

9
ответ дан 13 December 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: