七.2--展示、新增、编辑跟进记录

1.展示记录页面创建

(1)crm/urls.py中:

# 展示跟进记录
url(r'consult_record_list/', views.ConsultRecord.as_view(), name='consult_record'),#我用CBV(用类写View)方式写.

(2)views.py中:

#展示跟进记录
class ConsultRecord(View):
    def get(self, request):#定义get方法
        all_consult_record = models.ConsultRecord.objects.filter(delete_status=False)
        return render(request, 'crm/consult_record_list.html',{'all_consult_record':all_consult_record})#传给模版  

(3)templates/crm/consult_record_list.html中:

{% extends 'layout.html' %}
{% block css %}
    
{% endblock %}

{% block content %}
    
Panel heading
添加
{% csrf_token %} {% for record in all_consult_record %}{# 循环渲染 #} {# #} {% endfor %}
选择 序号 客户 跟进内容 跟进状态 跟进日期 跟进人 操作
{{ forloop.counter }} {{ record.customer }} {{ record.note }} {{ record.get_status_display }} {{ record.date }} {{ record.consultant }}
{% endblock %}

效果如下:

七.2--展示、新增、编辑跟进记录_第1张图片

2.添加跟进记录页面创建:

(1)urls.py中:

    # 添加跟进记录
    url(r'consult_record/add/', views.add_consult_record, name='add_consult_record '), 

(2)views.py中:使用下步中from表单:

from crm.forms import CustomerForm,ConsultRecordForm#导入form
# 添加跟进记录
def add_consult_record(request):
    form_obj = ConsultRecordForm()#生成一个空的form对象
    return render(request, 'crm/add_consult_record.html',{'form_obj':form_obj})

(3)我现在要通过form表单才能提交数据,forms.py中:

from django import forms
from crm import models #导入crm下的数据库
from django.core.exceptions import ValidationError#导入报错方法

class BaseForm(forms.ModelForm):#定义一个基类
    def __init__(self, *args, **kwargs):  # 初始化--用来给多个插件做css样式
        super().__init__(*args, **kwargs)  # 继承父类的初始法
        for filed in self.fields.values():  # 给每一个插件
            filed.widget.attrs.update({'class': 'form-control'})  # update是更新attrs插件字典的css样式

# 注册form
class RegForm(BaseForm):
    password = forms.CharField( #给前端增加密码字段并展示
        label='密码',
        widget=forms.widgets.PasswordInput(), #给密码框做隐形输入
        min_length=6,
        error_messages={'min_length': '最小长度为6'} #配置字段的错误提示
    )
    re_password = forms.CharField(#给前端增加确认密码字段展示并隐形输入
        label='确认密码',
        widget=forms.widgets.PasswordInput()
    )

    class Meta:#这个类是为专字段做配置用
        model = models.UserProfile  #根据哪个表的models生成对应字段
        fields = ['username', 'password', 're_password', 'name', 'department']  # 在前端显示哪些指定字段
        # exclude = ['']
        widgets = {#为多个字段做隐形输入  ----用加插件widgets
            'username': forms.widgets.EmailInput(attrs={'class': 'form-control'}), #用插件attrs给username的input做css样式
            'password': forms.widgets.PasswordInput,
        }

        labels = {#让多个字段中文显示---用加插件labels
            'username': '用户名',
            'password': '密码',
            'name': '姓名',
            'department': '部门',
        }

        error_messages = { #配置字段的错误提示
            'password': {
                'required': '密码不能为空',
            }
        }
    def clean(self):#全局勾子---密码校验
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if pwd == re_pwd:
            return self.cleaned_data
        self.add_error('re_password', '两次密码不一致')#错误则添加到
        raise ValidationError('两次密码不一致')#报错

# 客户form
class CustomerForm(BaseForm):
    class Meta:#做配置用
        model = models.Customer
        fields = '__all__' #要显示的字段
        widgets = {  #此插件作用是把course课程字段改成多选框
            'course': forms.widgets.SelectMultiple
        }

# 跟进记录form
class ConsultRecordForm(BaseForm):
    class Meta:
        model = models.ConsultRecord
        exclude = ['delete_status']  

(4)templates/crm/add_consult_record.html中:

{% extends 'layout.html' %}
{% block content %}
 
添加跟进记录
{% csrf_token %} {% for field in form_obj %}
{{ field }} {{ field.errors.0 }}
{% endfor %}
{# 生成提交按钮 #}
{% endblock %}  

(5)consult_record_list.html:

{% extends 'layout.html' %}
{% block css %}
    
{% endblock %}

{% block content %}
    
Panel heading
添加
{% csrf_token %} {% for record in all_consult_record %}{# 循环渲染 #} {% endfor %}
选择 序号 客户 跟进内容 跟进状态 跟进日期 跟进人 操作
{{ forloop.counter }} {{ record.customer }} {{ record.note }} {{ record.get_status_display }} {{ record.date }} {{ record.consultant }}
{% endblock %}

效果如下:

七.2--展示、新增、编辑跟进记录_第2张图片

 

 

七.2--展示、新增、编辑跟进记录_第3张图片  

但是如下图中:出现的是对象所以要用__str__方法转换。

七.2--展示、新增、编辑跟进记录_第4张图片

 

 

(6)models.py的Customer表中定义__str__方法:

    def __str__(self):
        return "{}<{}>".format(self.name, self.qq)#拼接

 七.2--展示、新增、编辑跟进记录_第5张图片

 

 

 

(7)开始提交添加跟进记录页面的数据

即post请求,

views.py中:

# 添加跟进记录
def add_consult_record(request):
    form_obj = ConsultRecordForm()#生成一个空的form对象
    if request.method == 'POST':
        form_obj = ConsultRecordForm(request.POST)#添加到form对象中数据
        if form_obj.is_valid():#校验成功
            form_obj.save()#保存
            return redirect(reverse('consult_record'))#跳转到展示跟进记录页面(consult_recordj是别名)
    return render(request, 'crm/add_consult_record.html',{'form_obj':form_obj})#如果form对象是空的则在添加跟记录页面  

如下图中点击提交按钮后

七.2--展示、新增、编辑跟进记录_第6张图片

 

效果如下:

七.2--展示、新增、编辑跟进记录_第7张图片

 3.跟进记录的编辑页面创建

(1)urls.py中:

# 编辑跟进记录
url(r'consult_record/edit/(\d+)/', views.edit_consult_record, name='edit_consult_record'),
 

(2)views.py中:

# 编辑跟进记录
def edit_consult_record(request, edit_id):
    obj = models.ConsultRecord.objects.filter(id=edit_id).first()#返回queryset中匹配到的第一个对象
    form_obj = ConsultRecordForm(instance=obj)#将对象与form对象关联起来
    if request.method == 'POST':
        form_obj = ConsultRecordForm(request.POST, instance=obj)#添加到form对象中数据
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('consult_record'))
    return render(request, 'crm/edit_consult_record.html', {'form_obj': form_obj})  

(3)templates/crm/edit_consult_record.html(复制一份add_consult_record.html并修改)中:

<div class="panel-heading">编辑跟进记录div>

(4)consult_record_list.html跟进记录展示页面中:

{% extends 'layout.html' %}
{% block css %}
    
{% endblock %}

{% block content %}
    
Panel heading
添加
{% csrf_token %} {% for record in all_consult_record %}{# 循环渲染 #} 编辑按钮 {% endfor %}
选择 序号 客户 跟进内容 跟进状态 跟进日期 跟进人 操作
{{ forloop.counter }} {{ record.customer }} {{ record.note }} {{ record.get_status_display }} {{ record.date }} {{ record.consultant }}
{% endblock %}

  

效果如下图中:点击编辑按钮即可进入编辑页面:

七.2--展示、新增、编辑跟进记录_第8张图片

这样展示和添加跟进记录就做完了。

4.展示我的跟进记录

(1)layout.html中:添加如下代码

七.2--展示、新增、编辑跟进记录_第9张图片

 

 

 效果如下:

七.2--展示、新增、编辑跟进记录_第10张图片

 

 

 但这些跟进记录是所有的(如下图中),而不是当前销售的客户跟进记录,我应该只让它显示当前销售自己的:

七.2--展示、新增、编辑跟进记录_第11张图片

 上述这些客户是form自动给它生成的.--所以我对它的choices属性修改即可----所咨询的字段(models.py中是跟进记录表的customer字段)。

(2)forms.py中:

# 跟进记录form
class ConsultRecordForm(BaseForm):
    class Meta:
        model = models.ConsultRecord
        exclude = ['delete_status']
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.fields['customer'].widget.choices = ((1,'xxxx'),)

效果如下:

七.2--展示、新增、编辑跟进记录_第12张图片

 

 (3)但我这个是写死的,所咨询客户应该给我的是当前用户/销售的所有客户。

所以要先拿到用户request.user---而这个user就让它从views.py中传过来

# 跟进记录form
class ConsultRecordForm(BaseForm):
    class Meta:
        model = models.ConsultRecord
        exclude = ['delete_status']
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)#self.instance.consultant.customers.all()是拿到当前用户的所有客户
        #i就是一个客户,我把它组装成元组(id,名字)传到所咨询客户customer字段的choices中
        self.fields['customer'].widget.choices = [ (i.id, i) for i in self.instance.consultant.customers.all() ]

(4)views.py中:

# 添加跟进记录
def add_consult_record(request):
    # 注意models.CourseRecord()它是一个类对象(表),下行是我对它实例化并传参---即我自己给它封装数据--那它就只在内存中---等于object.create方法创建对象
    obj = models.ConsultRecord(consultant=request.user)#CourseRecord表中的consultant跟进人字段我给它传参为当前用户--即我对它做了封装
    #obj.save()#把我封装的数据保存到数据库中才能取
    form_obj = ConsultRecordForm(instance=obj)#通过instance把跟进人对象和form表单关联起来---forms.py中通过instance.consultant即可拿到跟进人即当前用户

    if request.method == 'POST':
        form_obj = ConsultRecordForm(request.POST)#添加到form对象中数据
        if form_obj.is_valid():#校验成功
            form_obj.save()#保存
            return redirect(reverse('consult_record'))#跳转到展示跟进记录页面(consult_recordj是别名)
    return render(request, 'crm/add_consult_record.html',{'form_obj':form_obj})#如果form对象是空的则在添加跟记录页面

效果如下:拿到当前用户的所有客户了---这样就可以了

七.2--展示、新增、编辑跟进记录_第13张图片

(5)限制跟进人是当前的用户(销售)---同样的跟进记录的编辑因为它也走__init__

跟进记录表ConsultRecord表中的consultant跟进人字段并在forms.py中写跟进人插件并让它的choice属性就行了,如下就行了

# 跟进记录form
class ConsultRecordForm(BaseForm):
    class Meta:
        model = models.ConsultRecord
        exclude = ['delete_status']
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)#self.instance.consultant.customers.all()是拿到当前用户的所有客户
        customer_choice =[(i.id, i) for i in self.instance.consultant.customers.all()]
        # 限制客户是当前销售的私户--
        self.fields['customer'].widget.choices = customer_choice
        # 限制跟进人是当前的用户(销售)
        self.fields['consultant'].widget.choices = [(self.instance.consultant.id, self.instance.consultant), ]

(6)views.py中把添加跟进记录和编辑跟进记录整合成一个views:

先让它们url走一个视图--->urls.py中:

from django.conf.urls import url, include
from crm import views
urlpatterns = [
    # 公户
    url(r'customer_list/', views.CustomerList.as_view(), name='customer'),
    # 私户
    url(r'my_customer/', views.CustomerList.as_view(), name='my_customer'),
    # 增加客户
    url(r'customer/add/', views.customer, name='add_customer'),
    # 编辑客户
    url(r'customer/edit/(\d+)', views.customer, name='edit_customer'),
    # 展示跟进记录
    url(r'consult_record_list/', views.ConsultRecord.as_view(), name='consult_record'),  # 我用CBV(用类写View)方式写.
    # 添加跟进记录
    url(r'consult_record/add/', views.consult_record, name='add_consult_record'),
    # 编辑跟进记录
    url(r'consult_record/edit/(\d+)/', views.consult_record, name='edit_consult_record'),
]  

再views.py中:

from django.shortcuts import render, redirect, reverse, HttpResponse
from django.contrib import auth
from crm.forms import RegForm
from crm.forms import RegForm, CustomerForm, ConsultRecordForm
from crm import models
from django.utils.safestring import mark_safe
from utils.pagination import Pagination
from django.views import View
from django.db.models import Q
from django.http import QueryDict
import copy
def login(request):
    err_msg = ''
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        obj = auth.authenticate(request, username=username, password=password)
        if obj:
            auth.login(request, obj)
            return redirect(reverse('my_customer'))
        err_msg = '用户名或密码错误'

    return render(request, 'login.html', {'err_msg': err_msg})
# 注册
def reg(request):
    form_obj = RegForm()
    if request.method == 'POST':
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            # 创建新用户
            # 方法一
            # form_obj.cleaned_data.pop('re_password')
            # models.UserProfile.objects.create_user(**form_obj.cleaned_data)

            # 方法二
            obj = form_obj.save()
            obj.set_password(obj.password)
            obj.save()

            return redirect('/login/')
    return render(request, 'reg.html', {'form_obj': form_obj})
# 展示客户列表
def customer_list(request):
    query = request.GET.get('query')
    if request.path_info == reverse('customer'):
        all_customer = models.Customer.objects.filter(Q(qq__contains=query)|Q(name_contains=query),consultant__isnull=True)
    else:
        all_customer = models.Customer.objects.filter(Q(qq__contains=query)|Q(name_contains=query),consultant=request.user)
    page = Pagination(request, all_customer.count())
    return render(request, 'crm/customer_list.html',
                  {"all_customer": all_customer[page.start:page.end], 'pagination': page.show_li})
# 展示客户列表CBV
class CustomerList(View):
    def get(self, request):
        q = self.get_search_contion(['qq','name'])
        if request.path_info == reverse('customer'):
            all_customer = models.Customer.objects.filter(q,consultant__isnull=True)
        else:
            all_customer = models.Customer.objects.filter(q,consultant=request.user)
        query_params = copy.deepcopy(request.GET)
        page = Pagination(request, all_customer.count(),query_params,2)
        add_btn,query_params = self.get_add_btn()# 接收查询的条件
        return render(request, 'crm/customer_list.html',
                      {"all_customer": all_customer[page.start:page.end], 'pagination': page.show_li,
                       'add_btn': add_btn, 'query_params': query_params})#把这个条件也传给模版

    def post(self, request):  # 定义post请求
        # 处理post提交的action的动作,处理完后让它返回上面的get这个方法再做一遍,相当于redirect跳转只不过不让用户再发一次请求了,一次性处理完
        action = request.POST.get('action')  # 拿到具体要操作的动作(如删除或放入私户这个动作)
        if not hasattr(self, action):  # 判断若没有action这个动作就不让你再往下执行
            return HttpResponse('非法操作')
        ret = getattr(self, action)()  # 获取action 这个就是自己定义的下面的action方法,加()是执行此方法
        if ret:
            return ret

        return self.get(request)  # 返回上面的get这个方法

    def multi_apply(self):  # action的方法
        # 公户变私户方法
        ids = self.request.POST.getlist('id')  # 拿到客户Id
        # models.Customer.objects.filter(id__in=ids)这个拿到的就是你当前的传过来的多个客户,前面加*号是把它打散
        # self.request.user.customers拿到的是models.py中的一对多的管理对象
        self.request.user.customers.add(*models.Customer.objects.filter(id__in=ids))

    def multi_pub(self):  # action的方法
        # 私户变公户方法
        ids = self.request.POST.getlist('id')
        self.request.user.customers.remove(*models.Customer.objects.filter(id__in=ids))

    def get_search_contion(self,query_list):
        query = self.request.GET.get('query', '')
        q = Q()
        q.connector = 'OR'
        for i in query_list:
            q.children.append(Q(('{}__contains'.format(i), query)))
        return q

    def get_add_btn(self):#做的就是跳转到它自己生成的a标签中的url中
        # 获取添加按钮
        url = self.request.get_full_path()#获取当前页面的url
        qd = QueryDict()#生成网址字典对象QueryDict
        qd._mutable = True#设置成可对字典对象修改格式
        qd['next'] = url#qd字典中加next键和值当前页面的url
        query_params = qd.urlencode()#做转换将网址字典转成query=6的格式
        # 做拼接生成a标签:add_customer是urls.py中的customer/add/的别名
        add_btn = '添加'.format(reverse('add_customer'), query_params)
        return mark_safe(add_btn),query_params#把查询的条件返回
# 新增和编辑客户
def customer(request, edit_id=None):#一个url传参数一个不传,那这个时候就用默认值edit_id=None即没有参数就是空的,有就传
    obj = models.Customer.objects.filter(id=edit_id).first()
    form_obj = CustomerForm(instance=obj)
    if request.method == 'POST':
        form_obj = CustomerForm(request.POST, instance=obj)
        if form_obj.is_valid():
            form_obj.save()
            # 获取到next
            next = request.GET.get('next')
            if next:
                return redirect(next)
            return redirect(reverse('customer'))
    return render(request, 'crm/customer.html', {"form_obj": form_obj, "edit_id": edit_id})

#展示跟进记录
class ConsultRecord(View):
    def get(self, request):#定义get方法
        all_consult_record = models.ConsultRecord.objects.filter(delete_status=False)
        return render(request, 'crm/consult_record_list.html',{'all_consult_record':all_consult_record})#传给模版

# 新增和编辑跟进记录
def consult_record(request, edit_id=None):
    obj = models.ConsultRecord.objects.filter(id=edit_id).first() or models.ConsultRecord(consultant=request.user)
    form_obj = ConsultRecordForm(instance=obj)
    if request.method == 'POST':
        form_obj = ConsultRecordForm(request.POST, instance=obj)
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('consult_record', args=(0,)))
    return render(request, 'crm/edit_consult_record.html', {'form_obj': form_obj})

# 测试分页
# 测试数据
users = [{'name': 'alex{}'.format(i), 'pwd': 'alexdsb{}'.format(i)} for i in range(1, 302)]
def user_list(request):
    page = Pagination(request, len(users))

    return render(request, 'user_list.html',
                  {
                      "data": users[page.start:page.end],
                      # 'total_num': range(page_start, page_end + 1)
                      'html_str': page.show_li
                  })

 5.跟进页面流程梳理:

1.展示某个客户的跟进记录:

(1)urls.py中:做限制 ---如果你要的是某个客户记录的id,那展示的就是这个客户的所有跟进记录--如果你输入0的话,就是所有人的跟进记录

# 展示跟进记录
    url(r'consult_record_list/(\d+)', views.ConsultRecord.as_view(), name='consult_record'),

(2)views.py中:

# 展示跟进记录
class ConsultRecord(View):    
    def get(self, request,customer_id):#customer_id是models.py中的跟进记录表的customer字段的外键
if customer_id == '0':#当前销售只能看他自己的客户跟进记录 all_consult_record = models.ConsultRecord.objects.filter(delete_status=False,consultant=request.user) else: all_consult_record = models.ConsultRecord.objects.filter(customer_id=customer_id,delete_status=False) return render(request, 'crm/consult_record_list.html', { 'all_consult_record': all_consult_record })

(3)此时我左侧的我的跟进记录页面的地址也得修改:layout.html中:

{% load static %}

"en">

    "UTF-8">
    "stylesheet" href="{% static 'plugins/bootstrap-3.3.7/css/bootstrap.css' %}">{# 导入bootstrap样式 #}
    "stylesheet" href="{% static 'css/layout.css' %}">
    "icon" href="{% static 'imgs/layout/luffy-logo.png' %}">
    "stylesheet" href="{% static 'plugins/font-awesome-4.7.0/css/font-awesome.css' %}">
    CRM管理系统
    {% block css %}
    {% endblock %}



    

    
class="container-fluid">
class="row">
class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> {% block content %} {% endblock %}
{% block js %} {% endblock %}

效果如下:

七.2--展示、新增、编辑跟进记录_第14张图片

 

(4)在我的客户页面客户后面还应该有一个按钮,一点击它就能看到该客户的跟进记录:customer_list.html中:

{% extends 'layout.html' %}

{% block css %}
    
{% endblock %}

{% block content %}
    
class="panel panel-default">
class="panel-heading">Panel heading
class="panel-body"> "{% url 'add_customer' %}?{{ query_params }}" class="btn btn-primary btn-sm">添加
"" class="form-inline pull-right"> "text" name="query" class="form-control">
"" method="post" class="form-inline"> {% csrf_token %} class="table table-condensed table-hover table-bordered"> {% for customer in all_customer %} {% endfor %}
选择 序号 QQ 姓名 性别 咨询课程 班级类型 状态 最后跟进日期 销售 已报班级 跟进记录 操作
"checkbox" name="id" value="{{ customer.id }}"> {{ forloop.counter }} {{ customer.qq }} {{ customer.name|default:'暂无' }} {{ customer.get_sex_display }} {{ customer.course }} {{ customer.get_class_type_display }} {{ customer.show_status }} {{ customer.last_consult_date }} {{ customer.consultant }} {{ customer.show_classes }} 查看跟进 "{% url 'edit_customer' customer.id %}?{{ query_params }}">class="fa fa-edit fa-fw">
"text-align: center">
{% endblock %}

效果如下:我的客户页面点某客户的查看跟进就能进入该客户的详细跟进页面中了

七.2--展示、新增、编辑跟进记录_第15张图片

 

 

 七.2--展示、新增、编辑跟进记录_第16张图片

 

 

 

(5)此时注意因为你urls.py中url地址变了加了参数id,所以你views.py中也得变:

# 展示跟进记录
url(r'consult_record_list/(\d+)', views.ConsultRecord.as_view(), name='consult_record'),

 views.py中:也应该再加参数

# 新增和编辑跟进记录
def consult_record(request, edit_id=None):
    obj = models.ConsultRecord.objects.filter(id=edit_id).first() or models.ConsultRecord(consultant=request.user)
    form_obj = ConsultRecordForm(instance=obj)
    if request.method == 'POST':
        form_obj = ConsultRecordForm(request.POST, instance=obj)
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('consult_record', args=(0,)))
    return render(request, 'crm/edit_consult_record.html', {'form_obj': form_obj})

 

(7)

 

你可能感兴趣的:(七.2--展示、新增、编辑跟进记录)