xadmin開發後臺管理系統常見問題

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">&times;</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】,拉你進羣,大家一起交流學習。
如果文章對您有幫助,請我喝杯咖啡吧!

公衆號

公衆號

讚賞碼

關注我,我們一起成長~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章