Администратор Django - встроенные строки (или редактирование трех моделей одновременно) - PullRequest
51 голосов
/ 31 марта 2009

У меня есть набор моделей, которые выглядят так:

class Page(models.Model):
    title = models.CharField(max_length=255)

class LinkSection(models.Model):
    page = models.ForeignKey(Page)
    title = models.CharField(max_length=255)

class Link(models.Model):
    linksection = models.ForeignKey(LinkSection)
    text = models.CharField(max_length=255)
    url = models.URLField()

и admin.py, который выглядит следующим образом:

class LinkInline(admin.TabularInline):
    model = Link
class LinkSectionInline(admin.TabularInline):
    model = LinkSection
    inlines = [ LinkInline, ]
class PageAdmin(admin.ModelAdmin):
    inlines = [ LinkSectionInline, ]

Моя цель - получить интерфейс администратора, который позволит мне редактировать все на одной странице. Конечным результатом этой структуры модели является то, что вещи генерируются в шаблоне view +, который выглядит примерно так:

<h1>{{page.title}}</h1>
{% for ls in page.linksection_set.objects.all %}
<div>
    <h2>{{ls.title}}</h2>
    <ul>
         {% for l in ls.link_set.objects.all %}
        <li><a href="{{l.url}}">{{l.title}}</a></li>
         {% endfor %}
    </ul>
</div>
{% endfor %}

Я знаю, что трюк inline-in-in-inline не работает у администратора Django, как я и ожидал. Кто-нибудь знает способ разрешить такой вид редактирования трехуровневой модели? Заранее спасибо.

Ответы [ 4 ]

22 голосов
/ 26 августа 2009

Вам необходимо создать пользовательскую форму и шаблон для LinkSectionInline.

Что-то вроде этого должно работать для формы:

LinkFormset = forms.modelformset_factory(Link)
class LinkSectionForm(forms.ModelForm):
    def __init__(self, **kwargs):
        super(LinkSectionForm, self).__init__(**kwargs)
        self.link_formset = LinkFormset(instance=self.instance, 
                                        data=self.data or None,
                                        prefix=self.prefix)

    def is_valid(self):
        return (super(LinkSectionForm, self).is_valid() and 
                    self.link_formset.is_valid())

    def save(self, commit=True):
        # Supporting commit=False is another can of worms.  No use dealing
        # it before it's needed. (YAGNI)
        assert commit == True 
        res = super(LinkSectionForm, self).save(commit=commit)
        self.link_formset.save()
        return res

(Это только что сорвалось с моей головы и не было проверено, но оно должно заставить вас двигаться в правильном направлении.)

Ваш шаблон просто должен правильно отобразить форму и form.link_formset.

4 голосов
/ 28 сентября 2014

Django-nested-inlines создан именно для этого. Использование просто.

from django.contrib import admin
from nested_inlines.admin import NestedModelAdmin, NestedStackedInline, NestedTabularInline
from models import A, B, C

class MyNestedInline(NestedTabularInline):
    model = C

class MyInline(NestedStackedInline):
    model = B
    inlines = [MyNestedInline,]

class MyAdmin(NestedModelAdmin):
    pass

admin.site.register(A, MyAdmin)
1 голос
/ 04 апреля 2009

Я бы порекомендовал изменить вашу модель. Почему бы не иметь ForeignKey в Link до LinkSection? Или, если это не OneToMany, возможно, поле ManyToMany? Интерфейс администратора создаст это бесплатно. Конечно, я не рекомендую это, если ссылки не имеют никакого логического отношения к разделам ссылок, но, возможно, они делают? Если они этого не делают, пожалуйста, объясните, что это за организация. (Например, 3 ссылки на раздел фиксированные или произвольные?)

0 голосов
/ 25 августа 2009

Вы можете создать новый класс, похожий на TabularInline или StackedInline, который может сам использовать встроенные поля.

Кроме того, вы можете создавать новые шаблоны администратора, специально для вашей модели. Но это, конечно, отменяет изящные функции интерфейса администратора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...