个人博客,欢迎查看:https://blog.starmeow.cn/
Github地址:https://github.com/xyliurui/DjangoCRM
注册APP列表显示
从这儿起,难度就有增加了
自动发现app和注册
可以实现页面显示所有APP和对应的表名
创建app_setup.py
djadmin应用下创建app_setup.py文件
from django import conf
def djadmin_auto_discover():
for app_name in conf.settings.INSTALLED_APPS:
try:
# 去每个app下执行djadmin.py文件
# crm.apps.CrmConfig和crm需要做判定
mod = __import__('{}.djadmin'.format(app_name if 'Config' not in app_name else app_name.split('.')[0]))
# 打印每个app已注册的model名字
print(mod.djadmin)
# 会打印:<module 'crm.djadmin' from 'E:\\Sync\\OneDrive\\PycharmProjects\\DjangoCRM\\crm\\djadmin.py'>
except ImportError:
pass
动态获取settings里面所有添加的app名字
Python __import__()
函数,具体用法查看 http://www.runoob.com/python/python-func-__import__.html
-
__import__()
函数用于动态加载类和函数 。 - 如果一个模块经常变化就可以使用
__import__()
来动态载入。
返回全局字典
在djadmin应用下创建sites.py文件
class AdminSite(object):
def __init__(self):
self.enable_admins = {}
# 两个参数,一个表名,一个自定义的admin类
def register(self, model_class, admin_class=None):
"""注册admin表"""
# print('register',model_class,admin_class)
# 获取app名字
app_name = model_class._meta.app_label
# 获取表名
model_name = model_class._meta.model_name
if app_name not in self.enable_admins:
self.enable_admins[app_name] = {}
self.enable_admins[app_name][model_name] = admin_class
# 实例化,就可以调用register方法
site = AdminSite()
应用下创建djadmin.py文件
crm应用下创建djadmin.py文件,用于注册模型
from djadmin.sites import site
from crm import models
print('crm models...')
# 注册model
class CustomerInfoAdmin(object):
list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
list_filter = ['source', 'consultant', 'status', 'created_time']
search_fields = ['contact', 'consultant__name']
site.register(models.CustomerInfo, CustomerInfoAdmin)
djadmin应用下添加执行入口
修改djadmin应用下的views.py文件,增加
from djadmin import app_setup
app_setup.djadmin_auto_discover()
from djadmin.sites import site
print('site:', site.enable_admins)
当程序一启动就会打印入口的信息
manage.py runserver 8000
Performing system checks...
crm models...
<module 'crm.djadmin' from 'E:\\Sync\\OneDrive\\PycharmProjects\\DjangoCRM\\crm\\djadmin.py'>
site: {'crm': {'customerinfo': <class 'crm.djadmin.CustomerInfoAdmin'>}}
会根据sites.py的配置显示字典信息。
前端页面显示
修改djadmin应用下的index视图,增加视图的参数
@login_required
def index(request):
return render(request, 'djadmin/index.html',
{
'site': site
})
修改djadmin/templates/djadmin/index.html页面显示
字典样式:{'crm': {'customerinfo': <class 'crm.djadmin.CustomerInfoAdmin'>, 'userprofile': <class 'djadmin.djadmin_base.BaseDjAdmin'>, ...},...}
模板中进行遍历
{% extends 'djadmin/base.html' %}
{% block title %}
主页 - 后台管理
{% endblock %}
{% block content %}
<h1 class="page-header">所有应用</h1>
{% for app_name, app_models in site.enable_admins.items %}
<table class="table table-striped">
<thead>
<tr>
<th>{{ app_name }}</th>
</tr>
</thead>
<tbody>
{% for model_name in app_models %}
<tr>
<td><a href="#">{{ model_name }}</a></td>
<td>增加</td>
<td>修改</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endblock %}
image.png
修改crm应用下的djadmin.py文件,增加注册其他models
from djadmin.sites import site
from crm import models
print('crm models...')
# 注册model
class CustomerInfoAdmin(object):
list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
list_filter = ['source', 'consultant', 'status', 'created_time']
search_fields = ['contact', 'consultant__name']
site.register(models.CustomerInfo, CustomerInfoAdmin)
site.register(models.Role)
site.register(models.Menu)
site.register(models.UserProfile)
刷新 http://127.0.0.1:8000/djadmin/ 页面
image.png如何在视图中获取模型实例
注册模型类属性赋值
修改djadmin应用下的sites.py文件,增加admin_class.model = model_class
class AdminSite(object):
def __init__(self):
self.enable_admins = {}
# 两个参数,一个表名,一个自定义的admin类
def register(self, model_class, admin_class=None):
"""注册admin表"""
# print('register',model_class,admin_class)
# 获取app名字
app_name = model_class._meta.app_label
# 获取表名
model_name = model_class._meta.model_name
# 获取表别名
# model_verbose_name = model_class._meta.verbose_name
# print(model_verbose_name)
# 把model_class赋值给了admin_class,然后在视图中可以通过admin_class找到对应的model类(表名字)
admin_class.model = model_class
if app_name not in self.enable_admins:
self.enable_admins[app_name] = {}
self.enable_admins[app_name][model_name] = admin_class
# 实例化,就可以调用register方法
site = AdminSite()
此时重新运行项目会报错
AttributeError: 'NoneType' object has no attribute 'model'
是因为我们在注册model的时候,有的写了自定义的model类site.register(models.CustomerInfo, CustomerInfoAdmin)
,有的没写site.register(models.Role)
,而我们都统一的赋值,导致那些没写自定义model类(空的)赋值的时候就会报NoneType错误
django自带的自定义admin类的写法继承了ModelAdmin,那注册的时候为什么有的没写自定义admin类没有报错呢?是因为继承的ModelAdmin帮我们写了(里面其实都定义为空了),我们模仿django admin的写法,也写个父类。
注册模型类继承
在djdadmin应用下新建个djadmin_base.py,写个父类
# djadmin/djadmin_base.py
class BaseDjAdmin(object):
pass
修改crm应用下的djadmin.py文件,继承BaseDjAdmin
from djadmin.sites import site
from crm import models
from djadmin.djadmin_base import BaseDjAdmin
print('crm models...')
# 注册model
class CustomerInfoAdmin(BaseDjAdmin): # 不使用object,直接继承BaseDjAdmin
list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time']
list_filter = ['source', 'consultant', 'status', 'created_time']
search_fields = ['contact', 'consultant__name']
site.register(models.CustomerInfo, CustomerInfoAdmin)
site.register(models.Role)
site.register(models.Menu)
site.register(models.UserProfile)
修改djadmin应用下的sites.py文件
如果传值site.register(models.CustomerInfo, CustomerInfoAdmin)
那么admin_class
就等于CustomerInfoAdmin
;如果没有传值site.register(models.Role)
,就使用默认值admin_class=BaseAdmin
from djadmin.djadmin_base import BaseDjAdmin
class AdminSite(object):
def __init__(self):
self.enable_admins = {}
# 两个参数,一个表名,一个自定义的admin类
def register(self, model_class, admin_class=BaseDjAdmin):
"""注册admin表"""
# print('register',model_class,admin_class)
# 获取app名字
app_name = model_class._meta.app_label
# 获取表名
model_name = model_class._meta.model_name
# 获取表别名
# model_verbose_name = model_class._meta.verbose_name
# print(model_verbose_name)
# 把model_class赋值给了admin_class,然后在视图中可以通过admin_class找到对应的model类(表名字)
admin_class.model = model_class
if app_name not in self.enable_admins:
self.enable_admins[app_name] = {}
self.enable_admins[app_name][model_name] = admin_class
# 实例化,就可以调用register方法
site = AdminSite()
访问 http://127.0.0.1:8000/djadmin/ 页面也是正常显示的
image.png会显示应用的名称,和已经注册的model
image.png
网友评论