基于admin自定义stark组件

在stark里面代码

from django.conf.urls import url
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.safestring import mark_safe  # 渲染成html页面


class ModelStark():  # 默认配置类对象

    def __init__(self, model):
        self.model = model
        self.model_name = self.model._meta.model_name
        self.app_label = self.model._meta.app_label
        self.app_model_name = (self.app_label, self.model_name)

    list_display = ["__str__"]
    list_display_links = []  # 默认的进入编辑,
    model_form_class = []  # 默认的错误提示英文
 
    #  方式1
    # 反向解析出增删改查的url

    # # 删除url
    # def get_delete_url(self,obj):
    #     url_name = "%s_%s_delete" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    # # 编辑url
    # def get_change_url(self, obj):
    #     url_name = "%s_%s_change" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    #
    # # 查看url
    # def get_list_url(self):
    #     url_name = "%s_%s_list" % self.app_model_name
    #     _url = reverse(url_name)
    #
    #     return _url
    #
    # # 添加url
    # def get_add_url(self, obj):
    #     url_name = "%s_%s_add" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    #

    #  方式2反向解析
    def get_reverse_url(self, type, obj=None):  # obj默认为空,因为我们只拼接了,app和表名  type:代表点击的增删查改

        url_name = "%s_%s_%s" % (self.app_label, self.model_name, type)  # 拼接出地址
        if obj:
            _url = reverse(url_name, args=(obj.pk,))  # 把地址传进来,还有有的url是动态的我们可以用一个元祖,把唯一id传进来
        else:
            _url = reverse(url_name)  # 如果没有动态的,直接拼接地址

        return _url

    #  选择,删除,编辑按钮
    def delete_col(self, obj=None, is_header=False):

        if is_header:
            return "删除"

        return mark_safe("<a href='%s'>删除</a>" % self.get_reverse_url("delete", obj))

    def edit_col(self, obj=None, is_header=False):
        if is_header:
            print(is_header)
            return "编辑"
        return mark_safe("<a href='%s'>编辑</a>" % (self.get_reverse_url("change", obj)))

    def check_col(self, obj=None, is_header=False):
        if is_header:
            return "选择"

        return mark_safe("<input type='checkbox'>")

    def get_new_list_display(self):  # 把上面的放在一个字典里面
        new_list_display = []

        new_list_display.extend(self.list_display)
        if not self.list_display_links:  # 如果没有自定义的就用默认编辑, # extend把两个列表里面放一起
            new_list_display.append(ModelStark.edit_col)
        new_list_display.append(ModelStark.delete_col)
        new_list_display.insert(0, ModelStark.check_col)

        return new_list_display

    def list_view(self, request):
        """
        data_list = [
            ["书",122],

        ]
        :param request:
        :return:
        """

        # 用户访问的模型表:  self.model
        print("self.model:", self.model)
        queryset = self.model.objects.all()
        print("self.list_display", self.list_display)  # ["nid","title","price","publish"]
        # 处理表头

        # header_list=["名称","价格","出版社"]
        header_list = []

        for field_or_func in self.get_new_list_display():  # ["title","price","publish",delete_col]

            if isinstance(field_or_func, str):

                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
            #  
表头怎么定义中文就是中文,不定义就是英文?Verbose_name=“中文”
        新的语法:book._meta.get_field("title")    title可以点里面的字段对象
        现在可以定义了:

            else:
                val = field_or_func(self, is_header=True)

            header_list.append(val)

        #  处理表单数据
        data_list = []
        for obj in queryset:  # [obj1,obj2,obj3]
            temp = []

            for field_or_func in self.get_new_list_display():  # list_display = ["title","price","publish",delete_col]

                if isinstance(field_or_func, str):
                    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_reverse_url("change", obj), val))
                else:
                    val = field_or_func(self, obj)

                temp.append(val)

            data_list.append(temp)

        print(data_list)

        #   获取添加url
        add_url = self.get_reverse_url("add")

        return render(request, "stark/list_view.html",
                      {"data_list": data_list, "header_list": header_list, "add_url": add_url})

    def get_model_form_class(self):  # 把自定义的提示中文和modelForm封装成函数
        if self.model_form_class:  # 如果有自定义的提示中文
            return self.model_form_class
        else:
            from django import forms

            class ModelFormDemo(forms.ModelForm):  # 帮我们把model 字段都转换form里面的字段
                class Meta:
                    model = self.model
                    fields = "__all__"

            return ModelFormDemo

    def add_view(self, request):
        """
        if GET请求:
           GET请求:
           form = BookModelForm()
           form:渲染

        if POST请求:
               form = BookModelForm(request.POST)
               form.is_valid()
               form.save()  # 添加数据 create

        :param request:
        :return:
        """
        ModelFormDemo = self.get_model_form_class()  # 验证get_model_form_class拿到
        if request.method == "GET":
            form = ModelFormDemo()
            return render(request, "stark/add_view.html", locals())  # locals 就是相当于一个元祖传值
        else:
            form = ModelFormDemo(request.POST)
            if form.is_valid():  # 做校验
                form.save()  # 这个的save相当于create
                return redirect(self.get_reverse_url("list"))
            else:
                return render(request, "stark/add_view.html", locals())

    def change_view(self, request, id):
        """
         edit_book = Book.objects.get(pk=id)
         GET:
             form = BookModelForm(instance=edit_book)
             form:渲染

         POST:
             form = BookModelForm(request.POST, instance=edit_book)
             form.is_valid
             form.save()  # 更新数据 update
        :param request:
        :param id:
        :return:
        """

        ModelFormDemo = self.get_model_form_class()
        edit_obj = self.model.objects.get(pk=id)
        if request.method == "GET":

            form = ModelFormDemo(instance=edit_obj)
            return render(request, "stark/change_view.html", locals())
        else:
            form = ModelFormDemo(data=request.POST, instance=edit_obj)  # instance 方法就是决定了是更新还是添加,有就是更新
            if form.is_valid():  # 做校验
                form.save()  # 这里相当于create
                return redirect(self.get_reverse_url("list")) # 返回list
            else:
                return render(request, "stark/change_view.html", locals())

    def delete_view(self, request, id):

        if request.method == "POST":
            self.model.objects.get(pk=id).delete()
            return redirect(self.get_reverse_url("list"))

        list_url = self.get_reverse_url("list")
        return render(request, "stark/delete_view.html", locals())

    def get_urls(self):

        temp = [
            url("^$", self.list_view, name="%s_%s_list" % (self.app_model_name)),  # 取别名 取别名app+表名是唯一的
            url("^add/$", self.add_view, name="%s_%s_add" % (self.app_model_name)),
            url("^(d+)/change/$", self.change_view, name="%s_%s_change" % (self.app_model_name)),
            url("^(d+)/delete/$", self.delete_view, name="%s_%s_delete" % (self.app_model_name)),  后面不只一个参数是动态数据

        ]

        return temp

    @property
    def urls(self):

        return self.get_urls(), None, None


class StarkSite(object):

    def __init__(self, name='admin'):
        self._registry = {}

    def register(self, model, admin_class=None, **options):
        if not admin_class: #如果自己没有配置
            admin_class = ModelStark  # 配置类

        self._registry[model] = admin_class(model)     # 拿到键值对

    # {Book:BookConfig(Book),Publish:ModelAdmin(Publish)} 

    def get_urls(self):

        temp = [

        ]

        for model_class, config_obj in self._registry.items():
            print("===>", model_class, config_obj)

            model_name = model_class._meta.model_name                                          # 拿到表名
            app_label = model_class._meta.app_label                                                       #拿到所在的app
            print("===>", app_label, model_name)

            temp.append(url(r'^%s/%s/' % (app_label, model_name), config_obj.urls))# 配置对象里面调用配置类对象的二级路由

        '''
        创建url:

            url("app01/book/$",self.list_view,name="app01_book_list"),
            url("app01/book/add$",self.add_view,name="app01_book_add"),
            url("app01/book/(d+)/change/$",self.change_view),
            url("app01/book/(d+)/delete/$",self.delete_view),



            url("app01/publish/$",self.list_view,name="app01_publish_list"),
            url("app01/publish/add$",self.add_view,name="app01_publish_add"),
            url("app01/publish/(d+)/change/$",self.change_view),
            url("app01/publish/(d+)/delete/$",self.delete_view),



        '''

        return temp

    @property
    def urls(self):

        return self.get_urls(), None, None


site = StarkSite()   #  这里应用的是一个单例模式,对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象


整理2
from django.conf.urls import url
from django.db.models import Q
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.safestring import mark_safe  # 渲染成html页面

from stark.utils.page import Pagination

'''
封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param base_url: 分页中显示的URL前缀
        :param pager_count:  最多显示的页码个数
'''


class Showlist(object):
    def __init__(self, conf_obj, queryset, request):  # 把配置类对象拿过来,request:从哪里过来的请求,queryset:就是下面showlist传进来的值
        self.conf_obj = conf_obj
        self.queryset = queryset
        self.request = request

        # 分页
        current_page = self.request.GET.get("page")
        pagination = Pagination(current_page, self.queryset.count(), self.request.GET, per_page_num=2)
        self.pagination = pagination

        self.page_queryset = self.queryset[self.pagination.start:self.pagination.end]  # 根据用户访问页码

    def get_header(self):
        #  处理表头
        # header_list=["名称","价格","出版社"]
        header_list = []

        for field_or_func in self.conf_obj.get_new_list_display():  # ["title","price","publish",delete_col]

            if isinstance(field_or_func, str):

                if field_or_func == "__str__":
                    val = self.conf_obj.model._meta.model_name.upper()
                else:

                    field_obj = self.conf_obj.model._meta.get_field(field_or_func)
                    val = field_obj.verbose_name  # 表头的字段如果用户设置了就显示中文

            else:
                val = field_or_func(self.conf_obj, is_header=True)

            header_list.append(val)
        return header_list

    def get_body(self):
        #  处理表单数据
        data_list = []
        for obj in self.page_queryset:  # [obj1,obj2,obj3]
            temp = []

            for field_or_func in self.conf_obj.get_new_list_display():  # list_display = ["title","price","publish",delete_col]

                if isinstance(field_or_func, str):
                    val = getattr(obj, field_or_func)
                    if field_or_func in self.conf_obj.list_display_links:
                        val = mark_safe("<a href='%s'>%s</a>" % (self.conf_obj.get_reverse_url("change", obj), val))
                else:
                    val = field_or_func(self.conf_obj, obj)

                temp.append(val)

            data_list.append(temp)

        print(data_list)
        return data_list

    # action 批量处理
    def get_actions(self):
        temp = []
        for func in self.conf_obj.actions:  # [patch_delete,]
            temp.append({
                "name": func.__name__,  # 拿到是函数名
                "desc": func.desc  # 拿到中文翻译
            })

        return temp  # [{"name":"patch_delete","desc":"批量删除"},]

    # filter操作
    def get_filter_links(self):

        print("self.conf_obj.list_filter", self.conf_obj.list_filter)  # ['publish', 'authors']

        links_dict = {}

        for filter_field in self.conf_obj.list_filter:  # ['publish', 'authors']
            filter_field_obj = self.conf_obj.model._meta.get_field(filter_field)
            print(filter_field_obj)
            print(type(filter_field_obj))

            print("rel", filter_field_obj.rel.to)
            queryset = filter_field_obj.rel.to.objects.all()
            print("queryset", queryset)
            temp = []

            import copy

            params = copy.deepcopy(self.request.GET)

            # 渲染标签

            current_filter_field_id = self.request.GET.get(filter_field)

            #  all 的链接标签
            params2 = copy.deepcopy(self.request.GET)
            if filter_field in params2:
                params2.pop(filter_field)
                all_link = "<a href='?%s'>All</a>" % params2.urlencode()
            else:
                all_link = "<a href=''>All</a>"
            temp.append(all_link)

            for obj in queryset:
                params[filter_field] = obj.pk# 判断当前的zd
                _url = params.urlencode()

                if current_filter_field_id == str(obj.pk):
                    s = "<a class='item active2' href='?%s'>%s</a>" % (_url, str(obj))
                else:
                    s = "<a class='item' href='?%s'>%s</a>" % (_url, str(obj))
                temp.append(s)

            links_dict[filter_field] = temp

        return links_dict


class ModelStark():  # 默认配置类对象

    def __init__(self, model):
        self.model = model
        self.model_name = self.model._meta.model_name
        self.app_label = self.model._meta.app_label
        self.app_model_name = (self.app_label, self.model_name)
        self.key_word = ""  # search 操作设置为空

    list_display = ["__str__"]
    list_display_links = []  # 默认的进入编辑,
    model_form_class = []  # 默认的错误提示英文

    search_fields = []  # 模糊搜索框

    actions = []  # 批量初始化

    list_filter = []  # filter   对多对多,多对一 做查询

    #  方式1
    # 反向解析出增删改查的url

    # # 删除url
    # def get_delete_url(self,obj):
    #     url_name = "%s_%s_delete" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    # # 编辑url
    # def get_change_url(self, obj):
    #     url_name = "%s_%s_change" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    #
    # # 查看url
    # def get_list_url(self):
    #     url_name = "%s_%s_list" % self.app_model_name
    #     _url = reverse(url_name)
    #
    #     return _url
    #
    # # 添加url
    # def get_add_url(self, obj):
    #     url_name = "%s_%s_add" % self.app_model_name
    #     _url = reverse(url_name, args=(obj.pk,))
    #
    #     return _url
    #
    #

    #  方式2反向解析
    def get_reverse_url(self, type, obj=None):  # obj默认为空

        url_name = "%s_%s_%s" % (self.app_label, self.model_name, type)  # 拼接出地址
        if obj:
            _url = reverse(url_name, args=(obj.pk,))  # 把地址传进来,还有有的url是动态的我们可以用一个元祖,把唯一id传进来
        else:
            _url = reverse(url_name)  # 如果没有动态的,直接拼接地址

        return _url

    #  选择,删除,编辑按钮
    def delete_col(self, obj=None, is_header=False):

        if is_header:
            return "删除"

        return mark_safe("<a href='%s'>删除</a>" % self.get_reverse_url("delete", obj))

    def edit_col(self, obj=None, is_header=False):
        if is_header:
            print(is_header)
            return "编辑"
        return mark_safe("<a href='%s'>编辑</a>" % (self.get_reverse_url("change", obj)))

    def check_col(self, obj=None, is_header=False):
        if is_header:
            return "选择"

        return mark_safe("<input type='checkbox' name='selected_action' value='%s'>" % obj.pk)

    def get_new_list_display(self):  # 把上面的放在一个字典里面
        new_list_display = []

        new_list_display.extend(self.list_display)
        if not self.list_display_links:  # 如果没有自定义的就用默认编辑
            new_list_display.append(ModelStark.edit_col)
        new_list_display.append(ModelStark.delete_col)
        new_list_display.insert(0, ModelStark.check_col)

        return new_list_display

    #  search 搜索框
    def search_filter(self, request, queryset):
        # search 操作
        key_word = request.GET.get("q")  # 拿到搜索框值
        print(self.search_fields)  # ["title","price"]
        self.key_word = ""  # 判断搜索框里面有没有值
        if key_word:
            self.key_word = key_word  # 如果有把值赋给默认的
            # 调用q的另外的一个方法拿到值,不然我们普通循环拿到是字符串
            search_condition = Q()  # 定义一个q所有查询
            search_condition.connector = "or"  # 拿到的值是一个或的关系
            for field in self.search_fields:
                search_condition.children.append(
                    (field + "__icontains", key_word))  # field+"__icontains"里面包含有key_word有没
            queryset = queryset.filter(search_condition)

        return queryset

    # FILTER  操作
    def filter_list(self, request, queryset):
        # filter  操作
        filter_condition = Q()
        for key, val in request.GET.items():  # publish=2&authors=1

            if key in ["page", "q"]:
                continue
            filter_condition.children.append((key, val))
        if filter_condition:  # 如果输入不合法
            try:
                queryset = queryset.filter(filter_condition)
            except Exception:
                pass

        return queryset

    def list_view(self, request):
        """
        data_list = [
            ["书",122],

        ]
        :param request:
        :return:
        """

        # action 批量处理操作
        #  action操作
        if request.method == "POST":
            actions = request.POST.get("action")  # 拿到选择的方法名
            if not actions:
                pk_list = request.POST.getlist("selected_action")  # 通过getlist 拿到所有的id列表
                queryset = self.model.objects.filter(pk__in=pk_list)  # 筛选选择的那些id

                func1 = getattr(self, actions)  # 通过方法名拿到对应的方法

                func1(request, queryset)  # 把值传给app01 下的stark 看选择的是哪个

        # 用户访问的模型表:  self.model
        print("self.model:", self.model)
        queryset = self.model.objects.all()
        print("self.list_display", self.list_display)  # ["nid","title","price","publish"]
        # 处理表头

        # search 操作
        queryset = self.search_filter(request, queryset)  # 分页之后的结果 赋值给queryset,然后下面拿到的就是新的

        # filter操作
        queryset = self.filter_list(request, queryset)

        showlist = Showlist(self, queryset, request)  # Showlist封装成一个类,前端可以通过showlist点方法

        #   获取添加url
        add_url = self.get_reverse_url("add")

        return render(request, "stark/list_view.html", locals())

    def get_model_form_class(self):  # 把自定义的提示中文和modelForm封装成函数
        if self.model_form_class:  # 如果有自定义的提示中文
            return self.model_form_class
        else:
            from django import forms

            class ModelFormDemo(forms.ModelForm):  # 帮我们把model 字段都转换form里面的字段
                class Meta:
                    model = self.model
                    fields = "__all__"

            return ModelFormDemo

    def add_view(self, request):
        """
        if GET请求:
           GET请求:
           form = BookModelForm()
           form:渲染

        if POST请求:
               form = BookModelForm(request.POST)
               form.is_valid()
               form.save()  # 添加数据 create

        :param request:
        :return:
        """
        ModelFormDemo = self.get_model_form_class()  # 验证get_model_form_class拿到

        from django.forms.models import ModelChoiceField
        if request.method == "GET":
            form = ModelFormDemo()

            # pop开始
            for bfield in form:

                # print(type(bfield.field))拿到对象的是什么类型的字段

                if isinstance(bfield.field, ModelChoiceField):  # 用isinstance  bfield.field是不是ModelChoiceField类型
                    bfield.is_pop = True  # 属性
                    filed_rel_model = self.model._meta.get_field(bfield.name).rel.to  # 拿到字段对象拿到关联表
                    model_name = filed_rel_model._meta.model_name
                    app_label = filed_rel_model._meta.app_label

                    _url = reverse("%s_%s_add" % (app_label, model_name))  # 反向拿到表和model名字
                    bfield.url = _url + "?pop_back_id=" + bfield.auto_id  # 拼接地址,auto_id 拼接_id 上面的路径
                # pop结束

            return render(request, "stark/add_view.html", locals())  # locals 就是相当于一个元祖传值
        else:
            form = ModelFormDemo(request.POST)
            if form.is_valid():  # 做校验
                obj = form.save()  # 这个的save相当于create,pop赋值给obj拿到
                # pop
                # 判断是不是pop请求弹出框
                pop_back_id = request.GET.get("pop_back_id")
                if pop_back_id:
                    pk = obj.pk
                    text = str(obj)
                    return render(request, "stark/pop.html", locals())
                # pop 结束
                return redirect(self.get_reverse_url("list"))
            else:
                return render(request, "stark/add_view.html", locals())

    def change_view(self, request, id):
        """
         edit_book = Book.objects.get(pk=id)
         GET:
             form = BookModelForm(instance=edit_book)
             form:渲染

         POST:
             form = BookModelForm(request.POST, instance=edit_book)
             form.is_valid
             form.save()  # 更新数据 update
        :param request:
        :param id:
        :return:
        """

        ModelFormDemo = self.get_model_form_class()
        edit_obj = self.model.objects.get(pk=id)
        if request.method == "GET":

            form = ModelFormDemo(instance=edit_obj)
            return render(request, "stark/change_view.html", locals())
        else:
            form = ModelFormDemo(data=request.POST, instance=edit_obj)  # instance 方法就是决定了是更新还是添加,有就是更新
            if form.is_valid():  # 做校验
                form.save()  # 这里相当于create
                return redirect(self.get_reverse_url("list"))  # 返回list
            else:
                return render(request, "stark/change_view.html", locals())

    def delete_view(self, request, id):

        if request.method == "POST":
            self.model.objects.get(pk=id).delete()
            return redirect(self.get_reverse_url("list"))

        list_url = self.get_reverse_url("list")
        return render(request, "stark/delete_view.html", locals())

    def get_urls(self):

        temp = [
            url("^$", self.list_view, name="%s_%s_list" % (self.app_model_name)),  # 取别名
            url("^add/$", self.add_view, name="%s_%s_add" % (self.app_model_name)),
            url("^(d+)/change/$", self.change_view, name="%s_%s_change" % (self.app_model_name)),
            url("^(d+)/delete/$", self.delete_view, name="%s_%s_delete" % (self.app_model_name)),

        ]

        return temp

    @property
    def urls(self):

        return self.get_urls(), None, None


class StarkSite(object):

    def __init__(self, name='admin'):
        self._registry = {}

    def register(self, model, admin_class=None, **options):
        if not admin_class:
            admin_class = ModelStark  # 配置类

        self._registry[model] = admin_class(model)

    # {Book:BookConfig(Book),Publish:ModelAdmin(Publish)}

    def get_urls(self):

        temp = [

        ]

        for model_class, config_obj in self._registry.items():
            print("===>", model_class, config_obj)

            model_name = model_class._meta.model_name
            app_label = model_class._meta.app_label
            print("===>", app_label, model_name)

            temp.append(url(r'^%s/%s/' % (app_label, model_name), config_obj.urls))

        '''
        创建url:

            url("app01/book/$",self.list_view,name="app01_book_list"),
            url("app01/book/add$",self.add_view,name="app01_book_add"),
            url("app01/book/(d+)/change/$",self.change_view),
            url("app01/book/(d+)/delete/$",self.delete_view),



            url("app01/publish/$",self.list_view,name="app01_publish_list"),
            url("app01/publish/add$",self.add_view,name="app01_publish_add"),
            url("app01/publish/(d+)/change/$",self.change_view),
            url("app01/publish/(d+)/delete/$",self.delete_view),



        '''

        return temp

    @property
    def urls(self):

        return self.get_urls(), None, None


site = StarkSite()
View Code

html

add_view

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">


    <link rel="stylesheet" href="/static/css/commonn.css">
</head>
<body>



{% include "stark/class_form.html" %}

<script>
    function show_option(pop_back_id,pk,text) {
        console.log(pop_back_id,pk,text);

        var option=document.createElement("option");
        option.innerHTML=text;
        option.value=pk;
        option.selected="selected";

        select=document.getElementById(pop_back_id);
        select.appendChild(option);


    }
</script>


</body>
</html>
View Code

change_view

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/css/commonn.css">
</head>
<body>

{% include "stark/class_form.html" %}

</body>
</html>
View Code

class_form_view

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">

            <form action="" method="post" novalidate>
                {% csrf_token %}

                {% for field in form %}
                    <div class="form-group field_region">
                        <label for="">{{ field.label }}</label>
                        {{ field }} <span class="erorr pull-right">{{ field.errors.0 }}</span>

{#                         pop开始#}
                        {% if field.is_pop %}
                        <span class="plus"><a onclick="add_option('{{ field.url }}')">+</a></span>
                        {% endif %}
                    </div>
                {% endfor %}


                <input type="submit" class="btn btn-default pull-right">

            </form>
        </div>
    </div>
</div>

<script>
{#    把上面传值进来拿到展示#}
    function add_option(url) {

        window.open(url,"","height=500,width=800,top=100,left=100")

    }
</script>
View Code

delete_view

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1.min.js"></script>
    <link rel="stylesheet" href="/static/css/commonn.css">


</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-3 col-md-offset-3">
            <form action="" method="post">
                {% csrf_token %}
                <div class="panel panel-warning">
                    <div class="panel-heading">
                        <h3 class="panel-title">确定删除吗</h3>
                    </div>
                    <div class="panel-body">
                        <input type="submit" class="btn btn-warning" value="确认删除">
                        <a href="{{ list_url }}"class="btn btn-warning">取消</a>
                    </div>
                </div>

            </form>

        </div>
    </div>
</div>


</body>
</html>
View Code

list_view

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1.min.js"></script>
    <script src="/static/mystyle.css"></script>
    <link rel="stylesheet" href="/static/css/commonn.css">
    <style>
        .a {
            margin-top: -7px;
        }

        .action {
             40%;
            margin-top: 10px;
        }

        .action1 {

            margin-top: 10px;
        }
        .item{
            color: gray;
        }

        .active2{
            color: red;
        }
    </style>


</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-2">
            <div class="panel panel-warning">
                <div class="panel-heading">
                    <h3 class="panel-title">
                        <a href="{{ add_url }}" class=" glyphicon glyphicon-plus"></a>

                        {#                         search 搜索#}
                        {% if showlist.conf_obj.search_fields %}
                            <form class="form-inline pull-right a ">
                                <div class="input-group">
                                    <div class="input-group">
                                        <input type="text" class="form-control" name="q"
                                               value="{{ showlist.conf_obj.key_word }}"
                                               placeholder="关键字">
                                    </div>
                                </div>
                                <button type="submit" class="btn btn-warning">Search</button>
                            </form>
                        {% endif %}
                        {#                        结束#}

                    </h3>
                </div>

                <form action="" class="form-inline" method="post">
                    {% csrf_token %}
                    <div class="panel-body">
                        <select class="form-control action action  " name="action">
                            <option>-----------------------</option>
                            {% for func_dict in showlist.get_actions %}
                                <option value="{{ func_dict.name }}">{{ func_dict.desc }}</option>
                            {% endfor %}
                        </select>
                        <input type="submit" class="btn btn-warning " style="vertical-align: -8px">
                        <table class="table table-bordered  table-striped action1 ">
                            <thead>
                            <tr>
                                {% for item in showlist.get_header %}
                                    <td>{{ item }}</td>
                                {% endfor %}

                            </tr>
                            </thead>
                            <tbody>
                            {% for data  in showlist.get_body %}
                                <tr>
                                    {% for foo in data %}
                                        <td>{{ foo }}</td>
                                    {% endfor %}
                                </tr>
                            {% endfor %}

                            </tbody>

                        </table>
                    </div>
                </form>

            </div>
            <div>
                <nav aria-label="...">
                    <ul class="pagination">
                        {{ showlist.pagination.page_html|safe }}
                    </ul>

                </nav>
            </div>



        </div>
        <div class="col-md-3">
            <div class="filter_region">
                <div class="alert-warning text-center">FILTER</div>
                {% for key,val in showlist.get_filter_links.items %}
                    <div class="panel panel-warning">
                        <div class="panel-heading">By{{ key|upper }}</div>
                        <div class="panel-body">
                            {% for link in val %}
                             <p>{{ link|safe }}</p>
                             {% endfor %}
                        </div>
                    </div>
                {% endfor %}
            </div>
        </div>
    </div>
</div>


</body>
</html>
View Code

pop

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>

<h1>POP</h1>

<script>

    window.opener.show_option("{{ pop_back_id }}",'{{ pk }}','{{ text }}');

    window.close();


</script>

</body>
</html>
View Code

分页

fromdjango.conf.urlsimporturl
fromdjango.shortcutsimportredirect,render
fromdjango.urlsimportreverse
fromdjango.utils.safestringimportmark_safe#渲染成html页面
fromstark.utils.pageimportPagination

fromdjango.db.modelsimportQ


'''
封装分页相关数据
:paramcurrent_page:当前页
:paramall_count:数据库中的数据总条数
:paramper_page_num:每页显示的数据条数
:parambase_url:分页中显示的URL前缀
:parampager_count:最多显示的页码个数
'''

classShowlist(object):
def__init__(self,conf_obj,queryset,request):#把配置类对象拿过来,request:从哪里过来的请求,queryset:就是下面showlist传进来的值
self.conf_obj=conf_obj
self.queryset=queryset
self.request=request

#分页
current_page=self.request.GET.get("page")
pagination=Pagination(current_page,self.queryset.count(),self.request.GET,per_page_num=2)
self.pagination=pagination

self.page_queryset=self.queryset[self.pagination.start:self.pagination.end]

defget_header(self):
#处理表头
#header_list=["名称","价格","出版社"]
header_list=[]

forfield_or_funcinself.conf_obj.get_new_list_display():#["title","price","publish",delete_col]

ifisinstance(field_or_func,str):

iffield_or_func=="__str__":
val=self.conf_obj.model._meta.model_name.upper()
else:

field_obj=self.conf_obj.model._meta.get_field(field_or_func)
val=field_obj.verbose_name#表头的字段如果用户设置了就显示中文

else:
val=field_or_func(self.conf_obj,is_header=True)

header_list.append(val)
returnheader_list

defget_body(self):
#处理表单数据
data_list=[]
forobjinself.page_queryset:#[obj1,obj2,obj3]
temp=[]

forfield_or_funcinself.conf_obj.get_new_list_display():#list_display=["title","price","publish",delete_col]

ifisinstance(field_or_func,str):
val=getattr(obj,field_or_func)
iffield_or_funcinself.conf_obj.list_display_links:
val=mark_safe("<ahref='%s'>%s</a>"%(self.conf_obj.get_reverse_url("change",obj),val))
else:
val=field_or_func(self.conf_obj,obj)

temp.append(val)

data_list.append(temp)

print(data_list)
returndata_list

#action批量处理
defget_actions(self):
temp=[]
forfuncinself.conf_obj.actions:#[patch_delete,]
temp.append({
"name":func.__name__,#拿到是函数名
"desc":func.desc#拿到中文翻译
})

returntemp#[{"name":"patch_delete","desc":"批量删除"},]



classModelStark():#默认配置类对象

def__init__(self,model):
self.model=model
self.model_name=self.model._meta.model_name
self.app_label=self.model._meta.app_label
self.app_model_name=(self.app_label,self.model_name)
self.key_word=""#search操作设置为空

list_display=["__str__"]
list_display_links=[]#默认的进入编辑,
model_form_class=[]#默认的错误提示英文

search_fields=[]#模糊搜索框

actions=[]#批量初始化

#方式1
#反向解析出增删改查的url

##删除url
#defget_delete_url(self,obj):
#url_name="%s_%s_delete"%self.app_model_name
#_url=reverse(url_name,args=(obj.pk,))
#
#return_url
#
##编辑url
#defget_change_url(self,obj):
#url_name="%s_%s_change"%self.app_model_name
#_url=reverse(url_name,args=(obj.pk,))
#
#return_url
#
#
##查看url
#defget_list_url(self):
#url_name="%s_%s_list"%self.app_model_name
#_url=reverse(url_name)
#
#return_url
#
##添加url
#defget_add_url(self,obj):
#url_name="%s_%s_add"%self.app_model_name
#_url=reverse(url_name,args=(obj.pk,))
#
#return_url
#
#

#方式2反向解析
defget_reverse_url(self,type,obj=None):#obj默认为空

url_name="%s_%s_%s"%(self.app_label,self.model_name,type)#拼接出地址
ifobj:
_url=reverse(url_name,args=(obj.pk,))#把地址传进来,还有有的url是动态的我们可以用一个元祖,把唯一id传进来
else:
_url=reverse(url_name)#如果没有动态的,直接拼接地址

return_url

#选择,删除,编辑按钮
defdelete_col(self,obj=None,is_header=False):

ifis_header:
return"删除"

returnmark_safe("<ahref='%s'>删除</a>"%self.get_reverse_url("delete",obj))

defedit_col(self,obj=None,is_header=False):
ifis_header:
print(is_header)
return"编辑"
returnmark_safe("<ahref='%s'>编辑</a>"%(self.get_reverse_url("change",obj)))

defcheck_col(self,obj=None,is_header=False):
ifis_header:
return"选择"

returnmark_safe("<inputtype='checkbox'name='selected_action'value='%s'>"%obj.pk)

defget_new_list_display(self):#把上面的放在一个字典里面
new_list_display=[]

new_list_display.extend(self.list_display)
ifnotself.list_display_links:#如果没有自定义的就用默认编辑
new_list_display.append(ModelStark.edit_col)
new_list_display.append(ModelStark.delete_col)
new_list_display.insert(0,ModelStark.check_col)

returnnew_list_display


#search搜索框
defsearch_filter(self,request,queryset):
#search操作
key_word=request.GET.get("q")#拿到搜索框值
print(self.search_fields)#["title","price"]
self.key_word=""#判断搜索框里面有没有值
ifkey_word:
self.key_word=key_word#如果有把值赋给默认的
#调用q的另外的一个方法拿到值,不然我们普通循环拿到是字符串
search_condition=Q()#定义一个q
search_condition.connector="or"#拿到的值是一个或的关系
forfieldinself.search_fields:
search_condition.children.append((field+"__icontains",key_word))#field+"__icontains"里面包含有key_word有没
queryset=queryset.filter(search_condition)

returnqueryset


deflist_view(self,request):
"""
data_list=[
["书",122],

]
:paramrequest:
:return:
"""

#action批量处理操作
#action操作
ifrequest.method=="POST":
actions=request.POST.get("action")#拿到选择的方法名
pk_list=request.POST.getlist("selected_action")#通过getlist拿到所有的id列表
queryset=self.model.objects.filter(pk__in=pk_list)#筛选选择的那些id

func1=getattr(self,actions)#通过方法名拿到对应的方法

func1(request,queryset)#把值传给app01下的stark看选择的是哪个

#用户访问的模型表:self.model
print("self.model:",self.model)
queryset=self.model.objects.all()
print("self.list_display",self.list_display)#["nid","title","price","publish"]
#处理表头

#search操作
queryset=self.search_filter(request,queryset)#赋值给queryset,然后下面拿到的就是新的

showlist=Showlist(self,queryset,request)#Showlist封装成一个类,前端可以通过showlist点方法

#获取添加url
add_url=self.get_reverse_url("add")

returnrender(request,"stark/list_view.html",locals())

defget_model_form_class(self):#把自定义的提示中文和modelForm封装成函数
ifself.model_form_class:#如果有自定义的提示中文
returnself.model_form_class
else:
fromdjangoimportforms

classModelFormDemo(forms.ModelForm):#帮我们把model字段都转换form里面的字段
classMeta:
model=self.model
fields="__all__"

returnModelFormDemo

defadd_view(self,request):
"""
ifGET请求:
GET请求:
form=BookModelForm()
form:渲染

ifPOST请求:
form=BookModelForm(request.POST)
form.is_valid()
form.save()#添加数据create

:paramrequest:
:return:
"""
ModelFormDemo=self.get_model_form_class()#验证get_model_form_class拿到
ifrequest.method=="GET":
form=ModelFormDemo()
returnrender(request,"stark/add_view.html",locals())#locals就是相当于一个元祖传值
else:
form=ModelFormDemo(request.POST)
ifform.is_valid():#做校验
form.save()#这个的save相当于create
returnredirect(self.get_reverse_url("list"))
else:
returnrender(request,"stark/add_view.html",locals())

defchange_view(self,request,id):
"""
edit_book=Book.objects.get(pk=id)
GET:
form=BookModelForm(instance=edit_book)
form:渲染

POST:
form=BookModelForm(request.POST,instance=edit_book)
form.is_valid
form.save()#更新数据update
:paramrequest:
:paramid:
:return:
"""

ModelFormDemo=self.get_model_form_class()
edit_obj=self.model.objects.get(pk=id)
ifrequest.method=="GET":

form=ModelFormDemo(instance=edit_obj)
returnrender(request,"stark/change_view.html",locals())
else:
form=ModelFormDemo(data=request.POST,instance=edit_obj)#instance方法就是决定了是更新还是添加,有就是更新
ifform.is_valid():#做校验
form.save()#这里相当于create
returnredirect(self.get_reverse_url("list"))#返回list
else:
returnrender(request,"stark/change_view.html",locals())

defdelete_view(self,request,id):

ifrequest.method=="POST":
self.model.objects.get(pk=id).delete()
returnredirect(self.get_reverse_url("list"))

list_url=self.get_reverse_url("list")
returnrender(request,"stark/delete_view.html",locals())

defget_urls(self):

temp=[
url("^$",self.list_view,name="%s_%s_list"%(self.app_model_name)),#取别名
url("^add/$",self.add_view,name="%s_%s_add"%(self.app_model_name)),
url("^(d+)/change/$",self.change_view,name="%s_%s_change"%(self.app_model_name)),
url("^(d+)/delete/$",self.delete_view,name="%s_%s_delete"%(self.app_model_name)),

]

returntemp

@property
defurls(self):

returnself.get_urls(),None,None


classStarkSite(object):

def__init__(self,name='admin'):
self._registry={}

defregister(self,model,admin_class=None,**options):
ifnotadmin_class:
admin_class=ModelStark#配置类

self._registry[model]=admin_class(model)

#{Book:BookConfig(Book),Publish:ModelAdmin(Publish)}

defget_urls(self):

temp=[

]

formodel_class,config_objinself._registry.items():
print("===>",model_class,config_obj)

model_name=model_class._meta.model_name
app_label=model_class._meta.app_label
print("===>",app_label,model_name)

temp.append(url(r'^%s/%s/'%(app_label,model_name),config_obj.urls))

'''
创建url:

url("app01/book/$",self.list_view,name="app01_book_list"),
url("app01/book/add$",self.add_view,name="app01_book_add"),
url("app01/book/(d+)/change/$",self.change_view),
url("app01/book/(d+)/delete/$",self.delete_view),



url("app01/publish/$",self.list_view,name="app01_publish_list"),
url("app01/publish/add$",self.add_view,name="app01_publish_add"),
url("app01/publish/(d+)/change/$",self.change_view),
url("app01/publish/(d+)/delete/$",self.delete_view),



'''

returntemp

@property
defurls(self):

returnself.get_urls(),None,None


site=StarkSite()
View Code

原文地址:https://www.cnblogs.com/maojiang/p/9395838.html