2009-03-31 4 views
51

У меня есть множество моделей, которые выглядят так:Django администратора - встроенные встраивает (или три модели редактирования сразу)

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, ] 

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

<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 %} 

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

+3

Не могли бы вы показать свой окончательный код с решением, которое вы приняли? –

ответ

20

Вам необходимо создать таможню form и template для 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 

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

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

+7

Можем ли мы получить образец шаблона кода для этого ответа? Возможно ли это для fork Django change_form.html? Кроме того, в Django 1.2.3 первая строка должна быть LinkFormSet = forms.inlineformset_factory (Link) – Bluu

+3

Привет, я пытаюсь заставить это работать, но я получаю ошибки с LinkFormset, не желающим принимать экземпляр = self.instance, любые рекомендации – Hugoagogo

+1

Блестящая идея вложить форму в форму. Будет проверено, что :-) – vdboor

1

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

+0

Глупо мне, я омрачил поле ForeignKey, которое я хотел быть там :). Ссылки имеют отношение к разделам ссылок (предназначенных для сортировки заголовков). 3 ссылки на раздел произвольны. Я отредактирую OP, чтобы лучше отразить это. –

0

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

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

4

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) 
Смежные вопросы