Как отобразить встроенную модель администратора Django в наборе полей?
Рассмотрим следующую модель администратора. В этом случае я хотел бы, чтобы встроенный пользовательский интерфейс " книга "отображался между набором полей" нет " и набором полей Notes. Разве это возможно?
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
fieldsets = (
(None, {
'fields': ('author_name', 'date_of_birth')
}),
('Notes', {
'fields': (['notes'])
}),
)
3 ответа:
К сожалению, это невозможно с (стандартным шаблоном из) django. Если вы посмотрите на шаблон для формы change_form, то увидите, что строки inlines всегда отображаются отдельно после набора полей: https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
Единственное решение, которое я вижу, - это написать пользовательский шаблон в соответствии с тем порядком, который вы хотите.
Бертран Бортаж опубликовал здесь другое решение: https://groups.google.com/forum/#! topic / django-users/yUq2Nvx_4eM
Поздний ответ, чтобы сказать, что я просто подтолкнул довольно чистое решение к этому проблема в одном из моих проектов: https://github.com/dezede/dezede/commit/ed13ccaf34494e71fd913fd785c229052f6acdc8 .
Идея состоит в том, чтобы определить fieldsets_and_inlines_order в вашем ModelAdmin(s), итерируемый из символов' f 'и' i '(для " fieldset" и "inline"), который определяет порядок между первыми наборами полей и линейный. Если len (fieldsets_and_inlines_order)
Пример: У вас есть 5 наборов полей и 3 строки, определяющие fieldsets_and_inlines_order = ('f', 'f', 'i', 'f', 'i') даст вам: полей полей полей полей полей рядный рядный рядный надеюсь это помогает, Бертран
У меня был еще одна идея, которую стоит рассмотреть. Создайте поле заполнителя только для чтения в ваших наборах полей для каждого встроенного, а затем используйте jQuery для перемещения строк ввода на место для каждого заполнителя. Что-то вроде этого (jQuery опущен, поскольку я его еще не написал):
fieldsets = ( (None, { 'fields': ( ('inline_images',) ('thumbnail_image',), ('inline_authors',) ('title', 'is_active', 'order',) ), }), ) readonly_fields = ('inline_images', 'inline_authors') inline_images = '<span class="replaceme inline_images"></span>' inline_images.allow_tags = True inline_authors = '<span class="replaceme inline_authors"></span>' inline_authors.allow_tags = True
Еще одна вещь-есть открытая проблема Django, требующая такого позиционирования inlines: https://code.djangoproject.com/ticket/4848
Я построил еще одно довольно общее решение...
В вашем admin.py добавьте новое поле в строку:
class YourModelInline(admin.TabularInline): model = YourModel after_field = "fieldname_of_field_before_inline"
Затем настройте форму render_change_form AdminClass модели, которая содержит Inline:
class EditModelAdmin(model.ModelAdmin): inlines = [YourModelInline,] def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): sorted_inline_formsets = {} inline_admin_formsets = context['inline_admin_formsets'] formsets_to_remove = [] for inline_formset in inline_admin_formsets: if hasattr(inline_formset.opts, 'after_field'): fieldname = inline_formset.opts.after_field if fieldname in sorted_inline_formsets: sorted_inline_formsets[fieldname].append(inline_formset) else: sorted_inline_formsets.update({ fieldname: [inline_formset,] }) formsets_to_remove.append(inline_formset) for inline_formset in formsets_to_remove: inline_admin_formsets.remove(inline_formset) context.update({ 'sorted_inline_formsets': sorted_inline_formsets, 'inline_admin_formsets': inline_admin_formsets }) return super(EditModelAdmin, self).render_change_form(request, context, add=add, change=change, obj=obj, form_url=form_url)
Мы перемещаем все строки с дополнительным полем в собственный словарь с именем Поля в качестве ключа... Для корректной визуализации создайте файл / templates / admin / includes / fieldset.html, который переопределяет стандартный набор полей django.html со следующим содержание:
{% load custom_filter %} <fieldset class="module aligned {{ fieldset.classes }}"> {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %} {% if fieldset.description %} <div class="description">{{ fieldset.description|safe }}</div> {% endif %} {% for line in fieldset %} <div class="form-row{% if line.fields|length_is:'1' and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}"> {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %} {% for field in line %} <div{% if not line.fields|length_is:'1' %} class="field-box{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}"{% elif field.is_checkbox %} class="checkbox-row"{% endif %}> {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.errors }}{% endif %} {% if field.is_checkbox %} {{ field.field }}{{ field.label_tag }} {% else %} {{ field.label_tag }} {% if field.is_readonly %} <div class="readonly">{{ field.contents }}</div> {% else %} {{ field.field }} {% endif %} {% endif %} {% if field.field.help_text %} <div class="help">{{ field.field.help_text|safe }}</div> {% endif %} </div> {% if field.field.name %} {% with field.field.name as fieldname %} {% if sorted_inline_formsets|get_dict_value:fieldname != False %} {% for inline_admin_formset in sorted_inline_formsets|get_dict_value:fieldname %} {% include inline_admin_formset.opts.template %} {% endfor %} {% endif %} {% endwith %} {% endif %} {% endfor %} </div> {% endfor %} </fieldset>
Это добавит сортированные строки после соответствующего поля... Теперь вам нужен только custom_filter для работы со словарем в шаблоне django, создать templatetags/custom_filter.py и добавить:
@register.filter def get_dict_value(dict, key): if key in dict: return dict[key] else: return False
И вуаля: вы можете ввести любое имя поля в любой встроенный, чтобы добавить его после этого поля... Это немного работы для настройки, но если у вас есть несколько строк для сортировки, это может быть более чистым способом...