1、需求分析

CRM客户关系管理软件---》 学员管理

用户:企业内部用户

用户量:

业务场景:

2、数据库表设计

1 、表之间的对应关系

  1. from django.db import models
  2.  
  3. class Customer(models.Model):
  4. '''客户信息表'''
  5. pass
  6.  
  7. class CustomerFollowUp(models.Model):
  8. '''客户跟进表'''
  9. pass
  10.  
  11. class Course(models.Model):
  12. '''课程表'''
  13. pass
  14.  
  15. class ClassList(models.Model):
  16. '''班级表'''
  17. pass
  18.  
  19. class CourseRecord(models.Model):
  20. '''上课记录'''
  21. pass
  22.  
  23. class StudyRecord(models.Model):
  24. '''学习记录'''
  25. pass
  26.  
  27. class Enrollment(models.Model):
  28. '''报名表'''
  29. pass
  30.  
  31. class UserProfile(models.Model):
  32. '''账号表'''
  33. pass
  34.  
  35. class Role(models.Model):
  36. '''角色表'''
  37. pass

2、详细表设计models.py

  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. class Department(models.Model):
  6. """
  7. 部门表
  8. 市场部 1000
  9. 销售 1001
  10.  
  11. """
  12. title = models.CharField(verbose_name='部门名称', max_length=16)
  13. code = models.IntegerField(verbose_name='部门编号', unique=True, null=False)
  14.  
  15. def __str__(self):
  16. return self.title
  17.  
  18. class UserInfo(models.Model):
  19. """
  20. 员工表
  21. """
  22.  
  23. name = models.CharField(verbose_name='员工姓名', max_length=16)
  24. username = models.CharField(verbose_name='用户名', max_length=32)
  25. password = models.CharField(verbose_name='密码', max_length=64)
  26. email = models.EmailField(verbose_name='邮箱', max_length=64)
  27.  
  28. depart = models.ForeignKey(verbose_name='部门', to="Department", to_field="code",on_delete=True)
  29.  
  30. def __str__(self):
  31. return self.name
  32.  
  33. class Course(models.Model):
  34. """
  35. 课程表
  36. 如:
  37. Linux基础
  38. Linux架构师
  39. Python自动化开发精英班
  40. Python自动化开发架构师班
  41. Python基础班
  42. go基础班
  43. """
  44. name = models.CharField(verbose_name='课程名称', max_length=32)
  45.  
  46. def __str__(self):
  47. return self.name
  48.  
  49. class School(models.Model):
  50. """
  51. 校区表
  52. 如:
  53. 北京沙河校区
  54. 上海校区
  55.  
  56. """
  57. title = models.CharField(verbose_name='校区名称', max_length=32)
  58.  
  59. def __str__(self):
  60. return self.title
  61.  
  62. class ClassList(models.Model):
  63. """
  64. 班级表
  65. 如:
  66. Python全栈 面授班 5期 10000 2017-11-11 2018-5-11
  67. """
  68. school = models.ForeignKey(verbose_name='校区', to='School',on_delete=True)
  69. course = models.ForeignKey(verbose_name='课程名称', to='Course',on_delete=True)
  70.  
  71. semester = models.IntegerField(verbose_name="班级(期)")
  72. price = models.IntegerField(verbose_name="学费")
  73. start_date = models.DateField(verbose_name="开班日期")
  74. graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
  75. memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, )
  76. # teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart_id__in':[1003,1004],})
  77. teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',related_name="abc",limit_choices_to={"depart__in":[1002,1005]})
  78. tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',limit_choices_to={"depart":1001},on_delete=True)
  79.  
  80. def __str__(self):
  81. return "{0}({1}期)".format(self.course.name, self.semester)
  82.  
  83. class Customer(models.Model):
  84. """
  85. 客户表
  86. """
  87. qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一')
  88.  
  89. name = models.CharField(verbose_name='学生姓名', max_length=16)
  90. gender_choices = ((1, '男'), (2, '女'))
  91. gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)
  92.  
  93. education_choices = (
  94. (1, '重点大学'),
  95. (2, '普通本科'),
  96. (3, '独立院校'),
  97. (4, '民办本科'),
  98. (5, '大专'),
  99. (6, '民办专科'),
  100. (7, '高中'),
  101. (8, '其他')
  102. )
  103. education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )
  104. graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)
  105. major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True)
  106.  
  107. experience_choices = [
  108. (1, '在校生'),
  109. (2, '应届毕业'),
  110. (3, '半年以内'),
  111. (4, '半年至一年'),
  112. (5, '一年至三年'),
  113. (6, '三年至五年'),
  114. (7, '五年以上'),
  115. ]
  116. experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)
  117. work_status_choices = [
  118. (1, '在职'),
  119. (2, '无业')
  120. ]
  121. work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,
  122. null=True)
  123. company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)
  124. salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True)
  125.  
  126. source_choices = [
  127. (1, "qq群"),
  128. (2, "内部转介绍"),
  129. (3, "官方网站"),
  130. (4, "百度推广"),
  131. (5, "360推广"),
  132. (6, "搜狗推广"),
  133. (7, "腾讯课堂"),
  134. (8, "广点通"),
  135. (9, "高校宣讲"),
  136. (10, "渠道代理"),
  137. (11, "51cto"),
  138. (12, "智汇推"),
  139. (13, "网盟"),
  140. (14, "DSP"),
  141. (15, "SEO"),
  142. (16, "其它"),
  143. ]
  144. source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)
  145. referral_from = models.ForeignKey(
  146. 'self',
  147. blank=True,
  148. null=True,
  149. verbose_name="转介绍自学员",
  150. help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",
  151. related_name="internal_referral",on_delete=True
  152. )
  153. course = models.ManyToManyField(verbose_name="咨询课程", to="Course")
  154.  
  155. status_choices = [
  156. (1, "已报名"),
  157. (2, "未报名")
  158. ]
  159. status = models.IntegerField(
  160. verbose_name="状态",
  161. choices=status_choices,
  162. default=2,
  163. help_text=u"选择客户此时的状态"
  164. )
  165.  
  166. consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',
  167. limit_choices_to={'depart_id': 1001},on_delete=True)
  168.  
  169. date = models.DateField(verbose_name="咨询日期", auto_now_add=True)
  170. recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)
  171. last_consult_date = models.DateField(verbose_name="最后跟进日期", )
  172.  
  173. def __str__(self):
  174. return "姓名:{0},QQ:{1}".format(self.name, self.qq, )
  175.  
  176. class ConsultRecord(models.Model):
  177. """
  178. 客户跟进记录
  179. """
  180. customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer',on_delete=True)
  181. consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',on_delete=True)
  182. date = models.DateField(verbose_name="跟进日期", auto_now_add=True)
  183. note = models.TextField(verbose_name="跟进内容...")
  184.  
  185. def __str__(self):
  186. return self.customer.name + ":" + self.consultant.name
  187.  
  188. class Student(models.Model):
  189. """
  190. 学生表(已报名)
  191. """
  192. customer = models.OneToOneField(verbose_name='客户信息', to='Customer',on_delete=True)
  193.  
  194. username = models.CharField(verbose_name='用户名', max_length=32)
  195. password = models.CharField(verbose_name='密码', max_length=64)
  196. emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')
  197.  
  198. class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True)
  199. company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)
  200. location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)
  201. position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)
  202. salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)
  203. welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)
  204. date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)
  205. memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True)
  206.  
  207. def __str__(self):
  208. return self.username
  209.  
  210. class CourseRecord(models.Model):
  211. """
  212. 上课记录表
  213. """
  214. class_obj = models.ForeignKey(verbose_name="班级", to="ClassList",on_delete=True)
  215. day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
  216. teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={"depart_id__in":[1002,1003]},on_delete=True)
  217. date = models.DateField(verbose_name="上课日期", auto_now_add=True)
  218.  
  219. course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)
  220. course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)
  221. has_homework = models.BooleanField(default=True, verbose_name="本节有作业")
  222. homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)
  223. homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)
  224. exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True)
  225.  
  226. def __str__(self):
  227. return "{0} day{1}".format(self.class_obj, self.day_num)
  228.  
  229. class StudyRecord(models.Model):
  230. course_record = models.ForeignKey(verbose_name="第几天课程", to="CourseRecord",on_delete=True)
  231. student = models.ForeignKey(verbose_name="学员", to='Student',on_delete=True)
  232. record_choices = (('checked', "已签到"),
  233. ('vacate', "请假"),
  234. ('late', "迟到"),
  235. ('noshow', "缺勤"),
  236. ('leave_early', "早退"),
  237. )
  238. record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)
  239. score_choices = ((100, 'A+'),
  240. (90, 'A'),
  241. (85, 'B+'),
  242. (80, 'B'),
  243. (70, 'B-'),
  244. (60, 'C+'),
  245. (50, 'C'),
  246. (40, 'C-'),
  247. (0, ' D'),
  248. (-1, 'N/A'),
  249. (-100, 'COPY'),
  250. (-1000, 'FAIL'),
  251. )
  252. score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
  253. homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)
  254. note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True)
  255.  
  256. homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)
  257. stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)
  258. date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True)
  259.  
  260. def __str__(self):
  261. return "{0}-{1}".format(self.course_record, self.student)

3、起步

1、urls

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3.  
  4. from stark.service.stark import site
  5. urlpatterns = [
  6. url(r'^admin/', admin.site.urls),
  7. url(r'^stark/', site.urls),
  8. ]

2、导入stark组件,配置

stark/apps.py配置

  1. from django.apps import AppConfig
  2. from django.utils.module_loading import autodiscover_modules
  3.  
  4. class StarkConfig(AppConfig):
  5. name = 'stark'
  6.  
  7. def ready(self):
  8. autodiscover_modules('stark')

crm.apps.py不配置

3、Xadmin配置

  1. from .models import *
  2. from stark.service.stark import site
  3.  
  4. site.register(Department)
  5. site.register(UserInfo)
  6. site.register(Course)
  7. site.register(School)
  8. site.register(ClassList)
  9. site.register(Customer)
  10. site.register(ConsultRecord)
  11. site.register(Student)
  12. site.register(CourseRecord)
  13. site.register(StudyRecord)

4、录入数据

1、校区school

2、员工表userinfo

3、班级表classlist

4、公开客户表customer

5、部门表department

6、课程表course

5、知识点

1、limit_choices_to

model与form组件的多对多关系如何渲染的

limit_choices_to

  1. teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name="abc",
  2. limit_choices_to={"depart__in": [1002, 1005]})
  3. tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',
  4. limit_choices_to={"depart": 1001}, on_delete=True)

2、自定制 display_classname

  1. class ClassConfig(ModelStark):
  2.  
  3. def display_classname(self,obj=None,header=False):
  4. if header:
  5. return "班级名称"
  6. class_name="%s(%s)"%(obj.course.name,str(obj.semester))
  7. return class_name
  8.  
  9. list_display = [display_classname,"tutor","teachers"]
  10.  
  11. site.register(ClassList,ClassConfig)

3、obj.get_gender_display()  显示option的值

  1. class CusotmerConfig(ModelStark):
  2.  
  3. def display_gender(self,obj=None,header=False):
  4. if header:
  5. return "性别"
  6. return obj.get_gender_display()
  7.  
  8. # list_display = ["name",'gender',"consultant",]
  9. list_display = ["name",display_gender,"consultant",]

4.mark_safe()

  1. from django.utils.safestring import mark_safe
  2.  
  3. class CusotmerConfig(ModelStark):
  4.  
  5. def display_course(self,obj=None,header=False):
  6. if header:
  7. return "咨询课程"
  8. temp=[]
  9. for course in obj.course.all():
  10. s="<a href='/stark/crm/customer/cancel_course/%s/%s' style='border:1px solid #369;padding:3px 6px'><span>%s</span></a>&nbsp;"%(obj.pk,course.pk,course.name,)
  11. temp.append(s)
  12. return mark_safe("".join(temp))
  13.  
  14. # list_display = ["name",'course',"consultant",]
  15. list_display = ["name",display_course,"consultant",]

5、extra_url()  额外的url

  1. def extra_url(self):
  2.  
  3. return []
  4.  
  5. def get_urls_2(self):
  6.  
  7. temp = []
  8.  
  9. model_name=self.model._meta.model_name
  10. app_label=self.model._meta.app_label
  11.  
  12. temp.append(url(r"^add/", self.add_view,name="%s_%s_add"%(app_label,model_name)))
  13. temp.append(url(r"^(\d+)/delete/", self.delete_view,name="%s_%s_delete"%(app_label,model_name)))
  14. temp.append(url(r"^(\d+)/change/", self.change_view,name="%s_%s_change"%(app_label,model_name)))
  15. temp.append(url(r"^$", self.list_view,name="%s_%s_list"%(app_label,model_name)))
  16.  
  17. temp.extend(self.extra_url())
  18.  
  19. return temp

6、课程点击取消

  1. class CusotmerConfig(ModelStark):
  2.  
  3. def display_course(self,obj=None,header=False):
  4. if header:
  5. return "咨询课程"
  6. temp=[]
  7. for course in obj.course.all():
  8. s="<a href='/stark/crm/customer/cancel_course/%s/%s' style='border:1px solid #369;padding:3px 6px'><span>%s</span></a>&nbsp;"%(obj.pk,course.pk,course.name,)
  9. temp.append(s)
  10. return mark_safe("".join(temp))
  11.  
  12. # list_display = ["name",'gender','course',"consultant",]
  13. list_display = ["name",display_gender,display_course,"consultant",]
  14.  
  15. def cancel_course(self,request,customer_id,course_id):
  16. print(customer_id,course_id)
  17.  
  18. obj=Customer.objects.filter(pk=customer_id).first()
  19. obj.course.remove(course_id)
  20. return redirect(self.get_list_url())
  21.  
  22. def extra_url(self):
  23. temp=[]
  24. temp.append(url(r"cancel_course/(\d+)/(\d+)",self.cancel_course))
  25. return temp
  26.  
  27. site.register(Customer,CusotmerConfig)

6、代码

1、starkadmin代码

  1. # by luffycity.com
  2.  
  3. from stark.service.stark import site,ModelStark
  4.  
  5. from .models import *
  6. site.register(School)
  7.  
  8. class UserConfig(ModelStark):
  9. list_display = ["name","email","depart"]
  10.  
  11. site.register(UserInfo,UserConfig)
  12.  
  13. class ClassConfig(ModelStark):
  14.  
  15. def display_classname(self,obj=None,header=False):
  16. if header:
  17. return "班级名称"
  18. class_name="%s(%s)"%(obj.course.name,str(obj.semester))
  19. return class_name
  20.  
  21. list_display = [display_classname,"tutor","teachers"]
  22.  
  23. site.register(ClassList,ClassConfig)
  24.  
  25. from django.utils.safestring import mark_safe
  26. from django.conf.urls import url
  27.  
  28. from django.shortcuts import HttpResponse,redirect
  29.  
  30. class CusotmerConfig(ModelStark):
  31.  
  32. def display_gender(self,obj=None,header=False):
  33. if header:
  34. return "性别"
  35. return obj.get_gender_display()
  36.  
  37. def display_course(self,obj=None,header=False):
  38. if header:
  39. return "咨询课程"
  40. temp=[]
  41. for course in obj.course.all():
  42. s="<a href='/stark/crm/customer/cancel_course/%s/%s' style='border:1px solid #369;padding:3px 6px'><span>%s</span></a>&nbsp;"%(obj.pk,course.pk,course.name,)
  43. temp.append(s)
  44. return mark_safe("".join(temp))
  45.  
  46. # list_display = ["name",'gender','course',"consultant",]
  47. list_display = ["name",display_gender,display_course,"consultant",]
  48.  
  49. def cancel_course(self,request,customer_id,course_id):
  50. print(customer_id,course_id)
  51.  
  52. obj=Customer.objects.filter(pk=customer_id).first()
  53. obj.course.remove(course_id)
  54. return redirect(self.get_list_url())
  55.  
  56. def extra_url(self):
  57.  
  58. temp=[]
  59.  
  60. temp.append(url(r"cancel_course/(\d+)/(\d+)",self.cancel_course))
  61.  
  62. return temp
  63.  
  64. site.register(Customer,CusotmerConfig)
  65. site.register(Department)
  66. site.register(Course)
  67. site.register(ConsultRecord)
  68. site.register(CourseRecord)
  69. site.register(StudyRecord)
  70. site.register(Student)

2、stark组件代码:修改过

  1. # by luffycity.com
  2. from django.conf.urls import url
  3.  
  4. from django.shortcuts import HttpResponse,render,redirect
  5. from django.urls import reverse
  6. from django.db.models import Q
  7. from django.utils.safestring import mark_safe
  8.  
  9. from stark.utils.page import Pagination
  10. from django.db.models.fields.related import ManyToManyField,ForeignKey
  11.  
  12. class ShowList(object):
  13. def __init__(self,config,data_list,request):
  14. self.config=config
  15. self.data_list=data_list
  16. self.request=request
  17. #分页
  18. data_count=self.data_list.count()
  19. current_page=int(self.request.GET.get("page",1))
  20. base_path=self.request.path
  21.  
  22. self.pagination=Pagination(current_page,data_count,base_path,self.request.GET,per_page_num=10, pager_count=11, )
  23. self.page_data=self.data_list[self.pagination.start:self.pagination.end]
  24.  
  25. # actions
  26. self.actions=self.config.new_actions() # [patch_init,]
  27.  
  28. def get_filter_linktags(self):
  29. print("list_filter:",self.config.list_filter)
  30. link_dic={}
  31. import copy
  32.  
  33. for filter_field in self.config.list_filter: # ["title","publish","authors",]
  34. params = copy.deepcopy(self.request.GET)
  35.  
  36. cid=self.request.GET.get(filter_field,0)
  37.  
  38. print("filter_field",filter_field) # "publish"
  39. filter_field_obj=self.config.model._meta.get_field(filter_field)
  40. print("filter_field_obj",filter_field_obj)
  41. print(type(filter_field_obj))
  42. from django.db.models.fields.related import ForeignKey
  43. from django.db.models.fields.related import ManyToManyField
  44. print("rel======...",filter_field_obj.rel)
  45.  
  46. if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
  47. data_list=filter_field_obj.rel.to.objects.all()# publish1,publish2...】
  48. else:
  49. data_list=self.config.model.objects.all().values("pk",filter_field)
  50. print("data_list",data_list)
  51.  
  52. temp=[]
  53. # 处理 全部标签
  54. if params.get(filter_field):
  55. del params[filter_field]
  56. temp.append("<a href='?%s'>全部</a>"%params.urlencode())
  57. else:
  58. temp.append("<a class='active' href='#'>全部</a>")
  59.  
  60. # 处理 数据标签
  61. for obj in data_list:
  62. if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
  63. pk=obj.pk
  64. text=str(obj)
  65. params[filter_field] = pk
  66. else: # data_list= [{"pk":1,"title":"go"},....]
  67. print("========")
  68. pk=obj.get("pk")
  69. text=obj.get(filter_field)
  70. params[filter_field] =text
  71.  
  72. _url=params.urlencode()
  73. if cid==str(pk) or cid==text:
  74. link_tag="<a class='active' href='?%s'>%s</a>"%(_url,text)
  75. else:
  76. link_tag = "<a href='?%s'>%s</a>" % (_url, text)
  77. temp.append(link_tag)
  78.  
  79. link_dic[filter_field]=temp
  80.  
  81. return link_dic
  82.  
  83. def get_action_list(self):
  84. temp=[]
  85. for action in self.actions:
  86. temp.append({
  87. "name":action.__name__,
  88. "desc":action.short_description
  89. }) # [{"name":""patch_init,"desc":"批量初始化"}]
  90.  
  91. return temp
  92.  
  93. def get_header(self):
  94. # 构建表头
  95. header_list = []
  96. print("header",
  97. self.config.new_list_play()) # [checkbox,"pk","name","age",edit ,deletes] 【checkbox ,"__str__", edit ,deletes】
  98.  
  99. for field in self.config.new_list_play():
  100.  
  101. if callable(field):
  102. # header_list.append(field.__name__)
  103. val = field(self.config, header=True)
  104. header_list.append(val)
  105.  
  106. else:
  107. if field == "__str__":
  108. header_list.append(self.config.model._meta.model_name.upper())
  109. else:
  110. # header_list.append(field)
  111. val = self.config.model._meta.get_field(field).verbose_name
  112. header_list.append(val)
  113. return header_list
  114.  
  115. def get_body(self):
  116. # 构建表单数据
  117. new_data_list = []
  118. for obj in self.page_data:
  119. temp = []
  120.  
  121. for filed in self.config.new_list_play(): # ["__str__",] ["pk","name","age",edit]
  122.  
  123. if callable(filed):
  124. print("obj-----:",obj)
  125. val = filed(self.config, obj)
  126. else:
  127. try:
  128. field_obj=self.config.model._meta.get_field(filed)
  129. if isinstance(field_obj,ManyToManyField):
  130. ret = getattr(obj,filed).all()
  131. t=[]
  132. for mobj in ret:
  133. t.append(str(mobj))
  134. val=",".join(t)
  135. else:
  136.  
  137. val = getattr(obj, filed)
  138. if filed in self.config.list_display_links:
  139. # "app01/userinfo/(\d+)/change"
  140. _url = self.config.get_change_url(obj)
  141.  
  142. val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
  143.  
  144. except Exception as e:
  145. val = getattr(obj, filed)
  146.  
  147. temp.append(val)
  148.  
  149. new_data_list.append(temp)
  150. return new_data_list
  151.  
  152. '''
  153. [
  154. [1,"alex",12],
  155. [1,"alex",12],
  156. [1,"alex",12],
  157. [1,"alex",12],
  158.  
  159. ]
  160.  
  161. '''
  162.  
  163. class ModelStark(object):
  164.  
  165. list_display=["__str__",]
  166. list_display_links=[]
  167. modelform_class=None
  168. search_fields=[]
  169. actions = []
  170. list_filter=[]
  171.  
  172. def patch_delete(self, request, queryset):
  173.  
  174. queryset.delete()
  175.  
  176. patch_delete.short_description = "批量删除"
  177.  
  178. def __init__(self,model,site):
  179. self.model=model
  180. self.site=site
  181.  
  182. # 删除 编辑,复选框
  183. def edit(self,obj=None,header=False):
  184. if header:
  185. return "操作"
  186. #return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
  187. _url=self.get_change_url(obj)
  188.  
  189. return mark_safe("<a href='%s'>编辑</a>"%_url)
  190.  
  191. def deletes(self,obj=None,header=False):
  192. if header:
  193. return "操作"
  194. # return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
  195.  
  196. _url=self.get_delete_url(obj)
  197.  
  198. return mark_safe("<a href='%s'>删除</a>" % _url)
  199.  
  200. def checkbox(self,obj=None,header=False):
  201. if header:
  202. return mark_safe('<input id="choice" type="checkbox">')
  203.  
  204. return mark_safe('<input class="choice_item" type="checkbox" name="selected_pk" value="%s">'%obj.pk)
  205.  
  206. def get_modelform_class(self):
  207.  
  208. if not self.modelform_class:
  209. from django.forms import ModelForm
  210. from django.forms import widgets as wid
  211. class ModelFormDemo(ModelForm):
  212. class Meta:
  213. model = self.model
  214. fields = "__all__"
  215. labels={
  216. ""
  217. }
  218. return ModelFormDemo
  219. else:
  220. return self.modelform_class
  221.  
  222. def get_new_form(self,form):
  223.  
  224. for bfield in form:
  225. from django.forms.boundfield import BoundField
  226. print(bfield.field) # 字段对象
  227. print("name",bfield.name) # 字段名(字符串)
  228. print(type(bfield.field)) # 字段类型
  229. from django.forms.models import ModelChoiceField
  230. if isinstance(bfield.field,ModelChoiceField):
  231. bfield.is_pop=True
  232.  
  233. print("=======>",bfield.field.queryset.model) # 一对多或者多对多字段的关联模型表
  234.  
  235. related_model_name=bfield.field.queryset.model._meta.model_name
  236. related_app_label=bfield.field.queryset.model._meta.app_label
  237.  
  238. _url=reverse("%s_%s_add"%(related_app_label,related_model_name))
  239. bfield.url=_url+"?pop_res_id=id_%s"%bfield.name
  240.  
  241. return form
  242.  
  243. def add_view(self, request):
  244. ModelFormDemo = self.get_modelform_class()
  245. form = ModelFormDemo()
  246.  
  247. form=self.get_new_form(form)
  248.  
  249. if request.method=="POST":
  250. form = ModelFormDemo(request.POST)
  251. if form.is_valid():
  252. obj=form.save()
  253.  
  254. pop_res_id=request.GET.get("pop_res_id")
  255.  
  256. if pop_res_id:
  257. res ={"pk":obj.pk,"text":str(obj),"pop_res_id":pop_res_id}
  258. import json
  259. return render(request, "pop.html", {"res":res})
  260.  
  261. else:
  262. return redirect(self.get_list_url())
  263.  
  264. return render(request, "add_view.html", locals())
  265.  
  266. def delete_view(self, request, id):
  267. url = self.get_list_url()
  268. if request.method=="POST":
  269. self.model.objects.filter(pk=id).delete()
  270. return redirect(url)
  271.  
  272. return render(request, "delete_view.html", locals())
  273.  
  274. def change_view(self, request, id):
  275. ModelFormDemo = self.get_modelform_class()
  276. print("=====id",id)
  277. edit_obj = self.model.objects.filter(pk=id).first()
  278.  
  279. if request.method=="POST":
  280. form = ModelFormDemo(request.POST,instance=edit_obj)
  281. if form.is_valid():
  282. form.save()
  283. return redirect(self.get_list_url())
  284.  
  285. return render(request, "add_view.html", locals())
  286.  
  287. print("***********",edit_obj)
  288. form = ModelFormDemo(instance=edit_obj)
  289. form = self.get_new_form(form)
  290.  
  291. return render(request, "change_view.html", locals())
  292.  
  293. def new_list_play(self):
  294. temp=[]
  295. temp.append(ModelStark.checkbox)
  296. temp.extend(self.list_display)
  297. if not self.list_display_links:
  298. temp.append(ModelStark.edit)
  299. temp.append(ModelStark.deletes)
  300. return temp
  301.  
  302. def new_actions(self):
  303. temp=[]
  304. temp.append(ModelStark.patch_delete)
  305. temp.extend(self.actions)
  306.  
  307. return temp
  308.  
  309. def get_change_url(self,obj):
  310. model_name = self.model._meta.model_name
  311. app_label = self.model._meta.app_label
  312. print("obj===========",obj)
  313. _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))
  314.  
  315. return _url
  316.  
  317. def get_delete_url(self, obj):
  318. model_name = self.model._meta.model_name
  319. app_label = self.model._meta.app_label
  320.  
  321. _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))
  322.  
  323. return _url
  324.  
  325. def get_add_url(self):
  326.  
  327. model_name = self.model._meta.model_name
  328. app_label = self.model._meta.app_label
  329.  
  330. _url = reverse("%s_%s_add" % (app_label, model_name))
  331.  
  332. return _url
  333.  
  334. def get_list_url(self):
  335.  
  336. model_name = self.model._meta.model_name
  337. app_label = self.model._meta.app_label
  338.  
  339. _url = reverse("%s_%s_list" % (app_label, model_name))
  340.  
  341. return _url
  342.  
  343. def get_serach_conditon(self,request):
  344. key_word = request.GET.get("q","")
  345. self.key_word=key_word
  346.  
  347. search_connection = Q()
  348. if key_word:
  349. # self.search_fields # ["title","price"]
  350. search_connection.connector = "or"
  351. for search_field in self.search_fields:
  352. search_connection.children.append((search_field + "__contains", key_word))
  353. return search_connection
  354.  
  355. def get_filter_condition(self,request):
  356. filter_condition=Q()
  357.  
  358. for filter_field,val in request.GET.items():
  359. if filter_field in self.list_filter:
  360. filter_condition.children.append((filter_field,val))
  361.  
  362. return filter_condition
  363.  
  364. def list_view(self, request):
  365. if request.method=="POST": # action
  366. print("POST:",request.POST)
  367. action=request.POST.get("action") # patch_init
  368. selected_pk=request.POST.getlist("selected_pk")
  369. action_func=getattr(self,action)
  370. queryset=self.model.objects.filter(pk__in=selected_pk)
  371. ret=action_func(request,queryset)
  372.  
  373. #return ret
  374.  
  375. # 获取serach的Q对象
  376. search_connection=self.get_serach_conditon(request)
  377.  
  378. # 获取filter构建Q对象
  379.  
  380. filter_condition=self.get_filter_condition(request)
  381.  
  382. # 筛选获取当前表所有数据
  383. data_list=self.model.objects.all().filter(search_connection).filter(filter_condition) # 【obj1,obj2,....】
  384.  
  385. # 按这ShowList展示页面
  386. showlist=ShowList(self,data_list,request)
  387.  
  388. # 构建一个查看URL
  389. add_url=self.get_add_url()
  390. return render(request, "list_view.html", locals())
  391.  
  392. def extra_url(self):
  393.  
  394. return []
  395.  
  396. def get_urls_2(self):
  397.  
  398. temp = []
  399.  
  400. model_name=self.model._meta.model_name
  401. app_label=self.model._meta.app_label
  402.  
  403. temp.append(url(r"^add/", self.add_view,name="%s_%s_add"%(app_label,model_name)))
  404. temp.append(url(r"^(\d+)/delete/", self.delete_view,name="%s_%s_delete"%(app_label,model_name)))
  405. temp.append(url(r"^(\d+)/change/", self.change_view,name="%s_%s_change"%(app_label,model_name)))
  406. temp.append(url(r"^$", self.list_view,name="%s_%s_list"%(app_label,model_name)))
  407.  
  408. temp.extend(self.extra_url())
  409.  
  410. return temp
  411.  
  412. @property
  413. def urls_2(self):
  414. print(self.model)
  415. return self.get_urls_2(), None, None
  416.  
  417. class StarkSite(object):
  418. def __init__(self):
  419. self._registry={}
  420.  
  421. def register(self,model,stark_class=None):
  422. if not stark_class:
  423. stark_class=ModelStark
  424.  
  425. self._registry[model] = stark_class(model, self)
  426.  
  427. def get_urls(self):
  428. temp=[]
  429. for model,stark_class_obj in self._registry.items():
  430. model_name=model._meta.model_name
  431. app_label=model._meta.app_label
  432. # 分发增删改查
  433. temp.append(url(r"^%s/%s/"%(app_label,model_name),stark_class_obj.urls_2))
  434.  
  435. '''
  436. url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
  437. url(r"^app01/book/",ModelStark(Book).urls_2),
  438.  
  439. '''
  440. return temp
  441.  
  442. @property
  443. def urls(self):
  444.  
  445. return self.get_urls(),None,None
  446.  
  447. site=StarkSite()

1 CRM需求分析,数据库表,录入数据的更多相关文章

  1. MySQL数据库表的数据插入、修改、删除、查询操作及实例应用

    一.MySQL数据库表的数据插入.修改.删除和查询 CREATE DATABASE db0504; USE db0504; CREATE TABLE student ( sno ) NOT NULL ...

  2. C# - VS2019 WinFrm应用程序连接Access数据库,并简单实现数据库表的数据查询、显示

    序言 众所周知,Oracle数据库和MySQL数据库一般在大型项目中使用,在某些小型项目中Access数据库使用较为方便,今天记录一下VS2019 WinFrm应用程序连接Access数据库,并实现数 ...

  3. 查看数据库表的数据量和SIZE大小的脚本修正

    在使用桦仔的分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)的脚本时,遇到下面一些错误 这个是因为这些表的Schema是Maint,而不是默认的dbo,造成下面这段SQ ...

  4. Oracle 通过dblink和job方式实现两个数据库表之间数据同步

    需求是需要将Database_A中的dev_test表中的数据同步到Database_B中的dev_test表中. 因为是通过Database_B去同步Database_A库中的数据,所以操作都建立在 ...

  5. 我们在删除SQL Sever某个数据库表中数据的时候,希望ID重新从1开始,而不是紧跟着最后一个ID开始需要的命令

    一.如果数据重要,请先备份数据 二.删除表中数据 SQL: Delete From ('表名')  如:Delete From abcd 三.执行新语句 SQL: dbcc checkident('表 ...

  6. mybatis使用注解往postgresql数据库表insert数据[主键自增]的写法

    建表SQL: DROP TABLE IF EXISTS person; CREATE TABLE person( person_id serial PRIMARY KEY NOT NULL, pers ...

  7. U8API——向U8数据库表导入数据

    一.打开API资源管理器 替换两个引用 打开应用实例,选择相应的功能 复制相应的封装类到自己的目录下 在数据库新建临时表,与目标表相同 数据导入: 思路:先将要导入的数据导入到与U8目标表相同的临时表 ...

  8. Oracle数据库表空间 数据文件 用户 以及表创建的SQL代码

    --create the tablespace CREATE SMALLFILE TABLESPACE "TABLE_CONTAINER" --创建表空间 DATAFILE 'E: ...

  9. MySQL----DQL(查询数据库表中数据)

    ##DQL:查询表中的记录 1.语法: select 字段列名 from 表名列表 where 条件列表 group  by 分组字段 having  分组之后的条件 order  by 排序 lim ...

  10. c# .Net :Excel NPOI导入导出操作教程之数据库表信息数据导出到一个Excel文件并写到磁盘示例分享

      string sql = @"select * from T_Excel"; ----------------DataTable Star----------------    ...

随机推荐

  1. [VS2008] 安装 AnkhSVN 后,选项中选择它,Pending Changes 窗口一闪而过,源代码管理工具自动跳回 【None】

    执行以下命令以修复: "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe" /re ...

  2. 新建一个去除storyboard的项目

    新建一个去除storyboard的项目 1. 新建项目并删除 *.storyboard 以及与之相关的杂项 2. 设置 UIWindow 的 rootViewController 复制粘贴代码如下 s ...

  3. [控件] AngleGradientView

    AngleGradientView 效果 说明 1. 用源码产生带环形渐变色的view 2. 可以配合maskView一起使用 (上图中的右下角图片的效果) 源码 https://github.com ...

  4. spider-抓取页面内容

    # -*- coding: UTF-8 -*- from HTMLParser import HTMLParser import sys,urllib2,string,re,json reload(s ...

  5. Redis学习---CentOs/RedHat下Redis的安装

    redis是C语言开发,建议在linux上运行,本教程使用Centos6.4作为安装环境.      安装redis需要先将官网下载的源码进行编译,编译依赖gcc环境,如果没有gcc环境,需要安装gc ...

  6. 铁乐学python_day29_模块与包学习4

    大部份内容摘自授课老师的博客http://www.cnblogs.com/Eva-J/ 编译python文件 编译python文件是为了提高加载模块的速度,强调强调强调:提高的是加载速度而绝非运行速度 ...

  7. 预估高并发下API服务器数量

    我的主要工作就是API的编写,应该关注API的响应时间,以及并发时候的响应.那么如何测试API响应时间,以及预计高并发服务器压力呢? 从访问日志开始查起. 1 首先统计API每日访问总数.举例假设某个 ...

  8. debian 7上安装svn

    1.在终端中直接输入  sudo apt-get install subversion,选择安装即可 2.查看版本命令 svnserve --version(更多命令直接键入svnserve --he ...

  9. oracle 禁用/启动job

    注意:dbms_job只能在job的所在用户使用,如果broken其它用户的job用dbms_ijob dbms_job只能在当期用户内创建job.修改和删除job,不能对其他用户的job进行操作;s ...

  10. chrome的uget扩展程序红色 Unable to connect with uget-integrator问题

    我们根据网上的教程在ubuntu16.04中安装下载工具uget+aria2并配置chrome时,最后重新打开chrome浏览器,发现uget扩展程序是红色的,点开看到”Unable to conne ...