zoukankan      html  css  js  c++  java
  • CRM客户关系管理系统(三)

    第四章、kingadmin开发设计

     4.1.kingadmin设计

    django admin注册model的写法

    crm/admin.py

    class CustomerAdmin(admin.ModelAdmin):
        #显示
        list_display = ['name','source','contact_type','contact','consultant','consult_content','status','date']
        #过滤
        list_filter = ['source','consultant','status','date']
        #搜索,consultant是外键,必须加“__字段名”
        search_fields = ['contact','consultant__name']
    
    admin.site.register(models.CustomerInfo,CustomerAdmin)

    后台显示

    这是后台显示的样子,如果我们想让前端也显示类似这样的页面该怎么做呢?这就需要照django自带的admin写法,自己自定义个kingadmin(模仿admin)

    kingadmin

    (1)创建app kingadmin

    python manage.py startapp kingadmin

    添加到settings的INSTALL_APPS里面

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'crm',
        'kingadmin',
    ]

    因为想让kingadmin app以后可以直接移植到其它项目中,所以在kingadmin目录下单独创建templates/kingadmin和static目录,把之前的静态文件和模板拷贝进去

    (2) settings里面设置kingadmin静态文件和templates路径

    STATIC_URL = '/static/'
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'statics'),
        os.path.join(BASE_DIR, 'kingadmin/statics'),  
    )

    (4)PerfectCRM/url.py添加路由分发

    urlpatterns = [
        url(r'^kingadmin/', include('kingadmin.urls')),
    ]

     (5)kingamdin/urls.py

    # kingadmin/urls.py
    
    from django.conf.urls import url
    
    from kingadmin import views
    
    urlpatterns = [
        url(r'^login/', views.acc_login,name='login'),
        url(r'^logout/', views.acc_logout,name='logout'),
    ]

    (6)kingamdin/views.py

     登录界面也单独创建

     

    # kingadmin/views.py
    
    from django.shortcuts import render,redirect
    from django.contrib.auth import authenticate,login,logout
    
    def acc_login(request):
        error_msg = ''
        if request.method == 'POST':
            username = request.POST.get('username',None)
            password = request.POST.get('password',None)
            #user是一个对象
            #验证
            user = authenticate(username=username,password=password)
            if user:
                #登录(已生成session)
                login(request, user)
                #如果有next值就获取next值,没有就跳转到首页
                return redirect(request.GET.get('next','/kingadmin/'))
            else:
                error_msg = '用户名或密码错误!'
    
        return render(request,'kingadmin/login.html',{'error_msg':error_msg})
    
    
    def acc_logout(request):
        logout(request)
        return redirect("/login/")

    (7)kingamdin/urls.py

    添加登录后跳转到“app_index.html”页面

    urlpatterns = [
        url(r'^$', views.app_index,name='app_index'),
        url(r'^login/', views.acc_login,name='login'),
        url(r'^logout/', views.acc_logout,name='logout'),
    ]
        

    (8)kingadmin/views.py

    def app_index(request):
        return render(request,'kingadmin/app_index.html')

    (9)kingadmin/app_index.html

     kingadmin/index.html中添加block right-content-container

    king/index.html

     app_index.html

    {#templates/kingadmin/app_index.html#}
    
    {% extends 'kingadmin/index.html' %}
    
    {% block right-content-container %}
        <h2 class="page-header">APPS</h2>
    {% endblock %}

    4.2.kingadmin自动发现及注册功能开发

     想让app_index.html页面像后台一样显示所有注册的app以及下面的表名

     

    (1)kingadmin/app_setup.py

    # kingadmin/app_setup.py
    
    from django import conf
    
    def kingadmin_auto_discover():
        for app_name in conf.settings.INSTALLED_APPS:
            try:
                #去每个app下面执行kingadmin.py文件
                mod = __import__('%s.kingadmin'%app_name)
                #打印每个app已注册的model名字
                print(mod.kingadmin)
            except ImportError:
                pass

    (2)crm/kingadmin.py

    # crm/kingadmin.py
    
    
    from kingadmin.sites import site
    from crm import models
    
    print('crm kingadmin....')
    
    #注册model
    class CustomerAdmin(object):
        list_display = ['name','source','contact_type','contact','consultant','consult_content','status','date']
        list_filter = ['source','consultant','status','date']
        search_fields = ['contact','consultant__name']
    
    site.register(models.CustomerInfo,CustomerAdmin)

    (3)student/kingadmin.py

    创建app student

    student/models.py

    # student/models.py
    
    from django.db import models
    
    class Test(models.Model):
        name = models.CharField(max_length=64)

    student/kingadmin.py

    # student/kingadmin.py
    
    from student import models
    from kingadmin.sites import site
    
    print('student kingadmin.....')
    
    #注册model
    class TestAdmin(object):
        list_display = ['name']
    
    site.register(models.Test,TestAdmin)

    (4)kingadmin/views.py

    # kingadmin/views.py
    
    from kingadmin import app_setup
    #程序一启动就自动执行
    app_setup.kingadmin_auto_discover()

    说明:

    程序一启动,会执行每个app下面的kingadmin.py,注册全局的字典

    from django import conf

    conf.settings.INSTALL_APPS

    动态获取settings里面所有添加的app名字

    运行程序

    (5)返回全局字典

    我们想要的字典格式如下:

    修改sites.py

    # kingadmin/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()

    kingamdin/views.py中打印看看

    from kingadmin import app_setup
    #程序已启动就自动执行
    app_setup.kingadmin_auto_discover()
    
    from kingadmin.sites import site
    print('site',site.enable_admins)

    运行程序

     (6)前端页面显示

     kingamdin/views.py

    def app_index(request):
    
        return render(request,'kingadmin/app_index.html',{'site':site})

    kingadmin/templates/app_index.html

    {#templates/kingadmin/app_index.html#}
    
    {% extends 'kingadmin/index.html' %}
    
    {% block right-content-container %}
    <h2 class="page-header">APPS</h2>
    
    <div>
        {% for app_name,app_tables in site.enable_admins.items %}
            {{ app_name }}{{ app_tables }}
    
        {% endfor %}
    
    </div>
    
    
    {% endblock %}

    4.3.kingadmin model obj list页面开发

    把前端页面做成表格的格式,跟admin后台显示一样

    bootstrap table:  https://v3.bootcss.com/css/#tables

    (1)kingadmin/app_index.html

    {#templates/kingadmin/app_index.html#}
    
    {% extends 'kingadmin/index.html' %}
    
    {% block right-content-container %}
    <h2 class="page-header">APPS</h2>
    
    <div>
        {% for app_name,app_tables in site.enable_admins.items %}
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th>{{ app_name }}</th>
                    </tr>
                </thead>
                <tbody>
                    {% for model_name in app_tables  %}
                        <tr>
                            <td><a href="{% url 'table_obj_list' app_name model_name %}">{{ model_name }}</a></td>
                            <td>ADD</td>
                            <td>Change</td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        {% endfor %}
    
    </div>
    
    
    {% endblock %}

    (2)crm/kingadmin.py注册三个model

    #注册model
    class CustomerAdmin(object):
        list_display = ['name','source','contact_type','contact','consultant','consult_content','status','date']
        list_filter = ['source','consultant','status','date']
        search_fields = ['contact','consultant__name']
    
    site.register(models.CustomerInfo,CustomerAdmin)
    site.register(models.Role)
    site.register(models.Menus)
    site.register(models.UserProfile)

    (3)kingadmin/url.py

    urlpatterns = [
            url(r'^(w+)/(w+)/$', views.table_obj_list,name='table_obj_list'),
    ]

    (4)kingadmin/sites.py

    class AdminSite(object):
        .
        .
        .
        def register(self,model_class,admin_class=None):
            .
            .
            .
             #获取app名字
            app_name = model_class._meta.app_label
            #获取表名
            model_name = model_class._meta.model_name
            #把model_class赋值给了admin_class,然后在视图中可以通过admin_class找到对应的model类(表名字)
            admin_class.model = model_class
            .
            .
            .    

    此时运行发现会报错

    是因为我们在注册model的时候,有的写了自定义的model类,有的没写,而我们都统一的赋值,导致那些没写自定义model类(空的)赋值的时候就会报NoneType错误

    django自带的自定义admin类的写法继承了ModelAdmin,那注册的时候为什么有的没写自定义admin类没有报错呢?

    是因为继承的ModelAdmin帮我们写了(里面其实都定义为空了),我们模仿django admin的写法,也写个父类。

     

    (5)kingadmin/admin_base.py

    新建个admin_base.py,写个父类

    # kingadmin/admin_base.py
    
    class BaseKingAdmin(object):
    
        pass

    (6)crm/kingadmin.py

    # crm/kingadmin.py
    
    from kingadmin.sites import site
    from crm import models
    from kingadmin.admin_base import BaseKingAdmin
    
    # print('crm kingadmin....')
    
    #注册model
    class CustomerAdmin(BaseKingAdmin):
        list_display = ['name','source','contact_type','contact','consultant','consult_content','status','date']
        list_filter = ['source','consultant','status','date']
        search_fields = ['contact','consultant__name']
    
    site.register(models.CustomerInfo,CustomerAdmin)
    site.register(models.Role)
    site.register(models.Menus)
    site.register(models.UserProfile)
    crm/kingadmin.py

    继承BaseKingAdmin

     (7)kingadmin/sites.py

    # kingadmin/sites.py
    from kingadmin.admin_base import BaseKingAdmin
    
    class AdminSite(object):
        def __init__(self):
            self.enable_admins = {}
    
        #两个参数,一个表名,一个自定义的admin类
        def register(self,model_class,admin_class=BaseKingAdmin):
            '''注册admin表'''
    
            # print('register',model_class,admin_class)
            #获取app名字
            app_name = model_class._meta.app_label
            #获取表名
            model_name = model_class._meta.model_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()
    kingadmin/sites.py

    现在运行程序,就正常了,访问:http://127.0.0.1:8000/kingadmin/

    (8)取出model里面的值

    kingadmin/views.py

    @login_required
    def table_obj_list(request, app_name, model_name):
        '''取出指定model里的数据返回给前端'''
        #拿到admin_class后,通过它找到拿到model
        admin_class = site.enable_admins[app_name][model_name]
        querysets = admin_class.model.objects.all()
    
        return render(request, 'kingadmin/table_obj_list.html',{'querysets':querysets})

    (9)templates/kingadmin/table_obj_list.html

    {#kingadmin/templates/kingadmin/table_obj_list.html#}
    
    {% extends 'kingadmin/index.html' %}
    
    {% block right-content-container %}
    <h2 class="page-header">app</h2>
    
    <div>
            {{ querysets }}
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
    
                </tbody>
            </table>
    </div>
    
    {% endblock %}

    现在拿到的是一个对象,但是有个问题就是:没注册三个model里面得到值是一样

     

    因为没注册的三个mdoel都共享同一个BaseKingAdmin内存对象(三个model内存地址一样),我们只需要实例化就可以了(实例化后就都有单独的内存空间了)

    修改kingadmin/sites.py

    # kingadmin/sites.py
    from kingadmin.admin_base import BaseKingAdmin
    
    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_class赋值给了admin_class,然后在视图中可以通过admin_class找到对应的model类(表名字)
            if not admin_class:
                # 实例化,如果没写注册的类,就用BaseKingAdmin
                admin_class = BaseKingAdmin()
            else:
                #如果写了注册的类,就实例化自己
                admin_class = admin_class()
            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()

     现在就可以取出对应model的数据了

     
     
     
  • 相关阅读:
    Mycat读写分离+高可用笔记
    MyCAT基础安装笔记
    C# Winform中DataGridView的DataGridViewCheckBoxColumn CheckBox选中判断
    C# winform DataTable 批量数据处理 增、删、改 .
    选中CheckBoxList的值放到TextBox中,再次选中从textBox中删除
    dede后台删除文章后台还有分页显示解决方法
    dedecms数据库表说明大全
    织梦自增函数[field:global name=autoindex/]常见用法
    http协议的状态码——400,401,403,404,500,502,503,301,302等常见网页错误代码
    web.config设置之system.webServer 详细介绍,为网站设置默认文档
  • 原文地址:https://www.cnblogs.com/gaidy/p/12097135.html
Copyright © 2011-2022 走看看