Python Day 76 Djaango框架 CRM项目(版本二)

  ##更新内容

#1、list_display_links

#2、form与modelform

#3、bulk_create批量插入数据

#4、封装展示类:

#5、使用分页器

#6、自动保存搜索条件,即保存url地址状态

  ##list_display_links

#1、实现给相应的字段添加a标签,连接功能,点击可以跳转、
        def list_view(self, request):
            #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
            # print(self.model)

            queryset = self.model.objects.all()
            # 表头展示
            header_list = []
            for field_or_func in self.get_new_list():
                if isinstance(field_or_func,str):
                    if field_or_func == '__str__': #当用户没有指定list_display 默认展示当前表的大写名字
                        val = self.model._meta.model_name.upper()
                    else:
                        val = self.model._meta.get_field(field_or_func).verbose_name
                else:
                    val = field_or_func(self,is_header=True)
                header_list.append(val)
            #表单展示
            body_list = [] #格式定义 [[obj1.title,obj1.price],[obj2.title,obj2.price],[]]

            for obj in queryset:
                tmp = []
                for field_or_func in self.get_new_list():#注意这里的list_display查找顺序,先查自己的,在查全局的,然后循环要展示的字段
                    if isinstance(field_or_func,str):
                        val = getattr(obj,field_or_func) #通过反射获取obj对象中field字段所对应的值
                        if field_or_func in self.list_display_links:
                            _url = self.get_reverse_url('edit',obj)
                            val = mark_safe('<a href="%s">%s</a>'%(_url,val))
                    else:
                        val = field_or_func(self,obj=obj)
                    tmp.append(val)

                body_list.append(tmp)


            return render(request,'stark/list_view.html',locals())
#2、当表中存在a标签链接后删除默认的编辑功能字段
        def get_new_list(self):
            tmp=[]
            tmp.append(ModelStark.check_box)
            tmp.extend(self.list_display)
            if not self.list_display_links:
                tmp.append(ModelStark.edit_col)
            tmp.append(ModelStark.delete_col)
            return tmp
View Code

  ##form与modelform

模型表的增删改查

form组件
    1.校验数据
    2.渲染标签
    3.展示信息

modelform用法
    class StudentList(ModelForm):
        class Meta:
            model =Student #对应的Model中的类
            fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
            exclude = None #排除的字段
            #error_messages用法:
            error_messages = {
            'name':{'required':"用户名不能为空",},
            'age':{'required':"年龄不能为空",},
            }
            #widgets用法,比如把输入用户名的input框给为Textarea
            #首先得导入模块
            from django.forms import widgets as wid #因为重名,所以起个别名
            widgets = {
            "name":wid.Textarea(attrs={"class":"c1"}) #还可以自定义属性
            }
            #labels,自定义在前端显示的名字
            labels= {
            "name":"用户名"
            }

  ##modelform实现增删改查

#1、modelform的前端渲染跟forms组件一模一样实现增删改查
    自定义配置类:C:\starkpro\app01\stark.py
        class BookConfig(ModelStark):

            list_display = ['title','price','publishDate','publish']
            list_display_links = ['title','price']

            class BookModelForm(ModelForm):
                class Meta:
                    model = models.Book
                    fields = '__all__'
                    from django.forms import widgets as wid
                    widgets = {
                        'title':wid.TextInput(attrs={'class':'form-control'}),
                        'price':wid.TextInput(attrs={'class':'form-control'}),
                        'publishDate':wid.DateInput(attrs={'class':'form-control'}),
                        'publish':wid.Select(attrs={'class':'form-control'}),
                        'authors':wid.SelectMultiple(attrs={'class':'form-control'})
                    }
            model_form_class = BookModelForm
    默认配置类:C:\starkpro\stark\service\stark.py
        class ModelStark(object):
            #ModelStark中时默认的参数,用户自定义的的在C:\starkpro\app01\stark.py
            list_display = ['__str__',]
            list_display_links = []
            model_form_class = None
            
            def list_view(self, request):
                #给前端(展示列表list_view)传一个反向解析出来的url,作为跳转使用
                url = self.get_reverse_url('add')
             ##默认定义一个model_form_class,如果自定义配置类在C:\starkpro\app01\stark.py 中配置了,就使用用户自定义的
            def get_model_form(self):
                if self.model_form_class:
                    return self.model_form_class
                from django.forms import ModelForm
                class ModelFormClass(ModelForm):
                    class Meta:
                        model = self.model
                        fields = '__all__'
                return ModelFormClass
            
            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 = self.model_form_class(request.POST)
                    if model_form_obj.is_valid():
                        model_form_obj.save()
                        return redirect(self.get_reverse_url('list'))
                return render(request, 'stark/add_view.html', locals())

            def edit_view(self, request, id):
                edit_obj = self.model.objects.filter(pk=id).first()
                model_form_class = self.get_model_form()
                model_form_obj =model_form_class(instance=edit_obj)
                if request.method  == 'POST':
                    model_form_obj = model_form_class(request.POST,instance=edit_obj)
                    if model_form_obj.is_valid():
                        model_form_obj.save()
                        return redirect(self.get_reverse_url('list'))
                return render(request,'stark/edit_view.html',locals())

            def delete_view(self, request, id):
                self.model.objects.filter(pk=id).delete()
                return redirect(self.get_reverse_url('list'))
            
#2、在后端代码更加精简
    母版:base.html
        <!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>
            <style>
                input[name],select {
                    display: block;
                    width: 100%;
                    height: 34px;
                    padding: 6px 12px;
                    font-size: 14px;
                    line-height: 1.42857143;
                    color: #555;
                    background-color: #fff;
                    background-image: none;
                    border: 1px solid #ccc;
                    border-radius: 4px;
                    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
                    -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
                    -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
                    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
                }
            </style>
        </head>
        <body>
        <div class="container">
            <div class="row">
                {% block content %}

                {% endblock %}
            </div>
        </div>
        </body>
        </html>
    子板:增加页面 add_view.html
        {% extends 'stark/base.html' %}
        {% 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 %}
                            <p>{{ form_obj.label }}{{ form_obj }}
                                <span>{{ form_obj.error.0 }}</span>
                            </p>

                        {% endfor %}
                        <input type="submit" class="btn btn-success pull-right">
                    </form>
                </div>
        {% endblock %}
    子板:编辑页面 edit_view.html
        {% extends 'stark/base.html' %}
        {% 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 %}
                            <p>{{ form_obj.label }}{{ form_obj }}
                                <span>{{ form_obj.error.0 }}</span>
                            </p>

                        {% endfor %}
                        <input type="submit" class="btn btn-success pull-right">
                    </form>
                </div>
        {% endblock %}
View Code

  ##bulk_create批量插入数据

 # for i in range(1000):
 #     models.Publish.objects.create(name='%s出版社'%i)

 # obj_list = []
 # for i in range(10000):
 #     obj_list.append(models.Publish(name='出版社%s'%i))
 # models.Publish.objects.bulk_create(obj_list)

  ##自动保存搜索条件

#1、核心代码:
    
    import copy
    params = copy.deepcopy(request.GET) #request字典是不能修改的,get请求后端获取到的数据格式如:use=owen&pwd=111  想要修改的话直通通过深拷贝方式
    params['xxx'] = 123 #然后可以进行修改
    print(params)
    print(params.urlencode())  # 将字典变成urlencoded数据格式,就能拿到数据格式为:use=owen&pwd=111
    return render(request,'publish.html',locals())


#2、分页器使用:
        queryset = models.Publish.objects.all()

        page_obj = Pagination(request.GET.get('page',1),queryset.count(),request)#给分页器传入request
        page_queryset = queryset[page_obj.start:page_obj.end]

  ##封装展示类

#1、展示类
class ShowList:#注意self的区别
    def __init__(self,config_obj,queryset):
        self.config_obj = config_obj #对应每一个配置类对象
        self.queryset = queryset

    def get_header(self):
        # 表头展示
        header_list = []
        for field_or_func in self.config_obj.get_new_list():
            if isinstance(field_or_func, str):
                if field_or_func == '__str__':  # 当用户没有指定list_display 默认展示当前表的大写名字
                    val = self.config_obj.model._meta.model_name.upper()
                else:
                    val = self.config_obj.model._meta.get_field(field_or_func).verbose_name
            else:
                val = field_or_func(self, is_header=True)
            header_list.append(val)
        return header_list
    def get_body(self):
        # 表单展示
        body_list = []  # 格式定义 [[obj1.title,obj1.price],[obj2.title,obj2.price],[]]

        for obj in self.queryset:
            tmp = []
            for field_or_func in self.config_obj.get_new_list():  # 注意这里的list_display查找顺序,先查自己的,在查全局的,然后循环要展示的字段
                if isinstance(field_or_func, str):
                    val = getattr(obj, field_or_func)  # 通过反射获取obj对象中field字段所对应的值
                    if field_or_func in self.config_obj.list_display_links:
                        _url = self.config_obj.get_reverse_url('edit', obj)
                        val = mark_safe('<a href="%s">%s</a>' % (_url, val))
                else:
                    val = field_or_func(self.config_obj, obj=obj)
                tmp.append(val)

            body_list.append(tmp)
        return body_list
#2、默认配置类
class ModelStark(object):
        def list_view(self, request):
        #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
        # print(self.model)

        queryset = self.model.objects.all()
        show_obj = ShowList(self,queryset)#传self :为展示类对象


        url = self.get_reverse_url('add')
        return render(request,'stark/list_view.html',locals())
#3、前端                 </tbody>

    {% 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>
                <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>
            </div>
    {% endblock %}
View Code

  ##使用分页器

class Pagination(object):
def __init__(self, current_page, all_count,request, per_page_num=10, pager_count=11):#添加request参数
    """
    封装分页相关数据
    :param current_page: 当前页
    :param all_count:    数据库中的数据总条数
    :param per_page_num: 每页显示的数据条数
    :param pager_count:  最多显示的页码个数

    用法:
    queryset = model.objects.all()
    page_obj = Pagination(current_page,all_count)
    page_data = queryset[page_obj.start:page_obj.end]
    获取数据用page_data而不再使用原始的queryset
    获取前端分页样式用page_obj.page_html
    """
    try:
        current_page = int(current_page)
    except Exception as e:
        current_page = 1

    if current_page < 1:
        current_page = 1

    self.current_page = current_page

    self.all_count = all_count
    self.per_page_num = per_page_num

    # 总页码
    all_pager, tmp = divmod(all_count, per_page_num)
    if tmp:
        all_pager += 1
    self.all_pager = all_pager

    self.pager_count = pager_count
    self.pager_count_half = int((pager_count - 1) / 2)


    import copy
    self.params = copy.deepcopy(request.GET) #对传入的request参数进行 深拷贝

@property
def start(self):
    return (self.current_page - 1) * self.per_page_num

@property
def end(self):
    return self.current_page * self.per_page_num

def page_html(self):
    # 如果总页码 < 11个:
    if self.all_pager <= self.pager_count:
        pager_start = 1
        pager_end = self.all_pager + 1
    # 总页码  > 11
    else:
        # 当前页如果<=页面上最多显示11/2个页码
        if self.current_page <= self.pager_count_half:
            pager_start = 1
            pager_end = self.pager_count + 1

        # 当前页大于5
        else:
            # 页码翻到最后
            if (self.current_page + self.pager_count_half) > self.all_pager:
                pager_end = self.all_pager + 1
                pager_start = self.all_pager - self.pager_count + 1
            else:
                pager_start = self.current_page - self.pager_count_half
                pager_end = self.current_page + self.pager_count_half + 1

    page_html_list = []
    # 添加前面的nav和ul标签
    page_html_list.append('''
                <nav aria-label='Page navigation>'
                <ul class='pagination'>
            ''')
    first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
    page_html_list.append(first_page)

    if self.current_page <= 1:
        prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
    else:
        prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

    page_html_list.append(prev_page)

    for i in range(pager_start, pager_end):
        self.params['page'] = i  #实现动态变化页码
        if i == self.current_page:
            temp = '<li class="active"><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,)
        else:
            temp = '<li><a href="?%s">%s</a></li>' % (self.params.urlencode(), i,)
        page_html_list.append(temp)

    if self.current_page >= self.all_pager:
        next_page = '<li class="disabled"><a href="#">下一页</a></li>'
    else:
        next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
    page_html_list.append(next_page)

    last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
    page_html_list.append(last_page)
    # 尾部添加标签
    page_html_list.append('''
                                       </nav>
                                       </ul>
                                   ''')
    return ''.join(page_html_list)
my_page分页器代码
#1、展示类
class ShowList:
    def __init__(self,config_obj,queryset,request):
        self.config_obj = config_obj
        self.queryset = queryset
        self.request = request
        current_page = self.request.GET.get('page',1)
        self.page_obj = Pagination(current_page=current_page,all_count=self.queryset.count(),request=self.request)
        self.page_queryset = self.queryset[self.page_obj.start:self.page_obj.end]
    def get_body(self):
        # 表单展示
        body_list = []  # 格式定义 [[obj1.title,obj1.price],[obj2.title,obj2.price],[]]

        for obj in self.page_queryset:#使用分页器
            tmp = []
            for field_or_func in self.config_obj.get_new_list():  # 注意这里的list_display查找顺序,先查自己的,在查全局的,然后循环要展示的字段
                if isinstance(field_or_func, str):
                    val = getattr(obj, field_or_func)  # 通过反射获取obj对象中field字段所对应的值
                    if field_or_func in self.config_obj.list_display_links:
                        _url = self.config_obj.get_reverse_url('edit', obj)
                        val = mark_safe('<a href="%s">%s</a>' % (_url, val))
                else:
                    val = field_or_func(self.config_obj, obj=obj)
                tmp.append(val)

            body_list.append(tmp)
        return body_list        

#2、默认配置类
class ModelStark(object):
        def list_view(self, request):
        #查看self.model  <class 'app01.models.Book'> 那张表查看就代表谁
        # print(self.model)

        queryset = self.model.objects.all()
        show_obj = ShowList(self,queryset,request)#创建展示类对象,给展示类传递一个request


        url = self.get_reverse_url('add')
        return render(request,'stark/list_view.html',locals())

#3、前端
    {{ show_obj.page_obj.page_html|safe }}
分页器使用代码

猜你喜欢

转载自www.cnblogs.com/liangzhenghong/p/11303574.html
76