目錄
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 導出功能只有在勾選了數據以后才能導出數據。
