zoukankan      html  css  js  c++  java
  • 项目一:CRM(客户关系管理系统)--1

    Djangoadmin已经为我们做好了,很完善的后台管理体系,但页面过于丑陋,自定义的能力还是有局限性的。特此,重写admin后台管理体系,同时也是考虑到其他轻量级框架并没有类似Django这么完善的admin!写成独立的app,便宜更好的进行复用迁移。

    1. 创建工程和项目

    命名根据自己的喜好吧,推荐使用PyCharm进行创建,减少一些配置操作,当然不要忘记在settings.py的一些配置!

    目录结构如下:

    ├─consultant  #销售
    │  ├─migrations
    │  │  └─__pycache__
    │  └─__pycache__
    ├─CRM    #主app
    │  ├─migrations
    │  │  └─__pycache__
    │  └─__pycache__
    ├─king_admin #重构的admin
    │  ├─migrations
    │  │  └─__pycache__
    │  ├─templatetags
    │  │  └─__pycache__
    │  └─__pycache__
    ├─PrefectCRM_new #工程
    │  └─__pycache__
    ├─statics
    │  ├─css
    │  ├─imgs
    │  ├─js
    │  └─plugins
    ├─student  #学生
    │  ├─migrations
    │  │  └─__pycache__
    │  └─__pycache__
    ├─templates
    │  ├─consultant
    │  ├─king_admin
    │  └─student
    └─utils
    由于在数据库表中,绑定了一些路由映射关系,顺便将路由的结构也显示一下:
     1 #这是总的urls.py中的配置,独立将在下面一次贴出来
     2 from django.conf.urls import url,include
     3 from django.contrib import admin
     4 urlpatterns = [
     5     url(r'^admin/', admin.site.urls),
     6     url(r'^crm/', include('CRM.urls')),
     7     url(r'^student/', include('student.urls')),
     8     url(r'^consultant/', include('consultant.urls')),
     9     url(r'^king_admin/', include('king_admin.urls')),
    10 ]

    2. 表结构设计

    表结构设计是非常关键的步骤,也是最难点!这会影响你以后的程序设计,稍有疏漏,很可能会导致你要进行代码重构或者一路填坑...

    由于要做的是CRM系统,这里就以XXX公司作为案例。

    在进行具体的代码之前,我们先进行一些数据关系的处理,这里推荐大家使用ER图(mac上我使用MindNode)。我这里是通过先前搞好的数据结构和ER图,就不在重复赘述,直接上处理好后的图和代码: 

    ER思维导图:

    数据关系图:

     在主appCRM中的models.py中创建数据结构:

      1 from django.db import models
      2 from django.contrib.auth.models import User
      3 # Create your models here.
      4 class Customer(models.Model):
      5     '''客户信息表'''
      6     name = models.CharField(max_length=32,blank=True,null=True)
      7     qq = models.CharField(max_length=64,unique=True)
      8     qq_name = models.CharField(max_length=64,blank=True,null=True)
      9     phone = models.CharField(max_length=64,blank=True,null=True)
     10     source_choices = ((0,'转介绍'),
     11                       (1,'QQ群'),
     12                       (2,'官网'),
     13                       (3,'百度推广'),
     14                       (4,'51CTO'),
     15                       (5,'知乎'),
     16                       (6,'市场推广')
     17                       )
     18     source = models.SmallIntegerField(choices=source_choices)
     19     referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True)
     20     consult_course = models.ForeignKey("Course",verbose_name="咨询课程")
     21     content = models.TextField(verbose_name="咨询详情")
     22     tags = models.ManyToManyField("Tag",blank=True)
     23     status_choices = ((0,'已报名'),
     24                       (1,'未报名'),
     25                       )
     26     status = models.SmallIntegerField(choices=status_choices,default=1)
     27     consultant = models.ForeignKey("UserProfile")
     28     memo = models.TextField(blank=True,null=True)
     29     date = models.DateTimeField(auto_now_add=True)
     30     def __str__(self):
     31         return self.qq
     32     class Meta:
     33         verbose_name ="客户表"
     34         verbose_name_plural ="客户表"
     35 class Tag(models.Model):
     36     name = models.CharField(unique=True,max_length=32)
     37     def __str__(self):
     38         return self.name
     39     class Meta:
     40         verbose_name = "标签"
     41         verbose_name_plural = "标签"
     42 class CustomerFollowUp(models.Model):
     43     '''客户跟进表'''
     44     customer = models.ForeignKey("Customer")
     45     content = models.TextField(verbose_name="跟进内容")
     46     consultant = models.ForeignKey("UserProfile")
     47     intention_choices  = ((0,'2周内报名'),
     48                           (1,'1个月内报名'),
     49                           (2,'近期无报名计划'),
     50                           (3,'已在其它机构报名'),
     51                           (4,'已报名'),
     52                           (5,'已拉黑'),
     53                           )
     54     intention = models.SmallIntegerField(choices=intention_choices)
     55     date = models.DateTimeField(auto_now_add=True)
     56     def __str__(self):
     57         return "<%s : %s>" %(self.customer.qq,self.intention)
     58     class Meta:
     59         verbose_name = '客户追踪'
     60         verbose_name_plural = "客户追踪"
     61 class Course(models.Model):
     62     '''课程表'''
     63     name = models.CharField(max_length=64,unique=True)
     64     price = models.PositiveSmallIntegerField()
     65     period = models.PositiveSmallIntegerField(verbose_name="周期(月)")
     66     outline = models.TextField()
     67     def __str__(self):
     68         return self.name
     69     class Meta:
     70         verbose_name = "课程表"
     71         verbose_name_plural = "课程表"
     72 class Branch(models.Model):
     73     '''校区'''
     74     name = models.CharField(max_length=128,unique=True)
     75     addr = models.CharField(max_length=128)
     76     def __str__(self):
     77         return self.name
     78     class Meta:
     79         verbose_name = "校区"
     80         verbose_name_plural = "校区"
     81 class ClassList(models.Model):
     82     '''班级表'''
     83     branch = models.ForeignKey("Branch",verbose_name="校区")
     84     course = models.ForeignKey("Course")
     85     class_type_choices = ((0,'面授(脱产)'),
     86                           (1,'面授(周末)'),
     87                           (2,'网络班')
     88                           )
     89     class_type = models.SmallIntegerField(choices=class_type_choices,verbose_name="班级类型")
     90     semester = models.PositiveSmallIntegerField(verbose_name="学期")
     91     teachers = models.ManyToManyField("UserProfile")
     92     start_date = models.DateField(verbose_name="开班日期")
     93     end_date = models.DateField(verbose_name="结业日期",blank=True,null=True)
     94     def __str__(self):
     95         return "%s %s %s" %(self.branch,self.course,self.semester)
     96     class Meta:
     97         unique_together = ('branch','course','semester')
     98         verbose_name_plural = "班级"
     99         verbose_name = "班级"
    100 class CourseRecord(models.Model):
    101     '''上课记录'''
    102     from_class = models.ForeignKey("ClassList",verbose_name="班级")
    103     day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)")
    104     teacher = models.ForeignKey("UserProfile")
    105     has_homework = models.BooleanField(default=True)
    106     homework_title = models.CharField(max_length=128,blank=True,null=True)
    107     homework_content = models.TextField(blank=True,null=True)
    108     outline = models.TextField(verbose_name="本节课程大纲")
    109     date = models.DateField(auto_now_add=True)
    110     def __str__(self):
    111         return "%s %s" %(self.from_class,self.day_num)
    112     class Meta:
    113         unique_together = ("from_class", "day_num")
    114         verbose_name_plural = "上课记录"
    115 class StudyRecord(models.Model):
    116     '''学习记录'''
    117     student = models.ForeignKey("Enrollment")
    118     course_record = models.ForeignKey("CourseRecord")
    119     attendance_choices = ((0,'已签到'),
    120                           (1,'迟到'),
    121                           (2,'缺勤'),
    122                           (3,'早退'),
    123                           )
    124     attendance = models.SmallIntegerField(choices=attendance_choices,default=0)
    125     score_choices = ((100,"A+"),
    126                      (90,"A"),
    127                      (85,"B+"),
    128                      (80,"B"),
    129                      (75,"B-"),
    130                      (70,"C+"),
    131                      (60,"C"),
    132                      (40,"C-"),
    133                      (-50,"D"),
    134                      (-100,"COPY"),
    135                      (0,"N/A"),
    136                      )
    137     score = models.SmallIntegerField(choices=score_choices,default=0)
    138     memo = models.TextField(blank=True,null=True)
    139     date = models.DateField(auto_now_add=True)
    140     def __str__(self):
    141         return "%s %s %s" %(self.student,self.course_record,self.score)
    142     class Meta:
    143         unique_together = ('student','course_record')
    144         verbose_name_plural = "学习记录"
    145 class Enrollment(models.Model):
    146     '''报名表'''
    147     customer = models.ForeignKey("Customer")
    148     enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级")
    149     consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问")
    150     contract_agreed = models.BooleanField(default=False,verbose_name="学员已同意合同条款")
    151     contract_approved = models.BooleanField(default=False,verbose_name="合同已审核")
    152     date = models.DateTimeField(auto_now_add=True)
    153     def __str__(self):
    154         return "%s %s" %(self.customer,self.enrolled_class)
    155     class Meta:
    156         unique_together = ("customer","enrolled_class")
    157         verbose_name_plural = "报名表"
    158 class Payment(models.Model):
    159     '''缴费记录'''
    160     customer = models.ForeignKey("Customer")
    161     course = models.ForeignKey("Course",verbose_name="所报课程")
    162     amount = models.PositiveIntegerField(verbose_name="数额",default=500)
    163     consultant = models.ForeignKey("UserProfile")
    164     date = models.DateTimeField(auto_now_add=True)
    165     def __str__(self):
    166         return "%s %s" %(self.customer,self.amount)
    167     class Meta:
    168         verbose_name_plural = "缴费记录"
    169 class UserProfile(models.Model):
    170     '''账号表'''
    171     user = models.OneToOneField(User)
    172     name = models.CharField(max_length=32)
    173     roles = models.ManyToManyField("Role",blank=True)
    174     def __str__(self):
    175         return self.name
    176     class Meta:
    177         verbose_name_plural = '用户账号'
    178 class Role(models.Model):
    179     '''角色表'''
    180     name = models.CharField(max_length=32,unique=True)
    181     menus = models.ManyToManyField("Menu",blank=True)
    182     def __str__(self):
    183         return self.name
    184     class Meta:
    185         verbose_name_plural = "角色"
    186 class Menu(models.Model):
    187     '''菜单'''
    188     name = models.CharField(max_length=32)
    189     url_name = models.CharField(max_length=64)
    190     def __str__(self):
    191         return self.name
    192     class Meta:
    193         verbose_name_plural = '菜单栏'

    1.以上内容只是作为参考,并不一定能够作为生产上的应用,若要上生产还要考虑更多的因素,这里是为写CRM提供一种通用的思路。
    2.如果你考虑到以后的数据会很大,那建议你对数据进行拆分,每个独立的app中进行独自的表结构设计,然后在主app中进行处理

    3. 原生Django的admin分析

    在进行分析之前,我们需要创建超级用户,然后登陆到后台中,添加一些测试数据。

    3.1 admin初始化操作

     

    3.1.1. 创建超级用户

    1 >>> python  manage.py  createsuperuser
    2 #下面的用户名和密码自己耍吧!

    3.1.2. 注册admin

    其实,创建完用户我们就已经可以进入到后台了,将写好数据表models.py里面的类注册CRM项目的admin.py中,并进行一些简单的自定义操作:

     1 from django.contrib import admin
     2 from CRM import models
     3 # Register your models here.
     4 #注册操作
     5 admin.site.register(models.Branch)
     6 admin.site.register(models.ClassList)
     7 admin.site.register(models.Course)
     8 admin.site.register(models.CourseRecord)
     9 admin.site.register(models.Customer)
    10 admin.site.register(models.CustomerFollowUp)
    11 admin.site.register(models.Enrollment)
    12 admin.site.register(models.Payment)
    13 admin.site.register(models.Role)
    14 admin.site.register(models.StudyRecord)
    15 admin.site.register(models.UserProfile)
    16 admin.site.register(models.Tag)
    17 admin.site.register(models.Menu)

    3.1.3. 登陆admin后台

    以下是将数据库表结构设计好后的显示效果,其中添加了一些测试数据:

    3.2 自定义显示样式

    我们在上面看到客户表中显示的内容太过稀少,而且功能也是少的可怜,好在Django为我们提供了自定义功能。

    同样在admin.py中进行自定义操作:

    支持中文:

    1 'django.contrib.sessions.middleware.SessionMiddleware',
    2 'django.middleware.locale.LocaleMiddleware',    # 设置admin为中文,必须放在django.contrib.sessions....之后

    修改时区:

    1 LANGUAGE_CODE = 'en-us'
    2 
    3 TIME_ZONE = 'Asia/Shanghai'    # 设置为东八区的时区
    4 
    5 USE_I18N = True
    6 
    7 USE_L10N = True
    8 
    9 USE_TZ = True
     1 from django.contrib import admin
     2 from CRM import models
     3 # Register your models here.
     4 #自定义操作
     5 class CustomerAdmin(admin.ModelAdmin):
     6     list_display = ('name', 'id','qq','source','consultant','content','status','date')
     7     list_filter = ('source','consultant','date')
     8     search_fields = ('qq','name')
     9     raw_id_fields = ('consult_course',)
    10     filter_horizontal = ('tags',)
    11     list_editable = ('status',)
    12 class UserProfileAdmin(admin.ModelAdmin):
    13     list_display = ('user','name')
    14 #注册操作
    15 #注册操作
    16 admin.site.register(models.Branch)
    17 admin.site.register(models.ClassList)
    18 admin.site.register(models.Course)
    19 admin.site.register(models.CourseRecord)
    20 admin.site.register(models.Customer, CustomerAdmin)  #这里要添加自定义操作
    21 admin.site.register(models.CustomerFollowUp)
    22 admin.site.register(models.Enrollment)
    23 admin.site.register(models.Payment)
    24 admin.site.register(models.Role)
    25 admin.site.register(models.StudyRecord)
    26 admin.site.register(models.UserProfile, UserProfileAdmin)  #这里要添加自定义操作
    27 admin.site.register(models.Tag)
    28 admin.site.register(models.Menu)

    在这里我们能看到很多功能,搜索,过滤,自定义操作action,排序,分页(数据量多时),添加等等。下面的文章中,就进行重构这些功能!

     1. 显示内容定制:list_display

    2. 过滤功能 list_filter

    3. 搜索功能 search_fields

    4. 字段搜索功能 raw_id_fields

    5. 字段过滤功能  filter_horizontal

    6. 可编辑字段 list_editable



  • 相关阅读:
    Ubuntu中pip的疑难杂症
    Python 分类方法记录
    Python 绘制热图
    脚本学习
    Ubuntu 基础使用教程
    机器学习各种相似性度量及Python实现
    Ubuntu 16.04安装R及Rstudio
    机器学习和数据挖掘领域大牛
    vux+vue-cli3.0坑
    函数的抖动以及节流
  • 原文地址:https://www.cnblogs.com/eaglesour/p/8094339.html
Copyright © 2011-2022 走看看