admin组件详解

admin组件详解

删除所有表:

SELECT concat('DROP TABLE IF EXISTS ', table_name, ';')
FROM information_schema.tables
WHERE table_schema = 'mydb';

admin 管理:

注册:
from django.contrib import admin
from blog.models import Blog
  
#Blog模型的管理器
class BlogAdmin(admin.ModelAdmin):
    # 展示字段
    list_display=('id', 'caption', 'author', 'publish_time')
     
#在admin中注册绑定
admin.site.register(Blog, BlogAdmin)
from django.contrib import admin
from blog.models import Blog
  
#Blog模型的管理器
@admin.register(Blog)
class BlogAdmin(admin.ModelAdmin):
    list_display=('id', 'caption', 'author', 'publish_time')
界面汉化:
settings.py中设置:
	LANGUAGE_CODE = 'zh-hans'
	TIME_ZONE = 'Asia/Shanghai'

基本设置:

 #listdisplay设置要显示在列表中的字段(id字段是Django模型的默认主键)
    list_display = ('id', 'caption', 'author', 'publish_time')
    
    #list_per_page设置每页显示多少条记录,默认是100条
    list_per_page = 50
    
    #ordering设置默认排序字段,负号表示降序排序
    ordering = ('-publish_time',)
  
    #list_editable 设置默认可编辑字段
    list_editable = ['machine_room_id', 'temperature']
  
    #fk_fields 设置显示外键字段
     fk_fields = ('machine_room_id',)
        
 注意:
	默认可以点击每条记录第一个字段的值可以进入编辑界面
    
 设置其他字段也可以点击链接进入编辑界面:
	 list_display_links = ('id', 'caption')

筛选器:

@admin.register(Blog)
class BlogAdmin(admin.ModelAdmin):
    list_display = ('id', 'caption', 'author', 'publish_time')
     
    #筛选器
    list_filter =('trouble', 'go_time', 'act_man__user_name', 'machine_room_id__machine_room_name') #过滤器
    
    search_fields =('server', 'net', 'mark') #搜索字段
    date_hierarchy = 'go_time'    # 详细时间分层筛选 

报错处理:

 date_hierarchy  进行详细时间筛选的时候 可能出现报错:Database returned an invalid datetime value. Are time zone definitions for your database and pytz installed?

处理方法:  

命令行直接执行此命令:     [root@mysql ~]#    mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
然后重启数据库即可。
 
一般ManyToManyField多对多字段用过滤器;标题等文本字段用搜索框;日期时间用分层筛选。

过滤器如果是外键需要遵循这样的语法:本表字段__外键表要显示的字段。如:“user__user_name”

颜色设置:

某些字段设置颜色:
    from django.db import models
from django.contrib import admin
from django.utils.html import format_html
 
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    color_code = models.CharField(max_length=6)
 
    def colored_name(self):
        return format_html(
            '<span style="color: #{};">{} {}</span>',
            self.color_code,
            self.first_name,
            self.last_name,
        )
 
class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'colored_name')
    
 注意:
	代码,是写在models里,而不是admin中的ModelAdmin里

调整标题:

class MyAdminSite(admin.AdminSite):
    site_header = '好医生运维资源管理系统'  # 此处设置页面显示标题
    site_title = '好医生运维'  # 此处设置页面头部标题
 
admin_site = MyAdminSite(name='management')

admin_site = MyAdminSite(name='management') 此处括号内name值必须设置,否则将无法使用admin设置权限

注册的时候使用admin_site.register,而不是默认的admin.site.register
from django.contrib import admin
from hys_operation.models import *

admin.site.site_header = '修改后'
admin.site.site_title = '哈哈'

 不继承 admin.AdminSite 了,直接用admin.site 下的 site_header 和 site_title 

当前用户过滤显示数据:

@admin.register(MachineInfo)
class MachineInfoAdmin(admin.ModelAdmin):
 
    def get_queryset(self, request):
        """函数作用:使当前登录的用户只能看到自己负责的服务器"""
        qs = super(MachineInfoAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(user=UserInfo.objects.filter(user_name=request.user))
 
    list_display = ('machine_ip', 'application', 'colored_status', 'user', 'machine_model', 'cache',
                    'cpu', 'hard_disk', 'machine_os', 'idc', 'machine_group')
    
 ---> 功能: 不同用户·后得到不同界面

编辑页设置:

ManyToMany多对多字段设置。可以用filter_horizontal或filter_vertical:

#Many to many 字段
filter_horizontal=('tags',)

用fields或exclude控制显示或者排除的字段,二选一即可
fields =  ('caption', 'author', 'tags', 'content')
或者

exclude = ('recommend',) #排除该字段
两个字段放在同一行可以如下设置:

fields =  (('caption', 'author'), 'tags', 'content')

关联字段:

fieldsets。该设置可以对字段分块,看起来比较整洁

fieldsets = (
    ("base info", {'fields': ['caption', 'author', 'tags']}),
    ("Content", {'fields':['content', 'recommend']})
)


一对多:
订单主表(BillMain),记录主要信息;一个是订单明细(BillSub),记录购买商品的品种和数量等

from django.contrib import admin
from bill.models import BillMain, BillSub
 
@admin.register(BillMain)
class BillMainAdmin(admin.ModelAdmin):
    inlines = [BillSubInline,]    #Inline把BillSubInline关联进来
    list_display = ('bill_num', 'customer',)
    
class BillSubInline(admin.TabularInline):
    model = BillSub
    extra = 5 #默认显示条目的数量

设置只读:

class MachineInfoAdmin(admin.ModelAdmin):
 
    def get_readonly_fields(self, request, obj=None):
        """  重新定义此函数,限制普通用户所能修改的字段  """
        if request.user.is_superuser:
            self.readonly_fields = []
        return self.readonly_fields
     
    readonly_fields = ('machine_ip', 'status', 'user', 'machine_model', 'cache',
                       'cpu', 'hard_disk', 'machine_os', 'idc', 'machine_group')

数据保存操作:

重写ModelAdmin的save_model实现:
    
    def save_model(self, request, obj, form, change):
    """  重新定义此函数,提交时自动添加申请人和备案号  """
 
    def make_paper_num():
        """ 生成随机备案号 """
        import datetime
        import random
        CurrentTime = datetime.datetime.now().strftime("%Y%m%d%H%M%S")  # 生成当前时间
        RandomNum = random.randint(0, 100)  # 生成的随机整数n,其中0<=n<=100
        UniqueNum = str(CurrentTime) + str(RandomNum)
        return UniqueNum
 
    obj.proposer = request.user
    obj.paper_num = make_paper_num()
    super(DataPaperStoreAdmin, self).save_model(request, obj, form, change)
    
    添加数据时,会自动保存申请人和备案号

获取修改数据时获取保存前的数据:

change参数,可以判断是修改还是新增,同时做相应的操作

def save_model(self, request, obj, form, change):
    if change:  # 更改的时候
        machine_code = self.model.objects.get(pk=obj.pk).machine
        disk_id = self.model.objects.get(pk=obj.pk).disk_id
        disk_code = self.model.objects.get(pk=obj.pk).disk
        machine.Device.objects.filter(pk=disk_id).update(device_status='待报废')
        data = {'server_code': machine_code,
                'device_type': '硬盘',
                'original_code': disk_code,
                'way': '变更',
                'current_code': obj.disk}
        common.DeLog.objects.create(**data)  # 创建日志
    else:  # 新增的时候
        data = {'server_code': obj.machine,
                'device_type': '硬盘',
                'original_code': '',
                'way': '新增',
                'current_code': obj.disk}
        common.DeLog.objects.create(**data)  # 创建日志
    super(MachineExDiskAdmin, self).save_model(request, obj, form, change)

删除操作:

def delete_model(self, request, obj):
    machine.Device.objects.filter(pk=obj.pk).update(device_status='待报废')
    data = {'server_code': obj.machine,
            'device_type': '硬盘',
            'original_code': obj.disk,
            'way': '删除',
            'current_code': '',
            'user_name': request.user}
    common.DeLog.objects.create(**data)  # 创建日志
    super(MachineExDiskAdmin, self).delete_model(request, obj)

限制:

def get_readonly_fields(self, request, obj=None):
    """  重新定义此函数,限制普通用户所能修改的字段  """
    if request.user.is_superuser:
        self.readonly_fields = ['commit_date', 'paper_num']
    elif hasattr(obj, 'is_sure'):
        if obj.is_sure:
            self.readonly_fields = ('project_name', 'to_mail', 'data_selected', 'frequency', 'start_date',
                                    'end_date')
    else:
        self.readonly_fields = ('paper_num', 'is_sure', 'proposer', 'sql', 'commit_date')
 
    return self.readonly_fields
 
def change_view(self, request, object_id, form_url='', extra_context=None):
    change_obj = DataPaperStore.objects.filter(pk=object_id)
    self.get_readonly_fields(request, obj=change_obj)
    return super(DataPaperStoreAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)

修改显示:

修改app的显示名称:
    	在应用的__init__.py里面进行修改即可:
from django.apps import AppConfig
import os
 
 
default_app_config = 'hys_operation.PrimaryBlogConfig'
 
VERBOSE_APP_NAME = u"1-本地服务器资源"
 
 
def get_current_app_name(_file):
    return os.path.split(os.path.dirname(_file))[-1]
 
 
class PrimaryBlogConfig(AppConfig):
    name = get_current_app_name(__file__)
    verbose_name = VERBOSE_APP_NAME

自定义列表字段:

	DataPaperStore模型中有 end_date 字段,如果当前时间大于end_date 是我们想显示一个“已过期”,但admin列表显示不能直接用该字段,也显示不出来。此时可以通过自定义列表字段显示
    
    def expired(self, ps):
    """自定义列表字段, 根据数据单截止日期和当前日期判断是否过期,并对数据库进行更新"""
    import datetime
    from django.utils.html import format_html
    end_date = ps.end_date
    if end_date >= datetime.date.today():
        ret = '未过期'
        color_code = 'green'
    else:
        ret = '已过期'
        color_code = 'red'
    DataPaperStore.objects.filter(pk=ps.pk).update(is_expired=ret)
    return format_html(
                '<span style="color: {};">{}</span>',
                color_code,
                ret,
            )
expired.short_description = '是否已过期'


expired.admin_order_field = 'end_date'  # 使自定义字段 可以通过单击进行排序

筛选:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

admin 扩展:

	默认的django会自动根据我们定义的模型生成form给admin使用,使用到这个form的地方分别是change和add
    
    admin.py:
        
class RecordAdmin(admin.ModelAdmin):
    change_form_template = 'admin/extras/record_change_form.html'
    
 --> 使用change_form_template 重置 change_form所使用得模版

配置的路径下新建html文件 record_change_form.html:
    {% extends "admin/change_form.html" %}
{% load i18n admin_urls static admin_modify %}
 
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
    <script>
        django.jQuery(function() {
            var select = django.jQuery("#id_machine_room_id");
            console.log(select);
            select.change(function(){
{#                console.log("value change"+django.jQuery(this).val());#}
                var url = "/report/sub_servers/"+django.jQuery(this).val();//能够正确的访问到view的url
{#                console.log(url);#}
                django.jQuery.get(
                    url,
                    function(data){
                        var target = django.jQuery("#id_server_ip_id");
                        target.empty();//先要清空一下
                        data.forEach(function(e){
                            // 将从view得到的id和db_user名称赋值给db_server的select
                            console.log(e,e.id,e.name);
                            target.append("<option value='"+e.id+"'>"+e.name+"<option>");
                            target.eq(0).attr('selected', 'true');
                        });
                })
            });
 
        });
    </script>
{#{{ media }}#}
{% endblock %}
from django.conf.urls import url
from hys_operation import views
 
urlpatterns = [
    # url(r'^sub_users/(?P<obj_id>d+)', views.get_sub_users),
    url(r'^sub_servers/(?P<obj_id>d+)', views.get_sub_servers),
]

view.py:

def get_sub_servers(request, obj_id):
    # 查找此机房id下的ip
    servers = MachineInfo.objects.filter(idc=obj_id)
    result = []
    for i in servers:
        # 对应的id和ip组成一个字典
        result.append({'id': i.id, 'name': i.machine_ip})
    # 返回json数据
    return HttpResponse(json.dumps(result), content_type="application/json")

案列:

@admin.register(AmountChangeRecord)
class AmountChangeRecordAdmin(AutoUpdateUserModelAdmin):
    readonly_fields = ['current_amounts', 'created_by', 'confirmed_by', 'datetime_created', 'datetime_updated']
    list_display = [
        'pk', 'customer', 'amounts', 'current_amounts', 'notes',
        'created_by', 'confirmed_by', 'datetime_created', 'datetime_updated']
    list_display_links = ['pk', 'customer', 'amounts', 'current_amounts', 'notes']
    search_fields = ['customer__name', 'customer__mobile']
    autocomplete_fields = ['customer']
    fieldsets = (
        (_('基础信息'), {'fields': ('customer', 'amounts', 'current_amounts', 'notes')}),
        (_('操作记录'), {'fields': ('created_by', 'confirmed_by', 'datetime_created', 'datetime_updated')})
    )

    
        def save_execl(self, request, queryset):
        filename = 'media/{0}_{1}.xls'.format('amounts', datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
        headers = [
            'ID', '姓名', '手机号', '金额变更', '变更后余额', '创建人员', '最后变更人员', '创建日期', '最后更新时间']
        columns = [
            'pk', 'customer__name', 'customer__mobile', 'amounts', 'current_amounts',
            'created_by__full_name', 'confirmed_by__full_name', 'datetime_created', 'datetime_updated']
        return export_excel(queryset, headers, columns, filename)

    save_execl.short_description = "导出Excel"

    actions = [save_execl]

    
    ---> 方法构建的 Excel 导出功能只有在勾选了数据以后才能导出数据。
原文地址:https://www.cnblogs.com/shaozheng/p/12889928.html