Подтвердить что ты не робот

Как я могу отобразить встроенную модель администратора Django в наборе полей?

Рассмотрим следующий ModelAdmin. В этом случае я хотел бы иметь встроенный дисплей "Book" UI между полем "Нет" и полем "Примечания". Возможно ли это?

class AuthorAdmin(admin.ModelAdmin):
    inlines = [BookInline]

    fieldsets = (
            (None, {
                'fields': ('author_name', 'date_of_birth')
            }),
            ('Notes', {
                'fields': (['notes'])
            }),
    )
4b9b3361

Ответ 1

К сожалению, это невозможно с (стандартным шаблоном) django. Если вы посмотрите на шаблон для change_form, вы увидите, что строки всегда отображаются отдельно после набора полей: https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html

Единственный рабочий процесс, который я вижу, заключается в написании настраиваемого шаблона в соответствии с желаемым заказом.

Ответ 2

Bertrand Bortage опубликовал еще одно решение: 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) < len (поля) + len (inlines), остальные следуют первоначальному поведению (наборы полей сначала, затем все строки).

Пример: у вас есть 5 полей и 3 строки, определяющие fieldsets_and_inlines_order = ('f', 'f', 'i', 'f', 'i') даст вам: fieldset fieldset inline fieldset inline fieldset fieldset inline Hope это помогает, Бертран

У меня была другая идея, которую стоит рассмотреть. Создайте поле ввода только для чтения в своих полях для каждой строки, затем используйте jQuery для перемещения встроенных строк на место для каждого заполнителя. Что-то вроде этого (jQuery опущен, поскольку я еще не написал его):

fieldsets = (
        (None, {
            'fields': (
                ('inline_images',)
                ('thumbnail_image',),
                ('inline_authors',)
                ('title', 'is_active', 'order',)
            ),
        }),
    )

readonly_fields = ('inline_images', 'inline_authors')

inline_images = '<span id='replaceme inline_images'></span>'
inline_images.allow_tags = True
inline_authors = '<span id='replaceme inline_authors'></span>'
inline_authors.allow_tags = True

Еще одна вещь - есть проблема с открытым Django, требующая такого позиционирования строк: https://code.djangoproject.com/ticket/4848

Ответ 3

Нашел "более чистый" способ встроенных полей в класс admin.ModelAdmin - согласно документации:

" Как и в случае с параметрами полей, чтобы отображать несколько полей в одной строке, оберните эти поля в их собственный кортеж. В этом примере поля first_name и last_name будут отображаться в одной строке:

{
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
}

"см. здесь: https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets

Ответ 4

Я построил еще одно довольно общее решение...

В вашем admin.py добавьте новое поле в свой Inline:

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)

Мы перемещаем все Inlines с дополнительным полем в собственный словарь с именем поля в качестве ключа... Чтобы он правильно отображался, создайте файл /templates/admin/includes/fieldset.html, который переопределяет стандартный django fieldset.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>