项目一:CRM(客户关系管理系统)--7--添加页面(增加一条新数据)

添加功能在前面的编辑基础上继承,相对来说就简单太多,没有太多的修改。

1. 添加–创建页面

1.1 创建页面路由

1 urlpatterns = [
2     url(r'^$', views.index, name='table_index'),
3     url(r'^(\w+)/(\w+)/$', views.display_objects, name='display_objects'),
4     url(r'^(\w+)/(\w+)/(\d+)/edit/$', views.table_object_edit,name="table_object_edit"),
5     url(r'^(\w+)/(\w+)/add/$', views.table_object_add,name="table_object_add"),#添加页面的路由
6 ]

 

1.2 创建页面模板文件

templates/king_admin/目录下创建模板文件:table_object_add.html,并继承编辑文件内容:

1 {% extends 'king_admin/table_object_edit.html' %}
2  
3 {% block top %}
4   <div class="panel-heading">
5     <button  class="btn btn-success pull-right" ><a href="{% url 'king_admin:display_objects' app_name table_name %}" style="color: white">返回</a></button>
6   </div>
7 {% endblock %}

上面的块内容包含的是返回键按钮。

1.3 创建页面视图函数

添加功能的视图函数和编辑页面基本上是大同小异:

 1 def table_object_add(request, app_name, table_name):
 2     admin_class = site.enabled_admins[app_name][table_name]
 3     model_form = create_model_form(request, admin_class)
 4  
 5     if request.method == 'POST':
 6         form_object = model_form(request.POST)
 7         if form_object.is_valid():
 8             form_object.save()
 9             return redirect('/king_admin/{app_name}/{table_name}'.format(app_name = app_name,
10                                                                          table_name = table_name))
11     else:
12         form_object = model_form()
13  
14     return render(request, 'king_admin/table_object_add.html', {'admin_class': admin_class,
15                                                                 'form_object': form_object,
16                                                                 "app_name": app_name,
17                                                                 "table_name": table_name})

其中的redirect()比较关键,添加后返回的url

这里有一个错误会产生,原因是动态form:model_form在实例化的时候是None,而我们的添加新数据页面是继承table_object_change.html页面的,该页面用到了form_object.instance方法,会报一下错误:

需要修改tags.py文件,

  1 from django import template
  2 from django.utils.safestring import mark_safe
  3 from kingadmin.utils import filters_to_text
  4 
  5 register = template.Library()
  6 
  7 
  8 @register.simple_tag
  9 def table_verbose_name(admin_class):
 10     return admin_class.model._meta.verbose_name
 11 
 12 
 13 @register.simple_tag
 14 def create_page_num(contacts, ordering, _q, filter_text):
 15     """
 16     返回分页按钮的html方式
 17     :param contacts: Paginator.page(num)
 18     :return:
 19     """
 20     page_num_html = ''
 21     dot_sign = False
 22     for number in contacts.paginator.page_range:
 23         btn_element = """<li class="{0}"><a href="?page={1}&o={2}&_q={3}&{4}">{5}</a></li>"""
 24         li_class = ''
 25         if number < 3 \
 26                 or number > contacts.paginator.num_pages - 2 \
 27                 or abs(number - contacts.number) <= 2:  # 前三页,后2页,当前页的前后2页
 28             if number == contacts.number:  # 页码等于当前页
 29                 li_class = "active"
 30             dot_sign = False
 31             page_num_html += btn_element.format(li_class, number, ordering, _q, filter_text, number)
 32         else:
 33             if not dot_sign:
 34                 page_num_html += '<li><a>...</a></li>'
 35                 dot_sign = True
 36     return mark_safe(page_num_html)
 37     # for number in contacts.paginator.page_range:
 38     #     if number < 3 or number > contacts.paginator.num_pages - 2 or abs(contacts.number - number) <= 2:      # 前两页或最后两页 #}
 39     #         if number == contacts.number:
 40     #             page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number, number)
 41     #             dot_sign = False
 42     #         else:
 43     #             dot_sign = False
 44     #             page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 45     #     elif contacts.paginator.num_pages < 7:      # 总页数为6,直接显示页码
 46     #         dot_sign = False
 47     #         page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 48     #     elif contacts.paginator.num_pages >= 7:      # 7页以上
 49     #         temp = contacts.paginator.num_pages / 2
 50     #         if type(temp) is int:     # 能整除,偶数页,显示中间四页
 51     #             if temp - 1 <= number <= temp + 2:     # 中间四页
 52     #                 if number == contacts.number:       # 判断当前页
 53     #                     page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number,
 54     #                                                                                                        number)
 55     #                     dot_sign = False
 56     #                 else:
 57     #                     dot_sign = False
 58     #                     page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 59     #             else:                               # 非中间四页
 60     #                 page_num_html += """<li><a href="#">...</a></li>"""
 61     #         else:                   # 不能整除,奇数页,显示中间三页
 62     #             if int(temp) <= number <= temp + 2:   # 中间三页
 63     #                 if number == contacts.number:
 64     #                     page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number,
 65     #                                                                                                        number)
 66     #                     dot_sign = False
 67     #                 else:
 68     #                     dot_sign = False
 69     #                     page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 70     #             else:                               # 非中间三页
 71     #                 if not dot_sign:
 72     #                     page_num_html += """<li><a href="#">...</a></li>"""
 73     #                     dot_sign = True
 74     # return mark_safe(page_num_html)
 75 
 76 
 77 @register.simple_tag
 78 def field_verbose_name(filter_condition, admin_class, filter_conditions_customer):
 79     """
 80     返回表中的字段的verbose_name,取代英文
 81     :param filter_condition: string
 82     :param admin_class: class
 83     :return:
 84     """
 85     if hasattr(admin_class.model, filter_condition):
 86         field_class = admin_class.model._meta.get_field(filter_condition)
 87         name = field_class.verbose_name
 88         choices = field_class.choices
 89         selected_value = ''
 90         label_html = """<label for={0}>{1}</label>""".format(field_class.name, name)  # label content
 91         select_html = """<select class="form-control" id="{0}" name="{1}">""".format(field_class.name, field_class.name)
 92         # '<option>1</option></select>'                                 # select content
 93 
 94         # selected
 95         if field_class.name in filter_conditions_customer:
 96             selected_value = filter_conditions_customer[field_class.name]
 97 
 98         if choices or type(field_class).__name__ == 'ForeignKey':  # 外键
 99             for item in field_class.get_choices():
100                 if str(item[0]) == selected_value:
101                     select_html += """<option value={0} selected>{1}</option>""".format(item[0], item[1])
102                 else:
103                     select_html += """<option value={0}>{1}</option>""".format(item[0], item[1])
104         select_html += '</select>'
105         group_html = label_html + select_html
106 
107         return mark_safe(group_html)
108     else:
109         return 'there is no %s' % filter_condition
110 
111 
112 @register.simple_tag
113 def ret_field_value(request, query_set, fields_name, page, order, filter_conditions_customer, search_text):
114     """
115     返回admin_class中list_display包含字段对应的一行数据,并组装成html格式
116     :param request:
117     :param query_set: class instanceme
118     :param fields_name:
119     :param page:
120     :param order:
121     :param filter_conditions_customer:
122     :param search_text:
123     :return:
124     """
125     row_data = ''
126     filter_text = filters_to_text(filter_conditions_customer)
127     for k, field_name in enumerate(fields_name):
128         # options的数据类型如下:
129         # ((0, '转介绍'),
130         #  (1, 'QQ群'),
131         #  (2, '官网'),
132         #  (3, '百度推广'),
133         #  (4, '51CTO'),
134         #  (5, '知乎'),
135         #  (6, '市场部推广'))
136         # """<th><span><input type="checkbox"></span></th>"""
137         field_type = query_set._meta.get_field(field_name)
138         options = field_type.choices
139         option_value = getattr(query_set, field_name)
140         if options:  # 处理多选字段,即choices属性不为空
141             option_means = [item for item in options if item[0] == option_value][0][1]
142             unit_data = '<td>{0}</td>'.format(option_means)
143         elif type(option_value).__name__ == 'datetime':  # 处理时间格式
144             option_value = option_value.strftime("%Y-%m-%d %H:%M:%S")
145             unit_data = '<td>{0}</td>'.format(option_value)
146         elif k == 0:
147             unit_data = '<td><a href="{0}/{1}/edit?page={2}&o={3}&_q={4}&{5}">{6}</a></td>'.format(
148                 request.path,
149                 query_set.id,
150                 page,
151                 order,
152                 search_text,
153                 filter_text,
154                 option_value,
155             )
156         elif type(field_type).__name__ == 'ManyToManyField':        # 处理多对多字段
157             field_values = getattr(query_set, field_name).all()
158             temp = ''
159             for k, v in enumerate(field_values):
160                 temp += v.name + ','
161             temp = temp.rstrip(',')
162             unit_data = '<td>{0}</td>'.format(temp)
163         else:
164             unit_data = '<td>{0}</td>'.format(option_value)
165         row_data += unit_data
166     row_data = '<tr><td><span><input type="checkbox" tag="object_checkbox" value="{0}"></span></td>{1}</tr>'.format(
167         query_set.id,
168         row_data
169     )
170     return mark_safe(row_data)
171 
172 
173 @register.simple_tag
174 def ret_getattr(query_set, field_name):
175     return hasattr(query_set, field_name)
176 
177 
178 @register.simple_tag
179 def create_row(query_set_obj, admin_class):
180     element = ''
181     for row in admin_class.list_display:
182 
183         field_obj = admin_class.model._meta.get_field(row)
184         if field_obj.choices:
185             row_data = getattr(query_set_obj, 'get_{0}_display'.format(row))()
186         else:
187             row_data = getattr(query_set_obj, row)
188         if type(row_data).__name__ == 'datetime':
189             row_data = row_data.strftime('%Y-%m-%d %H:%M:%S')
190 
191         element += "<td>{0}</td>".format(row_data)
192     return mark_safe(element)
193 
194 
195 @register.simple_tag
196 def create_page_element(page, filter_conditions):
197     page_btns = ''
198     filters = ''
199     for k, v in filter_conditions.items():
200         filters += '&{0}={1}'.format(k, v)
201     add_dot_ele = False  # 标志符
202     for page_num in page.paginator.page_range:  # query_set.paginator.page_range: range(1,n),分的总页数,
203         # page_num:每页的页码
204         # query_set.paginator.num_pages: 一共分了多少页
205         # query_set.number: 页对应的页码
206         if page_num < 3 or \
207                 page_num > page.paginator.num_pages - 2 or \
208                 abs(page.number - page_num) <= 2:  # 代表最前2页或最后2页 #abs判断前后1页
209             element_class = ""
210             if page.number == page_num:
211                 add_dot_ele = False
212                 element_class = "active"
213             page_btns += '''<li class="%s"><a href="?page=%s%s">%s</a></li>''' % (element_class,
214                                                                                   page_num,
215                                                                                   filters,
216                                                                                   page_num)
217         else:
218             if not add_dot_ele:
219                 page_btns += '<li><a href="#">...</a></li>'
220                 add_dot_ele = True
221 
222     return mark_safe(page_btns)
223 
224 
225 @register.simple_tag
226 def render_filter_element(condition, admin_class, filter_conditions):
227     '''
228 
229     :param condition: 字符串, list_filter中的一个
230     :param admin_class: 数据库中的数据表类
231     :param filter_conditions: 字典,key=list_filter中的一个, value=前端传回的对应的option的value值
232     :return:
233     '''
234     # 初始化下拉框
235     select_element = """<select class='form-control' name={0}><option value=''>------
236                                                                         </option>""".format(condition)
237     field_object = admin_class.model._meta.get_field(condition)  # 获取字段, admin_class中的字段
238     # 字段处理, 默认不选中
239     selected = ''  # choice处理
240     if field_object.choices:  # 遍历choices值
241         for choice_item in field_object.get_choices()[1:]:
242             # print(choice_item)
243             # 判断选择条件是否和choice值相等,
244             if filter_conditions.get(condition) == str(choice_item[0]):
245                 # 被选中
246                 selected = 'selected'
247             select_element += """<option value='{0}' {1}>{2}</option>""".format(choice_item[0],
248                                                                                 selected, choice_item[1])
249             selected = ''
250     # 外键处理
251     if type(field_object).__name__ == 'ForeignKey':
252         for choice_item in field_object.get_choices()[1:]:
253             # 判断选择条件是否和choice值相等
254             if filter_conditions.get(condition) == str(choice_item[0]):
255                 # 被选中
256                 selected = 'selected'
257             select_element += """<option value='{0}' {1}>{2}</option>""".format(choice_item[0],
258                                                                                 selected, choice_item[1])
259             selected = ''
260     select_element += '</select>'
261     return mark_safe(select_element)
262 
263 
264 @register.simple_tag
265 def ret_search_help(admin_class):
266     help_info = ''
267     if admin_class.search_fields:
268         # help_info += '搜索:'
269         for item in admin_class.search_fields:
270             help_info += item + ''
271     else:
272         help_info += '未定义搜索字段'
273 
274     return help_info
275 
276 
277 @register.simple_tag
278 def create_table_title(fields, order_after, filter_conditions_customer, search_text):
279     """
280 
281     :param fields:
282     :param order_after:
283     :param filter_conditions_customer:
284     :return:
285     """
286     # """<th><span><input type="checkbox"></span>"""
287     # """<a href="?o={{ field.name }} style="display:block;font-size:14px;">{{ field.verbose_name }}</a>"""
288     # 添加一列checkbox
289     ele_checkbox = """<th><span><input type="checkbox" id="test" οnclick="select_all_checkbox(this);"></span></th>"""
290     # filter_text
291     filter_text = ''
292     for k, v in filter_conditions_customer.items():
293         temp = k + '=' + v
294         filter_text += temp + '&'
295     filter_text = filter_text.rstrip('&')
296     # 添加title
297     ele_title = ''
298     # 设置标题的href
299     for field in fields:
300         temp = order_after.lstrip('-')
301         if temp == field.name:
302             ele_title += """<th><a href="?{0}&o={1}&_q={2}">{3}</a></th>""".format(
303                 filter_text,
304                 order_after,
305                 search_text,
306                 field.verbose_name
307             )
308         else:
309             ele_title += """<th><a href="?{0}&o={1}&_q={2}">{3}</a></th>""".format(
310                 filter_text,
311                 field.name,
312                 search_text,
313                 field.verbose_name
314             )
315     table_title = ele_checkbox + ele_title
316     return mark_safe(table_title)
317 
318 
319 @register.simple_tag
320 def get_horizontal_tag_values(field, admin_class, form_object):
321     field_obj = getattr(admin_class.model, field.name)
322     query_sets_all = field_obj.rel.to.objects.all()
323     try:            # 在添加页面时,form_object是空实例,获取tags字段数据的时候会报错
324         instance_field = getattr(form_object.instance, field.name)
325     except ValueError as e:
326         print(e)
327         return query_sets_all
328     else:
329         query_sets_select = instance_field.all()
330         diff_query_sets = query_sets_all.difference(query_sets_select)
331         return diff_query_sets
332 
333 
334 @register.simple_tag
335 def get_horizontal_field_value(field, form_object):
336     try:            # 在添加页面时,form_object是空实例,获取tags字段数据的时候会报错
337         field_obj = getattr(form_object.instance, field.name)
338     except ValueError as e:
339         print(e)
340         return None
341     else:
342         selected_list = field_obj.all()
343         return selected_list

后台打印的错误信息如下:

/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/pp/Documents/workplace/pycharm/51cto/ProjectCRM/manage.py runserver 8000
Performing system checks...

System check identified no issues (0 silenced).
January 27, 2018 - 00:49:49
Django version 1.11.7, using settings 'ProjectCRM.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
"<CustomerInfo: QQ: -- Name:None>" needs to have a value for field "id" before this many-to-many relationship can be used.
"<CustomerInfo: QQ: -- Name:None>" needs to have a value for field "id" before this many-to-many relationship can be used.
[27/Jan/2018 00:49:57] "GET /kingadmin/CRM/customerinfo/add HTTP/1.1" 200 15589

这个暂时没有想到更好的解决办法,只能先通过这种方式进行解决。

如果有更好的方法,后续进行更新,有知道的也可以指点一下,非常感谢。

最后效果如下:

 

 

 

讨论:

其实在这个添加页面还有个问题没有解决:从table_list.html(列出所有表中的数据)跳转到table_object_add.html过程中,页码、检索、排序、搜索等自定义操作的数据没有一起传递,当数据添加完成后,再返回的时候这些数据是丢失掉的,如果想要完整返回添加前的状态,需要将这些数据一起传递。

这里的矛盾是其实添加页面根本用不到这些数据,而且地址栏中的过多参数会导致一些url地址过长,很多参数也是暴露出来的,如何解决简单、有效的解决这两个问题?!

解决思路: 

1.通过http协议头中的refer字段。

request.MEAT.keys()共有以下字段:

1 dict_keys(['PATH', 'PYTHONPATH', 'SHELL', 'LSCOLORS', 'PYTHONIOENCODING', 
'SECURITYSESSIONID', 'CLICOLOR', 'USER', 'TMPDIR', 'SSH_AUTH_SOCK', 'DJANGO_SETTINGS_MODULE',
'XPC_FLAGS', 'PYTHONUNBUFFERED', '__CF_USER_TEXT_ENCODING', 'Apple_PubSub_Socket_Render',
'LS_OPTIONS', 'LOGNAME', 'LC_CTYPE', 'XPC_SERVICE_NAME', 'PWD', 'PYCHARM_HOSTED', 'HOME',
'PYCHARM_MATPLOTLIB_PORT', '__PYVENV_LAUNCHER__', 'TZ', 'RUN_MAIN', 'SERVER_NAME',
'GATEWAY_INTERFACE', 'SERVER_PORT', 'REMOTE_HOST', 'CONTENT_LENGTH', 'SCRIPT_NAME',
'SERVER_PROTOCOL', 'SERVER_SOFTWARE', 'REQUEST_METHOD', 'PATH_INFO', 'QUERY_STRING',
'REMOTE_ADDR', 'CONTENT_TYPE', 'HTTP_HOST', 'HTTP_CONNECTION', 'HTTP_UPGRADE_INSECURE_REQUESTS',
'HTTP_USER_AGENT', 'HTTP_ACCEPT', 'HTTP_REFERER', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE',
'HTTP_COOKIE', 'wsgi.input', 'wsgi.errors', 'wsgi.version', 'wsgi.run_once', 'wsgi.url_scheme',
'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.file_wrapper', 'CSRF_COOKIE'])

很多头部都是http协议头,其中HTTP_REFERER就是我们要的,但是这个字段会带来另外一个问题,当你保存的时候,其实

是以POST方式提交给http://127.0.0.1:8000/kingadmin/CRM/customerinfo/add页面,HTTP_REFERER字段变成了

http://127.0.0.1:8000/kingadmin/CRM/customerinfo/add,而不是http://127.0.0.1:8000/kingadmin/CRM/customerinfo?&o=id&_q=,

而且有时,刷新add页面或者输入的信息有误的时候,都是重复提交到add页面,都会引起HTTP_REFERER值得改变,所以通过这种方法不是明智之举。

需要解决将第一次的HTTP_REFERER字段保存到全局变量中,以区分后面的访问造成的HTTP_REFERER值变动。

2. 将这些特定字段信息埋在前端页面table_list.html中,即“添加”这个超级链接中。

具体做法如下:

埋标签

 1 {% extends 'project/head.html' %}
 2 {% load tags %}
 3 {% block main %}
 4 
 5     <div class="container">
 6         <div class="row">
 7             <div class="panel panel-info">
 8                 <!-- Default panel contents -->
 9                 <div class="panel-heading">
10                     <span>{{ table_name }}</span>
11                     <a href="{% ret_add_url request page order_before filter_text search_text %}" class="pull-right">添加</a>
12                 </div>
13                 <div class="panel-body">
14                     <form class="form-inline" action="{% url 'table_list' app_name table_name %}"
15                           method="GET">
16                         {# 检索 #}
17                         <div class="form-group col-lg-9">
18                             {% for filter_condition in filter_conditions %}
19                                 {% field_verbose_name filter_condition admin_class filter_conditions_customer %}
20                             {% endfor %}
21                             <button type="submit" class="btn-success btn-xs">检索</button>
22                         </div>
23                         {# 搜索 #}
24                         <div class="form-group">
25                             <div class="input-group">
26                                 <input type="search" class="form-control"
27                                        placeholder="{% ret_search_help admin_class %}" name="_q"
28                                        value="{{ search_text }}" maxlength="100">
29                                 <span class="input-group-btn">
30                                     <button class="btn-success btn-xs" type="submit">搜索</button>
31                                 </span>
32                             </div>
33                         </div>
34                     </form>
35                 </div>
36                 <!-- Table 数据展示 -->
37                 <table class="table table-hover">
38                     <thead>
39                     <tr>
40                         {% create_table_title fields order_after filter_conditions_customer search_text %}
41                     </tr>
42                     </thead>
43                     <tbody>
44                     {% for query_set in contacts %}
45                         {% ret_field_value request query_set admin_class.list_display page order_before filter_conditions_customer search_text %}
46                     {% endfor %}
47                     </tbody>
48                 </table>
49                 {# 分页功能 #}
50                 <div class="panel-footer">
51                     <nav aria-label="...">
52                         <ul class="pagination">
53                             {# 上一页 #}
54                             {% if contacts.has_previous %}
55                                 <li>
56                                     <a href="?page={{ contacts.previous_page_number }}&o={{ order_before }}"
57                                        aria-label="Previous">
58                                         <span aria-hidden="true">上一页</span>
59                                     </a>
60                                 </li>
61                             {% else %}
62                                 <li class="disabled">
63                                     <a href="?page={{ contacts.number }}&o={{ order_before }}&_q={{ search_text }}&{{ filter_text }}" aria-label="Previous">
64                                         <span aria-hidden="true">上一页</span>
65                                     </a>
66                                 </li>
67                             {% endif %}
68                             {# 页码 #}
69                             {% create_page_num contacts order_before search_text filter_text %}
70                             {# 下一页 #}
71                             {% if contacts.has_next %}
72                                 <li>
73                                     <a href="?page={{ contacts.next_page_number }}&o={{ order_before }}&_q={{ search_text }}&{{ filter_text }}"
74                                        aria-label="Next">
75                                         <span aria-hidden="true">下一页</span></a>
76                                 </li>
77                             {% else %}
78                                 <li class="disabled">
79                                     <a href="?page={{ contacts.number }}&o={{ order_before }}&_q={{ search_text }}&{{ filter_text }}" aria-label="Next">
80                                         <span aria-hidden="true">下一页</span></a>
81                                 </li>
82                             {% endif %}
83                             <span id="data_sum">
84                                 总计:{{ contacts.paginator.count }}
85                             </span>
86                         </ul>
87                     </nav>
88                 </div>
89             </div>
90         </div>
91     </div>
92     {{ error }}
93 {% endblock %}

后端处理

  1 from django import template
  2 from django.utils.safestring import mark_safe
  3 from kingadmin.utils import filters_to_text
  4 
  5 register = template.Library()
  6 
  7 
  8 @register.simple_tag
  9 def table_verbose_name(admin_class):
 10     return admin_class.model._meta.verbose_name
 11 
 12 
 13 @register.simple_tag
 14 def create_page_num(contacts, ordering, _q, filter_text):
 15     """
 16     返回分页按钮的html方式
 17     :param contacts: Paginator.page(num)
 18     :return:
 19     """
 20     page_num_html = ''
 21     dot_sign = False
 22     for number in contacts.paginator.page_range:
 23         btn_element = """<li class="{0}"><a href="?page={1}&o={2}&_q={3}&{4}">{5}</a></li>"""
 24         li_class = ''
 25         if number < 3 \
 26                 or number > contacts.paginator.num_pages - 2 \
 27                 or abs(number - contacts.number) <= 2:  # 前三页,后2页,当前页的前后2页
 28             if number == contacts.number:  # 页码等于当前页
 29                 li_class = "active"
 30             dot_sign = False
 31             page_num_html += btn_element.format(li_class, number, ordering, _q, filter_text, number)
 32         else:
 33             if not dot_sign:
 34                 page_num_html += '<li><a>...</a></li>'
 35                 dot_sign = True
 36     return mark_safe(page_num_html)
 37     # for number in contacts.paginator.page_range:
 38     #     if number < 3 or number > contacts.paginator.num_pages - 2 or abs(contacts.number - number) <= 2:      # 前两页或最后两页 #}
 39     #         if number == contacts.number:
 40     #             page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number, number)
 41     #             dot_sign = False
 42     #         else:
 43     #             dot_sign = False
 44     #             page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 45     #     elif contacts.paginator.num_pages < 7:      # 总页数为6,直接显示页码
 46     #         dot_sign = False
 47     #         page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 48     #     elif contacts.paginator.num_pages >= 7:      # 7页以上
 49     #         temp = contacts.paginator.num_pages / 2
 50     #         if type(temp) is int:     # 能整除,偶数页,显示中间四页
 51     #             if temp - 1 <= number <= temp + 2:     # 中间四页
 52     #                 if number == contacts.number:       # 判断当前页
 53     #                     page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number,
 54     #                                                                                                        number)
 55     #                     dot_sign = False
 56     #                 else:
 57     #                     dot_sign = False
 58     #                     page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 59     #             else:                               # 非中间四页
 60     #                 page_num_html += """<li><a href="#">...</a></li>"""
 61     #         else:                   # 不能整除,奇数页,显示中间三页
 62     #             if int(temp) <= number <= temp + 2:   # 中间三页
 63     #                 if number == contacts.number:
 64     #                     page_num_html += """<li class ="active"><a href="?page={0}">{1}</a></li>""".format(number,
 65     #                                                                                                        number)
 66     #                     dot_sign = False
 67     #                 else:
 68     #                     dot_sign = False
 69     #                     page_num_html += """<li><a href="?page={0}">{1}</a></li>""".format(number, number)
 70     #             else:                               # 非中间三页
 71     #                 if not dot_sign:
 72     #                     page_num_html += """<li><a href="#">...</a></li>"""
 73     #                     dot_sign = True
 74     # return mark_safe(page_num_html)
 75 
 76 
 77 @register.simple_tag
 78 def field_verbose_name(filter_condition, admin_class, filter_conditions_customer):
 79     """
 80     返回表中的字段的verbose_name,取代英文
 81     :param filter_condition: string
 82     :param admin_class: class
 83     :return:
 84     """
 85     if hasattr(admin_class.model, filter_condition):
 86         field_class = admin_class.model._meta.get_field(filter_condition)
 87         name = field_class.verbose_name
 88         choices = field_class.choices
 89         selected_value = ''
 90         label_html = """<label for={0}>{1}</label>""".format(field_class.name, name)  # label content
 91         select_html = """<select class="form-control" id="{0}" name="{1}">""".format(field_class.name, field_class.name)
 92         # '<option>1</option></select>'                                 # select content
 93 
 94         # selected
 95         if field_class.name in filter_conditions_customer:
 96             selected_value = filter_conditions_customer[field_class.name]
 97 
 98         if choices or type(field_class).__name__ == 'ForeignKey':  # 外键
 99             for item in field_class.get_choices():
100                 if str(item[0]) == selected_value:
101                     select_html += """<option value={0} selected>{1}</option>""".format(item[0], item[1])
102                 else:
103                     select_html += """<option value={0}>{1}</option>""".format(item[0], item[1])
104         select_html += '</select>'
105         group_html = label_html + select_html
106 
107         return mark_safe(group_html)
108     else:
109         return 'there is no %s' % filter_condition
110 
111 
112 @register.simple_tag
113 def ret_field_value(request, query_set, fields_name, page, order, filter_conditions_customer, search_text):
114     """
115     返回admin_class中list_display包含字段对应的一行数据,并组装成html格式
116     :param request:
117     :param query_set: class instanceme
118     :param fields_name:
119     :param page:
120     :param order:
121     :param filter_conditions_customer:
122     :param search_text:
123     :return:
124     """
125     row_data = ''
126     filter_text = filters_to_text(filter_conditions_customer)
127     for k, field_name in enumerate(fields_name):
128         # options的数据类型如下:
129         # ((0, '转介绍'),
130         #  (1, 'QQ群'),
131         #  (2, '官网'),
132         #  (3, '百度推广'),
133         #  (4, '51CTO'),
134         #  (5, '知乎'),
135         #  (6, '市场部推广'))
136         # """<th><span><input type="checkbox"></span></th>"""
137         field_type = query_set._meta.get_field(field_name)
138         options = field_type.choices
139         option_value = getattr(query_set, field_name)
140         if options:  # 处理多选字段,即choices属性不为空
141             option_means = [item for item in options if item[0] == option_value][0][1]
142             unit_data = '<td>{0}</td>'.format(option_means)
143         elif type(option_value).__name__ == 'datetime':  # 处理时间格式
144             option_value = option_value.strftime("%Y-%m-%d %H:%M:%S")
145             unit_data = '<td>{0}</td>'.format(option_value)
146         elif k == 0:
147             unit_data = '<td><a href="{0}/{1}/edit?page={2}&o={3}&_q={4}&{5}">{6}</a></td>'.format(
148                 request.path,
149                 query_set.id,
150                 page,
151                 order,
152                 search_text,
153                 filter_text,
154                 option_value,
155             )
156         elif type(field_type).__name__ == 'ManyToManyField':        # 处理多对多字段
157             field_values = getattr(query_set, field_name).all()
158             temp = ''
159             for k, v in enumerate(field_values):
160                 temp += v.name + ','
161             temp = temp.rstrip(',')
162             unit_data = '<td>{0}</td>'.format(temp)
163         else:
164             unit_data = '<td>{0}</td>'.format(option_value)
165         row_data += unit_data
166     row_data = '<tr><td><span><input type="checkbox" tag="object_checkbox" value="{0}"></span></td>{1}</tr>'.format(
167         query_set.id,
168         row_data
169     )
170     return mark_safe(row_data)
171 
172 
173 @register.simple_tag
174 def ret_getattr(query_set, field_name):
175     return hasattr(query_set, field_name)
176 
177 
178 @register.simple_tag
179 def create_row(query_set_obj, admin_class):
180     element = ''
181     for row in admin_class.list_display:
182 
183         field_obj = admin_class.model._meta.get_field(row)
184         if field_obj.choices:
185             row_data = getattr(query_set_obj, 'get_{0}_display'.format(row))()
186         else:
187             row_data = getattr(query_set_obj, row)
188         if type(row_data).__name__ == 'datetime':
189             row_data = row_data.strftime('%Y-%m-%d %H:%M:%S')
190 
191         element += "<td>{0}</td>".format(row_data)
192     return mark_safe(element)
193 
194 
195 @register.simple_tag
196 def create_page_element(page, filter_conditions):
197     page_btns = ''
198     filters = ''
199     for k, v in filter_conditions.items():
200         filters += '&{0}={1}'.format(k, v)
201     add_dot_ele = False  # 标志符
202     for page_num in page.paginator.page_range:  # query_set.paginator.page_range: range(1,n),分的总页数,
203         # page_num:每页的页码
204         # query_set.paginator.num_pages: 一共分了多少页
205         # query_set.number: 页对应的页码
206         if page_num < 3 or \
207                 page_num > page.paginator.num_pages - 2 or \
208                 abs(page.number - page_num) <= 2:  # 代表最前2页或最后2页 #abs判断前后1页
209             element_class = ""
210             if page.number == page_num:
211                 add_dot_ele = False
212                 element_class = "active"
213             page_btns += '''<li class="%s"><a href="?page=%s%s">%s</a></li>''' % (element_class,
214                                                                                   page_num,
215                                                                                   filters,
216                                                                                   page_num)
217         else:
218             if not add_dot_ele:
219                 page_btns += '<li><a href="#">...</a></li>'
220                 add_dot_ele = True
221 
222     return mark_safe(page_btns)
223 
224 
225 @register.simple_tag
226 def render_filter_element(condition, admin_class, filter_conditions):
227     '''
228 
229     :param condition: 字符串, list_filter中的一个
230     :param admin_class: 数据库中的数据表类
231     :param filter_conditions: 字典,key=list_filter中的一个, value=前端传回的对应的option的value值
232     :return:
233     '''
234     # 初始化下拉框
235     select_element = """<select class='form-control' name={0}><option value=''>------
236                                                                         </option>""".format(condition)
237     field_object = admin_class.model._meta.get_field(condition)  # 获取字段, admin_class中的字段
238     # 字段处理, 默认不选中
239     selected = ''  # choice处理
240     if field_object.choices:  # 遍历choices值
241         for choice_item in field_object.get_choices()[1:]:
242             # print(choice_item)
243             # 判断选择条件是否和choice值相等,
244             if filter_conditions.get(condition) == str(choice_item[0]):
245                 # 被选中
246                 selected = 'selected'
247             select_element += """<option value='{0}' {1}>{2}</option>""".format(choice_item[0],
248                                                                                 selected, choice_item[1])
249             selected = ''
250     # 外键处理
251     if type(field_object).__name__ == 'ForeignKey':
252         for choice_item in field_object.get_choices()[1:]:
253             # 判断选择条件是否和choice值相等
254             if filter_conditions.get(condition) == str(choice_item[0]):
255                 # 被选中
256                 selected = 'selected'
257             select_element += """<option value='{0}' {1}>{2}</option>""".format(choice_item[0],
258                                                                                 selected, choice_item[1])
259             selected = ''
260     select_element += '</select>'
261     return mark_safe(select_element)
262 
263 
264 @register.simple_tag
265 def ret_search_help(admin_class):
266     help_info = ''
267     if admin_class.search_fields:
268         # help_info += '搜索:'
269         for item in admin_class.search_fields:
270             help_info += item + ''
271     else:
272         help_info += '未定义搜索字段'
273 
274     return help_info
275 
276 
277 @register.simple_tag
278 def create_table_title(fields, order_after, filter_conditions_customer, search_text):
279     """
280 
281     :param fields:
282     :param order_after:
283     :param filter_conditions_customer:
284     :return:
285     """
286     # """<th><span><input type="checkbox"></span>"""
287     # """<a href="?o={{ field.name }} style="display:block;font-size:14px;">{{ field.verbose_name }}</a>"""
288     # 添加一列checkbox
289     ele_checkbox = """<th><span><input type="checkbox" id="test" οnclick="select_all_checkbox(this);"></span></th>"""
290     # filter_text
291     filter_text = ''
292     for k, v in filter_conditions_customer.items():
293         temp = k + '=' + v
294         filter_text += temp + '&'
295     filter_text = filter_text.rstrip('&')
296     # 添加title
297     ele_title = ''
298     # 设置标题的href
299     for field in fields:
300         temp = order_after.lstrip('-')
301         if temp == field.name:
302             ele_title += """<th><a href="?{0}&o={1}&_q={2}">{3}</a></th>""".format(
303                 filter_text,
304                 order_after,
305                 search_text,
306                 field.verbose_name
307             )
308         else:
309             ele_title += """<th><a href="?{0}&o={1}&_q={2}">{3}</a></th>""".format(
310                 filter_text,
311                 field.name,
312                 search_text,
313                 field.verbose_name
314             )
315     table_title = ele_checkbox + ele_title
316     return mark_safe(table_title)
317 
318 
319 @register.simple_tag
320 def get_horizontal_tag_values(field, admin_class, form_object):
321     field_obj = getattr(admin_class.model, field.name)
322     query_sets_all = field_obj.rel.to.objects.all()
323     try:            # 在添加页面时,form_object是空实例,获取tags字段数据的时候会报错
324         instance_field = getattr(form_object.instance, field.name)
325     except ValueError as e:
326         print(e)
327         return query_sets_all
328     else:
329         query_sets_select = instance_field.all()
330         diff_query_sets = query_sets_all.difference(query_sets_select)
331         return diff_query_sets
332 
333 
334 @register.simple_tag
335 def get_horizontal_field_value(field, form_object):
336     try:            # 在添加页面时,form_object是空实例,获取tags字段数据的时候会报错
337         field_obj = getattr(form_object.instance, field.name)
338     except ValueError as e:
339         print(e)
340         return None
341     else:
342         selected_list = field_obj.all()
343         return selected_list
344 
345 
346 @register.simple_tag
347 def ret_add_url(request, page, order_before, filter_text, search_text):
348     """
349     返回添加页面的href
350     :param request:
351     :param page:
352     :param order:
353     :param filter_conditions_customer:
354     :param search_text:
355     :return:
356     """
357     add_url = "{0}/add?page={1}&o={2}&_q={3}&{4}".format(request.path,
358                                                          page,
359                                                          order_before,
360                                                          search_text,
361                                                          filter_text,
362                                                          )
363     return add_url

views.py

  1 from django.shortcuts import render, HttpResponse, redirect, HttpResponseRedirect
  2 from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
  3 from kingadmin import kingadmin
  4 from kingadmin.utils import custom_filter, table_search, table_sort, table_filter, filters_to_text
  5 from kingadmin.forms import create_model_form
  6 # Create your views here.
  7 
  8 
  9 def default(request):
 10     """展示所有可管理的数据表"""
 11     manage_tables = kingadmin.enabled_admins
 12     return render(request,
 13                   'kingadmin/default.html',
 14                   {'manage_tables': manage_tables, })
 15 
 16 
 17 def table_list(request, app_name, table_name):
 18     """
 19     列出数据表中的所有数据
 20     :param request:
 21     :param app_name: app名称
 22     :param table_name: 数据表名称
 23     :return:
 24     """
 25     # app_name & table_name都存在enabled_admins中,取出其中的数据
 26     # for item in request.GET.items():
 27     #     print(item)
 28     if app_name in kingadmin.enabled_admins.keys() and \
 29             table_name in kingadmin.enabled_admins[app_name].keys():
 30         admin_class = kingadmin.enabled_admins[app_name][table_name]
 31 
 32         # 检索过滤数据
 33         # query_sets = admin_class.model.objects.all()
 34         query_sets, filter_conditions_customer = custom_filter(request, admin_class)
 35         # 搜索过滤数据
 36         query_sets, search_text = table_search(request, admin_class, query_sets)
 37         # query_sets 排序
 38         query_sets, order_before, order_after = table_sort(request, admin_class, query_sets)
 39         filter_conditions_preset = admin_class.list_filter
 40         # list_display中的所有字段对应的verbose_name
 41         field_verbose_names = []
 42         field_names = []
 43         fields = []
 44         for field_name in admin_class.list_display:
 45             for field in admin_class.model._meta.get_fields():
 46                 if field.name == field_name:
 47                     fields.append(field)
 48                     # field_names.append(field_name)
 49                     # field_verbose_names.append(field.verbose_name)
 50 
 51         # 分页
 52         page = request.GET.get('page', '')
 53 
 54         paginator = Paginator(query_sets, admin_class.list_per_page)
 55         # 检索参数
 56         filter_text = filters_to_text(filter_conditions_customer)
 57         try:
 58             contacts = paginator.page(page)
 59         except PageNotAnInteger:
 60             # If page is not an integer, deliver first page.
 61             contacts = paginator.page(1)
 62         except EmptyPage:
 63             # If page is out of range (e.g. 9999), deliver last page of results.
 64             contacts = paginator.page(paginator.num_pages)
 65         contacts_count = len(contacts)
 66         return render(request, 'kingadmin/table_list.html', {'app_name': app_name,
 67                                                              'table_name': table_name,
 68                                                              'query_sets': query_sets,
 69                                                              'admin_class': admin_class,
 70                                                              # 'field_verbose_names': field_verbose_names,
 71                                                              # 'field_names': field_names,
 72                                                              'order_before': order_before,
 73                                                              'order_after': order_after,
 74                                                              'fields': fields,
 75                                                              'contacts': contacts,
 76                                                              'contacts_count': contacts_count,
 77                                                              'filter_conditions': filter_conditions_preset,
 78                                                              'filter_conditions_customer': filter_conditions_customer,
 79                                                              'search_text': search_text,
 80                                                              'page': page,
 81                                                              'filter_text': filter_text,
 82                                                              })
 83     # app_name | table_name不存在enabled_admin中,就返回错误信息
 84     else:
 85         error = '应用名称或数据表名称不存在或未注册'
 86         return render(request,
 87                       'kingadmin/table_list.html',
 88                       {'error': error,
 89                        'app_name': app_name,
 90                        'table_name': table_name,
 91                        })
 92 
 93 
 94 def table_object_edit(request, app_name, table_name, object_id):
 95     """
 96     编辑表中的一条数据
 97     :param request:
 98     :param app_name:
 99     :param table_name:
100     :param id:
101     :return:
102     """
103     admin_class = kingadmin.enabled_admins[app_name][table_name]
104     model_form = create_model_form(request, admin_class)
105     object_list = admin_class.model.objects.get(id=object_id)
106     query_sets, filter_conditions = table_filter(request, admin_class)
107     page = request.GET.get('page', default='')
108     order = request.GET.get('o', '')
109     search_text = table_search(request, admin_class, query_sets)[1]
110     filter_conditions = custom_filter(request, admin_class)[1]
111     filter_text = filters_to_text(filter_conditions)
112     if request.method == 'POST':
113         form_object = model_form(request.POST, instance=object_list)
114         if form_object.is_valid():
115             form_object.save()
116             return redirect('/kingadmin/{0}/{1}?page={2}&o={3}&_q={4}&{5}'.format(
117                 app_name,
118                 table_name,
119                 page,
120                 order,
121                 search_text,
122                 filter_text,
123             ))
124         # else:                  # 目前可以删除(无论检验成功与否都是要返回table_object_edit.html)
125         #     return render(request, 'kingadmin/table_object_edit.html', {'form_object': form_object,
126         #                                                                 'admin_class': admin_class,
127         #                                                                 'app_name': app_name,
128         #                                                                 'table_name': table_name,
129         #                                                                 })              # 目前可以删除
130     else:
131         form_object = model_form(instance=object_list)
132     return render(request, 'kingadmin/table_object_edit.html', {'form_object': form_object,
133                                                                 'admin_class': admin_class,
134                                                                 'app_name': app_name,
135                                                                 'table_name': table_name,
136                                                                 })
137 
138 
139 def table_object_add(request, app_name, table_name):
140     """
141     添加页面
142     :param request:
143     :param app_name:
144     :param table_name:
145     :return:
146     """
147     admin_class = kingadmin.enabled_admins[app_name][table_name]
148     model_form = create_model_form(request, admin_class)
149 
150     query_string = request.META.get('QUERY_STRING', '')
151     redirect_url = '/kingadmin/{0}/{1}?{2}'.format(app_name, table_name, query_string)
152     if request.method == 'POST':
153         form_object = model_form(request.POST)
154         if form_object.is_valid():
155             form_object.save()
156             return redirect(redirect_url)
157     else:
158         form_object = model_form()
159     return render(request, 'kingadmin/table_object_add.html', {'app_name': app_name,
160                                                                'table_name': table_name,
161                                                                'admin_class': admin_class,
162                                                                'form_object': form_object,
163                                                                })

urls.py

 1 from django.conf.urls import url, include
 2 from django.contrib import admin
 3 from . import views
 4 
 5 urlpatterns = [
 6     url(r'^$', views.default),
 7     url(r'^(\w+)/(\w+)$', views.table_list, name='table_list'),
 8     url(r'^(\w+)/(\w+)/(\d+)/edit$', views.table_object_edit, name='table_object_edit'),
 9     url(r'^(\w+)/(\w+)/add$', views.table_object_add, name='table_object_add'),
10 ]

效果如下:

 

问题解决。

如果有更好的解决办法,欢迎指教。

 

转载于:https://www.cnblogs.com/eaglesour/p/8098596.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值