Xadmin開發後臺管理系統
關注公衆號“輕鬆學編程”瞭解更多。
添加小頭像
https://blog.csdn.net/qq_34964399/article/details/80303544?utm_source=blogxgwz5
導航欄設置
https://www.cnblogs.com/adc8868/p/7506973.html
管理器常用顯示設置
https://blog.csdn.net/weixin_33127753/article/details/80897240
添加插件
比如要做一個二級聯動過濾查詢數據,查找當前用戶所辦的套餐。
1、添加linkageFilter.py文件
在虛擬環境中找到/Lib/site-packages/xadmin/plugins(windows的在site-packages/xadmin/plugins),在該文件夾下添加一個linkDataFilter.py文件(文件命名隨意),內容如下:
from xadmin.views import BaseAdminPlugin, DeleteAdminView
from xadmin.views.edit import CreateAdminView, UpdateAdminView
import xadmin
# 點擊增加記錄時觸發
class LinkageAddFilter(BaseAdminPlugin):
# 默認不加載,只在需要加載的options中設置True來加載
is_execute = False
def init_request(self,*arg,**kwargs):
# return self.bool(is_execute)
return self.is_execute
def get_media(self, media):
# 此處用來加入我們自己的js文件
media = media + self.vendor("xadmin.self.select.js")
return media
# 點擊更新記錄時觸發
class LinkageUpdateFilter(BaseAdminPlugin):
# 默認不加載,只在需要加載的options中設置True來加載
is_execute = False
def init_request(self,*arg,**kwargs):
# return self.bool(is_execute)
return self.is_execute
def get_media(self, media):
# 此處用來加入我們自己的js文件
media = media + self.vendor("xadmin.self.update_select.js")
return media
# 點擊刪除記錄時觸發
class LinkageDeleteFilter(BaseAdminPlugin):
# 默認不加載,只在需要加載的options中設置True來加載
is_execute = False
def init_request(self,*arg,**kwargs):
# return self.bool(is_execute)
return self.is_execute
def get_media(self, media):
# 此處用來加入我們自己的js文件
media = media + self.vendor("xadmin.self.delete.js")
return media
xadmin.site.register_plugin(LinkageAddFilter, CreateAdminView)
xadmin.site.register_plugin(LinkageUpdateFilter, UpdateAdminView)
xadmin.site.register_plugin(LinkageDeleteFilter, DeleteAdminView)
2、在plugins文件夾下的init.py中PLUGINS = ()元組中添加linkDataFilter
3、寫js文件
在虛擬環境中找到/Lib/site-packages/xadmin/static/xadmin/js,在該文件夾下條件xadmin.self.select.js、xadmin.self.update_select.js和xadmin.self.delete_select.js三個文件
其中xadmin.self.select.js內容如下:
(function($){
function linkage_query(){
// 獲取用戶辦的套餐
$("#div_id_package").click(function () {
// 從導航欄處獲取用戶名
var master_name = $('#top-nav').find('strong').text();
master_name = master_name.substring(4);
url = "selectInfo/?master=" + master_name;
getSecNav(url,'#id_package');
});
function getSecNav(url,id_type){
$.ajax({
type:"GET",
url:url,
async:true,
beforeSend:function(xhr){
xhr.setRequestHeader("X-CSRFToken", $.getCookie("csrftoken"))
},
success:function(data){
$(id_type)[0].selectize.clearOptions(); //二級select清空選項
keys = Object.keys(data);//將JSON轉換);
for (var i = 0; i < keys.length; i++) {
console.log(data[i]);
var item = data[keys[i]];
var test = {text: item.name, value: item.value, $order: i + 1}; //遍歷數據,拼湊出selectize需要的格式
$(id_type)[0].selectize.addOption(test); //添加數據
}
},
error:function(xhr){
console.log(xhr);
}
});
}
}
linkage_query();
})(jQuery)
4、urls.py和views.py處理js發起的請求
5、adminx.py配置
# 用戶管理
class UserManageAdmin(object):
list_display = ['id', 'name','addtime','get_UserManage_Taocan' ]
search_fields = ['name']
list_filter = ['phone',]
ordering = ['-id'] # 進入xadmin頁面將某個字段倒序排列
readonly_fields = ['addtime'] # 只讀字段,不能編輯
# exclude = ['money'] # 不顯示的字段
list_editable = ['name', ] # 即使編輯器
relfield_style = 'level' # 帶有外鍵的字段變成搜索格式
model_icon = 'fa fa-user' # 表左邊的圖標
is_execute = True # 使用js插件
# 列聚合,可用的值:"count","min","max","avg", "sum"
aggregate_fields = {"id": "max"} # 顯示統計數據 統計id字段最大的值
# 禁止頁面批量刪除,重寫虛擬環境根目錄下\Lib\site-packages\xadmin\views\edit.py中的has_delete_permission方法
def has_delete_permission(self,*args,**kwargs):
if args:
return True
return False
# 自動添加管理員,重寫虛擬環境根目錄下\Lib\site-packages\xadmin\views\edit.py中的save_models方法
def save_models(self):
self.new_obj.user = self.request.user
super().save_models()
# 設置用戶只能查看自己填寫的數據
def queryset(self):
qs = super(UserManageAdmin, self).queryset()
if self.request.user.is_superuser: # 超級用戶可查看所有數據
return qs
else:
que = qs.filter(user=self.request.user)
return que
6、models.py
from django.db import models
from django.utils.safestring import mark_safe
from xadmin.plugins.auth import User
# 用戶管理
class UserManage(models.Model):
name = models.CharField(max_length=20, blank=True, null=True, verbose_name='用戶名')
phone = models.CharField(max_length=11, unique=True, verbose_name='手機號')
money = models.DecimalField(max_digits=20, decimal_places=2,default=0, verbose_name='餘額')
addtime = models.DateTimeField(auto_now_add=True, verbose_name='註冊時間')
user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False, null=True, verbose_name='管理員')
# 顯示時增加一列,比如顯示用戶辦的卡
def get_UserManage_Taocan(self):
text = '增加一列</br>'
# mark_safe允許換行
return mark_safe(text)
get_UserManage_Taocan.short_description = '用戶套餐'
7、xadmin後臺集成’導入‘插件,導入excel文件
效果圖:
1、添加插件
在虛擬環境根目錄\Lib\site-packages\xadmin\plugins中添加excel.py文件,內容如下:
from xadmin.views import BaseAdminPlugin, ListAdminView
from django.template import loader
import xadmin
class ListExcelImportPlugin(BaseAdminPlugin):
# 重寫init_request
import_excel = False
def init_request(self, *args, **kwargs):
return self.import_excel
def block_top_toolbar(self, context, nodes):
# 這裏 xadmin/excel/model_list.top_toolbar.import.html 是自己寫的html文件
nodes.append(loader.render_to_string("xadmin/excel/model_list.top_toolbar.import.html"))
xadmin.site.register_plugin(ListExcelImportPlugin, ListAdminView)
2、註冊插件
在虛擬環境根目錄\Lib\site-packages\xadmin\plugins__init__.py中,
PLUGINS = (
...
'excel', # 在這個元祖中添加元素,名稱與插件文件名同名
...
)
3、添加html文件
在虛擬環境根目錄\Lib\site-packages\xadmin\templates\xadmin\中增加文件夾excel,在文件夾中添加model_list.top_toolbar.import.html文件,內容如下:
{% load i18n %}
<div class="btn-group export">
<a class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown" href="#">
<i class="icon-share"></i> 導入物流單號 <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><a data-toggle="modal" data-target="#export-modal-import-excel"><i class="icon-circle-arrow-down"></i> 導入
Excel</a></li>
</ul>
<script type="text/javascript">
function fileChange(target) {
//檢測上傳文件的類型
var imgName = document.all.submit_upload.value;
var ext, idx;
if (imgName == '') {
document.all.submit_upload_b.disabled = true;
alert("請選擇需要上傳的 xls 文件!");
return;
} else {
idx = imgName.lastIndexOf(".");
if (idx != -1) {
ext = imgName.substr(idx + 1).toUpperCase();
ext = ext.toLowerCase();
if (ext != 'xls' && ext != 'xlsx') {
document.all.submit_upload_b.disabled = true;
alert("只能上傳 .xls 類型的文件!");
return;
}
} else {
document.all.submit_upload_b.disabled = true;
alert("只能上傳 .xls 類型的文件!");
return;
}
}
}
</script>
<div id="export-modal-import-excel" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form method="post" action="" enctype="multipart/form-data">
<!--{% csrf_token %}-->
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">導入 Excel</h4>
</div>
<div class="modal-body">
<input type="file" onchange="fileChange(this)" name="excel" id="submit_upload">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button class="btn btn-success" type="button" id="submit_upload_b"><i class="icon-share"></i> 導入
</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dalog -->
</div><!-- /.modal -->
</div>
<script type="text/javascript">
$(document).ready(function () {
function fileChange(target) {
//檢測上傳文件的類型
var imgName = document.all.submit_upload.value;
var ext, idx;
if (imgName == '') {
document.all.submit_upload_b.disabled = true;
alert("請選擇需要上傳的 xls 文件!");
return;
} else {
idx = imgName.lastIndexOf(".");
if (idx != -1) {
ext = imgName.substr(idx + 1).toUpperCase();
ext = ext.toLowerCase();
if (ext != 'xls' && ext != 'xlsx') {
document.all.submit_upload_b.disabled = true;
alert("只能上傳 .xls 類型的文件!");
return;
}
} else {
document.all.submit_upload_b.disabled = true;
alert("只能上傳 .xls 類型的文件!");
return;
}
}
}
$('#submit_upload_b').click(function () {
var form_data = new FormData();
var file_info = $('#submit_upload')[0].files[0];
form_data.append('file',file_info);
$.ajax({
url: 'http://127.0.0.1:8000/importkdorderno/',
type: 'POST',
data: form_data,
dataType:"json",
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", $.getCookie("csrftoken"))
},
processData: false, // tell jquery not to process the data
contentType: false, // tell jquery not to set contentType
success: function (res) {
alert(res.msg);
window.location.reload();
},
error: function (err) {
}
});
});
})
</script>
4、在views.py處理上傳的excel文件
import pandas as pd
from rest_framework.views import APIView
class ImportKDOrderNo(APIView):
def post(self, request, *args, **kwargs):
file = request.FILES.get('file')
# read = InMemoryUploadedFile().open()
data = pd.read_excel(file) # 使用pandas處理excel文件
if '訂單號' and '物流單號' not in data:
return Response(data={'msg': '文件格式有誤,第一行第一列應該爲【訂單號】,第一行第二列應該爲【物流單號】'})
ordernos = data['訂單號']
logistics = data['物流單號']
for i in range(len(ordernos)):
print('訂單號', ordernos[i], '物流單號', logistics[i])
return Response(data={'msg': '上傳成功'})
5、在urls.py中添加訪問路由
from django.urls import path
from 你的應用名稱 import views
app_name = '你的應用名稱'
urlpatterns = [
# 其他路由
...
# 導入物流單號
path('importkdorderno/', views.ImportKDOrderNo.as_view(), name='importkdorderno'),
]
8、xadmin後臺用戶操作表權限
虛擬環境根目錄\Lib\site-packages\xadmin\views\base.py
可以找到:
在項目子應用下的adminx.py中使用
import xadmin
from machine.models import Machine
class MachineAdmin(object):
list_display = ['code',] # 顯示的字段
search_fields = ['code'] # 搜索的字段
list_filter = ['code', 'is_delete'] # 過濾的字段
ordering = ('-id',) # 按id降序排序
list_editable = ['is_delete', ] # 數據即時編輯
list_per_page = 30 # 每頁顯示數據數量
model_icon = 'fa fa-cog fa-spin' # 左側顯示的小圖標
def has_delete_permission(self, *args, **kwargs):
# 刪除權限
if self.request.user.is_superuser: # 管理員才能增加
return True
return False
def has_add_permission(self, *args, **kwargs):
if self.request.user.is_superuser: # 管理員才能增加
return True
return False
def has_change_permission(self, *args, **kwargs):
if self.request.user.is_superuser: # 管理員才能修改
return True
return False
def queryset(self):
qs = super(MachineAdmin, self).queryset()
if self.request.user.is_superuser: # 管理員可以查看所有
return qs
else:
# 登錄用戶只能看到自己修改的數據
return qs.filter(master_id=self.request.user.last_name)
xadmin.site.register(MallMachine, MallMachineAdmin)
9、xadmin後臺發送郵件找回密碼
輸入你用戶綁定的郵箱
想要發送郵件,需要在settings.py中設置郵件發送器
settings.py最下面增加
# ------------------------郵箱配置-----------------------------------------
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' #把要發送的郵件顯示再控制檯上,方便調試
EMAIL_USE_SSL = True
EMAIL_HOST = 'smtp.qq.com' # 如果是 163 改成 smtp.163.com
EMAIL_PORT = 465
EMAIL_HOST_USER = '郵箱賬號' # 帳號
EMAIL_HOST_PASSWORD = '授權碼' # 密碼
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
由於django2與xadmin有些地方不兼容,需要修改源碼:
找到虛擬環境根目錄\Lib\site-packages\xadmin\plugins\passwords.py
在passwords.py文件中大概79行,修改爲:
return password_reset_confirm(request=request, uidb36=uidb36, token=token,
template_name=self.password_reset_confirm_template,
token_generator=self.password_reset_token_generator,
set_password_form=self.password_reset_set_form,
post_reset_redirect=self.get_admin_url('xadmin_password_reset_complete'),
current_app=self.admin_site.name, extra_context=context).dispatch(request=request,
uidb64=uidb36,token=token)
找到虛擬環境根目錄Lib\site-packages\django\contrib\auth\views.py
在views.py文件中大概258行,增加:
# 成功後跳轉路由,根據自己實際來定
self.success_url = self.request.build_absolute_uri('/') + 'xadmin/'
10、xadmin消息提醒
xadmin 使用
self.message_user(u'錯誤,','error')
self.message_user(u'警告,','warning')
self.message_user(u'恭喜,','success')
self.message_user(u'信息,','info')
效果
11、xadmin外鍵下拉框添加過濾
class MallGoodsAdmin(object):
"""商品管理"""
list_display = ['id', 'show_photo', 'nickname', 'merchant', 'goods_class', 'label',]
search_fields = ['nickname']
list_filter = ['goods_class', 'label',]
model_icon = 'fa fa-bars'
list_editable = ['goods_class', ]
# 重寫虛擬環境根目錄下\Lib\site-packages\xadmin\views\edit.py中的formfield_for_dbfield方法
def formfield_for_dbfield(self, db_field, **kwargs):
# 對MallGoodsClass這個表項的下拉框選擇進行過濾
# MallGoods中有一個goods_class商品分類外鍵MallGoodsClass,過濾掉外鍵MallGoodsClass中
# master_class爲空的值
if db_field.name == "goods_class":
kwargs["queryset"] = MallGoodsClass.objects.filter(master_class__isnull=False)
# 對assigned_recipient這個表項的下拉選擇進行過濾
return db_field.formfield(**dict(**kwargs))
return super().formfield_for_dbfield(db_field, **kwargs)
xadmin.site.register(models.MallGoods, MallGoodsAdmin)
12、xadmin即時編輯器去掉空標籤
虛擬環境根目錄下\Lib\site-packages\xadmin\plugins\editable.py,在大概
129行增加:
form.fields[fields[0]].empty_label = None
13、用戶增加的小組件,讓其他用戶可見
找到虛擬環境根目錄\Lib\site-packages\xadmin\views\dashboard.py
在548行、554行
改爲:
@filter_hook
def get_widgets(self):
if self.widget_customiz:
portal_pos = UserSettings.objects.filter(
key=self.get_portal_key())
if len(portal_pos):
portal_pos = portal_pos[0].value
widgets = []
if portal_pos:
user_widgets = dict([(uw.id, uw) for uw in UserWidget.objects.filter(page_id=self.get_page_id())])
for col in portal_pos.split('|'):
ws = []
for wid in col.split(','):
try:
widget = user_widgets.get(int(wid))
if widget:
ws.append(self.get_widget(widget))
except Exception as e:
import logging
logging.error(e, exc_info=True)
widgets.append(ws)
return widgets
return self.get_init_widget()
14 、xadmin導出插件處理,增加導出勾選數據項
常規的導出只有兩個選擇【導出表頭】、【導出全部數據】
現在想要做的是增加一個選擇,即【導出表頭】、【導出全部數據】、【導出勾選數據】,如下圖:
需要修改xadmin源代碼,具體如下
1、加載js文件
找到虛擬環境\Lib\site-packages\xadmin\views\list.py,在607行增加’xadmin.plugin.importexport.js’,如下圖所示
2、修改export.py,後端處理下載文件
找到虛擬環境\Lib\site-packages\xadmin\plugins\export.py
在84行把rows = context[‘results’]修改成如下函數
# 新增導出所選數據
# rows = context['results']
rows = []
select_across = self.request.GET.get('_select_across', False) == '1'
selected = self.request.GET.get('_selected_actions', '')
if self.request.GET.get('selected', 'off') == 'on':
if not select_across:
selected_pk = selected.split(',')
for i in context['results']:
if str(i['object'].id) in selected_pk:
rows.append(i)
else:
rows = context['results']
else:
rows = context['results']
3、 修改model_list.top_toolbar.exports.html
找到虛擬環境\Lib\site-packages\xadmin\templates\xadmin\blocks\model_list.top_toolbar.exports.html
使用以下代碼覆蓋原文件
{% load i18n %}
<div class="btn-group export">
<a id="export-menu" class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown" href="#">
<i class="fa fa-share"></i> {% trans "Export" %} <span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
{% for et in export_types %}
<li><a data-toggle="modal" data-target="#export-modal-{{et.type}}"><i class="fa fa-arrow-circle-down">
</i> {% trans "Export" %} {{et.name}}</a></li>
{% endfor %}
</ul>
{% for et in export_types %}
<div id="export-modal-{{et.type}}" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<form method="get" action="">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">{% trans "Export" %} {{et.name}}</h4>
</div>
<div class="modal-body">
{{ form_params|safe }}
<input type="hidden" name="export_type" value="{{et.type}}">
<!-- 增加 導出所選數據 一欄 -->
<input type="hidden" name="_selected_actions" value=""/>
<input type="hidden" name="_select_across" value=""/>
<label class="checkbox">
{% if et.type == "xlsx" %}
<input type="checkbox" name="export_xlsx_header" checked="checked" value="on">
{% trans "Export with table header." %}
{% endif %}
{% if et.type == "xls" %}
<input type="checkbox" name="export_xls_header" checked="checked" value="on">
{% trans "Export with table header." %}
{% endif %}
{% if et.type == "csv" %}
<input type="checkbox" name="export_csv_header" checked="checked" value="on">
{% trans "Export with table header." %}
{% endif %}
{% if et.type == "xml" %}
<input type="checkbox" name="export_xml_format" checked="checked" value="on">
{% trans "Export with format." %}
{% endif %}
{% if et.type == "json" %}
<input type="checkbox" name="export_json_format" checked="checked" value="on">
{% trans "Export with format." %}
{% endif %}
</label>
<label class="checkbox">
<input type="checkbox" name="all" value="on"> {% trans "Export all data." %}
</label>
<!-- 增加 導出所選數據 一欄 -->
<label class="checkbox">
<input type="checkbox" name="selected" value="on"> 導出勾選數據
</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{% trans "Close" %}</button>
<button class="btn btn-success myexport glyphicon glyphicon-export " type="submit"><i
class="fa fa-share"></i> {% trans "Export" %}
</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dalog -->
</div><!-- /.modal -->
{% endfor %}
</div>
<script type="text/javascript">
// 如果是訂單導出,把待出貨訂單設置成待收貨訂單
$(document).ready(function () {
$('.myexport').click(function () {
// 當把訂單導出時,需要修改訂單狀態爲待收貨狀態
var url = window.location.protocol + '//' + window.location.host + "/exportorder/";
$("input[name='_select_across']").val($("input[name='select_across']").val());
if ($("input[name='selected']").is(':checked')) {
var arr = [];
$.each($('.action-select'), function () {
if (true == $(this).prop('checked')) {
arr.push($(this).val());
}
});
if(arr.length == 0){
alert('請先勾選導出數據')
return false
}
}else{
var arr = []
var order_type = $('.breadcrumb li').eq(1).text().trim()
$('.grid-item').each(function (index, el) {
arr.push($(el).find('td').eq(1).text().trim())
})
}
if (($('.breadcrumb > li').eq(1).text()).indexOf('訂單') != -1) {
// 5秒後執行
setTimeout(function () {
$.ajax({
type: "POST",
url: url,
data: {'orderlist': JSON.stringify(arr), 'order_type': order_type,},
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", $.getCookie("csrftoken"))
},
success: function (data) {
window.location.reload();
},
error: function (xhr) {
alert("出現未知錯誤");
window.location.reload();
}
});
}, 5000);
}
});
})
</script>
15、常見問題及解決方案
1、使用django2.1+xadmin搭建後臺有時會出現如下錯誤:
lib/python3.5/site-packages/django/forms/boundfield.py", line 93, in as_widget
renderer=self.form.renderer,
TypeError: render() got an unexpected keyword argument 'renderer'
解決方案:
按提示路徑找到boundfield.py,然後把93行註釋掉即可。
2、 xadmin後臺刪除數據出現錯誤
get_deleted_objects() takes 3 positional arguments but 5 were given
這是由於Django2.1版本和xadmin不兼容導致的
知道虛擬環境\Lib\site-packages\xadmin\plugins\actions.py
修改93行,
把
deletable_objects, model_count, perms_needed, protected = get_deleted_objects(
queryset, self.opts, self.user, self.admin_site, using)
改爲
deletable_objects, model_count, perms_needed, protected = get_deleted_objects(
queryset, self.user, self.admin_site)
如果出現“‘User’ object has no attribute ‘request’”錯誤,則改爲:
deletable_objects, model_count, perms_needed, protected = get_deleted_objects(
queryset, self, self.admin_site)
然後在adminx.py文件中對應的模型類中允許刪除權限
class MaterialAdmin(object):
"""素材庫分類"""
list_display = ['id', 'name', 'class_id', 'is_delete', 'addtime']
def has_delete_permission(self, *args, **kwargs):
return True
xadmin.site.register(Material, MaterialAdmin)
3、xadmin後臺無法顯示下拉框完整內容
解決方案 在根目錄中找到/static/xadmin/vendor/selectize/selectize.bootstrap3.css
在331行後加入 position: static;
4、Django 更改超級用戶密碼
在工程文件目錄下敲入:
python manage.py shell
再在python交互界面輸入:
from django.contrib.auth.models import User
user = User.objects.get(username = 'username')
user.set_password('new_password')
user.save()
5、xadmin後臺加載數據慢,解決方案
list_filter: 過濾器要慎用,不要使用類似id這些數據量大的字段
class MallUserAdmin(object):
"""用戶管理"""
list_display = ['id', 'tp_icon', 'nickname', 'phone', 'level', 'balance', 'province', 'city', 'quxian'] # 顯示字段
search_fields = ['id', 'nickname', 'phone'] # 搜索
list_filter = ['level', 'province', 'city', 'quxian'] # 過濾器
# list_filter = ['id', 'level', 'province', 'city', 'quxian'] # 如果加id,xadmin加載回來的數據就會很慢,所以不要在過濾器上使用id
list_per_page = 30 # 默認每頁數量
model_icon = 'fa fa-users' # 左側圖標
ordering = ['-id'] # 排序
readonly_fields = ['subscribe', 'wx_openid', 'phone'] # 只讀字段
is_addbalance = True # 加載自定義的插件
relfield_style = 'fk-ajax' # 其他表如果外鍵到用戶表就做ajax搜索查詢,不一次性加載數據
6、xadmin使用富文本DjangoUeditor與時間插件產生衝突
現象:
原因:
加載富文本插件時,會覆蓋bootstrap-clockpicker.js,bootstrap-datepicker.js,xadmin.widget.datetime.js這三個js文件
解決方案:
做一個時間插件,手動加載這個插件即可。
在adminx.py中添加:
from xadmin.views import BaseAdminPlugin, UpdateAdminView, CreateAdminView
from indent import models
class JkdPtGoodsAdmin(object):
"""商品表"""
list_display = ["shop", "ptgoods_name", 'price', 'pt_price', 'pt_size', 'pt_validhours',
'pt_state', 'is_sale']
list_filter = ['is_sale', 'pt_size', 'start_time', 'pt_size']
list_editable = ['price', 'start_time', 'end_time']
show_detail_fields = ['ptgoods_name']
search_fields = ['ptgoods_name']
style_fields = {"content": "ueditor"} # content字段使用富文本
show_all_rel_details = True
is_datetime = True # 加載自定義的時間插件
model_icon = 'fa fa-ellipsis-h'
class DateTimeWidget(BaseAdminPlugin):
"""時間插件"""
# 默認不加載,只在需要加載的options中設置True來加載
is_datetime = False
def init_request(self, *arg, **kwargs):
return self.is_datetime
def get_media(self, media):
# 此處用來加入我們自己的js文件
media = media + self.vendor("xadmin.self.selectize.js",
"xadmin.self.select2.js",
"xadmin.self.select2_locale_zh-hans.js",
"xadmin.widget.select.js",
"xadmin.plugin.quick-form.js",
"xadmin.self.bootstrap-datepicker.js",
"xadmin.self.bootstrap-clockpicker.js",
"xadmin.widget.datetime.js", )
return media
# 註冊時間插件
xadmin.site.register_plugin(DateTimeWidget, CreateAdminView)
xadmin.site.register_plugin(DateTimeWidget, UpdateAdminView)
xadmin.site.register(models.JkdPtGoods, JkdPtGoodsAdmin)
把
xadmin.self.selectize.js、
xadmin.self.select2.js、
xadmin.self.select2_locale_zh-hans.js、
xadmin.self.bootstrap-clockpicker.js、
xadmin.self.bootstrap-datepicker.js
放到項目目錄/static/xadmin/js下,
xadmin.self.selectize.js中的內容複製項目根目錄/static/xadmin/vendor/selectize/selectize.js中的,
xadmin.self.select2.js中的內容複製項目根目錄/static/xadmin/vendor/select2/select2.js中的,
xadmin.self.select2_locale_zh-hans.js中的內容複製項目根目錄/static/xadmin/vendor/select2/select2_locale_zh-hans.js中的,
xadmin.self.bootstrap-clockpicker.js中的內容複製項目根目錄/static/xadmin/vendor/bootstrap-clockpicker/bootstrap-clockpicker.js中的,
xadmin.self.bootstrap-datepicker.js中的內容複製項目根目錄/static/xadmin/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js中的.
xadmin.widget.datetime.js、xadmin.widget.select.js、xadmin.widget.datetime.js已經在項目目錄/static/xadmin/js下了
最後在xadmin.main.js文件的最後加上以下代碼:
/*動態加載cee*/
var windowPrefix = window.__admin_media_prefix__;
var linkList = [
windowPrefix + "vendor/select2/select2.css",
windowPrefix + "vendor/selectize/selectize.css",
windowPrefix + "vendor/bootstrap-clockpicker/bootstrap-clockpicker.css",
windowPrefix + "vendor/bootstrap-datepicker/css/datepicker.css",
];
for (var i = 0; i < linkList.length; i++) {
$("<link>")
.attr({
rel: "stylesheet",
type: "text/css",
href: linkList[i]
})
.appendTo("head");
}
如圖
後記
【後記】爲了讓大家能夠輕鬆學編程,我創建了一個公衆號【輕鬆學編程】,裏面有讓你快速學會編程的文章,當然也有一些乾貨提高你的編程水平,也有一些編程項目適合做一些課程設計等課題。
也可加我微信【1257309054】,拉你進羣,大家一起交流學習。
如果文章對您有幫助,請我喝杯咖啡吧!
公衆號
關注我,我們一起成長~~