zoukankan      html  css  js  c++  java
  • 项目一: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" onclick="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" onclick="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 ]

    效果如下:

    问题解决。

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

  • 相关阅读:
    NOIP模拟题——小L的珍珠挂饰
    NOIP模拟题——小L的牛栏
    NOIP模拟题——小L的二叉树
    NOIP模拟题——愉快的logo设计
    NOIP模拟题——复制&粘贴2
    NOIP模拟题——Landscaping
    poj3264
    RMQ_ST算法
    Count Colour_poj2777(线段树+位)
    I Hate It(hdu1754)(线段树区间最大值)
  • 原文地址:https://www.cnblogs.com/eaglesour/p/8098596.html
Copyright © 2011-2022 走看看