目录
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 导出功能只有在勾选了数据以后才能导出数据。