Django-CRM項目學習(四)-stark的分頁器與搜索框

1.分頁器

分頁器相關知識點,請查看如下連接html

http://www.javashuo.com/article/p-bqfndgzo-cx.html前端

2.代碼歸類

歸類前代碼數據庫

header_list = []  # 定製一個空別表
        for field_or_func in self.get_new_list_display():
            # 若是是多對多的
            if callable(field_or_func):
                val = field_or_func(self, header=True)
                header_list.append(val)
                # header_list.append(field_or_func.__name__)
            # 若是是普通屬性
            else:

                if field_or_func == "__str__":
                    val = self.model._meta.model_name.upper()
                else:
                    field_obj = self.model._meta.get_field(field_or_func)
                    val = field_obj.verbose_name  # 自定義屬性名

                header_list.append(val)

        # 構建展現數據
        new_data = []
        for obj in queryset:
            temp = []
            for field_or_func in self.get_new_list_display():
                if callable(field_or_func):
                    val = field_or_func(self, obj)  # 獲取函數返回值,傳入obj進行從操做數據

                elif not field_or_func == "__str__":
                    from django.db.models.fields.related import ManyToManyField
                    field_obj = self.model._meta.get_field(field_or_func)  # 獲取模型對象
                    # 判斷是否爲多對多屬性
                    if type(field_obj) == ManyToManyField:
                        raise Exception("list_display不能是多對多字段!")
                    # 判斷是否有選擇屬性
                    if field_obj.choices:
                        val = getattr(obj, "get_%s_display" % field_or_func)()
                        # 調用這個方法,反射方法,調用方法獲取對應的內容
                    else:
                        val = getattr(obj, field_or_func)
                        if field_or_func in self.list_display_links:
                            val = mark_safe("<a href='%s'>%s</a>" % (self.get_change_url(obj), val))

                else:
                    val = getattr(obj, field_or_func)()

                temp.append(val)
                # print(">>>>>>>>>>>>",temp)
            new_data.append(temp)
歸類前代碼

2.1 本來內容整理

2.1.1 建立展現類

在原內容地方經過實例對象調用內容django

2.1.2 函數展現

2.1.3 調用說明

  • requset ,當前操做請求  對應requset
  • self ,當前操做自定義配置類, 對應config_obj
  • quseryset   當前操做數據對應 queryse

2.2 分頁包調用以及配置

2.2.1知識點

ruquset.GET.get("篩選內容",默認值=None) 即若是不寫默認值則爲空,這裏寫爲1 即,沒獲取到時候爲1app

2.2.2 設置接口

2.2.3 獲取數據

獲取分好頁的數據(經過切片[開始:結束])ide

2.2.4 擡頭部分

2.2.5 展現數據

2.2.6 前端的修改

前端效果:函數

歸類後完整代碼url

from django.urls import path, re_path

from app01.models import *
from django.shortcuts import HttpResponse, render, redirect

from django.utils.safestring import mark_safe
from django.urls import reverse


class ShowList(object):  #
    def __init__(self, request, config_obj, queryset):
        self.request = request # 接收請求
        self.config_obj = config_obj #接收自定義配置類
        self.queryset = queryset  #接收數據
        self.pager_queryset = self.get_pager_queryset() # 實例分頁對象獲取內容

    def get_pager_queryset(self):
        from stark.utils.page import Pagination  # 導入本身寫的分頁包
        current_page = self.request.GET.get("page", 1)  # 當前操做頁
        self.pagination = Pagination(self.request, current_page, self.queryset,
                                     per_page_num=self.config_obj.per_page_num or 5)
        queryset = self.queryset[self.pagination.start:self.pagination.end]
        return queryset

    def get_header(self):
        header_list = []  # 定製一個空別表
        for field_or_func in self.config_obj.get_new_list_display():  # 替換成config_obj 代用,self 表明原自定義配置類
            # 若是是多對多的
            if callable(field_or_func):
                val = field_or_func(self, header=True)
                header_list.append(val)
                # header_list.append(field_or_func.__name__)
            # 若是是普通屬性
            else:

                if field_or_func == "__str__":
                    val = self.config_obj.model._meta.model_name.upper()
                else:
                    field_obj = self.config_obj.model._meta.get_field(field_or_func)
                    val = field_obj.verbose_name  # 自定義屬性名

                header_list.append(val)
        return header_list   #f返回前端的內容
    def get_body(self):

        # 構建展現數據
        new_data = []
        for obj in self.pager_queryset:
            temp = []
            for field_or_func in self.config_obj.get_new_list_display():
                if callable(field_or_func):
                    val = field_or_func(self.config_obj, obj)  # 獲取函數返回值,傳入obj進行從操做數據
                    # self  統一換成self.config_obj
                elif not field_or_func == "__str__":
                    from django.db.models.fields.related import ManyToManyField
                    field_obj = self.config_obj.model._meta.get_field(field_or_func)  # 獲取模型對象
                    # 判斷是否爲多對多屬性
                    if type(field_obj) == ManyToManyField:
                        raise Exception("list_display不能是多對多字段!")
                    # 判斷是否有選擇屬性
                    if field_obj.choices:
                        val = getattr(obj, "get_%s_display" % field_or_func)()
                        # 調用這個方法,反射方法,調用方法獲取對應的內容
                    else:
                        val = getattr(obj, field_or_func)
                        if field_or_func in self.config_obj.list_display_links:
                            val = mark_safe("<a href='%s'>%s</a>" % (self.config_obj.get_change_url(obj), val))

                else:
                    val = getattr(obj, field_or_func)()

                temp.append(val)
                # print(">>>>>>>>>>>>",temp)
            new_data.append(temp)

        return new_data #返回前端數據部分
class ModelStark(object):
    '''
    默認配置類
    '''
    list_display = ("__str__",)
    list_display_links = []  # 設置默認爲空
    model_form_class = None  # 設置默認爲無
    per_page_num=None  #設置接口
    search_fields = []  #建立search_fidels接口
    search_val = None  # 默認讓search_val的值爲none
    def __init__(self, model):
        self.model = model
        self.model_name = self.model._meta.model_name
        self.app_label = self.model._meta.app_label


        # 反向解析當前訪問表的增刪改查URL

    def get_list_url(self):
        # 反向解析當前表的刪除的URL
        list_url = reverse("%s_%s_list" % (self.app_label, self.model_name))
        return list_url

    def get_add_url(self, obj=None):
        # 反向解析當前表的刪除的URL
        add_url = reverse("%s_%s_add" % (self.app_label, self.model_name))
        return add_url

    def get_delete_url(self, obj):
        # 反向解析當前表的刪除的URL
        delete_url = reverse("%s_%s_delete" % (self.app_label, self.model_name), args=(obj.pk,))
        return delete_url

    def get_change_url(self, obj):
        # 反向解析當前表的change的URL
        change_url = reverse("%s_%s_change" % (self.app_label, self.model_name), args=(obj.pk,))
        return change_url

    def get_new_list_display(self):
        temp = []
        temp.extend(self.list_display)  # 繼承原來的列表內容
        temp.append(ModelStark.show_editbtn)  # 注意傳過來的是屬性
        temp.append(ModelStark.show_delbtn)  # 注意傳過來的是屬性
        temp.insert(0, ModelStark.show_checkbox)
        # temp.insert(1,self.show_checkbox())
        # 同上不加括號,把方法名加入到列表方便掉用
        return temp

    def show_checkbox(self, obj=None, header=False):
        # 展現選擇列
        if header:
            return mark_safe("<input type='checkbox'>")
        return mark_safe("<input type='checkbox'>")

    def show_delbtn(self, obj=None, header=False):
        if header:
            return "刪除"

        return mark_safe("<a href='%s'>刪除</a>" % self.get_delete_url(obj))

    def show_editbtn(self, obj=None, header=False):
        if header:
            return "編輯"
        return mark_safe("<a href='%s'>編輯</a>" % self.get_change_url(obj))

    def get_search_condition(self, request):
        val = request.GET.get("q")  # 獲取name q的內容

        from django.db.models import Q  # 導入Q 包 .進行或操做
        q = Q()  # 實例一個Q 對象
        if val:# 若是進行了查詢操做
            self.search_val = val
            q.connector = "or"  # 更改q爲或操做
            for field in self.search_fields:  # ["title","price"] # 從接口中拿字段
                print(field)
                # queryset=queryset.filter(Q(title__contains=val)|Q(price__contains=val))
                q.children.append((field + "__contains", val))
                #  利用小q進行模糊查詢,和拼接
                # "__contains 模糊查詢" 即 title__contains=val  查詢
        else:
            self.search_val = None

        return q

    def list_view(self, request):
        # print(self)  # 當前訪問模型表對應的配置類對象
        # print(self.model)  # 當前訪問模型表
        queryset = self.model.objects.all()
        print("+>>>>>>>", queryset)
        # 構建表頭
        queryset=queryset.filter(self.get_search_condition(request))
        show_list = ShowList(request, self, queryset)
        # 當前請求 ,當前操做的自定製配置類,當前全部數據
        table_name = self.model._meta.verbose_name
        add_url = self.get_add_url()
        # print("<<<<<<<<<<<",new_data)
        return render(request, "stark/list_view.html", locals())

        # data = self.model.objects.all()
        # print(data)
        # print("-------",self.list_display)
        # data_list=[]
        # dict1={}
        # for obj in data:
        #     lis =[]
        #     for msg in self.list_display:
        #         lis.append(getattr(obj,msg))
        #     data_list.append(lis)
        # print("jjjjjjjjj",data_list)
        # return render(request, 'stark/list_view.html', {
        #     "data_list":data_list,
        #     "list_display":self.list_display
        # })

    def get_model_form(self):  # 建立獲取model_form 內容函數
        from django.forms import ModelForm  # 導入包
        class BaseModelForm(ModelForm):  # 建立modelform類,繼承modelform
            class Meta:  # 建立可調用內容
                model = self.model  # 導入當前操做模型對象
                fields = "__all__"  # 獲取所有

        return self.model_form_class or BaseModelForm  # 若是有內容就傳入內容,沒有就走默認的Base的
        # 有的時候須要從新寫class BasemodelForm類並繼承他

    def add_view(self, request):  # 視圖函數add_view
        BaseModelForm = self.get_model_form()  # 經過get_model_form運行獲取類
        if request.method == "GET":
            form_obj = BaseModelForm()  # 實例化對象獲取內容
            return render(request, "stark/add_view.html", locals())  # 傳到前端內容(屬性)
        else:
            form_obj = BaseModelForm(request.POST)  # 向渲染的模型類中加入數據
            if form_obj.is_valid():  # 判斷接收數據是否可用
                form_obj.save()  # 將數據保存到數據庫
                return redirect(self.get_list_url())  # 跳轉
            else:
                return render(request, "stark/add_view.html", locals())

    def change_view(self, request, id):  # 建立change_view路由 ,傳入request,id,經過反向解析獲取id
        BaseModelForm = self.get_model_form()  # 經過方法獲取modelform類
        edit_obj = self.model.objects.filter(pk=id).first()  # 經過id獲取當前操做對象
        if request.method == "GET":
            form_obj = BaseModelForm(instance=edit_obj)  # 經過instance參數,進行控制爲傳入對象能夠到前端進行渲染
            return render(request, "stark/change_view.html", locals())
        else:
            form_obj = BaseModelForm(request.POST, instance=edit_obj)  # 接收前端內容,instance對象,是內容進行覆蓋
            if form_obj.is_valid():
                form_obj.save()  # 數據保存
                return redirect(self.get_list_url())
            else:
                return render(request, "stark/change_view.html", locals())

    def delete_view(self, request, id):  # 接收反向解析傳過來的id
        if request.method == "POST":
            self.model.objects.filter(pk=id).delete()  # 接收id 刪除主鍵
            return redirect(self.get_list_url())  # 跳轉
        list_url = self.get_list_url()  # 把展現界面傳過去.方便用戶取消

        return render(request, "stark/delete_view.html", locals())  # 新建刪除html

    @property
    def get_urls(self):
        temp = [
            path("", self.list_view, name="%s_%s_list" % (self.app_label, self.model_name)),
            path("add/", self.add_view, name="%s_%s_add" % (self.app_label, self.model_name)),
            re_path("(\d+)/change/", self.change_view, name="%s_%s_change" % (self.app_label, self.model_name)),
            re_path("(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (self.app_label, self.model_name)),
        ]

        return (temp, None, None)


class StarkSite:
    '''
    stark全局類
    '''

    def __init__(self):
        self._registry = {}

    def register(self, model, admin_class=None, **options):
        admin_class = admin_class or ModelStark
        self._registry[model] = admin_class(model)

    def get_urls(self):
        #  動態爲註冊的模型類建立增刪改查URL
        temp = []
        # {Book:ModelAdmin(Book),Publish:ModelAdmin(Publish)}
        for model, config_obj in self._registry.items():
            # print("---->", model, config_obj)
            model_name = model._meta.model_name
            app_label = model._meta.app_label
            temp.append(
                path("%s/%s/" % (app_label, model_name), config_obj.get_urls)
            )

        '''
           path("stark/app01/book",self.list_view)
           path("stark/app01/book/add",self.add_view)      
           path("stark/app01/publish",self.list_view)
           path("stark/app01/publish/add",self.add_view)


        '''

        return temp

    @property
    def urls(self):
        return self.get_urls(), None, None


site = StarkSite()
歸類後完整代碼

3.搜索框

知識點:django中Q查詢的使用,實例化Q之後能夠進行更改內容且經過字符串進行修改spa

3.1 接口內容

註冊接口內容3d

3.2 前端代碼內容

設置name=q進行form表單數據進行操做,經過if進行判斷若是有配置search_fidleds接口則顯示出搜索框,不然則不顯示搜索框

3.3 sites數據

__contains進行數據模糊查詢

3.4 數據經過search進行數據過濾

3.5 展現以下

經過’啊’進行搜索

a

相關文章
相關標籤/搜索