stark 增删改
- 優雅裝飾器
- 判斷是函數,還是變量
- 類傳變量的一種方式
?? 實例方法傳參,要傳實例對象本身
class RoleConfig(object):def f1(self, arg):print('f1', arg)def f2(self, arg):print('f2', arg)list_display = [f1, f2]obj = RoleConfig() for item in RoleConfig.list_display:item(obj, 2)# obj就是self,實例變量本身# 傳變量的一種方式 view- 利用列表儲存函數對象
- 利用yield取數據
復選框實現
- 復選框函數 mark_safe
- 復選框函數實現與顯示
調用復選框函數,拿到標簽渲染
def changelist_view(self, request):# 所有URL的查看列表頁面# 獲取表所有數據queryset = self.model_class.objects.all().order_by(*self.get_order_by())# 要顯示的字段list_display = self.list_displayheader_list = [] # 表頭列表if list_display: # 判斷有沒有顯示字段for name_or_func in list_display:if isinstance(name_or_func, FunctionType): # 判斷是不是函數,是則執行verbose_name = name_or_func(self, header=True)else: # 不是函數,則按規則去取字段的名稱verbose_name = self.model_class._meta.get_field(name_or_func).verbose_nameheader_list.append(verbose_name)else: # 沒有顯示字段列表,取表名作為表頭header_list.append(self.model_class._meta.model_name)body_list = [] # 表體列表for row in queryset: # 從查找到的queryset對象里取row_list = [] # 行列表if not list_display: # 沒有規定顯示的字段row_list.append(row) # 直接將一條queryset 放到行列表里面body_list.append(row_list) # 再放到表體continuefor name_or_func in list_display: # 按照要顯示的字段,取數據,遇到函數就執行顯示復選框,并返回該行對象if isinstance(name_or_func, FunctionType): # 判斷是否是功能函數val = name_or_func(self, row=row) # 執行函數反回功能內容else: # 其他字段的數據正常取val = getattr(row, name_or_func) # getattr 映射 每個要顯示字段名 ,取queryset里面的字段值row_list.append(val) # 添加到行body_list.append(row_list) # 添加到表體# 反回渲染頁面return render(request, 'stark/changelist.html', {'header_list': header_list, 'body_list': body_list}) view- 前端頁面
??? 循環取值
<div><table class="table table-bordered"> {# 基于bootstrap 創建table表 #}<thead> {# 表頭 #}<tr>{% for item in header_list %}<th>{{ item }}</th>{% endfor %}</tr></thead><tbody> {# 表體 #}{% for row_list in body_list %}<tr>{% for col in row_list %}<td>{{ col }}</td>{% endfor %}</tr>{% endfor %}</tbody></table></div> view- 自定義的配置類
編輯刪除功能函數實現
def display_edit(self, row=None, header=False):if header:return "編輯"return mark_safe('<a href="%s"><i class="fa fa-edit" aria-hidden="true"></i></a></a>' % self.reverse_edit_url(row))def display_del(self, row=None, header=False):if header:return "刪除"return mark_safe('<a href="%s"><i class="fa fa-trash-o" aria-hidden="true"></i></a>' % self.reverse_del_url(row))def display_edit_del(self, row=None, header=False):if header:return "操作"tpl = """<a href="%s"><i class="fa fa-edit" aria-hidden="true"></i></a></a> |<a href="%s"><i class="fa fa-trash-o" aria-hidden="true"></i></a>""" %(self.reverse_edit_url(row),self.reverse_del_url(row),)return mark_safe(tpl)list display function前端循環取組裝好的列表里面的值即可{% block content %}<div>{% if add_btn %}<div style="margin: 5px 0;">{{ add_btn }}</div>{% endif %}<table class="table table-bordered"><thead><tr>{% for item in header_list %}<th>{{ item }}</th>{% endfor %}</tr></thead><tbody>{% for row_list in body_list %}<tr>{% for col in row_list %}<td>{{ col }}</td>{% endfor %}</tr>{% endfor %}</tbody></table></div> {% endblock %} view添加數據功能實現
modeform 實現表單更改驗證
model_form_class = Nonedef get_add_btn(self):return mark_safe('<a href="%s" class="btn btn-success">添加</a>' % self.reverse_add_url())def get_model_form_class(self):"""獲取ModelForm類 # 用于編輯 和 添加數據的表單 :return: #根據是否有自定義配置,返回不同表單"""if self.model_form_class:return self.model_form_class # 其他表的配置,如果有自定義的表單則返回自定義的class AddModelForm(forms.ModelForm): # 添加功能的表單,所有數據都需要填寫,所以默認所有字段都要class Meta:model = self.model_classfields = "__all__"return AddModelForm ModelFormdef changelist_view(self, request):"""所有URL的查看列表頁面 # 將添加按鈕功能,添加到這頁面視圖:param request::return:"""queryset = self.model_class.objects.all().order_by(*self.get_order_by())# ##### 添加按鈕 ######add_btn = self.get_add_btn()......def add_view(self, request):"""所有添加頁面,都在此函數處理使用ModelForm實現:param request::return:"""AddModelForm = self.get_model_form_class()if request.method == "GET":form = AddModelForm()return render(request, 'stark/change.html', {'form':form})form = AddModelForm(request.POST) # 校驗數據if form.is_valid():form.save() # 保存return redirect(self.reverse_list_url()) # 添加完反回主頁面return render(request, 'stark/change.html', {'form': form}) add_viewclass AdminSite(object):def __init__(self):self._registry = {}self.app_name = 'stark'self.namespace = 'stark'def register(self, model_class, stark_config=None):"""注冊表類:param model_class: 表類class:param stark_config: 自定義配置:return:"""if not stark_config:stark_config = StarkConfigself._registry[model_class] = stark_config(model_class, self) # 實例對象傳參"""{models.UserInfo: StarkConfig(models.UserInfo), # 封裝:model_class=UserInfo,site=site對象models.Role: RoleConfig(models.Role) # 封裝:model_class=Role,site=site對象}"""def get_urls(self):# 獲取urlurlpatterns = [] #url 列表# urlpatterns.append(url(r'^x3/', ([# url(r'^add/', self.x1),# url(r'^change/', self.x1),# url(r'^del/', self.x1),# url(r'^edit/', self.x1),# ],None,None)))for k, v in self._registry.items():# k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封裝:model_class=UserInfo,site=site對象# k=modes.Role,v=RoleConfig(models.Role) # 封裝:model_class=Role,site=site對象app_label = k._meta.app_labelmodel_name = k._meta.model_nameurlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))# 表類所在app/表類名的組裝 一個表類綁定的操作urlreturn urlpatterns@propertydef urls(self):return self.get_urls(), self.app_name, self.namespace# url列表 # 返回的元組site = AdminSite() AdminSite編輯視圖函數def change_view(self, request, pk):"""所有編輯頁面:param request::param pk: 操作該條數據的pk,路由有設置:return:"""obj = self.model_class.objects.filter(pk=pk).first()if not obj:return HttpResponse('數據不存在')ModelFormClass = self.get_model_form_class()if request.method == 'GET':form = ModelFormClass(instance=obj) # instance=obj 默認原先的編輯數據return render(request,'stark/change.html',{'form':form})form = ModelFormClass(data=request.POST,instance=obj)if form.is_valid():form.save()return redirect(self.reverse_list_url())return render(request, 'stark/change.html', {'form': form})編輯視圖處理函數{% block content %}<div style="width: 680px;margin: 0 auto;"><form class="change" method="post">{% csrf_token %}{% for filed in form %}<div class="form-group"><label>{{ filed.label }}</label>{{ filed }}{{ filed.errors.0 }}</div>{% endfor %}<button type="submit" class="btn btn-default">Submit</button></form></div> {% endblock %} 編輯前端頁面def delete_view(self, request, pk):"""所有刪除頁面:param request::param pk::return:"""if request.method == "GET":return render(request,'stark/delete.html',{'cancel_url':self.reverse_list_url()})# 跳轉到確認頁面 # 取消反回的urlself.model_class.objects.filter(pk=pk).delete() # 不是GET請求,說明確認刪除return redirect(self.reverse_list_url())刪除視圖處理函數{% extends 'stark/layout.html' %} {% block css %}{% endblock %} {% block content %}<div ><form method="post">{% csrf_token %}<p>是否確定要刪除?</p><a href="{{ cancel_url }}" class="btn btn-default">取消</a><button type="submit" class="btn btn-danger">確 認</button></form></div> {% endblock %}刪除確認頁面def get_urls(self):info = self.model_class._meta.app_label, self.model_class._meta.model_nameurlpatterns = [url(r'^list/$', self.wrapper(self.changelist_view), name='%s_%s_changelist' % info),url(r'^add/$', self.wrapper(self.add_view), name='%s_%s_add' % info),url(r'^(?P<pk>\d+)/change/', self.wrapper(self.change_view), name='%s_%s_change' % info),url(r'^(?P<pk>\d+)/del/', self.wrapper(self.delete_view), name='%s_%s_del' % info),]extra = self.extra_url()if extra:urlpatterns.extend(extra)return urlpatterns def extra_url(self):pass 每張表類綁定的路由
反向解析,前端提交變更的路由路徑
def reverse_list_url(self):app_label = self.model_class._meta.app_labelmodel_name = self.model_class._meta.model_namenamespace = self.site.namespacename = '%s:%s_%s_changelist' % (namespace, app_label, model_name)list_url = reverse(name)return list_urldef reverse_add_url(self):app_label = self.model_class._meta.app_labelmodel_name = self.model_class._meta.model_namenamespace = self.site.namespacename = '%s:%s_%s_add' % (namespace, app_label, model_name)add_url = reverse(name)return add_urldef reverse_edit_url(self,row):app_label = self.model_class._meta.app_labelmodel_name = self.model_class._meta.model_namenamespace = self.site.namespacename = '%s:%s_%s_change' % (namespace, app_label, model_name)edit_url = reverse(name, kwargs={'pk': row.pk})return edit_urldef reverse_del_url(self,row):app_label = self.model_class._meta.app_labelmodel_name = self.model_class._meta.model_namenamespace = self.site.namespacename = '%s:%s_%s_del' % (namespace, app_label, model_name)del_url = reverse(name, kwargs={'pk': row.pk})return del_url@property def urls(self):return self.get_urls() 路由解析應用配置app01/stark.py
class DepartModelForm(forms.ModelForm):class Meta:model = models.Departfields = "__all__"def clean_name(self):return self.cleaned_data['name']class DepartConfig(StarkConfig): #繼承默認配置類list_display = [StarkConfig.display_checkbox, 'id', 'name', 'tel', 'user', StarkConfig.display_edit_del]model_form_class = DepartModelFormdef changelist_view(self, request):return HttpResponse('自定義列表頁面')site.register(models.Depart, DepartConfig) view
class AdminSite(object):def __init__(self):self._registry = {}self.app_name = 'stark'self.namespace = 'stark'def register(self, model_class, stark_config=None):"""注冊表類:param model_class: 表類class:param stark_config: 自定義配置:return:"""if not stark_config:stark_config = StarkConfigself._registry[model_class] = stark_config(model_class, self) # 實例對象傳參"""{models.UserInfo: StarkConfig(models.UserInfo), # 封裝:model_class=UserInfo,site=site對象models.Role: RoleConfig(models.Role) # 封裝:model_class=Role,site=site對象}"""def get_urls(self):# 獲取urlurlpatterns = [] #url 列表# urlpatterns.append(url(r'^x3/', ([# url(r'^add/', self.x1),# url(r'^change/', self.x1),# url(r'^del/', self.x1),# url(r'^edit/', self.x1),# ],None,None)))for k, v in self._registry.items():# k=modes.UserInfo,v=StarkConfig(models.UserInfo), # 封裝:model_class=UserInfo,site=site對象# k=modes.Role,v=RoleConfig(models.Role) # 封裝:model_class=Role,site=site對象app_label = k._meta.app_labelmodel_name = k._meta.model_nameurlpatterns.append(url(r'^%s/%s/' % (app_label, model_name,), (v.urls, None, None)))# 表類所在app/表類名的組裝 一個表類綁定的操作urlreturn urlpatterns@propertydef urls(self):return self.get_urls(), self.app_name, self.namespace# url列表 # 返回的元組site = AdminSite()class AdminSite
自定義思路a.有自定義配置類的,重寫繼承的默認類變量,然后再由類方法自己去調用b. 在自定義配置類,直接重寫繼承配置類的默認方法1. 排序規則2. 顯示列第一種方法:class UserInfoConfig(StarkConfig):list_display = ['id','title',StarkConfig.display_edit,StarkConfig.display_del]site.register(models.UserInfo,UserInfoConfig)第二種方法:class UserInfoConfig(StarkConfig):order_by = ['-id']def get_list_display(self):return ['id','title',StarkConfig.display_edit,StarkConfig.display_del] 1. 排序規則3. 添加按鈕class UserInfoConfig(StarkConfig):list_display = ['id','title',StarkConfig.display_edit,StarkConfig.display_del]def get_add_btn(self):# 顯示 # return mark_safe('<a href="%s" class="btn btn-success">添加</a>' % self.reverse_add_url())# 不顯示return Nonesite.register(models.UserInfo,UserInfoConfig) 3. 添加按鈕4. 定制ModelForm第一種方法:class DepartModelForm(forms.ModelForm):class Meta:model = models.Departfields = "__all__"def clean_name(self):return self.cleaned_data['name']class DepartConfig(StarkConfig):list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]model_form_class = DepartModelForm第二種方法:class DepartModelForm(forms.ModelForm):class Meta:model = models.Departfields = "__all__"def clean_name(self):return self.cleaned_data['name']class DepartConfig(StarkConfig):list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]def get_model_form_class(self):return DepartModelForm 4. 定制ModelForm5. 自定義列表頁面class DepartConfig(StarkConfig):list_display = [StarkConfig.display_checkbox,'id', 'name', 'tel', 'user',StarkConfig.display_edit_del]model_form_class = DepartModelFormdef changelist_view(self, request):return HttpResponse('自定義列表頁面')site.register(models.Depart, DepartConfig)6. 增加URLclass RoleConfig(StarkConfig):order_by = ['-id', ]list_display = [StarkConfig.display_checkbox,'id','title',StarkConfig.display_edit,StarkConfig.display_del]def extra_url(self):data = [url(r'^xxxxxxx/$', self.xxxxxx),]return datadef xxxxxx(self,request):print('....')return HttpResponse('xxxxx')site.register(models.Role,RoleConfig)7. 自定制URLclass RoleConfig(StarkConfig):order_by = ['-id', ]list_display = [StarkConfig.display_checkbox,'id','title']def get_add_btn(self):return Falsedef extra_url(self):data = [url(r'^xxxxxxx/$', self.xxxxxx),]return datadef xxxxxx(self,request):print('....')return HttpResponse('xxxxx')def get_urls(self):info = self.model_class._meta.app_label, self.model_class._meta.model_nameurlpatterns = [url(r'^list/$', self.wrapper(self.changelist_view), name='%s_%s_changelist' % info),]extra = self.extra_url()if extra:urlpatterns.extend(extra)return urlpatternssite.register(models.Role,RoleConfig) 5. 自定義列表頁面
總結
- 上一篇: s111 stark组件
- 下一篇: Docker 环境的快速搭建