Django admin高级用法

@[toc]html

Django admin高级用法

使用Django意味着后台框架的几乎全部内容都会和Django产生互动,排除功能所有手撸的状况.python

Django 后台admin有大量的属性和方法,拥有强大的功能和自定义能力.经过完整的代码来看Django admin的基础设置和高级用法,并结合form表单来实现深度自定义.jquery

简单使用

若是只是使用admin自带的数据管理功能,只须要将模型注册到admin中,就能够实现.ajax

from django.contrib import admin

admin.site.register(News)
admin.site.register(NewsType)
admin.site.site_header = "数据库"
admin.site.index_title = "新闻后台"
复制代码

Django后台会将对应数据表的全部字段进行展现,默认点击id会进入修改页面,对应change_form.html模板.数据库

自定义admin类

使用admin也能够自定义一个admin的类,来自定义后台实现的属性和方法,而后经过register()来将自定义的类和模型注册在一块儿.django

注册方式有两种,一种是使用类装饰器,一种是使用siteapp

from django.contrib import admin

# 装饰器注册
@admin.register(ModelClass)
class CustomAdmin(admin.ModelAdmin):
    list_display = '__all__'
复制代码
# 使用site
class CustomAdmin(admin.ModelAdmin):
    exclude = ['id']

admin.site.register(CustomAdmin, ModelClass)
复制代码

admin显示属性的设置

ModelAdmin中的属性设置

admin能够设置在列表页和详情页显示的字段以及搜索字段等的限制,在admin的类中能够直接定义.框架

以使用较多的ModelAdmin为例,ModelAdmin源码中的属性有:ide

# 在列表页显示的字段,默认会显示全部字段,有对应的方法能够重写
list_display = ('__str__',)
# 在列表页显示的字段中,能够连接到change_form页面的字段
list_display_links = ()
# 右侧的筛选,必须是字段,能够继承自SimpleListFilter来自定义筛选字段和规则,SimpleListFilter的方法在后面详细介绍
list_filter = ()
# 联表查询是否自动查询,能够是布尔,列表或元组,若是是列表或元组,则级联查询指定的字段
list_select_related = False
# 列表页每页展现的条数
list_per_page = 100
# 分页,显示所有,真是数据小于该值时才会显示所有
list_max_show_all = 200
# 在列表页能够编辑的字段
list_editable = ()
# 在列表页能够模糊搜索的字段
search_fields = ()
# 对Date和DateTime类型进行搜索
date_hierarchy = None
# 在change_form页面,按钮为,save按钮的值(save as new和save add another)
save_as = False
# 点击保存并继续编辑
save_as_continue = True
# save按钮的位置,是True则显示在页面上方
save_on_top = False
# 自定义分页类
paginator = Paginator
# 详细页面,删除、修改,更新后跳转回列表后,是否保留原搜索条件管理员如今在建立,编辑或删除对象后保留列表视图中的过滤器。
# 能够将此属性设置为False,以恢复以前清除过滤器的行为。
preserve_filters = True
# 在详情页面,若是有FK到其余表,在详情页中能够动态的填加或删除级联数据
inlines = []
复制代码

admin中action操做的设置

admin中的action是指在列表页的动做,默认为删除所选的条目,能够自定义填加动做,将动做注册到action中,须要是一个方法post

# 定制action中的操做
actions = []

action_form = helpers.ActionForm
# action选项显示的位置,页面上方或者页面下方
actions_on_top = True
actions_on_bottom = False
# 是否显示action选择的个数
actions_selection_counter = True
checks_class = ModelAdminChecks
复制代码

BaseModelAdmin中的属性

除了ModelAdmin中的属性,也能够自定义在其父类BaseModelAdmin中的属性和方法,是一些通用的,在继承子BaseModelAdmin的类中也能够完成的属性设置.通常是详情页的属性.

# 自动补全,外键查询数据多时,方便查找
autocomplete_fields = ()
# 详情页,针对外键和M2M字段变成input框形式
raw_id_fields = ()
# 详情页面展现的字段
fields = None
# 详情页面排除的字段,字段能够是数据库中的也能够是自定义的
exclude = None
# 在详情页面对数据进行分隔显示,对应到admin模板中的'fieldsets.html'
fieldsets = None
# 为详情页指定form表单,能够自定义显示的数据,字段
form = forms.ModelForm
# 下面两个是M2M显示时,数据移动选择.能够参考admin中用户的权限操做
filter_vertical = ()  # 纵向展现
filter_horizontal = ()  # 横向展现
# 详情页面使用radio显示选项,FK默认使用select
radio_fields = {}
# 填加页面,在某字段输入值后,自动填加到指定字段
# prepopulated_fields = {"email": ("user",)},email字段会在用户填加user字段时自动填充
prepopulated_fields = {}
# 详情页指定显示的插件,后面详细说明
formfield_overrides = {}
# 详情页面的只读字段
readonly_fields = ()
# 详情页面排序规则
ordering = None
# 禁止某些排序,为空则禁止全部的排序
sortable_by = None
# 编辑时是否在页面上显示view on set,能够经过方法来返回一个连接,后面说明
view_on_site = True
# 列表页,模糊搜索后面显示的数据个数样式
# 为True是显示条数,为False时显示所有
show_full_result_count = True
checks_class = BaseModelAdminChecks
复制代码

模板的定制

指定自定义模板

在ModelAdmin中自带了几个指定模板的属性,能够本身定义HTML文件,来指定给某个模板页面

# Custom templates (designed to be over-ridden in subclasses)
# 添加数据模板页
add_form_template = None
# 修改数据的模板页
change_form_template = None
# 修改多条数据的模板页
change_list_template = None
# 删除确认信息模板页
delete_confirmation_template = None
# 删除关联数据的确认页
delete_selected_confirmation_template = None
# 修改历史的模板页
object_history_template = None
# 弹出框模板页
popup_response_template = None
复制代码

重写自带模板

在django admin里面有本身写好的模板,include模板,每一个app也有对应的模板

admin的自带模板在项目的django/contrib/admin/templates/admin,目录下面

include文目录下是include语法包含的模板。

change_form.html是数据修改页面的模板,若是想在数据详情页面自定义显示的内容,能够自定义这个页面

模板使用的全都是模板语法,注意模板语法的继承机制,在当前页面重写的元素,不会直接显示。

fieldset.htlm是拼接成详情页的块。前面提到,自定义admin类中的fieldset属性,能够自定义详情页,使数据字段分块显示,就是改变了传给这个页面的值。

例如,使用if语句来动态添加jQuery和div标签,只有在访问某个app的数据时添加

{% if app_name in request.path %}
    <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<div>
<fieldset class="custom">

<div id="div"></div>
</fieldset>
{% endif %}
复制代码

结合form表单

django admin结合form表单,重写fieldset.html来实现数据详情页面的深度自定义,经过处理form表单提交的数据,来实现后台功能的彻底自定义。

django的admin中能够指定form类,来自定义显示的内容

from django import forms
# TagValueManager是自定义的类
from tag_manager import TagValueManager

class CustomAddForm(forms.ModelForm):

    """ 根据标签的id,动态生成下拉选项框 """
    for i in TagValueManager.all_tag:
        locals()[
            'field_tag_id_{}'.format(
                i['id'])] = forms.ChoiceField(
            choices=TagValueManager.get_choice(
                i['id']),
            label=i['name'])

    class Meta:
        model = CandidateTag
        fields = '__all__'
        exclude = ['tag_id', 'tag_value', 'ext_1', 'ext_2', 'candidate_id']
复制代码

注意:在form表单中动态生成的属性,必须使用fields=’__all__‘属性,不然不会显示,能够结合exclude属性来控制须要显示的表单

而后在admin中注册form类

class CandidateTagAdmin(admin.ModelAdmin):
    list_display = [
        'id',
        'tag_count',
    ]
    form = CustomAddForm
复制代码

自定义列表页来源

除了能够经过修改admin的属性,来实现列表页展现字段的自定义,也能够对列表页数据进行筛选,例如,筛选出活跃的用户等,这个能够在action中定义新的方法

也能够重写admin中的get_queryset方法,返回的qs是从新筛选以后的数据,能够避免一些业务逻辑上的误操做

这里的代码展现了,在列表页,展现其余表中的数据,注册模型表的数据没有展现

def get_queryset(self, request):
        """ 从candidate表中查询数据,在list_display中统计其标签个数 """
        qs = Candidate.objects.all().order_by('id')
        return qs
复制代码

## 处理form数据

给admin类定义form属性以后,在详情页面传回的数据,会带上form表单里面的数据,而后结合业务逻辑处理这个数据

例如,业务场景,接受form数据,保存到其余几张表,对于展现数据的表,不进行任何操做,那就须要重写save_model方法,这个方法调用了模型的save方法

重写这个方法:

def save_model(self, request, obj, form, change):
        """ 重写save_model方法 """
        candidate_id = request.path.split('/')[4]
        post_dict = request.POST
        # 根据返回的form表单的标签来肯定修改的tag_id
        include_field = 'field_tag_id_'
        for key, value in post_dict.items():
            if include_field in key:
                tag_id = key.split('_')[-1]
                tag_value = value
                try:
                    obj, created = CandidateTag.objects.update_or_create(
                        defaults={'tag_value': tag_value}, candidate_id=candidate_id, tag_id=tag_id)
                except Exception as e:
                    tag_name = TagValueManager.all_tag.get(id=tag_id)['name']
                    messages.add_message(request, messages.ERROR, '求职者的"{}"标签信息保存失败'.format(tag_name))
复制代码

扩展

get_queryset方法中,展现类模型中的统计数据,这个统计数据,不是在数据库中生成的,实在模型类中定义的方法,这个方法的返回值,能够在列表页中直接展现。例如上文中说道的标签的个数

同时,也能够返回一个HTML标签,模板语法中获取这个字段时,获得的是一个HTML标签,直接渲染

from django.utils.safestring import mark_safe
# 使用mark_safe
@mark_safe
def get_user_dept(self,obj):
    """ 这个方法在模型中 """
    return "<p>this is a HTML tag</p>"
# 容许HTML标签
get_report_depts.allow_tags = True
# HTML展现时的字段名
get_report_depts.short_description = '所属部门'
复制代码
相关文章
相关标签/搜索