✘  list_view

处理表格(默认是显示表结构的所有字段)

 1 list_display = self.get_list_display()
# 4.1处理表头
header_list = []
if list_display:
for multi_key in list_display:
if isinstance(multi_key,FunctionType): #判断 传入值是否为函数
verbose_name = multi_key(self,obj=None,is_header=True)
else:
verbose_name = self.model_class._meta.get_field(multi_key).verbose_name
header_list.append(verbose_name)
else:
header_list.append(self.model_class._meta.model_name) # 4.2处理表的内容
data_list = queryset[pager.start:pager.end] body_list = []
for row in data_list: #row 是UserInfo object (1)
row_list = [] if list_display:
for multi_key in list_display:
if isinstance(multi_key,FunctionType):
row_list.append(multi_key(self,row,is_header=False,*args,**kwargs))
else:
row_list.append(getattr(row,multi_key)) #获取UserInfo object (1)的属性
else:
row_list.append(row) body_list.append(row_list)

为了能够扩展以后业务的功能(推出新的业务,高级用户可能要显示多的列或者新的功能),我们可以针对某张表进行自定义修改定制。只需在自己的Handler子类重写此方法

这是StarkHandler类的方法
1 list_display = []
def get_list_display(self):
"""
获取页面上应该显示的列,预留自定义扩展
:return:
"""
field_list = []
field_list.extend(self.list_display)
return field_list

在上面方法的架构基础下,实现以往对表〔编辑〕〔删除〕的基本功能,同样放在基类中

如图           

 def display_edit(self,obj=None,is_header=None):
"""
生成<编辑>a标签
:param obj:
:param is_header:
:return:
"""
if is_header:
return "编辑操作"
change_url = self.reverse_change_url(pk=obj.pk)
return mark_safe('<a href="%s">编辑</a>'%change_url) def display_delete(self,obj=None,is_header=None):
"""
生成<删除>a标签
:param obj:
:param is_header:
:return:
"""
if is_header:
return "删除操作"
delete_url = self.reverse_delete_url(pk=obj.pk)
return mark_safe('<a href="%s">删除</a>'% delete_url)

示例:

 #models.py下的Major类:
#class Major(models.Model):
# title = models.CharField(verbose_name='专业',max_length=32)
#
# def __str__(self):
# return self.title #该model类view函数下,继承StarkHanler,list_display[字段+方法]:
from stark.service.v1 import StarkHandler class MajorHandler(StarkHandler):
list_display = ['title',StarkHandler.display_edit,StarkHandler.display_delete]

但是,如果表结构里有choice字段呢?

则需要使用obj.get_字段名_display 获取orm对象的信息。解决的话,同样写一个方法放在基类,以后提取choice字段的信息直接使用

 这里不是StarkHandler类。
1 def get_choice_text(title,field):
"""
对于Stark组件中定义列时,choice如果想要显示中文信息,调用此方法即可
:param title: 表头名称(自定义)
:param field: 字段名称(需要提取的)
:return:
"""
def inner(self,obj=None,is_header=None):
if is_header:
return title
method = "get_%s_display" %field
return getattr(obj,method)() return inner Exa: list_display=[get_choice_text('性别','gender')]

表结构里有manytomany的字段呢?

 def get_m2m_text(title, field):
"""
对于Stark组件中定义列时,显示m2m文本信息
:param title: 表头名称
:param field: 字段名称
:return:
""" def inner(self, obj=None, is_header=None, *args, **kwargs):
if is_header:
return title
queryset = getattr(obj, field).all()
text_list = [str(row) for row in queryset]
return ','.join(text_list) return inner Exa: list_display=[get_m2m_text('授课老师','teacher')]

当存储数据多了呢?滚动查找所有数据?

这边借鉴了前辈所写的分页组件

 """
分页组件
"""
from django.utils.safestring import mark_safe class Pagination(object):
def __init__(self, current_page, all_count, base_url, query_params, per_page=20, pager_page_count=11):
"""
分页初始化
:param current_page: 当前页码
:param per_page: 每页显示数据条数
:param all_count: 数据库中总条数
:param base_url: 基础URL
:param query_params: QueryDict对象,内部含所有当前URL的原条件
:param pager_page_count: 页面上最多显示的页码数量
"""
self.base_url = base_url
try:
self.current_page = int(current_page)
if self.current_page <= 0:
raise Exception()
except Exception as e:
self.current_page = 1
self.query_params = query_params
self.per_page = per_page
self.all_count = all_count
self.pager_page_count = pager_page_count
pager_count, b = divmod(all_count, per_page)
if b != 0:
pager_count += 1
self.pager_count = pager_count half_pager_page_count = int(pager_page_count / 2)
self.half_pager_page_count = half_pager_page_count @property
def start(self):
"""
数据获取值起始索引
:return:
"""
return (self.current_page - 1) * self.per_page @property
def end(self):
"""
数据获取值结束索引
:return:
"""
return self.current_page * self.per_page def page_html(self):
"""
生成HTML页码
:return:
"""
# 如果数据总页码pager_count<11 pager_page_count
if self.pager_count < self.pager_page_count:
pager_start = 1
pager_end = self.pager_count
else:
# 数据页码已经超过11
# 判断: 如果当前页 <= 5 half_pager_page_count
if self.current_page <= self.half_pager_page_count:
pager_start = 1
pager_end = self.pager_page_count
else:
# 如果: 当前页+5 > 总页码
if (self.current_page + self.half_pager_page_count) > self.pager_count:
pager_end = self.pager_count
pager_start = self.pager_count - self.pager_page_count + 1
else:
pager_start = self.current_page - self.half_pager_page_count
pager_end = self.current_page + self.half_pager_page_count page_list = [] if self.current_page <= 1:
prev = '<li><a href="#">上一页</a></li>'
else:
self.query_params['page'] = self.current_page - 1
prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url, self.query_params.urlencode())
page_list.append(prev)
for i in range(pager_start, pager_end + 1):
self.query_params['page'] = i
if self.current_page == i:
tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
self.base_url, self.query_params.urlencode(), i,)
else:
tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
page_list.append(tpl) if self.current_page >= self.pager_count:
nex = '<li><a href="#">下一页</a></li>'
else:
self.query_params['page'] = self.current_page + 1
nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
page_list.append(nex)
page_str = "".join(page_list)
return mark_safe(page_str)

Combine▼

 list_view下的分页功能:
1 all_count = queryset.count()
query_params = request.GET.copy() # ?=page=1&name='李四'
query_params._mutable = True #query_params['page']默认是不可以修改的 pager = Pagination(
current_page=request.GET.get('page'),
all_count=all_count,
base_url=request.path_info,
query_params=query_params,
per_page=self.per_page_count,
)

✘  add_view

如图,    

为了能够在模板循环展示表单数据、错误信息等,我们得创建forms.ModelForm对象,然后把form对象传递过去。

但是每张表model_class所产生的form对象是不一样的,因此不同请求进来都得创建一个ModelForm,这样就太不方便了

解决:

 class DynamicModelForm(forms.ModelForm):
class Meta:
model = self.model_class 不把model表写死了,应该是动态的,即需要访问的model类
fields = "__all__"

在这基础下,封装成为一个方法,往后需要产生form对象时,代入model类,直接调用。

     model_form = False
def get_model_form(self):
if self.model_form: #预留勾子,拓展或者自定义定制覆盖即可
return self.model_form class DynamicModelForm(forms.ModelForm):
class Meta:
model = self.model_class
fields = "__all__" def __init__(self, *args, **kwargs):
super(DynamicModelForm, self).__init__(*args, **kwargs)
# 统一给ModelForm生成字段添加样式
for name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control' return DynamicModelForm

如果有需求想让form对象多一行确认密码,或者控制显示的行呢?

前者可以在子类重写ModelForm,而后者我们则需为form.save()预留勾子,方便拓展或重写覆盖。

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

实现save基操下,想到如果在点击添加按钮的时候,URL本身带有 /?page=1的参数下,执行添加操作后,理应返回原来页面的时候带回这个参数。

这里,简单地理一下。

1.在进入添加路由时,我们先把参数部分urlencode(),然后把数据作为键值"_filter"的value值,最后urlencode() 作为新的参数。

     def reverse_add_url(self,**kwargs):
name = "%s:%s" % (self.site.namespace, self.get_add_url_name) #stark:Web_customer_public_list
url = reverse(name,kwargs=kwargs) if not self.request.GET:
add_url = url
else:
param = self.request.GET.urlencode() # page=1 new_query_dict = QueryDict(mutable=True)
new_query_dict['_filter'] = param # <QueryDict: {'_filter': ['page=1']}> add_url = "%s?%s" % (url, new_query_dict.urlencode(())) return add_url

2.类似地,添加完后 redirect 回原来页面并带回参数

     def reverse_list_url(self,**kwargs):
name = "%s:%s" % (self.site.namespace, self.get_list_url_name)
url = reverse(name,kwargs=kwargs)
if not self.request.GET:
list_url = url
else:
param = self.request.GET.get('_filter')
# print(param) #page=1
if not param:
return redirect(url)
list_url = "%s?%s" % (url, param) return list_url

所有的铺垫下,添加视图方法基本完成。

     def add_view(self,request,*args,**kwargs):
"""
添加视图
:param request:
:return:
"""
model_form = self.get_model_form()
if request.method == 'GET':
form = model_form
return render(request, 'change.html', {'form': form}) form = model_form(data=request.POST)
if form.is_valid():
response = self.save(request,form,False,*args,**kwargs)
return response or redirect(self.reverse_list_url(**kwargs))
return render(request,'change.html',{'form':form})

✘  change_view

基本跟添加视图一样,只是form对象在表单默认显示数据

     def get_change_object(self, request, pk, *args, **kwargs):
return self.model_class.objects.filter(pk=pk).first() def change_view(self,request,pk,*args,**kwargs):
"""
编辑视图
:param request:
:param pk:
:return:
"""
checked_obj = self.get_change_object(request, pk, *args, **kwargs) if not checked_obj:
return render(request,'rbac\error.html') model_form = self.get_model_form()
if request.method == 'GET':
form = model_form(instance=checked_obj)
return render(request, 'change.html', {'form': form}) form = model_form(data=request.POST,instance=checked_obj)
if form.is_valid():
response = self.save(request, form, True, *args, **kwargs)
return response or redirect(self.reverse_list_url(**kwargs))
return render(request, 'change.html', {'form': form})

✘  delete_view

基本跟添加视图一样。

这里继承以往为了防止用户删除数据时小手一抖,做出的确认选择按钮

     def delete_object(self, request, pk, *args, **kwargs):
self.model_class.objects.filter(pk=pk).delete() def delete_view(self,request,pk,*args,**kwargs):
"""
删除视图
:param request:
:param pk:
:return:
"""
checked_obj = self.model_class.objects.filter(pk=pk).first()
if not checked_obj:
return render(request,'rbac\error.html',) list_url = self.reverse_list_url(**kwargs)
if request.method == 'GET':
return render(request,'delete.html',{'list_url':list_url}) response = self.delete_object(request, pk, *args, **kwargs)
return response or redirect(list_url)

stark - 4 ⇲ 视图函数的更多相关文章

  1. stark组件开发之提取公共视图函数

     路由问题, 已经解决! 然后就是视图函数的问题了: 不想重复写的解决途径就是, python  类的继承了! 写一个基类, 基类定义 增删改查. 然后其他的,全部去继承他! from django. ...

  2. stark组件(2):提取公共视图函数、URL分发和设置别名

    效果图: Handler类里处理的增删改查.路由分发.给URL设置别名等包括以后还要添加的很多功能,每一个数据库的类都需要,所以我们要把Handler提取成一个基类.提取成基类后,每一个数据表都可以继 ...

  3. Django视图函数

    一.视图函数 1. 视图函数的第一个参数一定是一个HTTPRequest类型的对象,这个对象是Django自动创建的,具体形参名通常用request.通过这个对象,可以调用请求的一些参数,比如requ ...

  4. Django创建模板、URL模式、创建视图函数

    1.在应用目录下创建模板(templates目录) 在模板目录下创建archive.html <!DOCTYPE html> <html lang="en"> ...

  5. Flask04 后台获取请求数据、视图函数返回类型、前台接受响应数据

    1 后台获取请求数据 1.1 提出问题 前台发送请求的方式有哪些 后台如何获取这些请求的参数 1.2 前台发送请求的方式 GET.POST.AJAX 点睛:如果不指定请求方式,浏览器默认使用GET请求 ...

  6. Django创建通用视图函数

    想在我们有两个视图: def thinkingview(request): user = request.user if request.method == 'GET': return render( ...

  7. Django - - - -视图层之视图函数(views)

    视图层之视图函数(views) 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档 ...

  8. python web框架篇:views视图函数

    Django请求的生命周期是怎样的? 简单地说,通过URL对应关系匹配 ->找到对应的函数(或者类)->返回字符串(或者读取Html之后返回渲染的字符串) 解剖起来如下: 1. 当用户在浏 ...

  9. flask 视图函数的使用

    flask框架 视图函数当中 各种实用情况简单配置 1 建立连接 2 路由参数 3 返回网络状态码 4 自定义错误页面 5 重定向 6 正则url限制 和 url 优化 7 设置和获取cookie # ...

随机推荐

  1. [Selenium]通过JavaScript来对隐藏的元素执行操作

    对不可见元素进行操作时,如果通过普通的方式不可行,可以尝试用Javascript Scroll hidden element into view ((JavascriptExecutor) drive ...

  2. 全球顶尖大学的UX课程资源,英文!

    本文由MOCKPLUS团队原创,转载请标明出处,原型设计工具就用更快.更简单的mockplus 要想成为一名优秀的UX设计师,需要掌握很多必备技能.比如,掌握用户体验设计的所有知识和信息架构(易用性方 ...

  3. xcconfig

    [xcconfig] 1.When you can use a .xcconfig file? Use .xcconfig files if you find yourself changing th ...

  4. Text Relatives

    [Text Relatives] With TextKit the resources at your disposal range from framework objects—such as te ...

  5. java 内存 线程 类 vm分析工具

    JMeter.Jconsole.JVMStat

  6. 3D 相关

    1. STL 2. AMF 3. X3D 网址: http://www.web3d.org/x3d-resources/content/examples/X3dResources.html

  7. C++中的关键知识点(汇总)

    1. class的virtual 与non-virtual的区别 (1)virtual 函数时动态绑定,而non-virtual是静态绑定,前者是多态效果. (2)多态类的析构函数应该为virtual ...

  8. Centos 7 安装记录

    0.安装中选择最小安装 1.centos7安装图形界面 之前转载过一篇“centos6安装图形界面”的文章,地址见http://my.oschina.net/u/1169607/blog/335304 ...

  9. Jquery 记一次使用fullcalendar的使用记录

    最近接了一个需求,把excel做的表格开发到系统里,本来想直接做成表格的形式,后来考虑到数据库中的表结构不好设计,最后决定做成日历的形式: 先上成品图 需要引用的js,fullcalendar官网可以 ...

  10. 使用Base64进行string的加密和解密

    //字符串转bytes var ebytes = System.Text.Encoding.Default.GetBytes(keyWord); //bytes进行base64加密 var strBa ...