自定义KingAdmin

  通过admin样式自己做KingAdmin

提前需知道的model操作

  1. # 获取app名
  2. >>> models.Customer._meta.app_label
  3. 'repository'
  4.  
  5. # 获取数据表名
  6. >>> models.Customer._meta.verbose_name # verbose_name
  7. 'customer'
  8. >>> models.Customer._meta.verbose_name_plural
  9. '客户表'
  10. >>> models.Customer._meta.model_name #表名小写
  11. 'customer'
  12.  
  13. # 获取数据表字段、是否为choices类型
  14. >>> models.Customer._meta.get_field('status')
  15. <django.db.models.fields.SmallIntegerField: status> #字段
  16. >>> models.Customer._meta.get_field('status').choices #choices字段
  17. ((0, '已报名'), (1, '未报名'), (2, '已退学'), (3, '其他'))
  18. >>> models.Customer._meta.get_field('id').choices # 普通字段
  19. []
  20. >>> models.Customer._meta.get_field('consultant').choices #外键字段
  21. []

1、在Django项目中创建kingadmin

2、app_config.py获取已注册以及存在kingadmin.py的App

  1. from django import conf
  2.  
  3. for app in conf.settings.INSTALLED_APPS:
  4. try:
  5. __import__('%s.kingadmin'%app)
  6. except ImportError as e:
  7. print('%s has no model kingadmin'%app)

3、views.py加载自定义的app_config.py文件

  1. from django.shortcuts import render
  2.  
  3. from kingadmin import app_config # 加载app_config
  4. from kingadmin.base_admin import site
  5.  
  6. def app_index(request):
  7.  
  8. print(id(site),site.registered_sites)
  9. return render(request, 'kingadmin/app_index.html',{'site':site})
  10.  
  11. def table_data_list(request,app_name,model_name):
  12. admin_obj = site.registered_sites[app_name][model_name]
  13. admin_obj.querysets = admin_obj.model.objects.all()
  14.  
  15. return render(request,"kingadmin/table_data_list.html",locals()) # locals 传入局部变量

4、base_admin.py定义注册的model(核心)

  1. class AdminRegisterException(Exception):
  2. def __init__(self,msg):
  3. self.message = msg
  4.  
  5. class BaseAdmin(object):
  6. list_display = ()
  7. list_filter = ()
  8. search_fields = ()
  9. list_editable = ()
  10.  
  11. class Adminsite(object):
  12. def __init__(self):
  13. self.registered_sites = {}
  14.  
  15. def register(self,model,admin_class=None):
  16. '''
  17. :param model: <class 'crm.models.Course'>
  18. :param admin_class:
  19. :return:
  20. '''
  21. app_name = model._meta.app_label # python manage.py shell
  22. model_name = model._meta.model_name # dir(<class 'crm.models.Course'>) 查看具有的方法
  23. if not admin_class:
  24. admin_class = BaseAdmin
  25.  
  26. if app_name not in self.registered_sites:
  27. self.registered_sites[app_name]={}
  28.  
  29. if model_name in self.registered_sites[app_name]:
  30. raise AdminRegisterException("app [%s] model [%s] has already registered!" % (app_name, model_name))
  31.  
  32. # admin_obj = admin_class()
  33. admin_obj = admin_class()
  34. admin_obj.model = model
  35. self.registered_sites[app_name][model_name] = admin_obj
  36.  
  37. site = Adminsite()
  38.  
  39. # site = {
  40. # 'crm':{
  41. # 'customers':CustomerAdmin,
  42. # 'customerfollowup':CustomerFollowUPAdmin,
  43. # }
  44. # }

 

5、crm目录下创建kingadmin.py进行models注册

  1. from kingadmin.base_admin import site,BaseAdmin
  2. from crm import models
  3.  
  4. class CustomerAdmin(BaseAdmin):
  5. list_display = ('id','name','qq','consultant','source','consult_content','status','data')
  6. list_filter = ('source','status','consultant')
  7. search_fields = ('qq','name')
  8. list_editable = ('status',)
  9.  
  10. site.register(models.Customer,CustomerAdmin)
  11. site.register(models.FollowUpRecord)
  12. site.register(models.Enrollment)
  1. from django.db import models
  2. from django.contrib.auth.models import User
  3. # Create your models here.
  4.  
  5. class Customer(models.Model):
  6. '''潜在客户信息'''
  7. name = models.CharField(max_length=32,blank=True,null=True)
  8. qq = models.CharField(max_length=64,unique=True)
  9. wechat = models.CharField(max_length=64,blank=True,null=True)
  10. age = models.PositiveIntegerField(blank=True,null=True)
  11. gender = models.PositiveIntegerField(choices=((0,'Female'),(1,'Male')),blank=True,null=True)
  12. phone = models.PositiveIntegerField(blank=True,null=True) #正整数
  13. source_choices = (
  14. (0,'Baidu商桥'),
  15. (1,'51CTO'),
  16. (2,'QQ群'),
  17. (3,'知乎'),
  18. (4,'SOGO'),
  19. (5,'转介绍'),
  20. (6,'其他'),
  21. )
  22. source = models.SmallIntegerField(choices=source_choices) # get_source_display 显示具体内容
  23. referral_from = models.ForeignKey('Customer',related_name='my_referrals',blank=True,null=True) # 自关联,字段可写slef,必须写related_name
  24. consult_courses = models.ManyToManyField(to='Course')
  25. status_choices = (
  26. (0,'已报名'),(1,'未报名'),(2,'已退学'),(3,'其他')
  27. )
  28. status = models.SmallIntegerField(choices=status_choices)
  29. consultant = models.ForeignKey(to="UserProfile",verbose_name='课程顾问')
  30. consult_content = models.TextField(max_length=1024)
  31. data = models.DateTimeField(auto_now_add=True)
  32.  
  33. class Meta:
  34. verbose_name_plural = '客户表'
  35.  
  36. # def __str__(self):
  37. # return self.name
  38.  
  39. class Enrollment(models.Model):
  40. '''注册用户'''
  41. customer = models.ForeignKey('Customer')
  42. class_grade = models.ForeignKey('ClassList')
  43. enrollment_date = models.DateField()
  44.  
  45. class Meta:
  46. unique_together = ('customer', 'class_grade') #联合唯一
  47. verbose_name_plural = '注册用户表'
  48.  
  49. # def __str__(self):
  50. # return '%s'%self.customer
  51.  
  52. class FollowUpRecord(models.Model):
  53. '''销售跟进记录'''
  54. customer = models.ForeignKey('Customer')
  55. content = models.TextField(max_length=1024)
  56. status_choices = (
  57. (0,'绝无报名计划'),
  58. (1,'一个月内报名'),
  59. (2,'两周内报名'),
  60. (3,'已报其他机构'),
  61. )
  62. status = models.SmallIntegerField(choices=status_choices)
  63. consultant = models.ForeignKey(to="UserProfile", verbose_name='课程顾问')
  64. data = models.DateTimeField(auto_now_add=True)
  65.  
  66. class Meta:
  67. verbose_name_plural = '跟进记录表'
  68.  
  69. # def __str__(self):
  70. # return self.customer
  71.  
  72. class Course(models.Model):
  73. '''课程Python,Go'''
  74. name = models.CharField(unique=True,max_length=32)
  75. price = models.PositiveIntegerField(default=19800)
  76. outline = models.TextField(max_length=1024)
  77.  
  78. class Meta:
  79. verbose_name_plural = '课程表'
  80.  
  81. def __str__(self):
  82. return self.name
  83.  
  84. class ClassList(models.Model):
  85. '''班级s14,g1'''
  86. course = models.ForeignKey("Course")
  87. semester = models.PositiveIntegerField(verbose_name='学期')
  88. class_type_choices = ((0,'脱产'),(1,'周末'),(2,'网络'))
  89. branch = models.ForeignKey("Branch")
  90. class_type = models.PositiveIntegerField(choices=class_type_choices)
  91. teachers = models.ManyToManyField(to='UserProfile')
  92. start_date = models.DateField()
  93. end_date = models.DateField()
  94.  
  95. class Meta:
  96. verbose_name_plural = '班级表'
  97.  
  98. def __str__(self):
  99. return '%s'%self.course
  100.  
  101. class CourseRecord(models.Model):
  102. '''每节课上课记录'''
  103. class_grade = models.ForeignKey('ClassList')
  104. day_num = models.PositiveIntegerField(verbose_name='节次')
  105. teacher = models.ForeignKey('UserProfile')
  106. CourseContent = models.TextField(verbose_name="课程内容", max_length=1024)
  107. has_homework = models.BooleanField(default=True) #布尔类型
  108. homework_title = models.CharField(max_length=128, blank=True, null=True)
  109. homework_requirement = models.TextField(verbose_name="作业需求", max_length=1024, blank=True, null=True)
  110.  
  111. class Meta:
  112. unique_together = ("class_grade", "day_num")
  113. verbose_name_plural = '课节次表'
  114.  
  115. def __str__(self):
  116. return " daynum:%s" % (self.day_number)
  117.  
  118. class StudyRecord(models.Model):
  119. '''每个学生上的每节课的成绩记录'''
  120. course_record = models.ForeignKey("CourseRecord")
  121. student = models.ForeignKey("Enrollment")
  122. score_choices = ((100, "A+"),
  123. (90, "A"),
  124. (85, "B+"),
  125. (80, "B"),
  126. (75, "B-"),
  127. (70, "C+"),
  128. (65, "C"),
  129. (40, "C-"),
  130. (-20, "D"),
  131. (-50, "COPY"),
  132. (0, "N/A"),
  133. )
  134. score = models.SmallIntegerField(choices=score_choices)
  135. show_status_choices = (
  136. (0, "缺勤"), (1, "已签到"), (2, "迟到")
  137. )
  138. show_status = models.SmallIntegerField(choices=show_status_choices)
  139. grade_comment = models.TextField(max_length=1024, blank=True, null=True)
  140.  
  141. class Meta:
  142. unique_together = ("course_record", "student")
  143. verbose_name_plural = '学员成绩记录表'
  144.  
  145. def __str__(self):
  146. return "%s daynum:%s" % (self.course_record, self.student)
  147.  
  148. class UserProfile(models.Model):
  149. '''员工用户表'''
  150. user = models.OneToOneField(User)
  151. name = models.CharField(max_length=32)
  152.  
  153. roles = models.ManyToManyField("Role")
  154.  
  155. class Meta:
  156. verbose_name_plural = '用户表'
  157.  
  158. def __str__(self):
  159. return self.name
  160.  
  161. class Role(models.Model):
  162. """角色表"""
  163. name = models.CharField(unique=True,max_length=32)
  164. menus = models.ManyToManyField("Menu")
  165.  
  166. class Meta:
  167. verbose_name_plural = '角色表'
  168.  
  169. def __str__(self):
  170. return self.name
  171.  
  172. class Branch(models.Model):
  173. """分校"""
  174. name = models.CharField(unique=True,max_length=128)
  175.  
  176. class Meta:
  177. verbose_name_plural = '分校表'
  178.  
  179. def __str__(self):
  180. return self.name
  181.  
  182. class Menu(models.Model):
  183. """动态菜单"""
  184. name = models.CharField(unique=True,max_length=32)
  185. url_type = models.SmallIntegerField(choices=((0,'relative_name'),(1,'absolute_url')))
  186. url_name = models.CharField(unique=True,max_length=128)
  187.  
  188. class Meta:
  189. verbose_name_plural = '菜单表'
  190.  
  191. def __str__(self):
  192. return self.name

model.py

6、kingadmin目录下创建templates/kingadmin页面目录

设置settings文件:

  1. TEMPLATES = [
  2. {
  3. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  4. 'DIRS': [os.path.join(BASE_DIR, 'templates'),
  5. os.path.join(BASE_DIR, 'kingadmin','templates'),] #加入环境变量
  6. ,
  7. 'APP_DIRS': True,
  8. 'OPTIONS': {
  9. 'context_processors': [
  10. 'django.template.context_processors.debug',
  11. 'django.template.context_processors.request',
  12. 'django.contrib.auth.context_processors.auth',
  13. 'django.contrib.messages.context_processors.messages',
  14. ],
  15. },
  16. },
  17. ]
  1. <!DOCTYPE html>
  2. <!-- saved from url=(0041)http://v3.bootcss.com/examples/dashboard/ -->
  3. <html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  4.  
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
  8. <meta name="description" content="">
  9. <meta name="author" content="">
  10. <link rel="icon" href="http://v3.bootcss.com/favicon.ico">
  11.  
  12. <title>Dashboard Template for Bootstrap</title>
  13.  
  14. <!-- Bootstrap core CSS -->
  15. <link href="/static/css/bootstrap.min.css" rel="stylesheet">
  16.  
  17. <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
  18. <link href="/static/css/e10-viewport-bug-workaround.css" rel="stylesheet">
  19.  
  20. <!-- Custom styles for this template -->
  21. <link href="/static/css/dashboard.css" rel="stylesheet">
  22.  
  23. <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
  24. <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
  25. <script src="/static/js/ie-emulation-modes-warning.js"></script>
  26.  
  27. {% block header-recources %}{% endblock %}
  28.  
  29. </head>
  30.  
  31. <body>
  32. {% block body %}body ....{% endblock %}
  33.  
  34. <!-- Bootstrap core JavaScript
  35. ================================================== -->
  36. <!-- Placed at the end of the document so the pages load faster -->
  37. <script src="/static/js/jquery.min.js"></script>
  38. <script src="/static/js/bootstrap.min.js"></script>
  39. <!-- Just to make our placeholder images work. Don't actually copy the next line! -->
  40. <script src="/static/js/holder.min.js"></script>
  41.  
  42. <script>
  43.  
  44. $(document).ready(function () {
  45.  
  46. $(".nav-sidebar a[href='{{ request.path }}']").parent().addClass("active");
  47.  
  48. });//end doc ready
  49.  
  50. </script>
  51. </body></html>

base.html

  1. {% extends "kingadmin/base.html" %}
  2.  
  3. {% block body %}
  4.  
  5. {% block nav-bar %}
  6. <nav class="navbar navbar-inverse navbar-fixed-top">
  7. <div class="container-fluid">
  8. <div class="navbar-header">
  9. <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
  10. <span class="sr-only">Toggle navigation</span>
  11. <span class="icon-bar"></span>
  12. <span class="icon-bar"></span>
  13. <span class="icon-bar"></span>
  14. </button>
  15. <a class="navbar-brand" href="http://v3.bootcss.com/examples/dashboard/#">Kinadmin</a>
  16. </div>
  17. <div id="navbar" class="navbar-collapse collapse">
  18. <ul class="nav navbar-nav navbar-right">
  19. <li><a href="http://v3.bootcss.com/examples/dashboard/#">Dashboard</a></li>
  20. <li><a href="http://v3.bootcss.com/examples/dashboard/#">Settings</a></li>
  21. <li><a href="http://v3.bootcss.com/examples/dashboard/#">Profile</a></li>
  22. <li class="dropdown">
  23. <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ request.user.userprofile.name }}<span class="caret"></span></a>
  24. <ul class="dropdown-menu">
  25. <li><a href="/logout/">logout</a></li>
  26. <li><a href="#">Another action</a></li>
  27. <li><a href="#">Something else here</a></li>
  28.  
  29. </ul>
  30. </li>
  31.  
  32. </ul>
  33. <form class="navbar-form navbar-right">
  34. <input type="text" class="form-control" placeholder="Search...">
  35. </form>
  36. </div>
  37. </div>
  38. </nav>
  39. {% endblock %}
  40.  
  41. <div class="container-fluid">
  42. <div class="row">
  43. {% block side-bar %}
  44. <div class="col-sm-3 col-md-2 sidebar">
  45. <ul class="nav nav-sidebar">
  46. {% block side-bar-menus %}
  47. {% for role in request.user.userprofile.roles.all %}
  48. {# <li class="active"><a href="http://v3.bootcss.com/examples/dashboard/#">Overview <span class="sr-only">(current)</span></a></li>#}
  49. <hr>
  50. {% for menu in role.menus.all %}
  51. <li>
  52. <a href="{% if menu.url_type == 0 %}{% url menu.url_name %}{% else %} {{ menu.url_name }}{% endif %}" >
  53. {{ menu.name }}
  54. </a>
  55. </li>
  56. {% endfor %}
  57. {% endfor %}
  58.  
  59. {% endblock %}
  60. </ul>
  61.  
  62. </div>
  63. {% endblock %}
  64. {% block right-container %}
  65. <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
  66. {% block right-container-content %}
  67. <h1 class="page-header">Dashboard</h1>
  68. {{ request.user.userprofile.name }}
  69. <div class="row placeholders">
  70. <div class="col-xs-6 col-sm-3 placeholder">
  71. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="" height="" class="img-responsive" alt="Generic placeholder thumbnail">
  72. <h4>Label</h4>
  73. <span class="text-muted">Something else</span>
  74. </div>
  75. <div class="col-xs-6 col-sm-3 placeholder">
  76. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="" height="" class="img-responsive" alt="Generic placeholder thumbnail">
  77. <h4>Label</h4>
  78. <span class="text-muted">Something else</span>
  79. </div>
  80. <div class="col-xs-6 col-sm-3 placeholder">
  81. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="" height="" class="img-responsive" alt="Generic placeholder thumbnail">
  82. <h4>Label</h4>
  83. <span class="text-muted">Something else</span>
  84. </div>
  85. <div class="col-xs-6 col-sm-3 placeholder">
  86. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" width="" height="" class="img-responsive" alt="Generic placeholder thumbnail">
  87. <h4>Label</h4>
  88. <span class="text-muted">Something else</span>
  89. </div>
  90. </div>
  91.  
  92. <h2 class="sub-header">Section title</h2>
  93. {% endblock %}
  94. </div>
  95. {% endblock %}
  96. </div>
  97. </div>
  98.  
  99. {% endblock %}

index.html

首页app_index.html:

  1. {% extends 'kingadmin/index.html' %}
  2. {% load kingadmin_tags %}
  3.  
  4. {% block right-container-content %}
  5. {% for app,app_tables in site.registered_sites.items %}
  6. <table class="table table-hover">
  7. <thead>
  8. <tr>
  9. <h3>{{ app }}</h3>
  10. </tr>
  11. </thead>
  12. <tbody>
  13. {% for model_name,admin_class in app_tables.items %}
  14. <tr>
  15. <th ><a href="/kingadmin/{% get_app_name admin_class.model %}/{% get_model_name admin_class.model %}/">{% get_model_verbose_name admin_class.model %}</a> </th>
  16. </tr>
  17. {% endfor %}
  18. </tbody>
  19. </table>
  20. {% endfor %}
  21. {% endblock %}

详情表table_data_list.html:  

  1. {% extends 'kingadmin/index.html' %}
  2. {% load kingadmin_tags %}
  3.  
  4. {% block right-container-content %}
  5.  
  6. <h4>{% get_model_verbose_name admin_obj.model %}</h4>
  7.  
  8. <table class="table table-hover">
  9. <thead>
  10. <tr>
  11. {% for column in admin_obj.list_display %}
  12. <th>{{ column }}</th>
  13. {% endfor %}
  14. </tr>
  15. </thead>
  16. <tbody>
  17.  
  18. {% for obj in admin_obj.querysets %}
  19. <tr>
  20. {% build_table_row admin_obj obj %}
  21.  
  22. </tr>
  23. {% endfor %}
  24. </tbody>
  25. </table>
  26.  
  27. {% endblock %}

7、创建templatetags目录下kingadmin_tags.py文件 自定义模板方法

  1. from django import template
  2. from django.utils.safestring import mark_safe
  3.  
  4. register = template.Library()
  5.  
  6. @register.simple_tag
  7. def get_model_verbose_name(model_obj):
  8.  
  9. model_name = model_obj._meta.verbose_name_plural
  10.  
  11. if not model_name:
  12. model_name = model_obj._meta.model_name
  13.  
  14. return model_name
  15.  
  16. @register.simple_tag
  17. def get_model_name(model_obj):
  18.  
  19. return model_obj._meta.model_name
  20.  
  21. @register.simple_tag
  22. def get_app_name(model_obj):
  23.  
  24. return model_obj._meta.app_label
  25.  
  26. @register.simple_tag
  27. def build_table_row(admin_obj,obj):
  28.  
  29. row_ele = ""
  30.  
  31. for column in admin_obj.list_display:
  32. column_obj = obj._meta.get_field(column)
  33. if column_obj.choices:
  34. get_column_data = getattr(obj,"get_%s_display" % column)
  35. column_data = get_column_data()
  36. else:
  37. column_data = getattr(obj, column)
  38.  
  39. td_ele = '''<td>%s</td>''' % column_data
  40. row_ele += td_ele
  41.  
  42. return mark_safe(row_ele)

初步效果:  

模仿Admin做检索

1、修改views.py

  1. from django.shortcuts import render
  2.  
  3. from kingadmin import app_config # 加载app_config
  4. from kingadmin.base_admin import site
  5.  
  6. def app_index(request):
  7.  
  8. print(id(site),site.registered_sites)
  9. return render(request, 'kingadmin/app_index.html',{'site':site})
  10.  
  11. def filter_querysets(request,model): #过滤
  12. condtions = {}
  13. for k,v in request.GET.items():
  14. if v :
  15. condtions[k] = v
  16. querysets =model.objects.filter(**condtions)
  17.  
  18. return querysets,condtions
  19.  
  20. def table_data_list(request,app_name,model_name): #重新改造函数,加上过滤条件
  21. # print(request.GET)
  22. admin_obj = site.registered_sites[app_name][model_name]
  23. model = admin_obj.model
  24. admin_obj.querysets,admin_obj.condtions = filter_querysets(request,model)
  25.  
  26. print(admin_obj.condtions)
  27. return render(request,"kingadmin/table_data_list.html",locals()) # locals 传入局部变量

2、新增自定义simple_tag

  1. @register.simple_tag
  2. def get_filter_field(filter_column,admin_obj):
  3. field_obj = admin_obj.model._meta.get_field(filter_column)
  4.  
  5. selected = None
  6. condtions = admin_obj.condtions
  7. if filter_column in condtions:
  8. selected = condtions[filter_column]
  9.  
  10. select_ele = """<select name= "%s">""" % filter_column
  11. for choice in field_obj.get_choices():
  12. if selected and selected == str(choice[0]):
  13. option_ele = """<option value="%s" selected> %s </option> """ % choice
  14. else:
  15. option_ele = """<option value="%s"> %s </option> """%choice
  16. select_ele +=option_ele
  17. select_ele += """</select>"""
  18.  
  19. return mark_safe(select_ele)

3、修改table_data_list.html

  1. {% extends 'kingadmin/index.html' %}
  2. {% load kingadmin_tags %}
  3.  
  4. {% block right-container-content %}
  5.  
  6. <h4>{% get_model_verbose_name admin_obj.model %}</h4>
  7. {# {{ admin_obj.list_filter }}#}
  8. {% if admin_obj.list_filter %}
  9. <div class="row">
  10. <form>
  11. {% for filter_column in admin_obj.list_filter %}
  12. <div class="col-lg-3">
  13. {{ filter_column }}:{% get_filter_field filter_column admin_obj %}
  14. </div>
  15. {% endfor %}
  16. <input type="submit" class="btn btn-success" value="过滤">
  17. </form>
  18. </div>
  19. {% endif %}
  20. <table class="table table-hover">
  21. <thead>
  22. <tr>
  23. {% for column in admin_obj.list_display %}
  24. <th>{{ column }}</th>
  25. {% endfor %}
  26. </tr>
  27. </thead>
  28. <tbody>
  29.  
  30. {% for obj in admin_obj.querysets %}
  31. <tr>
  32. {% build_table_row admin_obj obj %}
  33.  
  34. </tr>
  35. {% endfor %}
  36. </tbody>
  37. </table>
  38.  
  39. {% endblock %}

table_data_list.html

显示效果:

利用Django自带分页

1、Paginantor官方源码示例-》跳转

  1. >>> from django.core.paginator import Paginator
  2. >>> objects = ['john', 'paul', 'george', 'ringo']
  3. >>> p = Paginator(objects, 2)
  4.  
  5. >>> p.count
  6. 4
  7. >>> p.num_pages
  8. 2
  9. >>> type(p.page_range) # `<type 'rangeiterator'>` in Python 2.
  10. <class 'range_iterator'>
  11. >>> p.page_range
  12. range(1, 3)
  13.  
  14. >>> page1 = p.page(1)
  15. >>> page1
  16. <Page 1 of 2>
  17. >>> page1.object_list
  18. ['john', 'paul']
  19.  
  20. >>> page2 = p.page(2)
  21. >>> page2.object_list
  22. ['george', 'ringo']
  23. >>> page2.has_next()
  24. False
  25. >>> page2.has_previous()
  26. True
  27. >>> page2.has_other_pages()
  28. True
  29. >>> page2.next_page_number()
  30. Traceback (most recent call last):
  31. ...
  32. EmptyPage: That page contains no results
  33. >>> page2.previous_page_number()
  34. 1
  35. >>> page2.start_index() # The 1-based index of the first item on this page
  36. 3
  37. >>> page2.end_index() # The 1-based index of the last item on this page
  38. 4
  39.  
  40. >>> p.page(0)
  41. Traceback (most recent call last):
  42. ...
  43. EmptyPage: That page number is less than 1
  44. >>> p.page(3)
  45. Traceback (most recent call last):
  46. ...
  47. EmptyPage: That page contains no results

基本使用方法

  1. from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  2. from django.shortcuts import render
  3.  
  4. def listing(request):
  5. contact_list = Contacts.objects.all()
  6. paginator = Paginator(contact_list, 25) # Show 25 contacts per page
  7.  
  8. page = request.GET.get('page')
  9. try:
  10. contacts = paginator.page(page)
  11. except PageNotAnInteger:
  12. # If page is not an integer, deliver first page.
  13. contacts = paginator.page(1)
  14. except EmptyPage:
  15. # If page is out of range (e.g. 9999), deliver last page of results.
  16. contacts = paginator.page(paginator.num_pages)
  17.  
  18. return render(request, 'list.html', {'contacts': contacts})

后端处理

  1. {% for contact in contacts %}
  2. {# Each "contact" is a Contact model object. #}
  3. {{ contact.full_name|upper }}<br />
  4. ...
  5. {% endfor %}
  6.  
  7. <div class="pagination">
  8. <span class="step-links">
  9. {% if contacts.has_previous %}
  10. <a href="?page={{ contacts.previous_page_number }}">previous</a>
  11. {% endif %}
  12.  
  13. <span class="current">
  14. Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
  15. </span>
  16.  
  17. {% if contacts.has_next %}
  18. <a href="?page={{ contacts.next_page_number }}">next</a>
  19. {% endif %}
  20. </span>
  21. </div>

前端展示

2、添加分页全局变量kingadmin.py

  1. class CustomerAdmin(BaseAdmin):
  2. list_display = ('id','name','qq','consultant','source','consult_content','status','data')
  3. list_filter = ('source','status','consultant')
  4. search_fields = ('qq','name')
  5. list_editable = ('status',)
  6. list_per_page = 2

 

3、处理函数views.py

  1. def filter_querysets(request,model): #过滤
  2. condtions = {}
  3. for k,v in request.GET.items():
  4. if v and k !='page':
  5. condtions[k] = v
  6. querysets =model.objects.filter(**condtions)
  7.  
  8. return querysets,condtions
  9.  
  10. from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  11. from django.shortcuts import render
  12.  
  13. def listing(request,admin_obj):
  14.  
  15. paginator = Paginator(admin_obj.querysets, admin_obj.list_per_page) # Show 25 contacts per page
  16. page = request.GET.get('page')
  17. try:
  18. contacts = paginator.page(page)
  19. except PageNotAnInteger:
  20. # If page is not an integer, deliver first page.
  21. contacts = paginator.page(1)
  22. except EmptyPage:
  23. # If page is out of range (e.g. 9999), deliver last page of results.
  24. contacts = paginator.page(paginator.num_pages)
  25.  
  26. return contacts
  27.  
  28. def table_data_list(request,app_name,model_name): #重新改造函数,加上过滤条件
  29. # print(request.GET)
  30. admin_obj = site.registered_sites[app_name][model_name]
  31. model = admin_obj.model
  32. admin_obj.querysets,admin_obj.condtions = filter_querysets(request,model)
  33. print('before',admin_obj.querysets)
  34. admin_obj.querysets = listing(request,admin_obj)
  35. print('after',admin_obj.querysets)
  36.  
  37. return render(request,"kingadmin/table_data_list.html",locals()) # locals 传入局部变量

  

4、kingadmin_tags.py

  1. @register.simple_tag()
  2. def generate_filter_url(admin_obj):
  3. url = ""
  4. for k,v in admin_obj.condtions.items():
  5. url += "&%s=%s"%(k,v)
  6.  
  7. return url

5、table_data_list.html

  1. tfoot>
  2. <nav aria-label="...">
  3. <ul class="pagination">
  4. <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li>
  5. {% for page in admin_obj.querysets.paginator.page_range %}
  6. {% if page == admin_obj.querysets.number %}
  7. <li class="active">
  8. {% else %}
  9. <li >
  10. {% endif %}
  11. <a href="?page={{ page }}{% generate_filter_url admin_obj %}">{{ page }} <span class="sr-only">(current)</span></a>
  12. </li>
  13. {% endfor %}
  14. </ul>
  15. </nav>
  16. </tfoot>

显示效果:

过滤、排序、分页组合

1、在原views.py上新增:

  1. # 添加排序
  2. def get_orderby(request,querysets): #排序
  3. orderby_fieid = request.GET.get('o')
  4. if orderby_fieid:
  5. querys_res = querysets.order_by(orderby_fieid)
  6. else:
  7. querys_res = querysets
  8.  
  9. return querys_res
  10.  
  11. # 过滤修改
  12. def filter_querysets(request,model): #过滤
  13. condtions = {}
  14. except_list = ["page",'o']
  15. for k,v in request.GET.items():
  16. if k in except_list:continue
  17. if v:
  18. condtions[k] = v
  19. querysets =model.objects.filter(**condtions)
  20.  
  21. return querysets,condtions
  22.  
  23. # 分页添加
  24. def listing(request,admin_obj):
  25. querys_res = get_orderby(request, admin_obj.querysets)

  

2、自定义simple_tag

  1. @register.simple_tag()
  2. def generate_filter_url(admin_obj,request=None):
  3. url = ""
  4. if request:
  5. if request.GET.get('o'):
  6. url += "&o=%s" % request.GET.get('o')
  7. for k,v in admin_obj.condtions.items():
  8. url += "&%s=%s"%(k,v)
  9.  
  10. return url
  11.  
  12. @register.simple_tag
  13. def get_orderby_key(request,column):
  14. current_order_by_key = request.GET.get('o')
  15. if current_order_by_key:
  16. if current_order_by_key == column:
  17. if column.startswith('-'):
  18. column.strip("-")
  19. else:
  20. column = "-%s"%column
  21. return column
  22. else:
  23. return column
  24.  
  25. @register.simple_tag
  26. def display_order_by_icon(request,column):
  27. current_order_by_key = request.GET.get('o')
  28. if current_order_by_key:
  29. if current_order_by_key.strip('-') == column:
  30. if current_order_by_key.startswith('-'):
  31. icons = '''<span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>'''
  32. else:
  33. icons = '''<span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>'''
  34.  
  35. return mark_safe(icons)
  36.  
  37. return ' '

  

3、html前端页面

  1. // 过滤时添加排序
  2. <form>
  3. {% for filter_column in admin_obj.list_filter %}
  4. <div class="col-lg-3">
  5. {{ filter_column }}:{% get_filter_field filter_column admin_obj %}
  6. </div>
  7. {% endfor %}
  8. <input type="submit" class="btn btn-success" value="过滤">
  9. <input type="hidden" name="o" value="{{ request.GET.o }}"> //过滤时加上排序
  10. </form>
  11.  
  12. // 排序时加上过滤
  13. {% for column in admin_obj.list_display %}
  14. <th>
  15. // 排序时加上过滤
  16. <a href="?o={% get_orderby_key request column %}{% generate_filter_url admin_obj %}"> {{ column }}</a>
  17. {% display_order_by_icon request column %}
  18. </th>
  19. {% endfor %}
  20.  
  21. // 分页时加上过滤和排序
  22. {% for page in admin_obj.querysets.paginator.page_range %}
  23. {% if page == admin_obj.querysets.number %}
  24. <li class="active">
  25. {% else %}
  26. <li >
  27. {% endif %}
  28. // 分页时加上排序和过滤
  29. <a href="?page={{ page }}{% generate_filter_url admin_obj request%}">{{ page }} <span class="sr-only">(current)</span></a>
  30. </li>
  31. {% endfor %}

点击过滤或排序时页面恢复到第一页

搜索

1、views.py处理文件

  1. # 添加搜索函数 注意顺序
  2.  
  3. def get_search(request,admin_obj):
  4. search_content = request.GET.get('q')
  5. condition = Q()
  6. condition.connector = 'OR'
  7. if search_content:
  8. for column in admin_obj.search_fields:
  9. condition.children.append(("%s__contains"%column,search_content))
  10.  
  11. querysets = admin_obj.querysets.filter(condition)
  12. else:
  13. querysets = admin_obj.querysets
  14. return querysets
  15.  
  16. def table_data_list(request,app_name,model_name): #重新改造函数,加上过滤条件
  17.  
  18. admin_obj = site.registered_sites[app_name][model_name]
  19. model = admin_obj.model
  20.  
  21. admin_obj.querysets,admin_obj.condtions = filter_querysets(request,model) #加过滤条件
  22.  
  23. admin_obj.querysets = get_search(request,admin_obj) # 搜索
  24.  
  25. admin_obj.querysets = listing(request,admin_obj) #分页
  26.  
  27. return render(request,"kingadmin/table_data_list.html",locals()) # locals 传入局部变量

2、自定义simple_tag

  1. @register.simple_tag()
  2. def generate_filter_search(request):
  3. search_content = request.GET.get('q')
  4. url = ""
  5. if search_content:
  6. url = "&q=%s"%search_content
  7.  
  8. return url

 

3、前端html页面

  1. 过滤时的from
  2. <form>
  3. {% for filter_column in admin_obj.list_filter %}
  4. <div class="col-lg-3">
  5. {{ filter_column }}:{% get_filter_field filter_column admin_obj %}
  6. </div>
  7. {% endfor %}
  8. <input type="submit" class="btn btn-success" value="过滤">
  9. {# //过滤时加上排序#}
  10. <input type="hidden" name="o" value="{{ request.GET.o }}">
  11. <br/>
  12. <input type="text" name="q" value="{{ request.GET.q }}">
  13. </form>
  14.  
  15. 排序
  16. {% for column in admin_obj.list_display %}
  17. <th>
  18. {# // 排序时加上过滤#}
  19. <a href="?o={% get_orderby_key request column %}{% generate_filter_search request %}{% generate_filter_url admin_obj %}"> {{ column }}</a>
  20. {% display_order_by_icon request column %}
  21. </th>
  22. {% endfor %}
  23.  
  24. 分页
  25. <a href="?page={{ page }}{% generate_filter_search request %}{% generate_filter_url admin_obj request%}">{{ page }} <span class="sr-only">(current)</span></a>

页面显示:

数据修改

1、kingadmin下创建forms.py

  1. from django import forms
  2.  
  3. def CreateModelForm(admin_obj): # 动态生成modelfrom
  4. class Meta:
  5. model = admin_obj.model
  6. fields = "__all__"
  7.  
  8. dynamic_model_form = type("DynamicModelForm",(forms.ModelForm,),{'Meta':Meta})
  9.  
  10. return dynamic_model_form

2、views.py处理函数

  1. from kingadmin import forms
  2. def table_change(request,app_name,model_name,id):
  3. admin_obj = site.registered_sites[app_name][model_name]
  4. obj = admin_obj.model.objects.filter(id=id).first()
  5.  
  6. model_form = forms.CreateModelForm(admin_obj)
  7. obj_form = model_form(instance=obj)
  8.  
  9. return render(request,'kingadmin/table_change.html',locals())

 

3、html文件

  1. {% extends "kingadmin/index.html" %}
  2.  
  3. {% load kingadmin_tags %}
  4.  
  5. {% block right-container-content %}
  6. {{ obj_form }}
  7. {% endblock %}

table_change.html

显示视图:

修改完善

1、html文件

  1. {% extends "kingadmin/index.html" %}
  2.  
  3. {% load kingadmin_tags %}
  4.  
  5. {% block right-container-content %}
  6. <div class="row" style="margin-bottom: 20px" >
  7. <ol class="breadcrumb">
  8. <li><a href="/kingadmin/">Home</a></li>
  9. <li><a href="/kingadmin/{% get_app_name admin_obj.model %}/">{% get_app_name admin_obj.model %}</a></li>
  10. <li ><a href="/kingadmin/{% get_app_name admin_obj.model %}/{% get_model_name admin_obj.model %}/">{% get_model_verbose_name admin_obj.model%} </a></li>
  11. <li class="active">{{ obj_form.instance }}</li>
  12. </ol>
  13.  
  14. <h4>Change {% get_model_verbose_name admin_obj.model %}</h4>
  15. </div>
  16.  
  17. <form class="form-horizontal" method="post" onsubmit="return BeforeFormSubmit(this);">{% csrf_token %}
  18. {% for field in obj_form %}
  19. <div class="form-group">
  20. <label class="col-sm-2 " style="font-weight: normal">
  21. {% if field.field.required %}
  22. <b>{{ field.label }}</b>
  23. {% else %}
  24. {{ field.label }}
  25. {% endif %}
  26. </label>
  27. <div class="col-sm-10">
  28. <span style="color: red;">{{ field.errors }}</span>
  29. {{ field }}
  30. </div>
  31. </div>
  32. {% endfor %}
  33. <input type="submit" value="Save" class="pull-right btn btn-info" >
  34. </form>
  35. {% endblock %}

table_data_list.html

2、froms.py

  1. from django import forms
  2.  
  3. def CreateModelForm(admin_obj): # 动态生成modelfrom
  4. class Meta:
  5. model = admin_obj.model
  6. fields = "__all__"
  7.  
  8. def __new__(cls, *args, **kwargs):
  9. # print("base fields",cls.base_fields)
  10. for field_name, field_obj in cls.base_fields.items():
  11. print(field_name,dir(field_obj))
  12. field_obj.widget.attrs['class'] = 'form-control'
  13. # field_obj.widget.attrs['maxlength'] = getattr(field_obj,'max_length' ) if hasattr(field_obj,'max_length') \
  14. # else ""
  15. # if field_name in admin_obj.readonly_fields:
  16. # field_obj.widget.attrs['disabled'] = True
  17.  
  18. return forms.ModelForm.__new__(cls)
  19.  
  20. dynamic_model_form = type("DynamicModelForm",(forms.ModelForm,),{'Meta':Meta})
  21. setattr(dynamic_model_form,"__new__",__new__)
  22. return dynamic_model_form

 

3、views.py处理文件

  1. from kingadmin import forms
  2. def table_change(request,app_name,model_name,id):
  3. admin_obj = site.registered_sites[app_name][model_name]
  4. obj = admin_obj.model.objects.filter(id=id).first()
  5. model_form = forms.CreateModelForm(admin_obj)
  6.  
  7. if request.method == "GET":
  8. obj_form = model_form(instance=obj)
  9. elif request.method == "POST":
  10. obj_form = model_form(instance=obj, data=request.POST)
  11. if obj_form.is_valid():
  12. obj_form.save()
  13.  
  14. return render(request, "kingadmin/table_change.html", locals())

  

表单添加

1、html文件

  1. {% extends "kingadmin/index.html" %}
  2.  
  3. {% load kingadmin_tags %}
  4.  
  5. {% block right-container-content %}
  6. <div class="row" style="margin-bottom: 20px" >
  7. <ol class="breadcrumb">
  8. <li><a href="/kingadmin/">Home</a></li>
  9. <li><a href="/kingadmin/{% get_app_name admin_obj.model %}/">{% get_app_name admin_obj.model %}</a></li>
  10. <li ><a href="/kingadmin/{% get_app_name admin_obj.model %}/{% get_model_name admin_obj.model %}/">{% get_model_verbose_name admin_obj.model%} </a></li>
  11. <li class="active">Add {% get_model_name admin_obj.model %}</li>
  12. </ol>
  13.  
  14. <h4>Change {% get_model_verbose_name admin_obj.model %}</h4>
  15. </div>
  16.  
  17. <form class="form-horizontal" method="post" onsubmit="return BeforeFormSubmit(this);">{% csrf_token %}
  18. {% for field in obj_form %}
  19. <div class="form-group">
  20. <label class="col-sm-2 " style="font-weight: normal">
  21. {% if field.field.required %}
  22. <b>{{ field.label }}</b>
  23. {% else %}
  24. {{ field.label }}
  25. {% endif %}
  26. </label>
  27. <div class="col-sm-10">
  28. <span style="color: red;">{{ field.errors }}</span>
  29. {{ field }}
  30. </div>
  31. </div>
  32. {% endfor %}
  33. <input type="submit" value="Save" class="pull-right btn btn-info" >
  34. </form>
  35. {% endblock %}

table_add.html

2、froms.py文件

  1. from django import forms
  2.  
  3. def CreateModelForm(admin_obj): # 动态生成modelfrom
  4. class Meta:
  5. model = admin_obj.model
  6. fields = "__all__"
  7.  
  8. def __new__(cls, *args, **kwargs):
  9. # print("base fields",cls.base_fields)
  10. for field_name, field_obj in cls.base_fields.items():
  11. # print(field_name,dir(field_obj))
  12. field_obj.widget.attrs['class'] = 'form-control'
  13. # field_obj.widget.attrs['maxlength'] = getattr(field_obj,'max_length' ) if hasattr(field_obj,'max_length') \
  14. # else ""
  15. if field_name in admin_obj.readonly_fields:
  16. field_obj.widget.attrs['disabled'] = True
  17.  
  18. return forms.ModelForm.__new__(cls)
  19.  
  20. dynamic_model_form = type("DynamicModelForm",(forms.ModelForm,),{'Meta':Meta})
  21. setattr(dynamic_model_form,"__new__",__new__)
  22. return dynamic_model_form

3、views.py处理文件

  1. def table_add(request,app_name,model_name):
  2. admin_obj = site.registered_sites[app_name][model_name]
  3. model_form = forms.CreateModelForm(admin_obj)
  4. if request.method == "GET":
  5. obj_form = model_form()
  6.  
  7. if request.method == "POST":
  8. obj_form = model_form(data=request.POST)
  9. if obj_form.is_valid():
  10. obj_form.save()
  11. if not obj_form.errors:
  12. return redirect('/kingadmin/%s/%s'%(app_name,model_name))
  13.  
  14. return render(request, "kingadmin/table_add.html", locals())

  

 

增加readonly_fields字段

1、forms.py文件修改

  1. from django import forms
  2.  
  3. def CreateModelForm(admin_obj): # 动态生成modelfrom
  4. class Meta:
  5. model = admin_obj.model
  6. fields = "__all__"
  7.  
  8. def __new__(cls, *args, **kwargs):
  9. # print("base fields",cls.base_fields)
  10. for field_name, field_obj in cls.base_fields.items():
  11. # print(field_name,dir(field_obj))
  12. field_obj.widget.attrs['class'] = 'form-control'
  13. # field_obj.widget.attrs['maxlength'] = getattr(field_obj,'max_length' ) if hasattr(field_obj,'max_length') \
  14. # else ""
  15. if field_name in admin_obj.readonly_fields:
  16. field_obj.widget.attrs['disabled'] = True
  17.  
  18. return forms.ModelForm.__new__(cls)
  19.  
  20. def default_clean(self):
  21. # print("default clean:",self)
  22. for field in admin_obj.readonly_fields:
  23. print("readonly", field, self.instance)
  24. field_val_from_db = getattr(self.instance, field)
  25. field_val = self.cleaned_data.get(field)
  26. if field_val_from_db == field_val:
  27. print("field not change ")
  28. else: # 被篡改了
  29. self.add_error(field, ' "%s" is a readonly field ,value should be "%s" ' % (field, field_val_from_db))
  30.  
  31. print("cleaned data:", self.cleaned_data)
  32.  
  33. dynamic_model_form = type("DynamicModelForm",(forms.ModelForm,),{'Meta':Meta})
  34. setattr(dynamic_model_form,"__new__",__new__)
  35. setattr(dynamic_model_form,"clean",default_clean)
  36. return dynamic_model_form

 

添加action动作

1、kingadmin.py

  1. class CustomerAdmin(BaseAdmin):
  2. list_display = ('id','name','qq','consultant','source','consult_content','status','data')
  3. list_filter = ('source','status','consultant')
  4. search_fields = ('qq','name')
  5. list_editable = ('status',)
  6. readonly_fields = ('name',)
  7. list_per_page = 5
  8. actions = ["change_status", ]
  9.  
  10. def change_status(self, request, querysets):
  11. print("changeing status", querysets)
  12. querysets.update(status=1)
  13.  
  14. change_status.short_description = "改变报名状态"
  15.  
  16. class EnrollmentAdmin(BaseAdmin):
  17. list_display = ('customer','class_grade','enrollment_date')
  18.  
  19. site.register(models.Customer,CustomerAdmin)
  20. site.register(models.FollowUpRecord)
  21. site.register(models.Enrollment,EnrollmentAdmin)

2、views.py处理函数

  1. def table_data_list(request,app_name,model_name): #重新改造函数,加上过滤条件
  2. admin_obj = site.registered_sites[app_name][model_name]
  3.  
  4. if request.method == "POST":
  5.  
  6. action = request.POST.get("action_select")
  7. selected_ids = request.POST.get("selected_ids")
  8. selected_ids = json.loads(selected_ids)
  9. print("action:",selected_ids,action)
  10. selected_objs = admin_obj.model.objects.filter(id__in=selected_ids)
  11.  
  12. action_func = getattr(admin_obj,action)
  13. action_func(request,selected_objs)
  14.  
  15. model = admin_obj.model
  16.  
  17. admin_obj.querysets,admin_obj.condtions = filter_querysets(request,model) #加过滤条件
  18.  
  19. admin_obj.querysets = get_search(request,admin_obj) # 搜索
  20.  
  21. admin_obj.querysets = listing(request,admin_obj) #分页
  22.  
  23. return render(request,"kingadmin/table_data_list.html",locals()) # locals 传入局部变量

  

3、table_data_list.html

  1. {% extends 'kingadmin/index.html' %}
  2. {% load kingadmin_tags %}
  3.  
  4. {% block right-container-content %}
  5. <ol class="breadcrumb">
  6. <li><a href="/kingadmin/">Home</a></li>
  7. <li><a href="/kingadmin/{% get_app_name admin_obj.model %}/">{% get_app_name admin_obj.model %}</a></li>
  8. <li class="active">{% get_model_verbose_name admin_obj.model%} </li>
  9. <li class="pull-right">
  10. <a href="add/"><input type="button" class="btn btn-sm btn-success" value="+Add"></a>
  11. </li>
  12. </ol>
  13.  
  14. <h4>{% get_model_verbose_name admin_obj.model %}</h4>
  15. {# {{ admin_obj.list_filter }}#}
  16.  
  17. {% if admin_obj.list_filter %}
  18. <div class="row">
  19. <form>
  20. {% for filter_column in admin_obj.list_filter %}
  21. <div class="col-lg-3">
  22. {{ filter_column }}:{% get_filter_field filter_column admin_obj %}
  23. </div>
  24. {% endfor %}
  25. <input type="submit" class="btn btn-success" value="过滤">
  26. {# //过滤时加上排序#}
  27. <input type="hidden" name="o" value="{{ request.GET.o }}">
  28. <br/>
  29. <input type="text" name="q" value="{{ request.GET.q }}">
  30. </form>
  31.  
  32. <form method="post" onsubmit="return ActionValidation(this)">{% csrf_token %}
  33. <select name="action_select">
  34.  
  35. {% get_admin_actions admin_obj %}
  36. </select>
  37. <input type="submit" value="执行">
  38. </form>
  39.  
  40. </div>
  41. {% endif %}
  42.  
  43. <table class="table table-hover">
  44. <thead>
  45. <tr>
  46. <th><input type="checkbox" onclick="SelectAll(this)" /></th>
  47. {% for column in admin_obj.list_display %}
  48. <th>
  49. {# // 排序时加上过滤#}
  50. <a href="?o={% get_orderby_key request column %}{% generate_filter_search request %}{% generate_filter_url admin_obj %}"> {{ column }}</a>
  51. {% display_order_by_icon request column %}
  52. </th>
  53. {% endfor %}
  54. </tr>
  55. </thead>
  56.  
  57. <tbody>
  58.  
  59. {% for obj in admin_obj.querysets %}
  60. <tr>
  61. <td>
  62. <input tag="obj_checkbox" type="checkbox" value="{{ obj.id }}" />
  63. </td>
  64. {% build_table_row admin_obj obj %}
  65. </tr>
  66. {% endfor %}
  67. </tbody>
  68. </table>
  69. <tfoot>
  70. <nav aria-label="...">
  71. <ul class="pagination">
  72. <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
  73. {% for page in admin_obj.querysets.paginator.page_range %}
  74. {% if page == admin_obj.querysets.number %}
  75. <li class="active">
  76. {% else %}
  77. <li >
  78. {% endif %}
  79. {# // 分页时加上排序和过滤#}
  80. <a href="?page={{ page }}{% generate_filter_search request %}{% generate_filter_url admin_obj request%}">{{ page }} <span class="sr-only">(current)</span></a>
  81. </li>
  82. {% endfor %}
  83. </ul>
  84. </nav>
  85. </tfoot>
  86.  
  87. <script >
  88.  
  89. function SelectAll(ele) {
  90. if ($(ele).prop("checked")){
  91. $("input[tag='obj_checkbox']").prop("checked",true)
  92. }else {
  93. $("input[tag='obj_checkbox']").prop("checked",false)
  94. }
  95.  
  96. };//end SelectAll
  97.  
  98. function ActionValidation(form_ele) {
  99. if ($("select[name='action_select']").val() == "-1"){
  100. alert("must select action before submit!");
  101. return false;
  102. }
  103.  
  104. var selected_objs = [];
  105. $("input[tag='obj_checkbox']").each(function () {
  106. if ($(this).prop("checked")){
  107. selected_objs.push($(this).val());
  108. }
  109. });//end each
  110.  
  111. console.log(selected_objs)
  112. if ( selected_objs.length ==){
  113. alert("must select at least one object to run the action!");
  114. return false;
  115. }
  116.  
  117. var selected_objs_ele = "<input name='selected_ids' type='hidden' value=" + JSON.stringify(selected_objs) + " >" ;
  118. $(form_ele).append(selected_objs_ele);
  119.  
  120. return true;
  121.  
  122. }
  123.  
  124. </script>
  125. {% endblock %}

html

4、simple_tag

  1. @register.simple_tag
  2. def get_admin_actions(admin_obj):
  3.  
  4. options = "<option class='form-control' value='-1'>-------</option>"
  5. actions = admin_obj.default_actions + admin_obj.actions
  6.  
  7. for action in actions:
  8. action_func = getattr(admin_obj,action)
  9. if hasattr(action_func,"short_description"):
  10. action_name = action_func.short_description
  11. else:
  12. action_name = action
  13. options += """<option value="{action_func_name}">{action_name}</option> """.format(action_func_name=action,
  14. action_name=action_name)
  15.  
  16. return mark_safe(options)

  

Python开发【Django】:重构Admin的更多相关文章

  1. Python学习---django之admin简介

    Django之admin简介 参考文献:http://www.admin10000.com/document/2220.html   Djaogo为什么url可以匹配url.py里面的路径呢? 我们打 ...

  2. Python开发【Django】:Admin配置管理

    Admin创建登录用户 数据库结构表: from django.db import models # Create your models here. class UserProfile(models ...

  3. Python开发入门与实战2-第一个Django项目

    2.第一个Django项目 上一章节我们完成了python,django和数据库等运行环境的安装,现在我们来创建第一个django project吧,迈出使用django开发应用的第一步. 2.1.创 ...

  4. Python开发【第二十二篇】:Web框架之Django【进阶】

    Python开发[第二十二篇]:Web框架之Django[进阶]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 ...

  5. Python开发【第二十一篇】:Web框架之Django【基础】

    Python开发[第二十一篇]:Web框架之Django[基础]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之 ...

  6. Python开发【第十八篇】Web框架之Django【基础篇】

    一.简介 Python下有许多款不同的 Web 框架,Django 是重量级选手中最有代表性的一位,许多成功的网站和APP都基于 Django. Django 是一个开放源代码的Web应用框架,由 P ...

  7. python开发学习-day15(前端部分知识、web框架、Django创建项目)

    s12-20160430-day15 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

  8. Python开发【Django】:Model操作(一)

    Django ORM基本配置 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去 ...

  9. 《Python高效开发实战》实战演练——开发Django站点1

    6.2 实战演练:开发Django站点 用Django开发网站需要遵循Django的一套开发流程.本节通过建立一个消息录入页面演示Django的开发流程及相关技术. 6.12.1  建立项目 在进行D ...

  10. [Python] 利用Django进行Web开发系列(一)

    1 写在前面 在没有接触互联网这个行业的时候,我就一直很好奇网站是怎么构建的.现在虽然从事互联网相关的工作,但是也一直没有接触过Web开发之类的东西,但是兴趣终归还是要有的,而且是需要自己动手去实践的 ...

随机推荐

  1. Ubuntu下,如何解决Unable to locate package

    在虚拟机上新装了一个ubuntu 12.10,想在上面装一个Git,却发生了以下错误信息 我觉得原因可能是我换了163的源,没有更新所以找不到这个包. 这时候就要使用 sudo apt-get upd ...

  2. ActiveMQ-5.13.0集群

    ActiveMQ集群介绍 ActiveMQ具有强大和灵活的集群功能,但在使用的过程中会发现很多的缺点,ActiveMQ的集群方式主要由两种:Master-Slave(ActiveMQ5.8版本已不可用 ...

  3. chrome浏览器默认启动时打开2345导航的解决方法

    2345并没有改动chrome内部设置.它仅仅是把全部的快捷方式改动了.包含開始菜单旁边的快捷启动图标. 仅仅须要右键chrome快捷方式.在目标一栏中,把"----chrome.exe&q ...

  4. CPU性能判断指标---上下文切换,运行队列和使用率

    http://blog.chinaunix.net/uid-15007890-id-3064254.html uptime11:35:08 up 21:57,  6 users,  load aver ...

  5. jenkins第一次登陆,输入完密码之后,卡在了SetupWizard[jenkins]处

    问题描述: 前几天在安装测试环境的jenkins,启动tomcat之后,通过页面进行登录,输入完初始化的密码之后,就一直卡在 SetupWizard[jenkins]这个地方. 问题如下图: 备注:等 ...

  6. 第一章 Spring.Net介绍

    1.1 概述 在Java社区中Spring经历的长时间的考验,已经是一套很成熟稳定的框架.而Spring.Net 的前身是 Java版的Spring.Spring.Net是以Java版的Spring框 ...

  7. mysql 中实现行变列

    前言: mysql行列变化,最难的就是将多个列变成多行,使用的比较多的是统计学中行变列,列变行,没有找到现成的函数或者语句,所以自己写了存储过程,使用动态sql来实现,应用业务场景,用户每个月都有使用 ...

  8. 设置MySQL的字符编码

    前言 这里我已经将MySQL的数据库编码设置为UTF-8,所以下面现实的都是UTF-8. 设置MySQL数据库的编码方式有三种,分别是基于session会话的.基于全局gloable的.永久性改变的. ...

  9. Linux同步网络时间

    1.date '+%Y%M%D' 按照格式显示当前日期,结果如下: [root@LAMP ~]# date "+%Y-%m-%d %H:%M:%S" -- :: 2.date -s ...

  10. Linux命令之type - 显示命令的类型

    用途说明 type命令用来显示指定命令的类型.一个命令的类型可以是如下之一 alias 别名 keyword 关键字,Shell保留字 function 函数,Shell函数 builtin 内建命令 ...