python框架Django使用xadmin管理后台数据

Django使用xadmin管理后台数据

关注公众号“轻松学编程”了解更多。

作用:xadmin比Django内置的admin更美观、更方便。

一、导入xadmin(第三方库)

方法1、使用pip安装

pip install git+git://github.com/sshwsfc/xadmin.git

如果出现问题可参考https://blog.csdn.net/lm_is_dc/article/details/80558073解决

方法2、可直接到gitHub上找到xadmin的地址https://github.com/sshwsfc/xadmin 下载到项目根目录 ,然后pip:

pip3 install xadmin-master.zip

安装。

注意:如果使用的Django2.0版本以上的,需要到GitHua上找到xadmin,然后拉取django2的分支。
这里写图片描述
如果出现缺少安装包的可参考:
https://blog.csdn.net/Snail0Li/article/details/79694781

二、在settings.py里面配置

在注册应用处加上

'xadmin',
'crispy_forms',

这里写图片描述

三、在路由urls.py里面添加路由
import xadmin
urlpatterns = [
	url('xadmin/', xadmin.site.urls),
]

这里写图片描述

四、数据迁移
makemigrations
migrate

这里写图片描述

五、建立adminx.py

1、创建adminx.py

2、导入xadmin和model中建立的表模型

from xadmin import views
import xadmin
from .models import  User, Candidate

3、添加表管理类,继承于Object

# 基础设置
class BaseSetting(object):
    enable_themes = True    # 使用主题
    use_bootswatch = True

# 全局设置
class GlobalSettings(object):
    site_title = '个人网站管理系统'  # 标题
    site_footer = '个人网站'  # 页尾
    site_url = '/'
    menu_style = 'accordion'  # 设置左侧菜单  折叠样式

# 用户的后台管理
class UserAdmin(object):
    # 检索字段
    search_fields = ['uName','uIP',]
    # 要显示的字段
    list_display = ['id','uName','uIP' ,'uEmail' ,'uNickName' ,'uGender','uAge' ,'uIcon' ,'isDelete']
    # 分组过滤的字段
    list_filter = ['uName','uNickName','uGender','uAge','isDelete']
    # ordering设置默认排序字段,负号表示降序排序
    ordering = ('id',)
    # list_per_page设置每页显示多少条记录,默认是100条
    list_per_page = 50
    # list_editable 设置默认可编辑字段
    list_editable = ['uNickName', 'uIcon']
# 候选者的后台管理
class CandidateAdmin(object):
    # 检索字段
    search_fields = ['cName','cAge','cTimes','cVotes','cPinyin','isDelete',]
    # 要显示的字段
    list_display = ['id','cName','cAge','cEmail','cDeclaration','cIcon','cTimes','cVotes','cPinyin','isDelete','cVoteType',]
    # 分组过滤的字段
    list_filter = ['cName','cAge','cTimes','cVotes','cPinyin','isDelete',]
    # ordering设置默认排序字段,负号表示降序排序
    ordering = ('id',)
    # fk_fields 设置显示外键字段
    fk_fields = ('cVoteType',)

4、注册表管理类

xadmin.site.register(views.CommAdminView,GlobalSettings)
xadmin.site.register(views.BaseAdminView,BaseSetting)
xadmin.site.register(User,UserAdmin)
xadmin.site.register(Candidate,CandidateAdmin)

这里写图片描述

六、创建管理员
createsuperuser

这里写图片描述

七、效果图

这里写图片描述

这里写图片描述

八、xadmin后台编辑多对多字段

在models.py定义了多对多字段,想要在编辑时可以灵活使用这个字段的话,可以按以下方法设置:
modes.py

class Book(models.Model):
    title = models.CharField(verbose_name="书名", max_length=32)
    second_title = models.CharField(verbose_name="副标题", max_length=32, blank=True, null=True)
    author = models.CharField(verbose_name="作者", max_length=32)
    translator = models.CharField(verbose_name="译者", max_length=32, blank=True, null=True)
    intro = models.TextField(verbose_name="描述")
    pic = models.FileField(verbose_name="封面图片", max_length=64, upload_to='book_cover', null=True, blank=True)
    tags = models.ManyToManyField(Tags, verbose_name='书籍标签', blank=True)
    prizes = models.ManyToManyField(Prizes, verbose_name='获奖详情', blank=True)
    sump = models.IntegerField(verbose_name="收藏人数", default=0)
    rate_num = models.IntegerField(verbose_name="评分人数", default=0)
    num = models.IntegerField(verbose_name="浏览量", default=0)
    published_time = models.DateField(blank=True, null=True, verbose_name='出版时间')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

    class Meta:
        db_table = 'book'
        verbose_name = "图书"
        verbose_name_plural = "图书"

    def __str__(self):
        return self.title

adminx.py

# 书籍管理
class BookAdmin(object):
    search_fields = ['title', 'author', 'intro']  # 检索字段
    list_display = ['id', 'show_pic', 'title', 'second_title', 'author', 'translator', 'published_time', 'intro',
                    'tags', 'prizes', 'num', 'sump', 'rate_num']  # 要显示的字段
    list_filter = ['published_time', 'tags', 'prizes']  # 分组过滤的字段
    ordering = ('id',)  # 设置默认排序字段,负号表示降序排序
    list_per_page = 30  # 默认每页显示多少条记录,默认是100条
    model_icon = 'fa fa-book'  # 左侧小图标
    list_editable = ['title', 'author', 'intro', 'published_time']  # 可编辑字段
    style_fields = {'tags': 'm2m_transfer', 'prizes': 'm2m_transfer'}  # 控制字段的显示样式
    filter_horizontal = ('tags', 'prizes')  # 水平选择编辑多对多字段

重点是设置style_fields 和filter_horizontal ,效果:
在这里插入图片描述

九、遇到的问题和解决方案
1、render() got an unexpected keyword argument ‘renderer’

使用Django2.0和xadmin2.0版本以上的可能会遇到这个问题。
解决方案:
在虚拟环境中找到Lib\site-packages\xadmin\views\dashboard.py
也可以点击两次shift键搜索dashboard.py,然后在dashboard.py修改以下内容
在大概36行处增加一个参数

def render(self, name, value, attrs=None, renderer=None):

如下图所示

十、一些有用的设置
1、把静态文件集中到static中

先在项目根目录下创建一个static文件夹
然后在settings.py中设置

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

最后执行下面的命令:

python manage.py collectstatic
2、django app 如何在后台显示中文名

1.在app (这里以user为例)下面的__init__.py文件中

添加:

default_app_config = 'user.apps.UserConfig'

2.在apps.py中

from django.apps import AppConfig

class UserConfig(AppConfig):
    name = 'user'
    verbose_name = '用户'
3、xadmin通过展开方式显示TextField字段类型

由于TextField字段类型内容可能很长,在后台显示时很占屏幕位置,可以通过按钮来控制显示,代码如下:
models.py中定义了一个TextField字段类型:

class Prizes(models.Model):
    name = models.CharField(max_length=32, verbose_name="奖项")
    intro = models.TextField(blank=True, null=True, verbose_name='简介')

    class Meta:
        db_table = 'prizes'
        verbose_name = "奖项"
        verbose_name_plural = "奖项"

    def __str__(self):
        return self.name

在adminx.py中代码如下:

import xadmin
from django.utils.safestring import mark_safe
from xadmin import views

from .models import *

# 奖项管理
class PrizesAdmin(object):
    search_fields = ['name']  # 检索字段
    list_display = ['id', 'name', 'show_intro']
    list_filter = ['name']
    ordering = ('id',)

    def show_intro(self, obj):
        # 显示简介
        if not obj.intro:
            return mark_safe('')
        if len(obj.intro) < 20:
            return mark_safe(obj.intro)

        short_id = f'{obj._meta.db_table}_short_text_{obj.id}'
        short_text_len = len(obj.intro) // 4
        short_text = obj.intro[:short_text_len] + '......'
        detail_id = f'{obj._meta.db_table}_detail_text_{obj.id}'
        detail_text = obj.intro

        text = """<style type="text/css">
                        #%s,%s {padding:10px;border:1px solid green;} 
                  </style>
                    <script type="text/javascript">

                    function openShutManager(oSourceObj,oTargetObj,shutAble,oOpenTip,oShutTip,oShortObj){
                        var sourceObj = typeof oSourceObj == "string" ? document.getElementById(oSourceObj) : oSourceObj;
                        var targetObj = typeof oTargetObj == "string" ? document.getElementById(oTargetObj) : oTargetObj;
                        var shortObj = typeof oShortObj == "string" ? document.getElementById(oShortObj) : oShortObj;
                        var openTip = oOpenTip || "";
                        var shutTip = oShutTip || "";
                        if(targetObj.style.display!="none"){
                           if(shutAble) return;
                           targetObj.style.display="none";
                           shortObj.style.display="block";
                           if(openTip  &&  shutTip){
                            sourceObj.innerHTML = shutTip; 
                           }
                        } else {
                           targetObj.style.display="block";
                           shortObj.style.display="none";
                           if(openTip  &&  shutTip){
                            sourceObj.innerHTML = openTip; 
                           }
                        }
                        }
                    </script>
                    <p id="%s">%s</p>
                    <p><a href='###' οnclick="openShutManager(this,'%s',false,'点击关闭','点击展开','%s')">点击展开</a></p>

                    <p id="%s" style="display:none">
                       %s
                    </p>
                    """ % (short_id, detail_id, short_id, short_text, detail_id, short_id, detail_id, detail_text)
        return mark_safe(text)

    show_intro.short_description = '描述'

注意:复制代码后需要做如下修改:
在这里插入图片描述

一开始显示效果:
在这里插入图片描述
点击展开效果:
在这里插入图片描述

4、xadmin后台批量操作

adminx.py

import xadmin
from django.db.models import  Sum
from xadmin.plugins.actions import BaseActionView

class MyCountFeeAction(BaseActionView):
    """
        用户余额统计
        """
    action_name = "countuserfee"  #: 相当于这个 Action 的唯一标示, 尽量用比较针对性的名字
    description = u'统计用户总余额'  #: 描述, 出现在 Action 菜单中, 可以使用 ``%(verbose_name_plural)s`` 代替 Model 的名字.
    model_perm = 'view'  # 权限

    def do_action(self, queryset):
        all_balance = MallUser.objects.all().aggregate(Sum('balance'))
        return HttpResponse(f'用户总余额{all_balance}')
class UserAdmin(object):
    """用户信息管理"""
    list_display = ['username', 'balance', 'status', 'addtime']
    search_fields = ['username', ]
    list_filter = ['status', 'addtime']
    list_per_page = 30  # 默认每页数量
    model_icon = 'fa fa-user'
    list_editable = ['status']
    ordering = ['-addtime']
    actions = [ MyCountFeeAction]  # 添加批量选择操作

在这里插入图片描述

5、xadmin过滤器外键显示特定值(比如只能过滤自己与超级管理员定义的数据)

首先,修改xadmin源码,修改xadmin/filters.py,在401行,做如下修改,

把self.lookup_choices = field.get_choices(include_blank=False)
改为:
# 调用自定义的方法
        if hasattr(model_admin, '{field}_choices'.format(field=field.name)):
            self.lookup_choices = getattr(model_admin, '{field}_choices'.format(field=field.name))(field, request,params, model,model_admin,field_path)
        else:
            self.lookup_choices = field.get_choices(include_blank=False)

如图:
在这里插入图片描述

然后,在adminx.py中定义过滤的方法:

import xadmin
from django.db.models import  Q, Sum
from xadmin.plugins.actions import BaseActionView

class MeasurePointAdmin(object):
    # search_fields = ['user__name', 'user__account']  # 检索字段
    list_display = ['num', 'elevation', 'correct_num', 'cumulative_amount']
    list_filter = ['user', 'is_default', 'create_time']  # 分组过滤的字段
    list_editable = ['num', 'elevation', 'correct_num', 'cumulative_amount']
    ordering = ('id',)  # 设置默认排序字段,负号表示降序排序
    list_per_page = 30  # 默认每页显示多少条记录,默认是100条
    model_icon = 'fa fa-users'  # 左侧小图标
    readonly_fields = ['user', 'is_default']
    import_excel = True
    actions = [MyCountFeeAction]
	
	# 定义的函数名必须是  字段名_choices
    def user_choices(self, field, request, params, model, model_admin, field_path):
        # 超级用户不做控制
        if self.request.user.is_superuser:
            return field.get_choices(include_blank=False)

        # 过滤器只显示自己与超级管理员
        user_lst = field.related_model._default_manager.filter(Q(id=self.request.user.id) | Q(is_superuser=True))
        # 返回格式 [('pk','标题'),]
        return [(user.id, user.username) for user in user_lst]

效果:
在这里插入图片描述

后记

【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。

也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!

公众号
在这里插入图片描述

在这里插入图片描述

posted @ 2018-06-13 13:09  轻松学编程  阅读(200)  评论(0编辑  收藏  举报