Django之stark组件2
action批量处理功能
用户可以自定义批量处理功能,但是默认的有批量删除功能.
***思路***
1,定义一个列表用来装action的类名并extend用户自定义列表
2.循环该列表获取到函数名(用于执行)和方法名用于展示
3.post提交,(selected_id是几个checkbox)(actions是类名)判断actions提交的是什么方法,就执行该方法.
############ class ModelStark(object): actions=[] def get_actions_dict(self): temp=[] for item in self.config.new_actions: item_name = item.__name__ item_desc=getattr(item,'desc',item_name.replace('_',' ')) action_dict={ "name":item_name, "desc":item_desc, } temp.append(action_dict) return temp @property def new_actions(self): temp=[ModelStark.actions_delete] temp.extend(self.actions) return temp def show_list(self,request): '''展示页面''' # self--->stark_class_obj--->每一个单独的配置类. if request.method=='POST': actions = request.POST.get('actions') if actions: selected_id=request.POST.getlist('selected_id') queryset=self.model.objects.filter(id__in=selected_id) actions_func=getattr(self,actions) actions_func(request,queryset) ######前端######## <select name="actions" style="padding: 8px 10px"> <option value="">----------</option> {% for item in showlist.get_actions_dict %} <option value="{{ item.name }}">{{ item.desc }}</option> {% endfor %} </select><button type="submit" class="btn btn-success">Go</button>
class BookStark(ModelStark): def patch_init(self,request,queryset): queryset.update(price=100) patch_init.desc='批量初始化' actions = [patch_init] site.register(models.Book,BookStark)
2.过滤
这里只过滤:一对多,多对对,choices
***思路***
[需要注意的是,每一个字段的拼接都是过滤的条件filter]
1.过滤的a标签,每点一次都要重新生成一份新的url拼接到原来的url上.(保留原始字段,并且每点击一次都会增加字段名和对应的id值)
2.all标签在拼接的时候,把该字段的键值删除,点击的时候就不会过滤该键值
3.过滤的条件用Q()来构建
def get_filter_tags(self): handlerfilter =HandlerFilter(self.config.list_filter,self.request,self.config.model) # def __init__(self, list_filter, request, model): filter_dict=handlerfilter.process() return filter_dict class HandlerFilter(object):#['author','pub'] def __init__(self,list_filter,request,model): self.list_filter=list_filter self.request=request self.model =model self.filter_dict={} def process(self): for filter_field in self.list_filter: self.init_data(filter_field) self.handler_all(filter_field) self.distribute(filter_field) return self.filter_dict def init_data(self,filter_field): '''初始化数据''' self.temp = [] self._url = copy.deepcopy(self.request.GET) self.current_id = self._url.get(filter_field, 0) self.filter_field_obj = self.model._meta.get_field(filter_field) self.dict_name=getattr(self.filter_field_obj,'verbose_name',filter_field) def handler_all(self,filter_field): '''处理 all字段和页码bug''' if self._url.get('p'): self._url.pop('p') if self._url.get(filter_field): del self._url[filter_field] all_link = "<a href='?%s'>All</a>" % (self._url.urlencode()) else: all_link = "<a href='#' class='active'>All</a>" self.temp.append(all_link) def distribute(self,filter_field): '''分发方法''' if isinstance(self.filter_field_obj,ManyToManyField) \ or isinstance(self.filter_field_obj,ForeignKey): self.M2MorFk(filter_field) elif self.filter_field_obj.choices: self.choices(filter_field) else: self.commom_file(filter_field) def M2MorFk(self,filter_field): '''字段多对多,或者一对多的处理''' filter_obj_list=self.filter_field_obj.related_model.objects.all() for obj in filter_obj_list: self._url[filter_field]=obj.id if self.current_id==str(obj.id): link = "<a class='active' href='?%s'>%s</a>" % (self._url.urlencode(), str(obj)) else: link = "<a href='?%s'>%s</a>" % (self._url.urlencode(), str(obj)) self.temp.append(link) self.filter_dict[self.dict_name]=self.temp def choices(self,filter_field): '''字段为choice的处理''' for num,text in self.filter_field_obj.choices: self._url[filter_field]=num if self.current_id==str(num): link="<a class='active' href='?%s'>%s</a>"%(self._url.urlencode(),text) else: link="<a href='?%s'>%s</a>"%(self._url.urlencode(),text) self.temp.append(link) self.filter_dict[self.dict_name]=self.temp def commom_file(self,filter_field): '''处理普通字段''' pass
知识点补充/通过一对多和多对对字段,怎么获取到关联的model:
pub = models.ForeignKey(to='Publish',on_delete=models.CASCADE,verbose_name='出版社')
获取到了pub字段,怎么获取到Publish这个model
获取到了多对多的字段或一对多 self.filter_field_obj = self.model._meta.get_field(filter_field) 通过字段获取到model类.....filter_obj_list--->[obj,obj] filter_obj_list=self.filter_field_obj.related_model.objects.all()
def get_filter_connection(self,request): '''获取过滤条件''' _url = copy.deepcopy(request.GET) filter_connection=Q() for filter_field,val in _url.items(): if filter_field in self.list_filter: filter_connection.children.append((filter_field,val)) return filter_connection
用法:
list_filter = ['name']
pop方法:
***思路***
1.通过form构建添加不同model的url,且获取该select标签的id
2.构建是否显示pop按钮
3.利用window.close()和window.opener方法来实现pop添加后自动关闭窗口和默认选中
知识点补充/form字段获取model:
#bfield是form字段 related_model=bfield.field.queryset.model #获取该form字段对应的model
def get_form(self,form): from django.forms.models import ModelChoiceField for bfield in form: if isinstance(bfield.field,ModelChoiceField): bfield.is_pop = True #用于是否显示pop按钮 related_model=bfield.field.queryset.model #获取该form字段对应的model related_model_name=related_model._meta.model_name #获取model的名字 related_app_name=related_model._meta.app_label #获取model项目的名字 _url=reverse('%s_%s_add'%(related_app_name,related_model_name)) #反向解析url bfield.url = _url+"?pop_in=id_%s"%bfield.name return form def add_view(self,request): '''增加的视图函数''' # self--->stark_class_obj--->每一个单独的配置类. ModelDeMo=self.get_model_class() old_form =ModelDeMo() if request.method=='POST': old_form = ModelDeMo(request.POST) if old_form.is_valid(): obj=old_form.save() current_select =request.GET.get('pop_in') if current_select: ret={'id':obj.id,'text':str(obj),'current_select':current_select} return render(request,'oprate/pop.html',{'ret':ret}) else: return redirect(self.get_list_url()) form =self.get_form(old_form) return render(request,'oprate/add.html',{'form':form})
######form表单的+标签路径##########' {% for data in form %} <div class="form-item" style="position: relative"> <label>{{ data.label }}</label> {{ data }}<span class="errors-form">{{ data.errors.0 }}</span> {% if data.url %} <a onclick="pop_window('{{ data.url }}')" style="position: absolute;right: -20px;top: 20px"><span style="font-size: 32px">+</span></a> {% endif %} </div> {% endfor %} ########pop html########## <script> window.opener.pop_handle('{{ ret.id }}','{{ ret.text }}','{{ ret.current_select }}'); window.close(); </script> #########add html######## {% block extra_script %} <script> function pop_window(url) { window.open(url,'','width=600,height=400,top=200,left=200') } function pop_handle(id,text,current_select) { var $option =$('<option>'); $option.html(text); $option.val(id); $option.attr('selected','selected'); $('#'+current_select).append($option) } </script> {% endblock %}
知识点补充window.open/close:
window.open(url,'','设置大小') (第三个参数)
window.opener.func() 调用父窗口的方法
window.close()关闭窗口