CRM——插件流程回顾

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())