【问题标题】:Django admin - inline inlines (or, three model editing at once)Django admin - 内联内联(或者,一次编辑三个模型)
【发布时间】:2010-10-16 16:50:57
【问题描述】:

我有一组看起来像这样的模型:

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 管理员中的 inline-in-an-inline 技巧失败了。有谁知道允许这种三级模型编辑的方法?提前致谢。

【问题讨论】:

  • 你能用你接受的解决方案展示你的最终代码吗?

标签: python django django-models django-admin inlines


【解决方案1】:

我的建议实际上是更改您的模型。为什么在LinkLinkSection 中没有ForeignKey?或者,如果不是 OneToMany,也许是 ManyToMany 字段?管理界面将免费生成。当然,如果链接在逻辑上与链接部分没有任何关系,我不建议这样做,但也许它们有关系?如果他们不这样做,请解释预期的组织是什么。 (例如,每个部分 3 个链接是固定的还是任意的?)

【讨论】:

  • 愚蠢的我,我忽略了我本来应该在那里的 ForeignKey 字段:)。链接确实与链接部分(旨在作为各种标题)有关。每个部分的 3 个链接是任意的。我将编辑 OP 以更好地反映这一点。
【解决方案2】:

您可以创建一个类似于 TabularInline 或 StackedInline 的新类,它本身能够使用内联字段。

或者,您可以创建新的管理模板,专门用于您的模型。但这当然会推翻管理界面的漂亮功能。

【讨论】:

    【解决方案3】:

    您需要为LinkSectionInline 创建自定义formtemplate

    这样的东西应该适用于表单:

    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。

    【讨论】:

    • 我们可以获取此答案的示例模板代码吗?为此分叉 Django 的 change_form.html 是否可取?另外,在 Django 1.2.3 中,第一行应该是 LinkFormSet = forms.inlineformset_factory(Link)
    • 您好,我正在尝试让它工作,但是 LinkFormset 出现错误,不想采用 instance = self.instance,任何建议
    • 将表单集嵌套在表单中的绝妙想法。将测试:-)
    • TypeError: __init__() got an unexpected keyword argument 'instance'使用时,大概和@Hugoagogo一样
    【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-26
      • 2012-04-19
      • 2014-09-27
      • 1970-01-01
      • 2018-10-11
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多