码迷,mamicode.com
首页 > 其他好文 > 详细

CRM-项目

时间:2019-10-16 21:30:27      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:contain   widgets   需要   port   排除   mode   iss   登陆   digest   

?

CRM项目:

customer relationship management

?

需求分析

  • 使用系统的人员
    • 销售 财务 班主任 项目经理
  • 需求分析:
    • 注册
    • 登陆
  • 销售:
    • 客户信息的管理
      • 增加、编辑、查看客户信息
    • 跟进记录的管理
      • 增加、编辑、查看跟进记录
    • 报名记录的管理
      • 增加、编辑、查看报名记录
    • 缴费的记录
      • 增加、编辑、查看缴费记录
  • 班主任:
    • 班级的管理
      • 增加、编辑、查看班级的信息
    • 课程记录
      • 增加、编辑、查看课程记录
    • 学习记录表
      • 增加、编辑、查看课程记录

?

表结构的设计

  1. 用户表

  2. 客户表

  3. 跟进记录表

  4. 报名表

  5. 缴费记录表

  6. 校区表

  7. 班级表

  8. 课程记录

  9. 学习记录表

    ?

  • 下载 pip install django-multiselectfield

    ?

登录注册功能

  • views

    from django.shortcuts import render,redirect,HttpResponse 
    from crm import models 
    import hashlib 
    
    
    def login(request):
        if request.method == 'POST':
            user = request.POST.get('username')
            pwd = request.POST.get('password')
    
            md5 = hashlib.md5()               #将密码加密验证
            md5.update(pwd.encode('utf-8'))
            pwd = md5.hexdigest()
            obj = models.UserProfile.objects.filter(username=user,password=pwd,is_active=True).first()
    
            if obj:   #obj查询没有结果为none
                return redirect('crm:customer')
            return render(request, 'login.html',{'error':'用户名密码错误'})
        return render(request,'login.html')
    
    
    from django import forms             #forms组件
    from django.core.exceptions import ValidationError
    
    class RegForm(forms.ModelForm):
        password = forms.CharField(min_length=6,widget=forms.PasswordInput(
            attrs={'placeholder':'密码','autocomplete':'off'}))   #自定义会覆盖默认的
        re_password = forms.CharField(min_length=6,widget=forms.PasswordInput(
            attrs={'placeholder':'确认密码','autocomplete':'off'}))        #新增字段
    
    
        class Meta:                      #生成默认字段
            model = models.UserProfile
            fields = '__all__'  #所有字段在前端展示form组件,所有字段使用['username','password']
            exclude = ['is_active']      #排除字段,生成时候没有,默认使用数据库中的默认值
    
            widgets={                    #默认字段对应的插件,添加属性
                'username':forms.TextInput(attrs={'placeholder':'用户名','autocomplete':'off'}),
                'password':forms.PasswordInput(attrs={'placeholder':'密码','autocomplete':'off'}),
                'name':forms.TextInput(attrs={'placeholder':'真是姓名','autocomplete':'off'}),
                'mobile':forms.TextInput(attrs={'placeholder':'手机号','autocomplete':'off'}),
            }
    
            error_messages={
                'username':{
                    'unique':'用户名相同重新输入'
                }
            }
    
        def clean(self):  #全局钩子
            self._validate_unique = True   #到数据库效验唯一性,前端会展示数据已经存错误
            password = self.cleaned_data.get('password')
            re_password = self.cleaned_data.get('re_password')
    
            #判断两次密码是否一致,是将数据返回,and前面为判断是否为空
            if password and password == re_password:     
                md5 = hashlib.md5()
                md5.update(password.encode('utf-8'))
                self.cleaned_data['password'] = md5.hexdigest()  #将密码修改为加密后的
                return self.cleaned_data
    
            self.add_error('re_password','两次密码不一致!')  #加入到指定字段显示错误
            raise ValidationError('两次密码不一致')
    
    
    
    def reg(request):          #注册账号
        form_obj = RegForm()   #实例化对象
    
        if request.method == 'POST':
            form_obj = RegForm(request.POST)
            # print(form_obj)
            if form_obj.is_valid():             #获取form表单进行效验
                form_obj.save()
                return redirect('crm:login')    #数据写入后完,跳转至登录页面
    
            # print(form_obj.cleaned_data)
        return  render(request,'reg.html',{'form_obj':form_obj})

    ?

  • login.html

        <form action="" method="post">
            {% csrf_token %}
            <div>
                <input type="text" name="username" class="username" placeholder="输入账号" autocomplete="off">
            </div>
            <div>
                <input type="password" name="password" class="password" placeholder="输入密码" oncontextmenu="return false"
                       onpaste="return false">
            </div>
            <div>{{ error }}</div>
            <button id="submit" >登录</button>
    
        </form>

    ?

展示数据:

  • 展示方法

    • 普通字段

      #对象.字段名   ——》  数据库的值
      <td>{{ customer.qq }}</td>

      ?

    • choices

      #对象.字段名   ——》  数据库的值
      #对象.get_字段名_display()   ——》 对应显示的值
      <td>{{ customer.get_source_display }}</td>

      ?

    • 外键

      #对象.外键   ——》  关联的对象  __str__
      #对象.外键.字段  
      <td>{{ customer.consultant.name }}</td>    #consultant外键

      ?

    • 多对多

      <td>{% for foo in customer.class_list.all %}
          {{ foo.get_course_display }}
          {% endfor %}
      </td>

      ?

    • 自定义model方法

      from django.utils.safestring import mark_safe   #前端html不转义
      
      #前端调用:
      <td>{{ customer.show_status }}</td>
      
      #models
          def show_status(self):
              color_dict = {
                  'signed': 'green',
                  'unregistered':'red',
                  'studying': 'pink',
                  'paid_in_full':'gold'
              }
              return mark_safe(f'<span style="color: white;background-color: {color_dict.get(self.status)};padding: 3px">{self.get_status_display()}</span>')
      

    模糊查询

    Q((Q(qq__contains=query) | Q(name__contains=query) )
    
    q = Q()
    q.connector = 'OR'
    q.children.append(Q(qq__contains=query))
    q.children.append(Q(name__contains=query))
    
    Q(qq__contains=query)   Q(('qq__contains',query))

    分页的问题

    request.GET    QueryDict  默认不可修改
    request.GET._mutable = True
    request.GET['page'] = 1
    
    QueryDict(mutable=True)  可修改的字典
    request.GET.copy()       深拷贝  可修改
    
    request.GET.urlencode()     {query:123,page:2}   _>   query=123&page=2
    

    编辑后跳转到原页面

    生成url地址

    @register.simple_tag
    def url_tag(request,name,*args,**kwargs):
        url = reverse(name,args=args,kwargs=kwargs)
    
        next = request.get_full_path()
    
        qd = QueryDict(mutable=True)
        qd['next']=next
    
        return "{}?{}".format(url,qd.urlencode())
    

    编辑保存后跳转到原页面

    next = request.GET.get('next')
    if next:
        return redirect(next)
    return redirect('crm:customer_list')
    

    ?

权限

  • 用户登录成功,查询权限信息,也就是查询权限路径

    #去空去重
    permissions = user_obj.roles.filter(permissions__url__isnull=False).values('permissions__url').distinct()
    
    #user_obj.roles permissions__url 
    #获取到的是当前登录成功的用户对象,通过用户对象,找到用户角色,在用双下方法查找当前url权限有多少
    

    ?

  • 将路径信息保存在session中

    #query_set默认不可json序列化
    request.session['permissions'] = list(permissions) 
    
    #登录状态保存在session中
    request.session['is_login'] = True   #保存登录状态
    

    ?

  • 获取页面路径,进行效验:

    class RbacMiddleWare(MiddlewareMixin):
    
        def process_request(self,request):
            url = request.path_info                #获取当前访问的地址
    
    
            for i in settings.WHITE_LIST:          #白名单校验,判断url中是否含有login
                if re.match(i,url):                #i正则匹配url是否跟自己匹配
                    return
    
            is_login = request.session.get('is_login')  #没有登录状态,重新登录
            if not is_login:
                return redirect('login')
    
    
            for i in settings.PASS_AUTH_LIST:           #免认证登录,不需要权限,如首页
                if re.match(i,url):
                    return
    
            permissions = request.session.get('permissions')   #获取权限信息
            for i in  permissions:                       #判断访问的地址是否跟权限中地址匹配成功
                if re.match(r'^{}$'.format(i['permissions__url']), url):
                    return
    
            return HttpResponse('没有访问权限,练习管理员')  #效验全部不通过,拒绝请求
    

CRM-项目

标签:contain   widgets   需要   port   排除   mode   iss   登陆   digest   

原文地址:https://www.cnblogs.com/haiyang11/p/11688542.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!