• day063 CRM项目之stark组件第一天(初步写stark组件)


    本节内容:

    1、写stark的前期准备工作
    2、stark组件之启动
    3、stark组件之注册功能
    4、stark组件之类变量查询
    5、stark组件之url二级分发
    6、静态文件和模板的引入问题
    7、stark组件展示表格的体数据(即展示记录)
    8、stark组件之展示表头数据
    9、stark组件之默认列(为所有的查看页面默认显示编辑、删除、选择按钮)
    

    一、写stark的前期准备工作

    准备工作:
    1、stark也是一个app(用startapp stark创建),目标把这个做成一个可插拔的组件
    
    2、settings文件下的INSTALLED_APPS 路径要配置好
    
    3、写好sites.py中的site类,实例化出一个类对象,其他文件都直接引用这个类对象(单例模式),
    4、当然啦,你的模型类文件也要准备好,使用哪个数据库也要确定
    




    二、stark组件之启动

    启动所有app下的stark.py文件
    (在stark文件夹下的apps.py文件中的class StarkConfig(AppConfig):添加该方法)
    
    def ready(self):    # 这一句自动去加载所有的app下的stark.py文件
    autodiscover_modules("stark")
    

    “python

    添加位置:在stark文件夹下的apps.py文件

    from django.apps import AppConfig
    from django.utils.module_loading import autodiscover_modules

    class StarkConfig(AppConfig):
    name = ‘stark’

    def ready(self):  # 该方法默认去加载所有APP下的stark.py文件
        autodiscover_modules("stark")
    
    ## 三、stark组件之注册功能
        这里主要做两件事:
        1、在stark源码中,写好我们的starksite类,并实例化出一个site对象(单例对象供注册使用),
        2、在相应的APP下,注册site
    ```python
    # stark.py文件源码
    from django.shortcuts import HttpResponse,render
    
    from django.urls import path,re_path
    
    class ModelStark():  # 配置类
    
        list_display = ["__str__"]
        def __init__(self,model):
            self.model=model
    
    class StarkSite():
        '''
        # StarkSite: 基本类
        # model: 注册模型类
        # ModelStark: 注册模型类的配置类
        '''
    
        def __init__(self):  # 定义这个字典在url二级分发时体现出来作用,
            self._registry = {} # model_class class -> admin_class instance
    
        # 注册方法,关键的两步
        def register(self,model,stark_class=None): # 传参,注册模型类和对应的配置类,这里传的都是类名,所以在调用方法的时候,实际上是调用函数,所以要传self
            stark_class = stark_class or ModelStark  # 若自定制有子类配置类对象则用传入的子类的,没有用默认父类的
            self._registry[model] = stark_class(model) #  该模型类为键,该模型了的配置类为值
    
    site=StarkSite()
    
    # app01下的时stark.py文件代码
    from stark.service.sites import site,ModelStark
    from . import models
    
    site.register(models.Book,BookConfig) # 这里暂时先不传参,该参数为用户自定义的配置类
    site.register(models.Publish)
    
    Python

    四、stark组件之类变量查询

    回顾我们的面向对象的知识:
    类变量的查询的先后顺序(有继承关系的):
    1、首先在自己对象的内存空间中找该变量,找不到的话
    2、就到自己的类空间中找,还找不到的话
    3、就到自己的父类空间中找,一直逐级往上找,再找不到的话,就报错
    

    五、stark组件之url二级分发

    这里我们模仿,admin组件的使用静态方法进行url二级分发
    1、首先在urls中配置path路径,(这一步属于用户操作)
    2、在基本类中配置好一级分发
    3、在配置类中配置好二级分发
    
    # stark.py文件下的代码
    
    class ModelStark():  # 配置类
    
        # urls二级分发
        def get_urls(self):
            temp = [
                path('',self.list_view),
                path('add/',self.add_view),
                re_path('(d+)/change/',self.change_view),
                re_path('(d+)/delete/',self.delete_view),
            ]
            return temp
    
        # 将一个方法变成一个属性
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    class StarkSite():
        '''
        # StarkSite: 基本类
        # model: 注册模型类
        # ModelStark: 注册模型类的配置类
        '''
    
        def get_urls(self):
            temp = []
            for model, config_obj in self._registry.items():  # {Book:Bookconfig(Book),Publish:ModelStark(Publish)}
                model_name = model._meta.model_name  # 拿到该表的小写表名
                app_label = model._meta.app_label  # 拿到该表所在的APP名称
                temp.append(
                    path('%s/%s/' % (app_label, model_name),config_obj.urls) # 对象直接点该属性,这是一个方法封装的属性
                )
           '''
           最终效果:
           # 1 path('app01/book/',Bookconfig(Book).urls),
    
            path('app01/book/',Bookconfig(Book).list_view),
            path('app01/book/add',Bookconfig(Book).add_view),
            path('app01/book/(d+)/change/',Bookconfig(Book).change_view),
            path('app01/book/(d+)/delete/',Bookconfig(Book).delete_view),
            '''
            return temp
    
        @property # 将一个方法变成属性,这样在使用的时候就可以不用加括号,直接点
        def urls(self):
            return self.get_urls(), None, None
    
    # 用户项目中的urls.py文件中配置path路径
    
    from stark.service.sites import site
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('stark/',site.urls),
    ]
    
    Python

    六、静态文件和模板的引入问题

    主要这里我们要将stark组件做成可插拔式的,所有静态文件和模板文件都要放在我们的stark文件夹下。
    这样就可以保证用户在使用我们的stark组件时,不会缺少配置文件。
    

    七、stark组件展示表格的体数据(即展示记录)

    这个统一在最后面的实例中有详解
    

    八、stark组件之展示表头数据

    这个统一在最后面的实例中有详解
    

    九、stark组件之默认列(为所有的查看页面默认显示编辑、删除、选择按钮)

    1、下面是今天的所有代码实例

    用户app01下的models.py文件
    from django.db import models
    
    # Create your models here.
    
    # Create your models here.
    class Book(models.Model):
        title = models.CharField( max_length=32,verbose_name="书籍名称")
        pub_date=models.DateField(verbose_name="出版日期")
        price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
        publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE,null=True)
        authors=models.ManyToManyField("Author",db_table="book2authors") # 创建关系表
        def __str__(self):
            return self.title
    
    class Publish(models.Model):
        name=models.CharField( max_length=32,verbose_name="名字")
        city=models.CharField( max_length=32)
        email=models.CharField(max_length=32)
        def __str__(self):
            return self.name
    
    class Author(models.Model):
        name=models.CharField( max_length=32)
        age=models.IntegerField()
        #books=models.ManyToManyField("Book")
        ad=models.OneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE)
        def __str__(self):
            return self.name
    class AuthorDetail(models.Model):
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
        # author=models.OneToOneField("Author",on_delete=models.CASCADE)
        def __str__(self):
            return str(self.telephone)
    
    Python
    stark.py源码
    from django.shortcuts import HttpResponse,render
    
    from django.urls import path,re_path
    
    from django.core.exceptions import FieldDoesNotExist # 引入这个错误类型
    from app01.models import *
    from django.utils.safestring import mark_safe # 告诉前端不要把我这个写的标签转义,直接渲染我写的这个标签
    
    class ModelStark():  # 配置类
    
        list_display = ["__str__"]
        def __init__(self,model):
            self.model=model
    
        # 选择,删除,编辑 列
        def _checkbox(self, obj=None, is_header=False):
            if is_header:
                return "选择"
            return mark_safe("<input type='checkbox'>") # 注意引号啊,要细心
    
        def _edit(self,obj=None,is_header=False): # obj是当前表记录的对象
            if is_header:
                return "编辑"
            app_label = obj._meta.app_label
            model_name = obj._meta.model_name  # 这里先暂时写成这个动态url,后面我们使用url反向解析来解决这个问题
            return mark_safe("<a href='/stark/%s/%s/%s/change/'>编辑</a>" %(app_label,model_name,obj.pk))
    
        def _delete(self,obj=None,is_header=False): # obj是当前表记录的对象
            if is_header:
                return "删除"
            app_label = obj._meta.app_label
            model_name = obj._meta.model_name
            return mark_safe("<a href='/stark/%s/%s/%s/delete/'>删除</a>" %(app_label,model_name,obj.pk))
    
        # 让所有的查看页面都默认带上这三列选项,选择,删除,编辑
        def get_new_list_display(self):
            new_list_display=[]
            new_list_display.extend(self.list_display) # 将当前的要显示的列表遍历添加到这个新列表中
            new_list_display.insert(0,ModelStark._checkbox) # 在第一个位置插入选择列
            new_list_display.append(ModelStark._edit)  # 后面添加编辑,删除功能列
            new_list_display.append(ModelStark._delete)
            return new_list_display
    
    
        def list_view(self,request):
            # self  ;        模型类对应的配置类对象,可能是自定义配置类对象,也可能是默认配置类ModelStark对象
            # self.model:    当前访问表的模型类
    
            # header_list=["名称","价格","出版日期","出版社"]
            # 展示当前表头数据  header_list=["名称","价格","出版日期","出版社"]
            header_list = []
            for field in self.get_new_list_display():
                try:
                    field_obj = self.model._meta.get_field(field) # 拿到该字段的对象
                    header_list.append(field_obj.verbose_name) # verbose.name是字段对象的一个属性,默认是字段名,可以在模型类设置等于中文
                except FieldDoesNotExist as e:
                    if field == "__str__": # 特例,不传参,使用父类的默认值"__str__",如:publish表这时拿到的是__str__字符串
                        val = self.model._meta.model_name.upper()
                    else:
                        val = field(self,is_header=True) # 调用子类的函数,因为是类名直接调用所以此时是方法,需要传self参数
                    header_list.append(val)
    
    
            # 展示当前表体数据
            data = [] # 最终传给模板文件的样式:[["西游记",price],[title,price],]
            queryset = self.model.objects.all() # 拿到一个queryset的集合对象,元素为每一本书或每一个模型类的对象(表的数据每一条记录)
            # print(queryset)
    
            for obj in queryset:
                temp = []
                for field in self.get_new_list_display():
                    if callable(field): # 多对多字段会调用函数(类名调用方法即调用函数)
                        val = field(self,obj) # 执行函数要传参数self,
                    else:
                        val = getattr(obj,field)  # 这里要注意拿到的field从列表中取出来是一个字符串,需要用反射来拿
                                                # 如果是__str__它会去执行,拿到返回值
                    temp.append(val)
                data.append(temp)
            print("data最终效果",data)
            return render(request, "stark/list_view.html", locals())
    
    
        def add_view(self,request):
            # self  ;        模型类对应的配置类对象,可能是自定义配置类对象,也可能是默认配置类ModelStark对象
            # self.model:    当前访问表的模型类
    
            return HttpResponse("add_view")
    
        def change_view(self,request,id):
            # self  ;        模型类对应的配置类对象,可能是自定义配置类对象,也可能是默认配置类ModelStark对象
            # self.model:    当前访问表的模型类
    
            return HttpResponse("change_view")
    
    
        def delete_view(self,request,id):
            # self  ;        模型类对应的配置类对象,可能是自定义配置类对象,也可能是默认配置类ModelStark对象
            # self.model:    当前访问表的模型类
    
            return HttpResponse("delete_view")
    
    
        # urls二级分发
        def get_urls(self):
            temp = [
                path('',self.list_view),
                path('add/',self.add_view),
                re_path('(d+)/change/',self.change_view),
                re_path('(d+)/delete/',self.delete_view),
            ]
            return temp
    
        # 将一个方法变成一个属性
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    
    class StarkSite():
        '''
        # StarkSite: 基本类
        # model: 注册模型类
        # ModelStark: 注册模型类的配置类
        '''
    
        def __init__(self):  # 定义这个字典在url二级分发时体现出来作用,
            self._registry = {} # model_class class -> admin_class instance
    
        def register(self,model,stark_class=None): # 传参,注册模型类和对应的配置类,这里传的都是类名,所以在调用方法的时候,实际上是调用函数,所以要传self
            stark_class = stark_class or ModelStark  # 若自定制有子类配置类对象则用传入的子类的,没有用默认父类的
            self._registry[model] = stark_class(model) #  该模型类为键,该模型了的配置类为值
    
    
        def get_urls(self):
            temp = []
            for model, config_obj in self._registry.items():  # {Book:Bookconfig(Book),Publish:ModelStark(Publish)}
                model_name = model._meta.model_name  # 拿到该表的小写表名
                app_label = model._meta.app_label  # 拿到该表所在的APP名称
                temp.append(
                    path('%s/%s/' % (app_label, model_name),config_obj.urls) # 对象直接点该属性,这是一个方法封装的属性
                )
    
            return temp
    
        @property
        def urls(self):
            return self.get_urls(), None, None
    
    
    site=StarkSite()
    
    Python
    用户app01下的stark.py
    print("app01>>>>>")
    
    from stark.service.sites import site,ModelStark
    from . import models
    
    
    class BookConfig(ModelStark):
    
        def show_authors(self,obj=None,is_header=False): # 需要自定义这个方法,在显示的时候用方法来调用,表头和表体显示不一样
            if is_header:
                return "作者"
    
            return " ".join([obj.name for obj in obj.authors.all()])
    
        list_display = ["title","price","pub_date",show_authors] # 这里直接publish拿到的是该表的一个object对象
    
    
    
    
    site.register(models.Book,BookConfig)
    site.register(models.Publish)
    site.register(models.Author)
    site.register(models.AuthorDetail)
    
    Python
    stark文件夹下的查看模板文件list_view.py文件
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    </head>
    <body>
    
    <h3>数据列表</h3>
    
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <table class="table table-hover table-striped">
                    <thead>
                        <tr>
                            {% for item in header_list %}
                            <th>{{ item }}</th>
                            {% endfor %}
    
                        </tr>
                    </thead>
                    <tbody>
    
                    {% for item in data %}
                       <tr>
                           {% for val in item %}
                           <td>{{ val }}</td>
                           {% endfor %}
    
                       </tr>
                    {% endfor %}
    
                    </tbody>
                </table>
            </div>
        </div>
    </div>
    
    </body>
    </html>
    
    Python
     
  • 相关阅读:
    docker 容器启动初始化,centos镜像启动并执行
    odoo 分布式session 失效解决方案
    文件分布式存储 minio docker
    odoo reports 报表打印pdf初探
    odoo 分布式快速更新
    linux Warning: Stopping docker.service, but it can still be activated by:
    linux 查看80端口的连接数
    css flex 涨姿势了
    odoo 后台打印日志修改
    iOS 导航栏消失
  • 原文地址:https://www.cnblogs.com/yipianshuying/p/10278488.html
Copyright © 2020-2023  润新知