stark - 4 ⇲ 視圖函數

✘  list_viewhtml

處理表格(默認是顯示錶結構的全部字段)數據庫

 1 list_display = self.get_list_display()
 2 # 4.1處理表頭
 3 header_list = []
 4 if list_display:
 5     for multi_key in list_display:
 6         if isinstance(multi_key,FunctionType):  #判斷 傳入值是否爲函數
 7             verbose_name = multi_key(self,obj=None,is_header=True)
 8         else:
 9             verbose_name = self.model_class._meta.get_field(multi_key).verbose_name
10         header_list.append(verbose_name)
11 else:
12     header_list.append(self.model_class._meta.model_name)
13 
14 # 4.2處理表的內容
15 data_list = queryset[pager.start:pager.end]
16 
17 body_list = []
18 for row in data_list:  #row 是UserInfo object (1)
19     row_list = []
20 
21     if list_display:
22         for multi_key in list_display:
23             if isinstance(multi_key,FunctionType):
24                 row_list.append(multi_key(self,row,is_header=False,*args,**kwargs))
25             else:
26                 row_list.append(getattr(row,multi_key))  #獲取UserInfo object (1)的屬性
27     else:
28         row_list.append(row)
29 
30     body_list.append(row_list)

 

爲了可以擴展之後業務的功能(推出新的業務,高級用戶可能要顯示多的列或者新的功能),咱們能夠針對某張表進行自定義修改定製。只需在本身的Handler子類重寫此方法django

這是StarkHandler類的方法
1
list_display = [] 2 def get_list_display(self): 3 """ 4 獲取頁面上應該顯示的列,預留自定義擴展 5 :return: 6 """ 7 field_list = [] 8 field_list.extend(self.list_display) 9 return field_list

 

 

在上面方法的架構基礎下,實現以往對錶〔編輯〕〔刪除〕的基本功能,一樣放在基類中架構

如圖           app

 1 def display_edit(self,obj=None,is_header=None):
 2     """
 3     生成<編輯>a標籤
 4     :param obj:
 5     :param is_header:
 6     :return:
 7     """
 8     if is_header:
 9         return "編輯操做"
10     change_url = self.reverse_change_url(pk=obj.pk)
11     return mark_safe('<a href="%s">編輯</a>'%change_url)
12 
13 def display_delete(self,obj=None,is_header=None):
14     """
15     生成<刪除>a標籤
16     :param obj:
17     :param is_header:
18     :return:
19     """
20     if is_header:
21         return "刪除操做"
22     delete_url = self.reverse_delete_url(pk=obj.pk)
23     return mark_safe('<a href="%s">刪除</a>'% delete_url)

 

示例:ide

 1 #models.py下的Major類:
 2 #class Major(models.Model):
 3 #    title = models.CharField(verbose_name='專業',max_length=32)
 4 #
 5 #    def __str__(self):
 6 #        return self.title
 7 
 8 #該model類view函數下,繼承StarkHanler,list_display[字段+方法]:
 9 from stark.service.v1 import StarkHandler
10 
11 class MajorHandler(StarkHandler):
12     list_display = ['title',StarkHandler.display_edit,StarkHandler.display_delete]
View Code

 


可是,若是表結構裏有choice字段呢?函數

則須要使用obj.get_字段名_display 獲取orm對象的信息。解決的話,一樣寫一個方法放在基類,之後提取choice字段的信息直接使用url

 這裏不是StarkHandler類。
1
def get_choice_text(title,field): 2 """ 3 對於Stark組件中定義列時,choice若是想要顯示中文信息,調用此方法便可 4 :param title: 表頭名稱(自定義) 5 :param field: 字段名稱(須要提取的) 6 :return: 7 """ 8 def inner(self,obj=None,is_header=None): 9 if is_header: 10 return title 11 method = "get_%s_display" %field 12 return getattr(obj,method)() 13 14 return inner

Exa: list_display=[get_choice_text('性別','gender')]

表結構裏有manytomany的字段呢?spa

 1 def get_m2m_text(title, field):
 2     """
 3     對於Stark組件中定義列時,顯示m2m文本信息
 4     :param title: 表頭名稱
 5     :param field: 字段名稱
 6     :return:
 7     """
 8 
 9     def inner(self, obj=None, is_header=None, *args, **kwargs):
10         if is_header:
11             return title
12         queryset = getattr(obj, field).all()
13         text_list = [str(row) for row in queryset]
14         return ','.join(text_list)
15 
16     return inner

Exa: list_display=[get_m2m_text('授課老師','teacher')]

 


當存儲數據多了呢?滾動查找全部數據?code

這邊借鑑了前輩所寫的分頁組件

  1 """
  2 分頁組件
  3 """
  4 from django.utils.safestring import mark_safe
  5 
  6 class Pagination(object):
  7     def __init__(self, current_page, all_count, base_url, query_params, per_page=20, pager_page_count=11):
  8         """
  9         分頁初始化
 10         :param current_page: 當前頁碼
 11         :param per_page: 每頁顯示數據條數
 12         :param all_count: 數據庫中總條數
 13         :param base_url: 基礎URL
 14         :param query_params: QueryDict對象,內部含全部當前URL的原條件
 15         :param pager_page_count: 頁面上最多顯示的頁碼數量
 16         """
 17         self.base_url = base_url
 18         try:
 19             self.current_page = int(current_page)
 20             if self.current_page <= 0:
 21                 raise Exception()
 22         except Exception as e:
 23             self.current_page = 1
 24         self.query_params = query_params
 25         self.per_page = per_page
 26         self.all_count = all_count
 27         self.pager_page_count = pager_page_count
 28         pager_count, b = divmod(all_count, per_page)
 29         if b != 0:
 30             pager_count += 1
 31         self.pager_count = pager_count
 32 
 33         half_pager_page_count = int(pager_page_count / 2)
 34         self.half_pager_page_count = half_pager_page_count
 35 
 36     @property
 37     def start(self):
 38         """
 39         數據獲取值起始索引
 40         :return:
 41         """
 42         return (self.current_page - 1) * self.per_page
 43 
 44     @property
 45     def end(self):
 46         """
 47         數據獲取值結束索引
 48         :return:
 49         """
 50         return self.current_page * self.per_page
 51 
 52     def page_html(self):
 53         """
 54         生成HTML頁碼
 55         :return:
 56         """
 57         # 若是數據總頁碼pager_count<11 pager_page_count
 58         if self.pager_count < self.pager_page_count:
 59             pager_start = 1
 60             pager_end = self.pager_count
 61         else:
 62             # 數據頁碼已經超過11
 63             # 判斷: 若是當前頁 <= 5 half_pager_page_count
 64             if self.current_page <= self.half_pager_page_count:
 65                 pager_start = 1
 66                 pager_end = self.pager_page_count
 67             else:
 68                 # 若是: 當前頁+5 > 總頁碼
 69                 if (self.current_page + self.half_pager_page_count) > self.pager_count:
 70                     pager_end = self.pager_count
 71                     pager_start = self.pager_count - self.pager_page_count + 1
 72                 else:
 73                     pager_start = self.current_page - self.half_pager_page_count
 74                     pager_end = self.current_page + self.half_pager_page_count
 75 
 76         page_list = []
 77 
 78         if self.current_page <= 1:
 79             prev = '<li><a href="#">上一頁</a></li>'
 80         else:
 81             self.query_params['page'] = self.current_page - 1
 82             prev = '<li><a href="%s?%s">上一頁</a></li>' % (self.base_url, self.query_params.urlencode())
 83         page_list.append(prev)
 84         for i in range(pager_start, pager_end + 1):
 85             self.query_params['page'] = i
 86             if self.current_page == i:
 87                 tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
 88                     self.base_url, self.query_params.urlencode(), i,)
 89             else:
 90                 tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
 91             page_list.append(tpl)
 92 
 93         if self.current_page >= self.pager_count:
 94             nex = '<li><a href="#">下一頁</a></li>'
 95         else:
 96             self.query_params['page'] = self.current_page + 1
 97             nex = '<li><a href="%s?%s">下一頁</a></li>' % (self.base_url, self.query_params.urlencode(),)
 98         page_list.append(nex)
 99         page_str = "".join(page_list)
100         return mark_safe(page_str)
View Code

Combine▼

 list_view下的分頁功能:
1
all_count = queryset.count() 2 query_params = request.GET.copy() # ?=page=1&name='李四' 3 query_params._mutable = True #query_params['page']默認是不能夠修改的 4 5 pager = Pagination( 6 current_page=request.GET.get('page'), 7 all_count=all_count, 8 base_url=request.path_info, 9 query_params=query_params, 10 per_page=self.per_page_count, 11 )

 

 

 

✘  add_view

如圖,    

 

爲了可以在模板循環展現表單數據、錯誤信息等,咱們得建立forms.ModelForm對象,而後把form對象傳遞過去。

可是每張表model_class所產生的form對象是不同的,所以不一樣請求進來都得建立一個ModelForm,這樣就太不方便了

解決: 

1 class DynamicModelForm(forms.ModelForm):
2     class Meta:
3         model = self.model_class  不把model表寫死了,應該是動態的,即須要訪問的model類 4         fields = "__all__"

 

在這基礎下,封裝成爲一個方法,日後須要產生form對象時,代入model類,直接調用。

 1     model_form = False
 2     def get_model_form(self):
 3         if self.model_form:   #預留勾子,拓展或者自定義定製覆蓋便可
 4             return self.model_form
 5 
 6         class DynamicModelForm(forms.ModelForm):
 7             class Meta:
 8                 model = self.model_class
 9                 fields = "__all__"
10 
11             def __init__(self, *args, **kwargs):
12                 super(DynamicModelForm, self).__init__(*args, **kwargs)
13                 # 統一給ModelForm生成字段添加樣式
14                 for name, field in self.fields.items():
15                     field.widget.attrs['class'] = 'form-control'
16 
17         return DynamicModelForm

 

若是有需求想讓form對象多一行確認密碼,或者控制顯示的行呢?

前者能夠在子類重寫ModelForm,然後者咱們則需爲form.save()預留勾子,方便拓展或重寫覆蓋。

1     def save(self,request,form,is_update,*args,**kwargs):
2 form.save()

 

實現save基操下,想到若是在點擊添加按鈕的時候,URL自己帶有 /?page=1的參數下,執行添加操做後,理應返回原來頁面的時候帶回這個參數。

這裏,簡單地理一下。

1.在進入添加路由時,咱們先把參數部分urlencode(),而後把數據做爲鍵值"_filter"的value值,最後urlencode() 做爲新的參數。

 1     def reverse_add_url(self,**kwargs):
 2         name = "%s:%s" % (self.site.namespace, self.get_add_url_name)  #stark:Web_customer_public_list
 3         url = reverse(name,kwargs=kwargs)
 4 
 5         if not self.request.GET:
 6             add_url = url
 7         else:
 8             param = self.request.GET.urlencode()  # page=1
 9 
10             new_query_dict = QueryDict(mutable=True)
11             new_query_dict['_filter'] = param  # <QueryDict: {'_filter': ['page=1']}>
12 
13             add_url = "%s?%s" % (url, new_query_dict.urlencode(()))
14 
15         return add_url

2.相似地,添加完後 redirect 回原來頁面並帶回參數

 1     def reverse_list_url(self,**kwargs):
 2         name = "%s:%s" % (self.site.namespace, self.get_list_url_name)
 3         url = reverse(name,kwargs=kwargs)
 4         if not self.request.GET:
 5             list_url = url
 6         else:
 7             param = self.request.GET.get('_filter')
 8             # print(param)  #page=1
 9             if not param:
10                 return redirect(url)
11             list_url = "%s?%s" % (url, param)
12 
13         return list_url

 

全部的鋪墊下,添加視圖方法基本完成。

 1     def add_view(self,request,*args,**kwargs):
 2         """
 3         添加視圖
 4         :param request:
 5         :return:
 6         """ 
 7         model_form = self.get_model_form()
 8         if request.method == 'GET':
 9             form = model_form
10             return render(request, 'change.html', {'form': form})
11 
12         form = model_form(data=request.POST)
13         if form.is_valid():
14             response =  self.save(request,form,False,*args,**kwargs)
15             return response or redirect(self.reverse_list_url(**kwargs))
16         return render(request,'change.html',{'form':form})

 

 

✘  change_view

 基本跟添加視圖同樣,只是form對象在表單默認顯示數據

 1     def get_change_object(self, request, pk, *args, **kwargs):
 2         return self.model_class.objects.filter(pk=pk).first()
 3 
 4     def change_view(self,request,pk,*args,**kwargs):
 5         """
 6         編輯視圖
 7         :param request:
 8         :param pk:
 9         :return:
10         """
11         checked_obj = self.get_change_object(request, pk, *args, **kwargs)
12 
13         if not checked_obj: 
14             return render(request,'rbac\error.html')
15 
16         model_form = self.get_model_form()
17         if request.method == 'GET':
18             form = model_form(instance=checked_obj)
19             return render(request, 'change.html', {'form': form})
20 
21         form = model_form(data=request.POST,instance=checked_obj)
22         if form.is_valid():
23             response = self.save(request, form, True, *args, **kwargs)
24             return response or redirect(self.reverse_list_url(**kwargs))
25         return render(request, 'change.html', {'form': form})

 

 

✘  delete_view

基本跟添加視圖同樣。

這裏繼承以往爲了防止用戶刪除數據時小手一抖,作出的確認選擇按鈕

 1     def delete_object(self, request, pk, *args, **kwargs):
 2         self.model_class.objects.filter(pk=pk).delete()
 3 
 4     def delete_view(self,request,pk,*args,**kwargs):
 5         """
 6         刪除視圖
 7         :param request:
 8         :param pk:
 9         :return:
10         """
11         checked_obj  = self.model_class.objects.filter(pk=pk).first()
12         if not checked_obj:
13             return render(request,'rbac\error.html',)
14 
15         list_url = self.reverse_list_url(**kwargs)
16         if request.method == 'GET':
17             return render(request,'delete.html',{'list_url':list_url})
18 
19         response = self.delete_object(request, pk, *args, **kwargs)
20         return response or redirect(list_url)
相關文章
相關標籤/搜索