zoukankan      html  css  js  c++  java
  • Python Day 77 Django框架 CRM项目(版本三)

      ##今日更新内容

    #1、search_field
        需要掌握技术点
            Q查询
                1.直接用Q去查
                
                2.    from app01 import models
                    models.Book.objects.filter(title__contains='',price__contains=2)
                    <QuerySet []>
                    from django.db.models import Q
                    models.Book.objects.filter(Q(title__contains='')|Q(price__contains=2))
                    <QuerySet [<Book: 三国演义>]>
                    models.Book.objects.filter(Q(title__contains='')|Q(price__contains=8))
                    <QuerySet [<Book: 红楼梦>, <Book: 三国演义>]>
                    q = Q()
                    q.children.append(('title__contains',''))  # 添加查询条件
                    q.children.append(('price__contains',8))
                    models.Book.objects.filter(q)
                    <QuerySet [<Book: 三国演义>]>
                    q.connector = 'or'  # q对象默认也是and关系 但是可以通过connector修改成or的关系
                    models.Book.objects.filter(q)
                    <QuerySet [<Book: 红楼梦>, <Book: 三国演义>]>
    #2、actions
        实现批处理操作,当用户选中相对应的check框,选择相应的批处理操作(如:更新、删除等)进行统一操作
    #3、list_filter
            1.显示外键字段 及外键字段所对应的模型表中的所有的数据
                获取外键字段所对应的模型表变量名
                models.Book._meta.get_field('publish').rel.to
            2.{'publish':[publish_obj,publish_obj1,]}
            3.给数据对象简单的配置href链接
            4.深拷贝request.GET 完成自动保存get携带的参数的功能
            5.点击标签后 样式变换 
            6.all标签
            7.后端还是利用q对象进行数据过滤  直接用默认的and关系
            
        需要掌握技术点
            #获取外键字段对应的表变量名,field是字段的字符串形式,该方法能根据他获取表名
            rel_model = self.config_obj.model._meta.get_field(field).rel.to
        
    #4、pop功能:父子页面如何通信? doc操作创建option标签
        需要解决的问题:
            1、在添加操作页面在外键字段右边添加一个加号,那后端怎么判断哪一个字段是外键字段
                解决方案:
                    循环模型表、拿到一个个对象,判断对象是否是,如果是,就给过滤的对象添加额外的属性,用于前端渲染的时候
                    根据是否存在这个额外添加的属性进行判断,判断通过就在外键字段后面添加+加号。
            2、给加号绑定点击事件、当点击加号时要跳转到对应外键表的添加页面,那后端要动态传对应不同表的添加页面的url,之前
                二级url是怎么拼接来着?
                    后端:
                    # print(form_obj.name) #拿到外键字段publish 、authors
                    rel_model = self.model._meta.get_field(form_obj.name).rel.to #通过字段名拿到所对应的模型表
                    rel_app_label = rel_model._meta.app_label #通过模型表拿到所对应的应用名
                    rel_model_name = rel_model._meta.model_name #通过模型表拿到所对应的模型表名
                    url = reverse('%s_%s_%s'%(rel_app_label,rel_model_name,'add'))
                    form_obj.url = url  #这里给对象添加属性,前端直接可以使用,这种方法牢记,解决前后端数据传递问题
            3、如何区分你子页面添加数据还是正常窗口添加页面?怎么理解呢?
                问题:当在添加书籍book页面,点击加号跳转小窗口到对应的authos页面或者出版社publish小窗口页面,添加完数据后,不能直接
                      返回的是author页面 而是自动关闭小窗口,继续进行book页面添加操作,而且选择下拉框默认选中你所创建的作者或者出版社
                      信息。
                解决方案:
                    为了识别父页面子页面,在打开子页面的url后面加get请求参数,获取form_obj渲染的标签id值form_obj.auto_id,然后拼接到
                    get请求url后面,这样子页面添加请求时通过url就能识别,当时别子页面以后,要return render(request,'stark/pop.html',locals()) 
                    在新子页面中要直接关闭子页面操作,再关闭之前还要调用父页面方法,不管是单标签还是多标签,
            4、父页面要干什么?父页面需要自动渲染一个option标签
                这里就学到了document创建option标签的方法,思考渲染标签需要什么数据?子页面pop.html怎么调用父页面add_view.html使用了
                    子页面可以调用父页面中的方法
                        window.opener.fatherFunc(...)
                        window.close()
                    父页面创建option标签:
                         function addOptions(pop_back_id,pk,text) {
                            //动态创建option标签  想想创建标签需要什么参数,不过函数比较好写的原因是所需要什么参数
                            //先定义形参就可以,到时谁调用谁给我传过来
                            var optEle = document.createElement('option');
                            //给标签赋属性
                            optEle.innerText = text;
                            optEle.value = pk;
                            optEle.selected = 'selected';//默认选中
                            //查找option所在的父标签
                            var seEle = document.getElementById(pop_back_id);
                            seEle.appendChild(optEle)
    
                        }

      ##search_field:或查询条件

    #自定义配置类中:
        class BookConfig(ModelStark):
            search_fields = ['title','price'] #自定义search_fields查询条件 且为or条件
    #默认配置类中
        class ModelStark(object):
            #ModelStark中时默认的参数,用户自定义的的在C:starkproapp01stark.py
            list_display = ['__str__',]
            list_display_links = []
            model_form_class = None
            search_fields = [] #默认search_fields
            def __init__(self,model):
                self.model = model #self.model是指拿到当前对象所对应的模型表名,即四张表对应都不一样
                self.app_label = self.model._meta.app_label  #直接给对象初始化应用名
                self.model_name = self.model._meta.model_name #直接给对象初始化表名
                self.key_word = '' #初始化
            def list_view(self, request):
                #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
                # print(self.model)
    
                queryset = self.model.objects.all()
                #search_file功能
                key_word = request.GET.get('q') #接受前端传来的数据
                #先对key_word初始值进行清空操作
                self.key_word = ''
                if key_word:
                    """
                    需要解决问题:
                        1、变量名问题
                            前后端传递的是字符串,orm数据查询语句时需要的是字段
                        2、查询条件由and改为or(这里再说明一下django源码中默认admin五大参数中search_files是或查询条件)  
                    解决方案:Q查询
                        Q查询有两种方法:
                            1、正常情况可以解决and 或者or 但是没法解决变量名问题
                            2、另一种用法
                                q = Q()
                                q.children.append(('title__contains','三'))  # 添加查询条件
                                q.children.append(('price__contains',8))
                                models.Book.objects.filter(q)
                                <QuerySet [<Book: 三国演义>]>
                                q.connector = 'or'  # q对象默认也是and关系 但是可以通过connector修改成or的关系
                                models.Book.objects.filter(q)
                                <QuerySet [<Book: 红楼梦>, <Book: 三国演义>]>
                            
                    """
                    self.key_word = key_word
                    from django.db.models import Q
                    q = Q() #创建q对象
                    q.connector = 'or' #指定q查询条件
                    #不停的往children中添加查询条件
                    for search_field in self.search_fields: #在自定义配置类中serch_fields = ['title','price']
                        print(search_field)
                        q.children.append(('%s__icontains'%search_field,key_word))  #contains为包含  价格i忽略大小写
                    queryset = queryset.filter(q)
                #展示类调用
                show_obj = ShowList(self,queryset,request)
    
    
                url = self.get_reverse_url('add')
                return render(request,'stark/list_view.html',locals())
    #前端list_view.html
    {% extends 'stark/base.html' %}
    {% block content %}
        <h2 class="text-center">数据展示</h2>
        <div class="col-md-8 col-md-offset-2">
            <a href="{{ url }}" class="btn btn-primary">添加数据</a>
            {% if show_obj.config_obj.search_fields %}
                <form class="form-inline pull-right">
                <div class="form-group">
                    <div class="input-group">
                        <input type="text" class="form-control" id="exampleInputAmount" placeholder="关键字" name="q" value="{{ show_obj.config_obj.key_word }}">
                    </div>
                </div>
                <button type="submit" class="btn btn-primary">Search</button>
            </form>
            {% endif %}
            <table class="table table-striped table-bordered table-hover">
                <thead>
                <tr>
                    {% for foo in show_obj.get_header %}
                        <td>{{ foo }}</td>
                    {% endfor %}
                </tr>
                </thead>
                <tbody>
                {% for body in show_obj.get_body %}
                    <tr>
                        {% for  foo in body %}
                            <td>
                                {{ foo }}
                            </td>
                        {% endfor %}
                    </tr>
                {% endfor %}
                </tbody>
    
            </table>
            {{ show_obj.page_obj.page_html|safe }}
        </div>
    {% endblock %}
    View Code

      ##actions批处理功能

    #前端 list_view.html
    {% extends 'stark/base.html' %}
    {% block content %}
        <h2 class="text-center">数据展示</h2>
        <div class="col-md-8 col-md-offset-2">
            <a href="{{ url }}" class="btn btn-primary">添加数据</a>
            {% if show_obj.config_obj.search_fields %}
                <form class="form-inline pull-right">
                <div class="form-group">
                    <div class="input-group">
                        <input type="text" class="form-control" id="exampleInputAmount" placeholder="关键字" name="q" value="{{ show_obj.config_obj.key_word }}">
                    </div>
                </div>
                <button type="submit" class="btn btn-primary">Search</button>
            </form>
            {% endif %}
             <form action="" method="post" class="form-inline">
                {% csrf_token %}
                <select name="action" id="" class="form-control">
    
                    <option value="">--------------------------</option>
                    {% for foo in show_obj.get_actions %}
                        <option value="{{ foo.name }}">{{ foo.desc }}</option>
                    {% endfor %}
    
                </select>
                <input type="submit" value="GO" class="btn btn-danger">
                <table class="table table-striped table-bordered table-hover">
                <thead>
                <tr>
                    {% for foo in show_obj.get_header %}
                        <td>{{ foo }}</td>
                    {% endfor %}
                </tr>
                </thead>
                <tbody>
                {% for body in show_obj.get_body %}
                    <tr>
                        {% for  foo in body %}
                            <td>
                                {{ foo }}
                            </td>
                        {% endfor %}
                    </tr>
                {% endfor %}
                </tbody>
    
            </table>
            </form>
    
            {{ show_obj.page_obj.page_html|safe }}
        </div>
    {% endblock %}
    
    #自定义配置类C:starkproapp01stark.py
    class BookConfig(ModelStark):
        def patch_init(self,request,queryset):
            queryset.update(price=888)
    
        patch_init.desc = '价格批量处理'
        def patch_delete(self,request,queryset):
            queryset.delete()
        patch_delete.desc = '价格批量删除'
        actions = [patch_init,patch_delete]
    #默认配置类
    class ModelStark(object):
        #ModelStark中时默认的参数,用户自定义的的在C:starkproapp01stark.py
        list_display = ['__str__',]
        list_display_links = []
        model_form_class = None
        search_fields = []
        actions = []  #添加一个默认action
        
        def check_box(self,is_header=False,obj=None):
            if is_header:
                return '选择'
            #添加每一个check的id值,以便用户选中后后台需要获取
            return mark_safe('<input type="checkbox" value="%s" name="selected_action"/>'%obj.pk) 
        def list_view(self, request):
            #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
            # print(self.model)
    
            if request.method == 'POST':
                #获取用户选中的函数字符串名
                action = request.POST.get('action')
                #获取用户选中的逐渐字段
                pk_list = request.POST.getlist('selected_action')
                #根据主键字段查询所有的数据
                queryset_list = self.model.objects.filter(pk__in=pk_list)
                #通过反射由函数字符串找函数名
                real_action = getattr(self,action) #这里self是指用户自定义的self
                #将queryset对象传给函数处理
                real_action(request,queryset_list)
            queryset = self.model.objects.all()
            queryset = self.search(queryset,request)
            #展示类调用
            show_obj = ShowList(self,queryset,request)
    
    
            url = self.get_reverse_url('add')
            return render(request,'stark/list_view.html',locals())
    #展示类
    class ShowList:
        def get_actions(self):
            tmp_list = [] #actions = [patch_init]
            for action in self.config_obj.actions: #循环用户自定义ations列表
                tmp_list.append({
                    'name':action.__name__,#字符串对应的名字
                    'desc':action.desc
                })
            return tmp_list  #[{'name':'','desc':''}]
    View Code

      ##filter前端渲染和筛选功能

    #自定义配置类
    class BookConfig(ModelStark):
        list_filter = ['publish','authors']
    
    #默认配置类
    class ModelStark(object):
        list_filter=[]
        def list_view(self, request):
            #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
            # print(self.model)
    
            if request.method == 'POST':
                #获取用户选中的函数字符串名
                action = request.POST.get('action')
                #获取用户选中的逐渐字段
                pk_list = request.POST.getlist('selected_action')
                #根据主键字段查询所有的数据
                queryset_list = self.model.objects.filter(pk__in=pk_list)
                #通过反射由函数字符串找函数名
                real_action = getattr(self,action) #这里self是指用户自定义的self
                #将queryset对象传给函数处理
                real_action(request,queryset_list)
            queryset = self.model.objects.all()
            queryset = self.search(queryset,request)
            #filter功能 list_filter=['publish','authors']
            q = Q()
            for field in self.list_filter:
                if field in request.GET:
                    filter_value = request.GET.get(field)
                    q.children.append((field,filter_value))
            queryset = queryset.filter(q)
            #展示类调用
            show_obj = ShowList(self,queryset,request)
    
    
            url = self.get_reverse_url('add')
            return render(request,'stark/list_view.html',locals())
    #展示类
    class ShowList:
        def get_filter(self):
            tmp_dict = {}
            for field in self.config_obj.list_filter: #用户自定配置数据格式为list_filter = ['publishs','authors']
                tmp_list = []
                #获取外键字段对应的表变量名,field是字段的字符串形式,该方法能根据他获取表名
                rel_model = self.config_obj.model._meta.get_field(field).rel.to
                rel_queryset = rel_model.objects.all()
                filter_value = self.request.GET.get(field)
                import copy
                """
                渲染前端ALL标签
                    点击ALL 标签,使当前所在的字段从访问网址中删除掉
                """
                params1 = copy.deepcopy(self.request.GET)
                if field in params1:
                    params1.pop(field)
                    s = mark_safe("<a href='?%s'>ALL</a>"%params1.urlencode())
                else:
                    s=mark_safe("<a href=''>ALL</a>")
                tmp_list.append(s)
                """
                下面渲染每一个表对象下的字段
                """
                params = copy.deepcopy(self.request.GET)
                for obj in rel_queryset:
                    params[field] = obj.pk #将每一个对象对应的id存到字典中
                    if filter_value == str(obj.pk):
                        #如果该标签被点击了,为了显示为红色,利用条件来添加一个action类属性
                        s = mark_safe('<a href="?%s" class="active">%s</a>' % (params.urlencode(), str(obj)))
                    else:
                        #params.urlencode() 将存入的对象以?publish=1&authors=1方式读出来,即前端访问网址能保存搜索条件了
                        s = mark_safe('<a href="?%s">%s</a>'%(params.urlencode(),str(obj)))
                    tmp_list.append(s)
                tmp_dict[field] = tmp_list #{'publishs':[obj1,obj2],'authors':[obj1,obj2]}
            return tmp_dict
            
    #前端list_view.html
    {% extends 'stark/base.html' %}
    {% block content %}
        <h2 class="text-center">数据展示</h2>
        <div class="col-md-9 ">
            <a href="{{ url }}" class="btn btn-primary">添加数据</a>
            {% if show_obj.config_obj.search_fields %}
                <form class="form-inline pull-right">
                    <div class="form-group">
                        <div class="input-group">
                            <input type="text" class="form-control" id="exampleInputAmount" placeholder="关键字" name="q"
                                   value="{{ show_obj.config_obj.key_word }}">
                        </div>
                    </div>
                    <button type="submit" class="btn btn-primary">Search</button>
                </form>
            {% endif %}
            <form action="" method="post" class="form-inline">
                {% csrf_token %}
                <select name="action" id="" class="form-control">
                    <option value="">--------------------------</option>
                    {% for foo in show_obj.get_actions %}
                        <option value="{{ foo.name }}">{{ foo.desc }}</option>
                    {% endfor %}
    
                </select>
                <input type="submit" value="GO" class="btn btn-danger">
                <table class="table table-striped table-bordered table-hover">
                    <thead>
                    <tr>
                        {% for foo in show_obj.get_header %}
                            <td>{{ foo }}</td>
                        {% endfor %}
                    </tr>
                    </thead>
                    <tbody>
                    {% for body in show_obj.get_body %}
                        <tr>
                            {% for  foo in body %}
                                <td>
                                    {{ foo }}
                                </td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                    </tbody>
    
                </table>
            </form>
    
            {{ show_obj.page_obj.page_html|safe }}
        </div>
        <div class="col-md-3">
            {% if show_obj.config_obj.list_filter %}
                <div class="alert-info text-center">FILTER</div>
                {% for k,v in show_obj.get_filter.items %}
                    <div class="panel panel-default">
                        <div class="panel-heading">By {{ k }}</div>
                        <div class="panel-body">
                            {% for foo in v %}
                                <p>{{ foo }}</p>
                            {% endfor %}
    
                        </div>
                    </div>
                {% endfor %}
            {% endif %}
        </div>
    {% endblock %}
    View Code

      ##pop功能:父子页面如何通信?怎么定义自动创建option标签函数?

    #默认配置类
    class ModelStark(object):
        def add_view(self, request):
            model_form_class = self.get_model_form()
            model_form_obj = model_form_class()
            if request.method == 'POST':
                model_form_obj = model_form_class(request.POST)
                pop_back_id = request.GET.get('pop_back_id')
                if model_form_obj.is_valid():
                    obj = model_form_obj.save() #保存以后能拿到一个对象
                    if pop_back_id: #如果pop_back_id有值 说明是子页面提交过来的post请求
                        #给子页面传创建option标签所需要的参数
                        pk = obj.pk
                        text = str(obj)
                        return render(request,'stark/pop.html',locals()) #如果是子页面 渲染一个新页面
                    return redirect(self.get_reverse_url('list'))
            #渲染外键字段后面添加加号
            from django.forms.models import ModelChoiceField
            for form_obj in model_form_obj:
                if isinstance(form_obj.field,ModelChoiceField):
                    form_obj.is_pop = True
                    # print(form_obj.name) #拿到外键字段publish 、authors
                    rel_model = self.model._meta.get_field(form_obj.name).rel.to #通过字段名拿到所对应的模型表
                    rel_app_label = rel_model._meta.app_label #通过模型表拿到所对应的应用名
                    rel_model_name = rel_model._meta.model_name #通过模型表拿到所对应的模型表名
                    url = reverse('%s_%s_%s'%(rel_app_label,rel_model_name,'add'))
                    # print(form_obj.auto_id) #拿到当前 input渲染的id值 id_publish、id_authors
                    url = url +'?pop_back_id=%s'%form_obj.auto_id
                    form_obj.url = url
            return render(request, 'stark/add_view.html', locals())
    #前端:add_view.html  渲染外键添加加号 和绑定点击事件跳出小窗口  和 定义自动创建option标签函数
    {% extends 'stark/base.html' %}
    {% block css %}
        <link rel="stylesheet" href="/static/css/my_css.css">
    {% endblock %}
    {% block content %}
        <div class="col-md-6 col-md-offset-3">
                <h2 class="text-center">添加数据</h2>
                <form action="" method="post">
                    {% csrf_token %}
                    {% for form_obj in model_form_obj %}
                        <div class="plus-father">
                            <p>{{ form_obj.label }}{{ form_obj }}
                            <span>{{ form_obj.error.0 }}</span>
                        </p>
                        <div>
                            {% if form_obj.is_pop %}
                                <span class="plus" onclick="WindowOpen('{{ form_obj.url }}')">+</span>
                            {% endif %}
                        </div>
                        </div>
    
                    {% endfor %}
                    <input type="submit" class="btn btn-success pull-right">
                </form>
            </div>
    
        <script>
            //绑定点击函数, window.open跳出子页面,url为动态数据,应该怎么获取这个是个难点
            function WindowOpen(url){
                window.open(url,'','width=800px,height=400px')
            }
            function addOptions(pop_back_id,pk,text) {
                //动态创建option标签  想想创建标签需要什么参数,不过函数比较好写的原因是所需要什么参数
                //先定义形参就可以,到时谁调用谁给我传过来
                var optEle = document.createElement('option');
                //给标签赋属性
                optEle.innerText = text;
                optEle.value = pk;
                optEle.selected = 'selected';//默认选中
                //查找option所在的父标签
                var seEle = document.getElementById(pop_back_id);
                seEle.appendChild(optEle)
    
            }
        </script>
    {% endblock %}
    #前端:base.html  使用相对绝对位置调节加号位置
     <style>
            table{
                margin-top: 10px;
            }
            .active{
                color: red;
            }
            .plus-father{
                position: relative;
            }
            .plus{
                font-size: 24px;
                color: #369;
                position: absolute;
                right: -20px;
                top: 20px;
    
            }
        </style>
    #前端:pop.html  关闭子页面 和 调用父页面自动创建option函数
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link rel="stylesheet" href="/static/bs-3.3.7/css/bootstrap.css">
        <script src="/static/bs-3.3.7/js/bootstrap.min.js"></script>
    </head>
    <body>
    <script>
        //调用父页面add_view.html函数,为父页面自动创建option标签,创建该标签所需要的参数,从后端拿,想想都需要哪些参数
        //这些参数从后端该怎么拿
        window.opener.addOptions('{{ pop_back_id }}','{{ pk }}','{{ text }}');
        window.close() //为父页面渲染option标签后,主动关闭子页面
    </script>
    </body>
    </html>
    View Code
  • 相关阅读:
    HUST 1017 Exact cover (Dancing links)
    HDU 1160 FatMouse's Speed (DP)
    HDU 1058 Humble Numbers (DP)
    Kubernetes(k8s)
    linux命令
    入侵检测系统
    lynis检测
    CPU死锁
    检测工具lynis
    Linux表面工作
  • 原文地址:https://www.cnblogs.com/liangzhenghong/p/11309720.html
Copyright © 2011-2022 走看看