添加:html
需求: 根据用户的权限, 决定是否,有添加按钮。 经过配置进行定制,预留钩子进行权限的判断。前端
class StartHandler(object): ..................... has_add_btn = True # 指定配置,默认显示。 用户在子类中,自定制是否显示 def get_add_btn(self): '''预留钩子,子类中重写该方法。 根据权限的判断是否显示添加按钮''' if self.has_add_btn: return "<a class='btn btn-primary'>添加</a>" return None def check_list_view(self, request, *args, **kwargs): # ################6. 处理添加按钮###################### add_btn = self.get_add_btn() return render(request, "stark/changelist.html", {"header_list": header_list, "data_list": data_list, "body_list": body_list, "pager": pager, "add_btn": add_btn, "search_list": search_list, "search_value": search_value, "action_dict": action_dict}) ..................
class UserInfoHandler(StartHandler): list_display = ["name", "age", "depart", get_choice_txt("性别", "gender"), StartHandler.display_edit, StartHandler.display_del] has_add_btn = True # False就表示, 不显示添加按钮
get_add_btn(self): # 能够进行重写。 权限的判断,或者,重写样式python
pass数据库
若是感受,默认的样式很差看!
能够在, 子类中, 重写get_add_btn() 方法。 返回一个,本身喜欢的样式的 a 标签。 就好了!django
而后,就是这个 a 标签的, 路有问题了! 而且还要,携带上,本次请求的 GET 的数据。
老套路: 自定义一个反向解析的,函数:闭包
def reverse_url(self): '''用于反向生成url, 而且携带,get请求的参数,跳转到下一个网页''' name = "%s:%s" % (self.site.namespace, self.get_add_url_name) base_url = reverse(name) # 记录原搜索条件 if not self.request.GET: add_url = base_url else: param = self.request.GET.urlencode() # 获取到GET请求的,全部的参数。 ?page=1&age=20 new_query_dict = QueryDict(mutable=True) new_query_dict["_filter"] = param add_url = "%s?%s" % (base_url, new_query_dict.urlencode()) return add_url
这里最重要的一个就是, self.request 这个东西, 是从前端传过来的, 我在初始化函数里面,定义了一下。 可是 他从哪里传给个人初始化函数呢? 就是在,获取 URL 的时候。app
def wrapper(self, func): @functools.wraps(func) # 保留原函数的 原信息 def inner(request, *args, **kwargs): # 这个inner 就是,个人每个视图函数了! self.request = request return func(request, *args, **kwargs) return inner def get_urls(self): partterns = [ re_path(r"list/$", self.wrapper(self.check_list_view), name=self.get_list_url_name), re_path(r"add/$", self.wrapper(self.add_view), name=self.get_add_url_name), re_path(r"change/(\d+)/$", self.wrapper(self.change_view), name=self.get_edit_url_name), re_path(r"del/(\d+)/$", self.wrapper(self.delete_view), name=self.get_del_url_name), ]
为了不麻烦, 使用了 闭包的方式。来作这件事!
解释一下:函数
def wrapper(self, func): @functools.wraps(func) # 保留原函数的 原信息 def inner(request, *args, **kwargs): # 这个inner 就是,个人每个视图函数了! self.request = request return func(request, *args, **kwargs) return inner
self.wrapper(self.check_list_view) 这个函数的工做其实就是: 从新赋值。 装饰器的套路
self.check_list_view = self.wrapper(self.check_list_view) # self.check_list_view == inner 能够这么理解
self.wrapper的返回值是 inner 函数的内存地址。因此其实执行 self.check_list_view 就至关于执行的是 inner。
re_path() 这个django内部的函数。 认为 self.wrapper(self.check_list_view) 是一个视图函数。 因此会给他带上一个 request 的参数。
注:self.wrapper(self.check_list_view) 这个一位加了 括号, 因此会先执行。并返回 inner。 而re_path 认为inner 就是视图函数。url
因此我才可以在 inner 这个函数这里, 直接收到这个 request 。 而后我就将他 赋值给了, __init__ 初始化函数中的。 self.request = Nonespa
这样这参数,就再也不是 None 而是一个,带着从前端返回的,带有参数的 request 对象。
我就能够,在程序的, 其余地方。 使用这个参数。
总体结构,就是这样:
def get_add_btn(self): '''预留钩子,子类中重写该方法。 根据权限的判断是否显示添加按钮''' if self.has_add_btn: # 根据别名反向生成, URL add_url = self.reverse_url() return "<a class='btn btn-primary' href='%s'>添加</a>" % add_url return None def reverse_url(self): '''用于反向生成url, 而且携带,get请求的参数,跳转到下一个网页''' name = "%s:%s" % (self.site.namespace, self.get_add_url_name) base_url = reverse(name) # 记录原搜索条件 if not self.request.GET: add_url = base_url else: param = self.request.GET.urlencode() # 获取到GET请求的,全部的参数。 ?page=1&age=20 new_query_dict = QueryDict(mutable=True) new_query_dict["_filter"] = param add_url = "%s?%s" % (base_url, new_query_dict.urlencode()) return add_url per_page = 10 # 默认每页显示,多少数据。 也可在子类中,自行定制 def check_list_view(self, request): ''' 列表查看页面 :param request: :return: ''' # self.request = request # 进入查看页面,为request赋值! 使其余地方能够用到! list_display = self.get_list_display() # 页面要显示的列 self.list_display 示例:['name', 'age', 'depart'] # 1. 制做表头, 就是每张表中,每一个字段写的 verbose_name.。 如何获取到这个值呢? # self.model_class._meta.get_field('name').verbose_name header_list = [] # 表头 if list_display: for key_or_func in list_display: if isinstance(key_or_func, FunctionType): # 判断当前参数, 是一个字符串仍是一个函数。 verbose_name = key_or_func(self, obj=None, is_header=True) else: verbose_name = self.model_class._meta.get_field(key_or_func).verbose_name header_list.append(verbose_name) else: header_list.append(self.model_class._meta.model_name) # 2. 处理 从数据库 取到的数据 # 用户访问的表 self.model_class # 2.1 ###############处理分页################# '''1.根据用户访问页面,计算出索引的位置, 好比 page=3 2. 生成html页码 ''' all_count = self.model_class.objects.all().count() query_params = request.GET.copy() # page=1&level=2 query_params._mutable = True # request.get中的值默认是不能被修改的。加上这句代码就能够修改了 pager = Pagination( current_page=request.GET.get("page"), # 用户访问的当前叶 all_count=all_count, # 数据库一共有多少数据 base_url=request.path_info, # 所在的url 就是 ?page=1 以前的URL # 用于保留,用户的请求信息,好比 level=2 被用户先选中。 那么分页后。由于查询的东西少了,分页也应该想要的减小, # 可是level=2这个, 请求的信息!不能由于。分页的缘由。而减小。 query_params=query_params, per_page=self.per_page, # 每页显示多少数据。 ) # 2.1 ###############处理表格################# data_list = self.model_class.objects.all()[pager.start:pager.end] body_list = [] for row in data_list: row_list = [] if list_display: for key_or_func in list_display: if isinstance(key_or_func, FunctionType): # 这里is_header=False obj=row(数据库中循环的每一行的对象) row_list.append(key_or_func(self, obj=row, is_header=False)) else: row_list.append(getattr(row, key_or_func)) else: row_list.append(row) body_list.append(row_list) # 3 ############# 处理添加按钮#################### add_btn = self.get_add_btn() # 在这里调用了!此方法! return render(request, "stark/changelist.html", {"header_list": header_list, "data_list": data_list, "body_list": body_list, "pager": pager, "add_btn": add_btn})