Django入门教程

前言

第一章: django快速入门

第二章: django MTV架构

第三章: django视图

第四章: django模板

第五章: django模型

第六章: django后台管理系统

第七章: 项目实战-简易的博客系统

第八章:django表单

第九章:django用户认证系统

第十章:django中的会话

第十一章:django安全

第十二章:django性能优化

第十三章:django实用工具

首页 > Django入门教程 > 第六章: django后台管理系统 > 6.4节: 自定义模型编辑页

6.4节: 自定义模型编辑页

薯条老师 2020-08-28 07:19:49 295517 0

编辑 收藏

广州番禺Python, Java小班周末班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人,学员的平均就业薪资有11K不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。培训的课程有Python爬虫,Python后端开发,Python办公自动化,Python大数据分析,Python量化投资,Python机器学习,Java中高级后端开发。授课详情请点击:http://chipscoco.com/?cate=6

6.4.1 自定义模型编辑页

ModelAdmin类型中提供了许多选项和方法,通过覆盖这些选项和方法可以灵活地对模型的列表页和编辑页进行自定义。对列表页或编辑页进行自定义,需要从ModelAdmin中派生一个子类,然后在子类中覆盖这些选项和方法。在本节的内容中,以Blog模型来进行演示。自定义模型编辑页,也是通过覆盖ModelAdmin类中的属性和方法来实现的。点击列表页中的数据项的链接,即可跳转至数据的编辑页:

 image.png 

6.4.2 exclude选项

exclude选项用来定义不在编辑页进行显示的字段。

代码实例:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    # 将author字段在编辑页中进行排除
    exclude = ("author",)

页面效果:

image.png 

6.4.3 readonly_fields选项

readonly_fields选项用来定义编辑页中哪些字段为只读。日期时间类型如果设置了auto_now或者auto_now_add选项,则也为只读,并且不会显示在页面中。

代码实例:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    
    # 定义author字段为只读
    readonly_fields = ["author"]

页面效果:

image.png 

从页面输出可知,作者一栏变成了只读,并被移到了页面底部。通过覆盖fields或fieldsets选项,可以自定义字段的排列顺序。

6.4.4 fields、fieldsets选项

fields与fieldsets选项都可以自定义模型字段的排列顺序,但只能同时定义其中一个,否则会出现布局冲突。fields的用法很简单,django会根据fields中元素的先后顺序来进行排列,未添加至fields中的元素不会进行显示。

代码实例:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    readonly_fields = ["author"]
    
    # 在编辑页中只显示作者,标题,内容,且按其先后顺序进行排列
    fields = ("author","title","content")

页面效果:

 image.png

将多个字段保存至二元元组或列表中,会将多个字段在一行中进行排列:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    readonly_fields = ["author"]
    
    # 将分类与插图在一行中进行排列
    fields = ("author","title","content",("category","illustration"))

页面效果:

image.png 

 

fieldsets是一个二元的元组或列表,用来对模型字段进行分组显示,格式为: ((name,field_options)):

name用来定义分组项的标题,field_options是一个字典类型,其常用的选项(键)为:

fields:必传参数,用来定义分组显示的字段,用法同fields选项

classes:可选参数,用来定义css类,常用的值为 collapse 与wide

description:可选参数,用来定义分组字段的描述信息

 

代码实例:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    readonly_fields = ["author"]
    
    # 将分类与插图在一行中进行排列
    fieldsets = (("作者信息",{"fields":("author",)}),
    ("博客正文",{"fields":("title", "content","category"),"classes":('collapse', )}),
    ("博客附件", {"fields": ("illustration",), "classes": ('wide',)}),)

页面效果:

image.png 

 

6.4.5 filter_horizontal、filter_vertical选项

当模型中定义了ManyToManyField字段时,编辑页显示的是一个下拉选择框,在需要选择多个对象时,较为繁琐,通过覆盖filter_horizontal选择,django会使用一个javascript过滤器来对多个数据项进行查询和筛选。filter_vertical同filter_horizontal类似,区别在于前者为垂直布局,后者为水平布局。

6.4.6 formfield_overrides选项

使用formfield_overrides选项来覆盖django模型的字段类型。例如对TextField类型进行了扩展,添加了富文本功能,则可通过formfield_overrides选项来进行覆盖。

代码实例:

class BlogAdmin(admin.ModelAdmin): 
    list_display = ("id","author","title","modify_time",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author",ModifyTimeListFilter,)
    date_hierarchy = "modify_time"
    search_fields = ["title","content"]
    list_editable = ["title"]
    readonly_fields = ["author"]
    
    fieldsets = (("作者信息",{"fields":("author",)}),
    ("博客正文", {"fields":("title", "content","category"),"classes":('collapse', )}),
    ("博客附件", {"fields": ("illustration",), "classes": ('wide',)}),
                 )
                 
  # RichTextEditorWidget为用户自定义的富文本组件
  # 读者在实际使用时需改成你自定义的组件类型    
  formfield_overrides = {
  models.TextField: {'widget': RichTextEditorWidget},
  }

6.4.7 change_view方法

使用change_view方法可以自定义编辑页的展现。 

方法的参数

描述

request

HttpRequest对象,可以基于HttpRequest对象的属性值来进行逻辑控制。

object_id

数据对象的id值

form_url

表单的url,默认为空

extra_context

用来定义一个额外的上下文对象,可以在模板中进行渲染,默认为None


方法的返回值

描述

TemplateResponse对象

在进行模板渲染之前,通过该对象自定义响应数据

现在通过change_view方法来针对不同的用户进行编辑页的展现,如果用户为普通用户则设置相应的字段为只读字段,并通过extra_context传递一个上下文对象在模板中进行渲染。

代码实例

class BlogAdmin(admin.ModelAdmin):
    list_display = ("id", "author", "title", "modify_time","category",custom_content)
    list_display_links = ("id", "author")
    list_filter = ("author", ModifyTimeListFilter)
    list_editable = ["title"]
    date_hierarchy = "modify_time"
    list_per_page = 1
    
    fieldsets = (("作者信息",{"fields":("author",)}),
    ("博客正文",{"fields":("title", "content","category"),"classes":('collapse', )}),
    ("博客附件", {"fields": ("illustration",), "classes": ('wide',)}),
    )
    
    
    def change_view(self, request, object_id, extra_context=None):
        extra_context = extra_context or {}
        # 通过extra_context字段传递一个上下文对象进行渲染
        extra_context['is_super'] = True
        # 如果不是超级管理员,则将作者,标题,内容字段设置为只读  
        if not request.user.is_superuser:
            self.readonly_fields =("author", "title", "content")
            extra_context['is_super'] = False
            return super(BlogAdmin, self).change_view(request, object_id, extra_context=extra_context)

模板页面需要从django安装包中的模板目录进行复制,然后拷贝到项目模板目录中的admin目录中。例如编辑页对应的模板页面为:change_form.html,其在django安装目录的路径:

django\contrib\admin\templates\admin\change_form.html

然后将其拷贝到项目模板目录中的admin目录中(需要先在模板目录中创建admin目录)。

change_form.html改动后的部分代码:

{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_modify %}
 
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{{ media }}
{% endblock %}
 
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}">{% endblock %}
 
{% block coltype %}colM{% endblock %}
 
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div>
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
› {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}
 
{% block content %}<div id="content-main">
{% block object-tools %}
{% if change %}{% if not is_popup %}
{% if is_super %}
<h1>你好管理员</h1>
{% endif %}

模板中的is_super变量即为通过extra_context上下文对象传递的参数。

页面效果:

 image.png

在编辑页中新增了一行对管理员的欢迎信息:“你好管理员”

6.4.7 最具实力的小班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人。不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。打算参加小班培训的同学,必须遵守薯条老师的学习安排,认真做作业和项目。把知识学好,学扎实,那么找到一份高薪的工作就是很简单的一件事。

(1) Python后端工程师高薪就业班,月薪11K-18K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,包拿Offer
(3) 数据分析高薪就业班,月薪11K-15K, 免费领取课程大纲
(4)
Python大数据挖掘,量化投资就业班,月薪12K-25K,免费领取课程大纲

扫码免费领取Python学习资料:



欢迎 发表评论: