• curd 插件


    1. Django项目启动 自动加载文件 制作启动文件

    1. 注册strak 在apps.py 类里面增加如下 
    
        def ready(self):
            from django.utils.module_loading import autodiscover_modules
            autodiscover_modules("stark")
    
    2. 在已经注册的app中创建stark.py文件 加载
    View Code

    2. 在stark中模仿AdminSite ModelAdmin类写代码 注册自己的类

    class StarkConfig(object):
    
        def __init__(self,model_class,site):
            self.model_class = model_class
            self.site = site
    
    
    class StarkSite(object):
    
        def __init__(self):
            self._registey = {}
    
        def register(self,model_class,stark_config_class=None):
            if not stark_config_class:
                stark_config_class = StarkConfig
    
            self._registey[model_class] = stark_config_class(model_class,self)
    
    site = StarkSite()
    View Code

    3. 将注册的类自动生成url

    - urls.py
        from stark.service import v1
    
        urlpatterns = [
            url(r'^stark/', v1.site.urls),
        ]
    
    - 为每个类生成4个url v1.py 
        
        class StarkConfig(object):
    
            def __init__(self,model_class,site):
                self.model_class = model_class
                self.site = site
    
            def get_urls(self):
                app_model_name = (self.model_class._meta.app_label,self.model_class._meta.model_name,)
                url_patterns = [
                    url(r'^$',self.changelist_view,name="%s_%s_changlist" %app_model_name),
                    url(r'^add/$',self.add_view,name="%s_%s_add" %app_model_name),
                    url(r'^(d+)/delete/$',self.delete_view,name="%s_%s_delete" %app_model_name),
                    url(r'^(d+)/change/$',self.change_view,name="%s_%s_chang" %app_model_name),
                ]
                return url_patterns
    
            @property
            def urls(self):
                return self.get_urls()
    
            def changelist_view(self,request,*args,**kwargs):
                return HttpResponse('列表')
    
            def add_view(self,request,*args,**kwargs):
                return HttpResponse('添加')
    
            def delete_view(self,request,nid,*args,**kwargs):
                return HttpResponse('删除')
    
            def change_view(self,request,nid,*args,**kwargs):
                return HttpResponse('修改')
    
    
        class StarkSite(object):
    
            def __init__(self):
                self._registey = {}
    
            def register(self,model_class,stark_config_class=None):
                if not stark_config_class:
                    stark_config_class = StarkConfig
    
                self._registey[model_class] = stark_config_class(model_class,self)
    
            def get_urls(self):
                url_pattern = []
    
                for model_class,stark_config_obj in self._registry.items():
                   
                    app_name = model_class._meta.app_label
                    model_name = model_class._meta.model_name
    
                    curd_url = url(r'^%s/%s/' %(app_name,model_name,) , (stark_config_obj.urls,None,None))
                    url_pattern.append(curd_url)
    
                return url_pattern
    
    
            @property
            def urls(self):
                return (self.get_urls(),None,'stark')
    
    
        site = StarkSite()
    View Code

    4. 列表页面展示 

    - v1.py
        def changelist_view(self,request,*args,**kwargs):
        # 处理表头
    
        head_list = []
        for field_name in self.list_display:
            if isinstance(field_name,str):
                # 根据类和字段名称,获取字段对象的verbose_name
                verbose_name = self.model_class._meta.get_field(field_name).verbose_name
            else:
                verbose_name = field_name(self,is_header=True)
            head_list.append(verbose_name)
    
        # 处理表中的数据
        # [ UserInfoObj,UserInfoObj,UserInfoObj,UserInfoObj,]
        # [ UserInfo(id=1,name='alex',age=18),UserInfo(id=2,name='alex2',age=181),]
        data_list = self.model_class.objects.all()
        new_data_list = []
        for row in data_list:
            # row是 UserInfo(id=2,name='alex2',age=181)
            # row.id,row.name,row.age
            temp = []
            for field_name in self.list_display:
                if isinstance(field_name,str):
                    val = getattr(row,field_name) # # 2 alex2
                else:
                    val = field_name(self,row)
                temp.append(val)
            new_data_list.append(temp)
    
        return render(request,'stark/changelist.html',{'data_list':new_data_list,'head_list':head_list})
    
    - shark.py
        class UserInfoConfig(v1.StarkConfig):
    
        def checkbox(self,obj=None,is_header=False):
            if is_header:
                return '选择'
            return mark_safe('<input type="checkbox" name="pk" value="%s" />' %(obj.id,))
        def edit(self,obj=None,is_header=False):
            if is_header:
                return '编辑'
            return mark_safe('<a href="/edit/%s">编辑</a>' %(obj.id,))
    
        list_display = [checkbox,'id','name',edit]
    View Code

    5. 显示增加按钮

    - 先判断是否显示,再通过反向解析生成增加链接
    - 后端
        # 是否显示增加按钮
        show_add_btn = True
        def get_show_btn(self):
            return self.show_add_btn
    
        return render(request, 'stark/changelist.html', {'data_list': new_data_list, 'head_list': head_list,"add_url":self.get_add_url(),"show_add_btn":self.get_show_bt
    - 前端
        {% if show_add_btn %}
            <a class="btn btn-primary" href="{{ add_url }}">增加
        {% endif %}

    6. 增加页面

    增加内容页面
    
        1. 通过ModelForm创建公共类 显示和提交
    
            - 后端
    
                def add_view(self, request, *args, **kwargs):
    
                    class AddTable(ModelForm):
                        class Meta:
                            model = self.model_class
                            fields = "__all__"
    
                    if request.method == "GET":
                        form = AddTable()
                        return render(request,"stark/add_view.html",{"form":form})
                    else:
                        form = AddTable(request.POST)
                        if form.is_valid():
                            form.save()
                            return redirect(self.get_list_url())
                        else:
                            return render(request, "stark/add_view.html", {"form": form})
    
            - 前端
                <form method="post" novalidate>
                    {% csrf_token %}
                    {{ form.as_p }}
                    <input type="submit" value="提交">
                </form>
    
        2. 升级 在子类自定义ModelForm类 子类之后可以自定义类
    
            - v1.py
                model_form_class = None
                    def get_model_form_class(self):
                        if self.model_form_class:
                            return self.model_form_class
                        else:
                            #方式一:
                            # class AddTable(ModelForm):
                            #     class Meta:
                            #         model = self.model_class
                            #         fields = "__all__"
                            # return AddTable
                            #方式二:
                            meta = type("Meta",(object,),{"model":self.model_class,"fields":"__all__"})
                            AddTable = type("AddTable",(ModelForm,),{"Meta":meta})
                            return AddTable
    
    
                def add_view(self, request, *args, **kwargs):
                    model_form_class = self.get_model_form_class()
                    if request.method == "GET":
                        form = model_form_class()
                        return render(request,"stark/add_view.html",{"form":form})
                    else:
                        form = model_form_class(request.POST)
                        if form.is_valid():
                            form.save()
                            return redirect(self.get_list_url())
                        else:
                            return render(request, "stark/add_view.html", {"form": form})
            - stark.py
    
                class UserInfoModelForm(ModelForm):
                    class Meta:
                        model = models.UserInfo
                        fields = ["name","password"]
                        error_messages = {
                            "name":{
                                'required':'用户名不能为空'
                            }
                        }
                class UserInfoConfig(v1.StarkConfig):
                    model_form_class = UserInfoModelForm
    View Code

    9. 修改 删除 

    def change_view(self, request, nid, *args, **kwargs):
    
        obj = self.model_class.objects.filter(pk=nid).first()
        if not obj:
            return redirect(self.get_list_url())
        model_form_class = self.get_model_form_class()
        if request.method == "GET":
            form = model_form_class(instance=obj)
            return render(request,"stark/change_view.html",{"form":form})
        else:
            form = model_form_class(instance=obj,data=request.POST)
            if form.is_valid:
                form.save()
                return redirect(self.get_list_url())
            return render(request,"stark/change_view.html",{"form":form})
    
    def delete_view(self, request, nid, *args, **kwargs):
        self.model_class.objects.filter(pk=nid).delete()
        return redirect(self.get_list_url())
    View Code

    10. 组合搜索

    阶段一:

    阶段一:
        
        - 派生类
            # 三个条件分别为 choice  M2M FK
            comb_filter = ["gender","depart","roles"]
    
        - 基类
    
            comb_filter = []
            def get_comb_filter(self):
                return self.comb_filter
    
        - ChangeList 初始化
            self.comb_filter = config.get_comb_filter()
    
            from django.db.models import ForeignKey,ManyToManyField
                # 根据列表的字符串找到数据的字段对象,判断对象是否是FK,M2M
                # 如果不是 为chioce
                def gen_comb_filter(self):
                    data_list = []
                    for item in self.comb_filter:
                        # item    gender
                        _field = self.model_class._meta.get_field(item)
                        # _field  app04.UserInfo.gender
                        if isinstance(_field,ForeignKey):
                            #如果字段的类型是ForeignKey 找到他对应的类和数据
                            data_list.append(_field.rel.to.objects.all())
                        elif isinstance(_field,ManyToManyField):
                            data_list.append(_field.rel.to.objects.all())
                        else:
                            #choice
                            data_list.append(_field.choices)
                    return data_list
    
    
        - 前端
        
            <div>
                {% for comb in self.gen_comb_filter %}
                    <div>
                        {% for item in comb %}
                            <a href="">{{ item }}</a>
                        {% endfor %}
                    </div>
                {% endfor %}
            </div>
    View Code

    阶段二:  用户查找的数据封装到类里面  前端循环 和上面效果一样

        class FilterRow(object):
    
            def __init__(self,data):
                self.data = data
    
            def __iter__(self):
                yield "全部"
                for val in self.data:
                    yield val
    
        def gen_comb_filter(self):
            data_list = []
            for item in self.comb_filter:
                # item    gender
                _field = self.model_class._meta.get_field(item)
                # _field  app04.UserInfo.gender
                if isinstance(_field,ForeignKey):
                    #如果字段的类型是ForeignKey 找到他对应的类和数据
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                elif isinstance(_field,ManyToManyField):
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                else:
                    #choice
                    data_list.append(FilterRow(_field.choices))
            return data_list
    View Code

    阶段三: 增加搜索条件可以为多选  封装到类里面判断

            comb_filter = [
                v1.filterOption("gender"),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False):
                    self.filed_name = filed_name
                    self.muti = muti
    
            def gen_comb_filter(self):
                data_list = []
                for obj in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(obj.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        data_list.append(FilterRow(_field.rel.to.objects.all()))
                    elif isinstance(_field,ManyToManyField):
                        data_list.append(FilterRow(_field.rel.to.objects.all()))
                    else:
                        #choice
                        data_list.append(FilterRow(_field.choices))
                return data_list
    View Code

    阶段四: 搜索条件自定义  效果如上

    好处1: 如部门表有 销售部门 运维部门 开发部门  默认只让显示 销售部门和运维部门
    好处2: 可以继承filterOption类 重写filterOption类底下的两个方法 
            comb_filter = [
                v1.filterOption("gender"),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False):
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
                   return _field.choices
    
    
            class FilterRow(object):
                def __init__(self,data):
                    self.data = data
                def __iter__(self):
                    yield "全部"
                    for val in self.data:
                        yield val
    
    
            def gen_comb_filter(self):
                data_list = []
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option.get_queryset(_field))
                        data_list.append(row)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option.get_queryset(_field))
                        data_list.append(row)
                    else:
                        #choice
                        row = FilterRow(option.get_choices(_field))
                        data_list.append(row)
                return data_list
    View Code

    阶段五:  返回列表变为生成器

     comb_filter = [
                v1.filterOption("gender"),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False):
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
                   return _field.choices
    
    
            class FilterRow(object):
                def __init__(self,data):
                    self.data = data
                def __iter__(self):
                    yield "全部"
                    for val in self.data:
                        yield val
    
    
    
        def gen_comb_filter(self):
            for option in self.comb_filter:
                # item    gender
                _field = self.model_class._meta.get_field(option.filed_name)
                # _field  app04.UserInfo.gender
                if isinstance(_field,ForeignKey):
                    #如果字段的类型是ForeignKey 找到他对应的类和数据
                    row = FilterRow(option.get_queryset(_field))
                elif isinstance(_field,ManyToManyField):
                    row = FilterRow(option.get_queryset(_field))
                else:
                    #choice
                    row = FilterRow(option.get_choices(_field))
                yield row
    View Code

    阶段六: 前端循环时 如果是choice根据索引取值 如果是对象 根据对象的方法取值 所以需要做出区分 并且在后端生成url 全部的a标签还未做 

        comb_filter = [
            v1.filterOption("gender",is_choice=True),
            v1.filterOption("depart"),
            v1.filterOption("roles",True)
        ]
    
        class filterOption(object):
            def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                """
    
                :param filed_name:
                :param muti:
                :param condition: 过滤条件
                """
    
                self.filed_name = filed_name
                self.muti = muti
                self.condition = condition
                self.is_choice = is_choice
    
            def get_queryset(self,_field):
                if self.condition:
                    return _field.rel.to.objects.filter()
    
                return _field.rel.to.objects.all()
    
            def get_choices(self,_field):
    
               return _field.choices
    
    
    
        class FilterRow(object):
    
            def __init__(self,option,data,params):
                self.option = option
                self.data = data
                self.params = copy.deepcopy(params)
    
            def __iter__(self):
                yield mark_safe("<a href={0}>全部</a>".format("111"))
                for val in self.data:
                    if self.option.is_choice:
                        pk,text = val
                    else:
                        pk,text = val.pk,str(val)
                    yield mark_safe("<a href={0}>{1}</a>".format(pk,text))
    
    
        def gen_comb_filter(self):
            for option in self.comb_filter:
                # item    gender
                _field = self.model_class._meta.get_field(option.filed_name)
                # _field  app04.UserInfo.gender
                if isinstance(_field,ForeignKey):
                    #如果字段的类型是ForeignKey 找到他对应的类和数据
                    row = FilterRow(option,option.get_queryset(_field),self.request.GET)
                elif isinstance(_field,ManyToManyField):
                    row = FilterRow(option,option.get_queryset(_field),self.request.GET)
                else:
                    #choice
                    row = FilterRow(option,option.get_choices(_field),self.request.GET)
                yield row
    View Code

    阶段七: 后端生成url 全部未做

            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                    """
    
                    :param filed_name:
                    :param muti:
                    :param condition: 过滤条件
                    """
    
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
                    self.is_choice = is_choice
    
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
    
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
    
                   return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
                    params._mutable = True
    
                    yield mark_safe("<a href={0}>全部</a>".format("111"))
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = val
                        else:
                            pk,text = val.pk,str(val)
    
                        params[self.option.filed_name] = pk
                        url = "%s?%s"%(self.request.path_info,params.urlencode())
    
    
                        yield mark_safe("<a href={0}>{1}</a>".format(url,text))
    
    
            def gen_comb_filter(self):
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    else:
                        #choice
                        row = FilterRow(option,option.get_choices(_field),self.request)
                    yield row
    View Code

    阶段八: 请求的值如果和循环的值如果相同  全部和其它按钮 都判断

            comb_filter = [
                v1.filterOption("gender",is_choice=True),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
    
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                    """
    
                    :param filed_name:
                    :param muti:
                    :param condition: 过滤条件
                    """
    
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
                    self.is_choice = is_choice
    
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
    
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
    
                   return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
                    params._mutable = True
                    current_id = params.get(self.option.filed_name)
    
                    # 如果循环的值 在前端传过来的里面 删除 
                    if self.option.filed_name in params:
                        del params[self.option.filed_name]
                        url = "{0}{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}">全部</a>'.format(url))
                    else:
                        url = "{0}{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}" class="active">全部</a>'.format(url))
    
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = str(val[0]),str(val[1])
                        else:
                            pk,text = str(val.pk),str(val)
    
                        params[self.option.filed_name] = pk
                        url = "%s?%s"%(self.request.path_info,params.urlencode())
    
                        if current_id == pk:
                            yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                        else:
                            yield mark_safe("<a href={0}>{1}</a>".format(url,text))
    
            
            def gen_comb_filter(self):
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    else:
                        #choice
                        row = FilterRow(option,option.get_choices(_field),self.request)
                    yield row
    View Code

    阶段九: 单选前后台完成 

            # 组合搜索过滤
            comb_codition = {}
            option_list = self.get_comb_filter()
            flag = False
            for key in request.GET.keys():
                value_list = request.GET.getlist(key)
                for option in option_list:
                    if option.filed_name == key:
                        flag = True
                        print("111")
                        break
                if flag:
                    print("22")
                    comb_codition["%s__in"%key] = value_list
            print(comb_codition)
    
    
            queryset = self.model_class.objects.filter(self.get_search_condition()).filter(**comb_codition)
    View Code

    阶段十  多选完成

        class filterOption(object):
            def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                """
    
                :param filed_name:
                :param muti:
                :param condition: 过滤条件
                """
    
                self.filed_name = filed_name
                self.muti = muti
                self.condition = condition
                self.is_choice = is_choice
    
    
            def get_queryset(self,_field):
                if self.condition:
                    return _field.rel.to.objects.filter()
    
                return _field.rel.to.objects.all()
    
    
            def get_choices(self,_field):
    
               return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
    
                    params._mutable = True
                    current_id = params.get(self.option.filed_name)
                    current_id_list = params.getlist(self.option.filed_name)
    
                    # 全部  如果循环的值 在前端传过来的里面 删除
                    if self.option.filed_name in params:
                        origin_list = params.pop(self.option.filed_name)
                        url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}">全部</a>'.format(url))
                        params.setlist(self.option.filed_name,origin_list)
                    else:
                        url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}" class="active">全部</a>'.format(url))
    
                    # 全部 后面的值
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = str(val[0]),str(val[1])
                        else:
                            pk,text = str(val.pk),str(val)
                        if not self.option.muti:
                            # 单选
                            params[self.option.filed_name] = pk
                            url = "%s?%s"%(self.request.path_info,params.urlencode())
    
                            if current_id == pk:
                                yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                            else:
                                yield mark_safe("<a href={0}>{1}</a>".format(url,text))
                        else:
                            # 多选
                            _params = copy.deepcopy(params)
                            id_list = params.getlist(self.option.filed_name)
                            if pk in current_id_list:
    
                                id_list.remove(pk)
                                _params.setlist(self.option.filed_name, id_list)
                                url = "%s?%s" % (self.request.path_info, _params.urlencode())
                                yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                            else:
    
                                id_list.append(pk)
                                _params.setlist(self.option.filed_name,id_list)
                                url = "%s?%s" % (self.request.path_info, _params.urlencode())
                                yield mark_safe("<a href={0}>{1}</a>".format(url, text))
    
    
            queryset = self.model_class.objects.filter(self.get_search_condition()).filter(**comb_codition).distinct()
    View Code
    阶段一:
        
        - 派生类
            # 三个条件分别为 choice  M2M FK
            comb_filter = ["gender","depart","roles"]
    
        - 基类
    
            comb_filter = []
            def get_comb_filter(self):
                return self.comb_filter
    
        - ChangeList 初始化
            self.comb_filter = config.get_comb_filter()
    
            from django.db.models import ForeignKey,ManyToManyField
                # 根据列表的字符串找到数据的字段对象,判断对象是否是FK,M2M
                # 如果不是 为chioce
                def gen_comb_filter(self):
                    data_list = []
                    [
                        ((1,男),(2,女)),
                        [obj,obj,obj,obj],
                        [obj,obj,obj,obj]
                    ]
                    for item in self.comb_filter:
                        # item    gender
                        _field = self.model_class._meta.get_field(item)
                        # _field  app04.UserInfo.gender
                        if isinstance(_field,ForeignKey):
                            #如果字段的类型是ForeignKey 找到他对应的类和数据
                            data_list.append(_field.rel.to.objects.all())
                        elif isinstance(_field,ManyToManyField):
                            data_list.append(_field.rel.to.objects.all())
                        else:
                            #choice
                            data_list.append(_field.choices)
                    return data_list
    
    
        - 前端
    
            <div>
                {% for comb in self.gen_comb_filter %}
                    <div>
                        {% for item in comb %}
                            <a href="">{{ item }}</a>
                        {% endfor %}
                    </div>
                {% endfor %}
            </div>
    
    
    
    阶段二:    用户查找的数据封装到类里面  前端循环 和上面效果一样
    
    
        class FilterRow(object):
    
            def __init__(self,data):
                self.data = data
    
            def __iter__(self):
                yield "全部"
                for val in self.data:
                    yield val
    
        def gen_comb_filter(self):
            data_list = []
            for item in self.comb_filter:
                # item    gender
                _field = self.model_class._meta.get_field(item)
                # _field  app04.UserInfo.gender
                if isinstance(_field,ForeignKey):
                    #如果字段的类型是ForeignKey 找到他对应的类和数据
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                elif isinstance(_field,ManyToManyField):
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                else:
                    #choice
                    data_list.append(FilterRow(_field.choices))
            return data_list
    
    
    阶段三:    搜索条件可以为多选  封装到类里面判断
        
            
        comb_filter = [
            v1.filterOption("gender"),
            v1.filterOption("depart"),
            v1.filterOption("roles",True)
        ]
    
        class filterOption(object):
            def __init__(self,filed_name,muti=False):
                self.filed_name = filed_name
                self.muti = muti
    
        def gen_comb_filter(self):
            data_list = []
            for obj in self.comb_filter:
                # item    gender
                _field = self.model_class._meta.get_field(obj.filed_name)
                # _field  app04.UserInfo.gender
                if isinstance(_field,ForeignKey):
                    #如果字段的类型是ForeignKey 找到他对应的类和数据
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                elif isinstance(_field,ManyToManyField):
                    data_list.append(FilterRow(_field.rel.to.objects.all()))
                else:
                    #choice
                    data_list.append(FilterRow(_field.choices))
            return data_list
    
    
    阶段四: 搜索条件自定义 
            好处1: 如部门表有 销售部门 运维部门 开发部门  默认只让显示 销售部门和运维部门
            好处2: 可以继承filterOption类 重写filterOption类底下的两个方法
    
            comb_filter = [
                v1.filterOption("gender"),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False):
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
                   return _field.choices
    
    
            class FilterRow(object):
                def __init__(self,data):
                    self.data = data
                def __iter__(self):
                    yield "全部"
                    for val in self.data:
                        yield val
    
    
            def gen_comb_filter(self):
                data_list = []
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option.get_queryset(_field))
                        data_list.append(row)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option.get_queryset(_field))
                        data_list.append(row)
                    else:
                        #choice
                        row = FilterRow(option.get_choices(_field))
                        data_list.append(row)
                return data_list
    
    
    阶段六: 前端循环时 如果是choice根据索引取值 如果是对象 根据对象的方法取值 所以需要做出区分 并且在后端生成url 全部的a标签还未做
    
    
            comb_filter = [
                v1.filterOption("gender",is_choice=True),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                    """
    
                    :param filed_name:
                    :param muti:
                    :param condition: 过滤条件
                    """
    
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
                    self.is_choice = is_choice
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
    
                    return _field.rel.to.objects.all()
    
                def get_choices(self,_field):
    
                   return _field.choices
    
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,params):
                    self.option = option
                    self.data = data
                    self.params = copy.deepcopy(params)
    
                def __iter__(self):
                    yield mark_safe("<a href={0}>全部</a>".format("111"))
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = val
                        else:
                            pk,text = val.pk,str(val)
                        yield mark_safe("<a href={0}>{1}</a>".format(pk,text))
    
    
            def gen_comb_filter(self):
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option,option.get_queryset(_field),self.request.GET)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option,option.get_queryset(_field),self.request.GET)
                    else:
                        #choice
                        row = FilterRow(option,option.get_choices(_field),self.request.GET)
                    yield row
    
    
    
    阶段七: 后端生成url 全部未做 
        
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                    """
    
                    :param filed_name:
                    :param muti:
                    :param condition: 过滤条件
                    """
    
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
                    self.is_choice = is_choice
    
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
    
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
    
                   return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
                    params._mutable = True
    
                    yield mark_safe("<a href={0}>全部</a>".format("111"))
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = val
                        else:
                            pk,text = val.pk,str(val)
    
                        params[self.option.filed_name] = pk
                        url = "%s?%s"%(self.request.path_info,params.urlencode())
    
    
                        yield mark_safe("<a href={0}>{1}</a>".format(url,text))
    
    
            def gen_comb_filter(self):
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    else:
                        #choice
                        row = FilterRow(option,option.get_choices(_field),self.request)
                    yield row
    
    
    阶段八 请求的值如果和循环的值如果相同  全部和其它按钮 都判断 
    
    
    
            comb_filter = [
                v1.filterOption("gender",is_choice=True),
                v1.filterOption("depart"),
                v1.filterOption("roles",True)
            ]
    
    
    
            class filterOption(object):
                def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                    """
    
                    :param filed_name:
                    :param muti:
                    :param condition: 过滤条件
                    """
    
                    self.filed_name = filed_name
                    self.muti = muti
                    self.condition = condition
                    self.is_choice = is_choice
    
    
                def get_queryset(self,_field):
                    if self.condition:
                        return _field.rel.to.objects.filter()
    
                    return _field.rel.to.objects.all()
    
    
                def get_choices(self,_field):
    
                   return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
                    params._mutable = True
                    current_id = params.get(self.option.filed_name)
    
                    # 如果循环的值 在前端传过来的里面 删除 
                    if self.option.filed_name in params:
                        del params[self.option.filed_name]
                        url = "{0}{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}">全部</a>'.format(url))
                    else:
                        url = "{0}{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}" class="active">全部</a>'.format(url))
    
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = str(val[0]),str(val[1])
                        else:
                            pk,text = str(val.pk),str(val)
    
                        params[self.option.filed_name] = pk
                        url = "%s?%s"%(self.request.path_info,params.urlencode())
    
                        if current_id == pk:
                            yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                        else:
                            yield mark_safe("<a href={0}>{1}</a>".format(url,text))
    
            
            def gen_comb_filter(self):
                for option in self.comb_filter:
                    # item    gender
                    _field = self.model_class._meta.get_field(option.filed_name)
                    # _field  app04.UserInfo.gender
                    if isinstance(_field,ForeignKey):
                        #如果字段的类型是ForeignKey 找到他对应的类和数据
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    elif isinstance(_field,ManyToManyField):
                        row = FilterRow(option,option.get_queryset(_field),self.request)
                    else:
                        #choice
                        row = FilterRow(option,option.get_choices(_field),self.request)
                    yield row
    
    
    阶段九  单选完成
    
    
            # 组合搜索过滤
            comb_codition = {}
            option_list = self.get_comb_filter()
            flag = False
            for key in request.GET.keys():
                value_list = request.GET.getlist(key)
                for option in option_list:
                    if option.filed_name == key:
                        flag = True
                        print("111")
                        break
                if flag:
                    print("22")
                    comb_codition["%s__in"%key] = value_list
            print(comb_codition)
    
    
            queryset = self.model_class.objects.filter(self.get_search_condition()).filter(**comb_codition)
    
    
    阶段十  多选完成
        
        class filterOption(object):
            def __init__(self,filed_name,muti=False,condition=False,is_choice=False):
                """
    
                :param filed_name:
                :param muti:
                :param condition: 过滤条件
                """
    
                self.filed_name = filed_name
                self.muti = muti
                self.condition = condition
                self.is_choice = is_choice
    
    
            def get_queryset(self,_field):
                if self.condition:
                    return _field.rel.to.objects.filter()
    
                return _field.rel.to.objects.all()
    
    
            def get_choices(self,_field):
    
               return _field.choices
    
    
            class FilterRow(object):
    
                def __init__(self,option,data,request):
                    self.option = option
                    self.data = data
                    self.request = request
    
                def __iter__(self):
                    params = copy.deepcopy(self.request.GET)
    
                    params._mutable = True
                    current_id = params.get(self.option.filed_name)
                    current_id_list = params.getlist(self.option.filed_name)
    
                    # 全部  如果循环的值 在前端传过来的里面 删除
                    if self.option.filed_name in params:
                        origin_list = params.pop(self.option.filed_name)
                        url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}">全部</a>'.format(url))
                        params.setlist(self.option.filed_name,origin_list)
                    else:
                        url = "{0}?{1}".format(self.request.path_info, params.urlencode())
                        yield mark_safe('<a href="{0}" class="active">全部</a>'.format(url))
    
                    # 全部 后面的值
                    for val in self.data:
                        if self.option.is_choice:
                            pk,text = str(val[0]),str(val[1])
                        else:
                            pk,text = str(val.pk),str(val)
                        if not self.option.muti:
                            # 单选
                            params[self.option.filed_name] = pk
                            url = "%s?%s"%(self.request.path_info,params.urlencode())
    
                            if current_id == pk:
                                yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                            else:
                                yield mark_safe("<a href={0}>{1}</a>".format(url,text))
                        else:
                            # 多选
                            _params = copy.deepcopy(params)
                            id_list = params.getlist(self.option.filed_name)
                            if pk in current_id_list:
    
                                id_list.remove(pk)
                                _params.setlist(self.option.filed_name, id_list)
                                url = "%s?%s" % (self.request.path_info, _params.urlencode())
                                yield mark_safe("<a href={0} class='active'>{1}</a>".format(url, text))
                            else:
    
                                id_list.append(pk)
                                _params.setlist(self.option.filed_name,id_list)
                                url = "%s?%s" % (self.request.path_info, _params.urlencode())
                                yield mark_safe("<a href={0}>{1}</a>".format(url, text))
    
    
            queryset = self.model_class.objects.filter(self.get_search_condition()).filter(**comb_codition).distinct()
    组合筛选

    11. popup

    阶段一: 对于多选或单选 在后面增加popup按钮 其余不加

        - 在后端生成返回给前端
        - 如果是field是ModelChoiceField 则是Fk, 如果是ModelMultipChoice 则是M2M
        - GET请求 循环form,打印各个字段的类型 发现类型都为 <class 'django.forms.boundfield.BoundField'> 它是对字段的一次封装
    
            def add_view(self, request, *args, **kwargs):
    
                model_form_class = self.get_model_form_class()
                if request.method == "GET":
                    form = model_form_class()
                    """
                    for field in form:
                        print(type(field))
    
                       <class 'django.forms.boundfield.BoundField'>
                    """
                    return render(request, "stark/add_view.html", {"form": form})
                else:
                    form = model_form_class(request.POST)
                    if form.is_valid():
                        form.save()
                        return redirect(self.get_list_url())
                    else:
                        return render(request, "stark/add_view.html", {"form": form})
        
        - 在 BoundField类里面再找一个field属性 九可以找到每个类的属性  最后三个类都为ModelChoiceField的子类
    
            """   
            for bfield in form:
                print(type(bfield.field))
    
            <class 'django.forms.fields.CharField'>
            <class 'django.forms.fields.CharField'>
            <class 'django.forms.fields.TypedChoiceField'>
            <class 'django.forms.models.ModelChoiceField'>
            <class 'django.forms.models.ModelMultipleChoiceField'>
            """
    说明
        - 后台代码
            def add_view(self, request, *args, **kwargs):
    
                model_form_class = self.get_model_form_class()
                if request.method == "GET":
                    form = model_form_class()
                    from django.forms import ModelChoiceField
                    new_choice = []
                    for bfield in form:
                        tmp = {"is_popup":False,"item":bfield}
                        if isinstance(bfield.field,ModelChoiceField):
                            tmp["is_popup"] = True
                        new_choice.append(tmp)
    
                    return render(request, "stark/add_view.html", {"form": new_choice})
                else:
                    form = model_form_class(request.POST)
                    if form.is_valid():
                        form.save()
                        return redirect(self.get_list_url())
                    else:
                        return render(request, "stark/add_view.html", {"form": form})
        - 前端
            {% for dic in form %}
              <div class="form-group">
                <label for="inputEmail3" class="col-sm-2 control-label">{{ dic.label }}</label>
                <div class="col-sm-10" style="position: relative">
                  {{ dic.item }}
                  {% if dic.is_popup %}
                      <div style="position: absolute;right: -8px;top: 10px;">
                        <a class="glyphicon glyphicon-search" aria-hidden="true"></a>
                      </div>
                  {% endif %}
                  {{ dic.item.errors.0 }}
                </div>
              </div>
            {% endfor %}
    代码

    阶段二: 实现popup 

    <form method="post"  class="form-horizontal" novalidate>
        {% csrf_token %}
        {% for dic in form %}
            <div class="col-sm-6">
                <div class="form-group" style="margin-bottom: 20px;">
                    <label for="inputEmail3" class="col-sm-2 control-label">{{ dic.item.field.label }}</label>
                    <div class="col-sm-10" style="position: relative">
                        <!-- 判断,如果field是ModelChoiceField,则FK; 如果是ModelMultipleChoiceField,则M2M -->
                        {{ dic.item }}
                        {% if dic.is_popup %}
                            <div style="position: absolute;right: -8px;top: 10px;">
                                <a onclick="popUp('{{ dic.popup_url }}')" class="glyphicon glyphicon-search"></a>
                            </div>
                        {% endif %}
                        <div style="position: absolute;font-size: 12px;left: 15px; right: 15px;color: #e4393c;background: #FFEBEB;">{{ dic.item.errors.0 }}</div>
                    </div>
                </div>
            </div>
        {% endfor %}
        <div class="col-sm-offset-11 col-sm-1">
            <input type="submit" class="btn btn-primary" value="提交">
        </div>
    </form>
    <script>
        function popupCallback(dic) {
            var op = document.createElement('option');
            op.value = dic.id;
            op.text = dic.text;
            op.setAttribute('selected','selected');
            document.getElementById(dic.popbackid).appendChild(op);
    
        }
        function popUp(url) {
            var popupPage = window.open(url, url, "status=1, height:500, 600, toolbar=0, resizeable=0");
        }
    </script>
    add_view.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>正在关闭</title>
    </head>
    <body>
        <script>
            (function () {
                var dic = {{ json_result|safe }};
                opener.popupCallback(dic);
                window.close();
            })()
    
        </script>
    </body>
    </html>
    popup_response.html
     def add_view(self, request, *args, **kwargs):
    
            model_form_class = self.get_model_form_class()
            _popbackid = request.GET.get('_popbackid')
    
            if request.method == "GET":
                form = model_form_class()
                from django.forms import ModelChoiceField
                new_choice = []
                for bfield in form:
                    temp = {"is_popup":False,"item":bfield}
                    if isinstance(bfield.field,ModelChoiceField):
                        #获取类名
                        related_class_name = bfield.field.queryset.model
                        app_model_name = related_class_name._meta.app_label,related_class_name._meta.model_name
                        print(app_model_name)
                        base_url = reverse("stark:%s_%s_add"%app_model_name)
                        popurl = "%s?_popbackid=%s"%(base_url,bfield.auto_id)
                        temp["popup_url"] = popurl
                        temp["is_popup"] = True
                    new_choice.append(temp)
    
                return render(request, "stark/add_view.html", {"form": new_choice})
            else:
                form = model_form_class(request.POST)
                if form.is_valid():
                    form_obj = form.save()
                    if _popbackid:
                        # 是popup请求
                        # render一个页面,写自执行函数
                        result = {'id':form_obj.pk, 'text':str(form_obj),'popbackid':_popbackid }
                        return render(request,'stark/popup_response.html',{'json_result':json.dumps(result,ensure_ascii=False)})
                    else:
                        return redirect(self.get_list_url())
                else:
                    return render(request, "stark/add_view.html", {"form": form})
    v1.py

    阶段三:  编辑和增加生成的页面都用到popup 代码需要重写一次,so引入 templatetags

    from django.template import Library
    from django.forms import ModelChoiceField
    from django.shortcuts import reverse
    
    register = Library()
    
    
    
    @register.inclusion_tag('stark/form.html')
    def form(model_form_obj):
    
        new_choice = []
        for bfield in model_form_obj:
            temp = {"is_popup": False, "item": bfield}
            if isinstance(bfield.field, ModelChoiceField):
                # 获取类名
                related_class_name = bfield.field.queryset.model
                app_model_name = related_class_name._meta.app_label, related_class_name._meta.model_name
                print(app_model_name)
                base_url = reverse("stark:%s_%s_add" % app_model_name)
                popurl = "%s?_popbackid=%s" % (base_url, bfield.auto_id)
                temp["popup_url"] = popurl
                temp["is_popup"] = True
            new_choice.append(temp)
        
        return {"form": new_choice}
    templatetags/change.form.py
    {% load staticfiles %}
    {% load change_form %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static "stark/bootstrap/css/bootstrap.css" %}" />
        <link rel="stylesheet" href="{% static "stark/css/stark-form.css" %}" />
    </head>
    <body>
    
        <div class="container" style=" 800px;height: 500px">
            <h1 class="text-center">增加页面</h1>
            {% form form %}
        </div>
    </body>
    </html>
    add_view.html
    {% load staticfiles %}
    {% load change_form %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static "stark/bootstrap/css/bootstrap.css" %}" />
        <link rel="stylesheet" href="{% static "stark/css/stark-form.css" %}" />
    </head>
    <body>
    {#    <h1>修改页面</h1>#}
    {#        <form method="post" novalidate>#}
    {#            {% csrf_token %}#}
    {#            {{ form.as_p }}#}
    {#            <input type="submit" value="提交">#}
    {#        </form>#}
    
        <div class="container" style=" 800px;height: 500px">
            <h1 class="text-center">编辑页面</h1>
            {% form form %}
        </div>
    
    
    
        </body>
    </html>
    change_view.html
        def add_view(self, request, *args, **kwargs):
    
            model_form_class = self.get_model_form_class()
            _popbackid = request.GET.get('_popbackid')
    
            if request.method == "GET":
                form = model_form_class()
    
                return render(request, "stark/add_view.html", {"form": form})
            else:
                form = model_form_class(request.POST)
                if form.is_valid():
                    form_obj = form.save()
                    if _popbackid:
                        # 是popup请求
                        # render一个页面,写自执行函数
                        result = {'id':form_obj.pk, 'text':str(form_obj),'popbackid':_popbackid }
                        return render(request,'stark/popup_response.html',{'json_result':json.dumps(result,ensure_ascii=False)})
                    else:
                        return redirect(self.get_list_url())
                else:
                    return render(request, "stark/add_view.html", {"form": form})
    def add_view()

    12. 其它列可编辑

    子类
    #8. 其它列可编辑
        # def get_list_display(self):
        #     data = []
        #     if self.list_display:
        #         data.extend(self.list_display)
        #         data.append(v1.StarkConfig.delete)
        #         data.insert(0, v1.StarkConfig.checkbox)
        #     return data
        edit_link = ["title"]
    
    
    class StarkConfig(object):
        edit_link = ["title"]
    
        edit_link = []
        def get_edit_link(self):
            result = []
            if self.edit_link:
                result.extend(self.edit_link)
            return result
    
    class ChangeList(object):
        self.edit_link = config.get_edit_link()
    
        def body_list(self):
            # 处理表中的数据
            # [ UserInfoObj,UserInfoObj,UserInfoObj,UserInfoObj,]
            # [ UserInfo(id=1,name='alex',age=18),UserInfo(id=2,name='alex2',age=181),]
            data_list = self.data_list
            new_data_list = []
            for row in data_list:
                # row是 UserInfo(id=2,name='alex2',age=181)
                # row.id,row.name,row.age
                temp = []
                for field_name in self.list_display:
                    if isinstance(field_name,str):
                        val = getattr(row,field_name) # # 2 alex2
                        # 判断是否在编辑列表中
                        if field_name in self.edit_link:
                            val = self.edit_link_url(row.pk,val)
                    else:
                        val = field_name(self.config,row)
                    temp.append(val)
                new_data_list.append(temp)
    
            return new_data_list    
    
    
        # 其它列的作为编辑功能的url
        def edit_link_url(self,pk,text):
            query_str = self.request.GET.urlencode()  # page=2&nid=1
            params = QueryDict(mutable=True)
            params[self.config._query_param_key] = query_str
    
            return mark_safe('<a href="%s?%s">%s</a>' % (self.config.get_change_url(pk), params.urlencode(),text))
    View Code

     

     

      

     

     

    整个流程 

    1. Django项目启动 自动加载文件 制作启动文件
        
        1. 注册strak 在apps.py 类里面增加如下 
    
            def ready(self):
                from django.utils.module_loading import autodiscover_modules
                autodiscover_modules("stark")
    
        2. 在已经注册的app中创建stark.py文件 加载
    
    
    2. 在stark中模仿AdminSite ModelAdmin类写代码 注册自己的类
    
        class StarkConfig(object):
    
            def __init__(self,model_class,site):
                self.model_class = model_class
                self.site = site
    
    
        class StarkSite(object):
    
            def __init__(self):
                self._registey = {}
    
            def register(self,model_class,stark_config_class=None):
                if not stark_config_class:
                    stark_config_class = StarkConfig
    
                self._registey[model_class] = stark_config_class(model_class,self)
    
        site = StarkSite()
    
    
    3. 将注册的类自动生成url
    
        - urls.py
            from stark.service import v1
    
            urlpatterns = [
                url(r'^stark/', v1.site.urls),
            ]
    
        - 为每个类生成4个url v1.py 
            
            class StarkConfig(object):
    
                def __init__(self,model_class,site):
                    self.model_class = model_class
                    self.site = site
    
                def get_urls(self):
                    app_model_name = (self.model_class._meta.app_label,self.model_class._meta.model_name,)
                    url_patterns = [
                        url(r'^$',self.changelist_view,name="%s_%s_changlist" %app_model_name),
                        url(r'^add/$',self.add_view,name="%s_%s_add" %app_model_name),
                        url(r'^(d+)/delete/$',self.delete_view,name="%s_%s_delete" %app_model_name),
                        url(r'^(d+)/change/$',self.change_view,name="%s_%s_chang" %app_model_name),
                    ]
                    return url_patterns
    
                @property
                def urls(self):
                    return self.get_urls()
    
                def changelist_view(self,request,*args,**kwargs):
                    return HttpResponse('列表')
    
                def add_view(self,request,*args,**kwargs):
                    return HttpResponse('添加')
    
                def delete_view(self,request,nid,*args,**kwargs):
                    return HttpResponse('删除')
    
                def change_view(self,request,nid,*args,**kwargs):
                    return HttpResponse('修改')
    
    
            class StarkSite(object):
    
                def __init__(self):
                    self._registey = {}
    
                def register(self,model_class,stark_config_class=None):
                    if not stark_config_class:
                        stark_config_class = StarkConfig
    
                    self._registey[model_class] = stark_config_class(model_class,self)
    
                def get_urls(self):
                    url_pattern = []
    
                    for model_class,stark_config_obj in self._registry.items():
                       
                        app_name = model_class._meta.app_label
                        model_name = model_class._meta.model_name
    
                        curd_url = url(r'^%s/%s/' %(app_name,model_name,) , (stark_config_obj.urls,None,None))
                        url_pattern.append(curd_url)
    
                    return url_pattern
    
    
                @property
                def urls(self):
                    return (self.get_urls(),None,'stark')
    
    
            site = StarkSite()
    
    4. 列表页面展示
    
    - v1.py
        def changelist_view(self,request,*args,**kwargs):
        # 处理表头
    
        head_list = []
        for field_name in self.list_display:
            if isinstance(field_name,str):
                # 根据类和字段名称,获取字段对象的verbose_name
                verbose_name = self.model_class._meta.get_field(field_name).verbose_name
            else:
                verbose_name = field_name(self,is_header=True)
            head_list.append(verbose_name)
    
        # 处理表中的数据
        # [ UserInfoObj,UserInfoObj,UserInfoObj,UserInfoObj,]
        # [ UserInfo(id=1,name='alex',age=18),UserInfo(id=2,name='alex2',age=181),]
        data_list = self.model_class.objects.all()
        new_data_list = []
        for row in data_list:
            # row是 UserInfo(id=2,name='alex2',age=181)
            # row.id,row.name,row.age
            temp = []
            for field_name in self.list_display:
                if isinstance(field_name,str):
                    val = getattr(row,field_name) # # 2 alex2
                else:
                    val = field_name(self,row)
                temp.append(val)
            new_data_list.append(temp)
    
        return render(request,'stark/changelist.html',{'data_list':new_data_list,'head_list':head_list})
    
    - shark.py
        class UserInfoConfig(v1.StarkConfig):
    
        def checkbox(self,obj=None,is_header=False):
            if is_header:
                return '选择'
            return mark_safe('<input type="checkbox" name="pk" value="%s" />' %(obj.id,))
        def edit(self,obj=None,is_header=False):
            if is_header:
                return '编辑'
            return mark_safe('<a href="/edit/%s">编辑</a>' %(obj.id,))
    
        list_display = [checkbox,'id','name',edit]
    
    
    
    4. 显示增加按钮
    
        - 先判断是否显示,再通过反向解析生成增加链接
        - 后端
            # 是否显示增加按钮
            show_add_btn = True
            def get_show_btn(self):
                return self.show_add_btn
    
            return render(request, 'stark/changelist.html', {'data_list': new_data_list, 'head_list': head_list,"add_url":self.get_add_url(),"show_add_btn":self.get_show_btn()})
    
        - 前端
            {% if show_add_btn %}
                <a class="btn btn-primary" href="{{ add_url }}">增加</a>
            {% endif %}
    
    
    5. 增加内容页面
    
        1. 通过ModelForm创建公共类 显示和提交
    
            - 后端
    
                def add_view(self, request, *args, **kwargs):
    
                    class AddTable(ModelForm):
                        class Meta:
                            model = self.model_class
                            fields = "__all__"
    
                    if request.method == "GET":
                        form = AddTable()
                        return render(request,"stark/add_view.html",{"form":form})
                    else:
                        form = AddTable(request.POST)
                        if form.is_valid():
                            form.save()
                            return redirect(self.get_list_url())
                        else:
                            return render(request, "stark/add_view.html", {"form": form})
    
            - 前端
                <form method="post" novalidate>
                    {% csrf_token %}
                    {{ form.as_p }}
                    <input type="submit" value="提交">
                </form>
    
        2. 升级 在子类自定义ModelForm类 子类之后可以自定义类
    
            - v1.py
                model_form_class = None
                    def get_model_form_class(self):
                        if self.model_form_class:
                            return self.model_form_class
                        else:
                            #方式一:
                            # class AddTable(ModelForm):
                            #     class Meta:
                            #         model = self.model_class
                            #         fields = "__all__"
                            # return AddTable
                            #方式二:
                            meta = type("Meta",(object,),{"model":self.model_class,"fields":"__all__"})
                            AddTable = type("AddTable",(ModelForm,),{"Meta":meta})
                            return AddTable
    
    
                def add_view(self, request, *args, **kwargs):
                    model_form_class = self.get_model_form_class()
                    if request.method == "GET":
                        form = model_form_class()
                        return render(request,"stark/add_view.html",{"form":form})
                    else:
                        form = model_form_class(request.POST)
                        if form.is_valid():
                            form.save()
                            return redirect(self.get_list_url())
                        else:
                            return render(request, "stark/add_view.html", {"form": form})
            - stark.py
    
                class UserInfoModelForm(ModelForm):
                    class Meta:
                        model = models.UserInfo
                        fields = ["name","password"]
                        error_messages = {
                            "name":{
                                'required':'用户名不能为空'
                            }
                        }
                class UserInfoConfig(v1.StarkConfig):
                    model_form_class = UserInfoModelForm
    
    
    6. 修改 和 删除
        def change_view(self, request, nid, *args, **kwargs):
    
            obj = self.model_class.objects.filter(pk=nid).first()
            if not obj:
                return redirect(self.get_list_url())
            model_form_class = self.get_model_form_class()
            if request.method == "GET":
                form = model_form_class(instance=obj)
                return render(request,"stark/change_view.html",{"form":form})
            else:
                form = model_form_class(instance=obj,data=request.POST)
                if form.is_valid:
                    form.save()
                    return redirect(self.get_list_url())
                return render(request,"stark/change_view.html",{"form":form})
    
        def delete_view(self, request, nid, *args, **kwargs):
            self.model_class.objects.filter(pk=nid).delete()
            return redirect(self.get_list_url())
    View Code
  • 相关阅读:
    Windows10下配置单机zookeeper(连接服务器上的zookeeper)
    尚硅谷Zookeeper教程学习讲义
    腾讯云服务器在防火墙上添加可访问端口(CentOS7)
    uniPaaS 2.0新功能
    uniPaas RIA 安装与使用方法
    unipaas2.0发布了,有需要试的请与我联系QQ:79982575
    UNIPAAS抢滩Web 2.0
    最简便最快速的开发工具—Magic eDeveloper/DBMAGIC/UNIPAAS
    RIA技术的应用(UNIPAAS)
    数据库开发工具Magic教程基本操作(以Magic eDeveloper V10为例,其他版本会有差异)
  • 原文地址:https://www.cnblogs.com/golangav/p/8043656.html
Copyright © 2020-2023  润新知