GVKun编程网logo

Django admin-内联内联(或一次编辑三个模型)(django内联保存)

20

最近很多小伙伴都在问Djangoadmin-内联内联和或一次编辑三个模型这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展DjangoAdminCookbook-15如何在Djang

最近很多小伙伴都在问Django admin-内联内联或一次编辑三个模型这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展Django Admin Cookbook-15 如何在 Django Admin 后台模型列表页面中添加自定义操作按钮、Django Admin Cookbook-16如何使用Django Admin管理后台导入CSV、Django Admin Cookbook-38如何获取特定对象的Django Admin后台URL、Django Admin Cookbook-42如何在Django Admin后台控制台中设置应用程序和模型的顺序等相关知识,下面开始了哦!

本文目录一览:

Django admin-内联内联(或一次编辑三个模型)(django内联保存)

Django admin-内联内联(或一次编辑三个模型)(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 = Linkclass 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管理员中失败。有人知道允许这种三级模型编辑的方法吗?提前致谢。

答案1

小编典典

你需要创建一个自定义表单和模板的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和form.link_formset。

Django Admin Cookbook-15 如何在 Django Admin 后台模型列表页面中添加自定义操作按钮

Django Admin Cookbook-15 如何在 Django Admin 后台模型列表页面中添加自定义操作按钮

15. 如何在 Django Admin 后台模型列表页面中添加自定义操作按钮?

UMSRA 之前决定,如果有足够的 k 石,所有 Hero 英雄都可以死亡。但是,他们希望能够改变主意,让所有 Hero 英雄都可以永生。

你需要添加两个按钮:一个按钮使所有英雄都可以死亡,而另一个按钮使所有英雄永生。由于它会影响所有英雄,而与选择无关,因此这需要一个单独的按钮,而不是操作下拉菜单。

首先,我们要更改 HeroAdmin 管理模型使用的模板文件,以便我们可以添加两个按钮:

@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):
    change_list_template = "entities/heroes_changelist.html"

然后,我们需要覆盖 get_urls 方法,并在管理模型上添加 set_immortal 和 set_mortal 方法。它们将用作两种 view 视图:

def get_urls(self):
    urls = super().get_urls()
    my_urls = [
        path(''immortal/'', self.set_immortal),
        path(''mortal/'', self.set_mortal),
    ]
    return my_urls + urls
def set_immortal(self, request):
    self.model.objects.all().update(is_immortal=True)
    self.message_user(request, "All heroes are now immortal")
    return HttpResponseRedirect("../")
def set_mortal(self, request):
    self.model.objects.all().update(is_immortal=False)
    self.message_user(request, "All heroes are now mortal")
    return HttpResponseRedirect("../")

最后,我们通过扩展 admin/change_list.html 来创建模板文件 entities/heroes_changelist.html:

{% extends ''admin/change_list.html'' %}
{% block object-tools %}
    <div>
        <form action="immortal/" method="POST">
            {% csrf_token %}
                <button type="submit">Make Immortal</button>
        </form>
        <form action="mortal/" method="POST">
            {% csrf_token %}
                <button type="submit">Make Mortal</button>
        </form>
    </div>
    <br />
    {{ block.super }}
{% endblock %}

在点击页面的 make_mortal 动作后,英雄全都可以死亡,你会看到如下消息提示。

返回目录

Django Admin Cookbook-16如何使用Django Admin管理后台导入CSV

Django Admin Cookbook-16如何使用Django Admin管理后台导入CSV

16.如何使用Django Admin管理后台导入CSV?

假设你需要允许在Hero管理页面上导入CSV数据。为此,您需要添加一个指向更改Hero列表页面的链接,点击这个链接会跳转到上传页面。你需要编写一个处理POST请求的方法,来从CSV文件中获取数据对象:

class CsvImportForm(forms.Form):
    csv_file = forms.FileField()
@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):
    ...
    change_list_template = "entities/heroes_changelist.html"
    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            ...
            path(''import-csv/'', self.import_csv),
        ]
        return my_urls + urls
    def import_csv(self, request):
        if request.method == "POST":
            csv_file = request.FILES["csv_file"]
            reader = csv.reader(csv_file)
            # Create Hero objects from passed in data
            # ...
            self.message_user(request, "Your csv file has been imported")
            return redirect("..")
        form = CsvImportForm()
        payload = {"form": form}
        return render(
            request, "admin/csv_form.html", payload
        )

然后创建模板文件entities/heroes_changelist.html,以覆盖原有的admin/change_list.html:

{% extends ''admin/change_list.html'' %}
{% block object-tools %}
    <a href="import-csv/">Import CSV</a>
    <br />
    {{ block.super }}
{% endblock %}

最后,创建上传页面csv_form.html:

{% extends ''admin/base.html'' %}
{% block content %}
    <div>
        <form action="." method="POST" enctype="multipart/form-data">
            {{ form.as_p }}
            {% csrf_token %}
                <button type="submit">Upload CSV</button>
        </form>
    </div>
    <br />
{% endblock %}

修改完后,会在更改Hero后台列表页面上会有一个Import CSV的链接.

点击后上传页面显示如下。

返回目录

Django Admin Cookbook-38如何获取特定对象的Django Admin后台URL

Django Admin Cookbook-38如何获取特定对象的Django Admin后台URL

38.如何获取特定对象的Django Admin后台URL?

Hero模型有一个children字段,显示每个英雄的孩子的名字。你被要求将每个childrin链接到Hero模型更改页面。实现如下:

@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):
    ...
    def children_display(self, obj):
        display_text = ", ".join([
            "<a href={}>{}</a>".format(
                    reverse(''admin:{}_{}_change''.format(obj._meta.app_label, obj._meta.model_name),
                    args=(child.pk,)),
                child.name)
             for child in obj.children.all()
        ])
        if display_text:
            return mark_safe(display_text)
        return "-"

以上的reverse(''admin:{}_{}_change''.format(obj._meta.app_label, obj._meta.model_name), args=(child.pk,))返回一个对象后台修改页的URL。

其他页面如下:

  • 删除页URL: reverse(''admin:{}_{}_delete''.format(obj._meta.app_label, obj._meta.model_name), args=(child.pk,))
  • 历史页URL: reverse(''admin:{}_{}_history''.format(obj._meta.app_label, obj._meta.model_name), args=(child.pk,))

返回目录

Django Admin Cookbook-42如何在Django Admin后台控制台中设置应用程序和模型的顺序

Django Admin Cookbook-42如何在Django Admin后台控制台中设置应用程序和模型的顺序

42.如何在Django Admin后台控制台中设置应用程序和模型的顺序

Django默认情况下,按字母顺序对模型进行排序。因此,Event应用模型的顺序为Epic、EventHero、EventVillain、Event

假设你希望顺序是

  • EventHero、EventVillain、Epic、Event。

用于呈现后台indxe页面的模板为admin/index.html,对应的视图函数为 ModelAdmin.index。

def index(self, request, extra_context=None):
    """
    Display the main admin index page, which lists all of the installed
    apps that have been registered in this site.
    """
    app_list = self.get_app_list(request)
    context = {
        **self.each_context(request),
        ''title'': self.index_title,
        ''app_list'': app_list,
        **(extra_context or {}),
    }
    request.current_app = self.name
    return TemplateResponse(request, self.index_template or
        ''admin/index.html'', context)

默认的get_app_list方法用于设置模型的顺序。

def get_app_list(self, request):
    """
    Return a sorted list of all the installed apps that have been
    registered in this site.
    """
    app_dict = self._build_app_dict(request)

    # Sort the apps alphabetically.
    app_list = sorted(app_dict.values(), key=lambda x: x[''name''].lower())

    # Sort the models alphabetically within each app.
    for app in app_list:
        app[''models''].sort(key=lambda x: x[''name''])
    return app_list

因此,可以通过覆盖get_app_list方法来修改显示顺序:

class EventAdminSite(AdminSite):
    def get_app_list(self, request):
        """
        Return a sorted list of all the installed apps that have been
        registered in this site.
        """
        ordering = {
            "Event heros": 1,
            "Event villains": 2,
            "Epics": 3,
            "Events": 4
        }
        app_dict = self._build_app_dict(request)
        # a.sort(key=lambda x: b.index(x[0]))
        # Sort the apps alphabetically.
        app_list = sorted(app_dict.values(), key=lambda x: x[''name''].lower())
        # Sort the models alphabetically within each app.
        for app in app_list:
            app[''models''].sort(key=lambda x: ordering[x[''name'']])
        return app_list

以上代码app[''models''].sort(key=lambda x: ordering[x[''name'']])用来设置默认顺序。修改后效果如下。

返回目录

我们今天的关于Django admin-内联内联或一次编辑三个模型的分享已经告一段落,感谢您的关注,如果您想了解更多关于Django Admin Cookbook-15 如何在 Django Admin 后台模型列表页面中添加自定义操作按钮、Django Admin Cookbook-16如何使用Django Admin管理后台导入CSV、Django Admin Cookbook-38如何获取特定对象的Django Admin后台URL、Django Admin Cookbook-42如何在Django Admin后台控制台中设置应用程序和模型的顺序的相关信息,请在本站查询。

本文标签: