crm 添加用户 编辑用户 公户和私户的展示,公户和私户的转化
1.添加用户 和编辑可以写在一起
urls.py
url(r'^customer_add/', customer.customer_change, name='customer_add'), url(r'^customer_edit/(\d+)/', customer.customer_change, name='customer_edit'),
form.py
class BSForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)# 这2句相当于执行了父类的init方法 # 自定义操作 for fied in self.fields.values(): fied.widget.attrs.update({'class': 'form-control'}) # 客户的form class CustomerForm(BSForm): class Meta: model = models.Customer#找到这个表 fields = '__all__'## 所有字段 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)#去掉course的form-control样式 self.fields['course'].widget.attrs.pop('class')
views目录下 函数添加
def customer_change(request, edit_id=None): obj = models.Customer.objects.filter(pk=edit_id).first() # 处理POST if request.method == 'POST': # 包含提交的数据 原始数据 form_obj = CustomerForm(request.POST, instance=obj) if form_obj.is_valid():#文件校验 form_obj.save() # 跳转到展示页面 return redirect(reverse('customer_list')) else: form_obj = CustomerForm(instance=obj)#也就是空的值 title = '编辑客户' if edit_id else '添加客户' return render(request, 'customer_change.html', {'title': title, 'form_obj': form_obj})
customer_change.html
{% extends 'layout.html' %} {% block content %} <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title">添加客户</h4> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2 " style="margin-top: 10px"> <form class="form-horizontal" novalidate method="post"> {% csrf_token %} {% for field in form_obj %} <div class="form-group {% if field.errors %}has-error{% endif %}"> //选中报红的样式 <label for="{{ field.id_for_label }}"//字段名字 class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {{ field }} <span class="help-block"> {{ field.errors.0 }}</span> </div> </div> {% endfor %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">保存</button> </div> </div> </form> </div> </div> </div> {% endblock %}
2. 公户和私户的展示
# 展示公户 # url(r'^customer_list/',customer.customer_list,name='customer_list'), url(r'^customer_list/',customer.CustomerList.as_view(),name='customer_list'), # 展示私户 # url(r'^my_customer/',customer.customer_list,name='my_customer'), url(r'^my_customer/',customer.CustomerList.as_view(),name='my_customer'),
之前的函数
def customer_list(request):#公户私户显示 if request.path_info == reverse('customer_list'): all_customer = models.Customer.objects.filter(consultant__isnull=True) else: all_customer = models.Customer.objects.filter(consultant=request.user_obj) return render(request, 'customer_list.html', {'all_customer': all_customer})
views/customer.py
# 展示客户列表 CBV from django.views import View class CustomerList(View): def get(self, request, *args, **kwargs): if request.path_info == reverse('customer_list'): all_customer = models.Customer.objects.filter(consultant__isnull=True) else: all_customer = models.Customer.objects.filter(consultant=request.user_obj) page = Pagination(request.GET.get('page', 1), all_customer.count(), ) return render(request, 'customer_list.html', { 'all_customer': all_customer[page.start:page.end], 'page_html': page.page_html }) def post(self, request, *args, **kwargs): action = request.POST.get('action') # multi_apply multi_pub # 判断是否有相应的操作 反射 if hasattr(self, action): # 有 获取并且执行 func = getattr(self, action) print(func) func() else: return HttpResponse('非法操作') return self.get(request, *args, **kwargs) def multi_apply(self, ): ids = self.request.POST.getlist('ids') # 把提交的客户的ID 都变成当前用户的私户 # 方式一 查询的客户 # models.Customer.objects.filter(pk__in=ids).update(consultant=self.request.user_obj) # models.Customer.objects.filter(pk__in=ids).update(consultant_id=self.request.session.get('pk')) # 方式二 查用户 self.request.user_obj.customers.add(*models.Customer.objects.filter(pk__in=ids)) def multi_pub(self): ids = self.request.POST.getlist('ids') # 把提交的客户的ID # 方式一 查询的客户 models.Customer.objects.filter(pk__in=ids).update(consultant=None) # 方式二 查用户 # self.request.user_obj.customers.remove(*models.Customer.objects.filter(pk__in=ids))
customer_list.html
{% extends 'layout.html' %} {% block content %} <a class="btn btn-success btn-sm" style="margin: 3px" href="{% url 'customer_add' %}"> <i class="fa fa-plus-square"></i> 添加 </a> <form action="" method="post" class="form-inline"> {% csrf_token %} <select name="action" id="" class="form-control"> {% if request.path_info == '/crm/my_customer/' %} <option value="multi_pub"> 私户变公户</option> {% else %} <option value="multi_apply"> 公户变私户</option> {% endif %} <option value="multi_del"> 批量删除</option> </select> <button class="btn btn-sm btn-primary">提交</button> <table class="table table-bordered table-hover"> <thead> <tr> <th>选择</th> <th>序号</th> <th>QQ</th> <th>姓名</th> <th>性别</th> {# <th>出生日期</th>#} {# <th>电话</th>#} <th>客户来源</th> <th>咨询课程</th> <th>状态</th> <th>最后跟进</th> <th>销售</th> <th>已报班级</th> <th>操作</th> </tr> </thead> <tbody> {% for customer in all_customer %} <tr> <td> <input type="checkbox" name="ids" value="{{ customer.pk }}"> </td> <td>{{ forloop.counter }}</td> <td>{{ customer.qq }}</td> <td>{{ customer.name|default:'未填写' }}</td> <td>{{ customer.get_sex_display }}</td> {# <td>{{ customer.birthday|default:'未填写' }}</td>#} {# <td>{{ customer.phone }}</td>#} <td>{{ customer.get_source_display }}</td> <td>{{ customer.course }}</td> <td> {{ customer.show_status }} </td> <td>{{ customer.last_consult_date }}</td> <td>{{ customer.consultant }}</td> {# <td>{{ customer.class_list.all }}</td>#} <td>{{ customer.show_class }}</td> <td> <a href="{% url 'customer_edit' customer.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> </td> </tr> {% endfor %} </tbody> </table> </form> {% endblock %}
3. 模糊查询 分页保留原搜索条件
1. 模糊查询 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)) 2. 分页保留原搜索条件 from django.http.request import QueryDict dic = request.GET # 不可编辑 dic._mutable = True dic['page'] = 1 dic.urlencode() # query=12&page=1 request.GET.copy() # 深拷贝 可编辑 QueryDict(mutable=True) # 可编辑
views/customer.py
class CustomerList(View): def get(self, request, *args, **kwargs): # dic = request.GET # dic._mutable = True # print(dic) # dic['page'] = 1 # print(dic.urlencode()) q = self.search(['qq', 'name', ]) if request.path_info == reverse('customer_list'): all_customer = models.Customer.objects.filter(q, consultant__isnull=True) else: all_customer = models.Customer.objects.filter(q, consultant=request.user_obj) page = Pagination(request.GET.get('page', 1), all_customer.count(), request.GET.copy(), 2) return render(request, 'customer_list.html', { 'all_customer': all_customer[page.start:page.end], 'page_html': page.page_html }) def search(self, field_list): query = self.request.GET.get('query', '') # 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)) for field in field_list: # q.children.append(Q(qq__contains=query)) q.children.append(Q(('{}__contains'.format(field), query))) return q
utils/pagination.py
class Pagination: #当前页面数 总页码数 显示页面数 几个页码 def __init__(self, page_num, all_count,params=QueryDict(mutable=True), per_num=10, max_show=11): # 获取页码 try: self.page_num = int(page_num) if self.page_num <= 0: self.page_num = 1 except Exception as e: self.page_num = 1 # 参数 self.params = params # 每页显示的数据量 self.per_num = per_num # 总数据量 all_count = all_count # 总页码数 self.page_count, more = divmod(all_count, per_num) if more: self.page_count += 1 # 最大显示页码数 self.max_show = max_show self.half_show = max_show // 2
page_list = []
if self.page_num == 1:
page_list.append('<li class="disabled"><a>上一页</a></li>')
else:
self.params['page']= self.page_num - 1 # {'query':'alex'} ——》 {'query':'alex','page':1}
page_list.append('<li><a href="?{}">上一页</a></li>'.format(self.params.urlencode())) # query=alex&page=1
在第二页 会保留 收缩条件
4. 新增和编辑后跳转到源页面
http://127.0.0.1:8000/crm/customer_edit/4/?next=/crm/customer_list/?query=123&page=2
next = /crm/customer_list/?query=123&page=2
next = /crm/customer_list/?query=123 page=2
点击 新增或编辑 之后 会有跳转到 原来的展示页面 怎么让他 变成 原来url
创建 自定义标签 templatetags my_tags.py
QueryDict解释 https://www.cnblogs.com/scolia/p/5634591.html
from django import template from django.urls import reverse from django.http.request import QueryDict register = template.Library() @register.simple_tag def reverse_url(request, name, *args, **kwargs): # 获取当前地址 下次操作完成后跳转回来 next = request.get_full_path() qd = QueryDict(mutable=True) qd['next'] = next # URL反向解析 base_url = reverse(name, args=args, kwargs=kwargs) return '{}?{}'.format(base_url, qd.urlencode())
customer_list.html
{% load my_tags %} <div> <a class="btn btn-success btn-sm" style="margin: 3px" href="{% reverse_url request 'customer_add' %}"> <i class="fa fa-plus-square"></i> 添加 </a> </div>
<a href="{% url 'customer_edit' customer.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> <a href="{% reverse_url request 'customer_edit' customer.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> </td>
5. 跟进记录管理
- 展示当前销售所有客户的跟进
- 展示摸个客户的所有的跟进
- 新增和编辑
- 限制客户为当前销售的客户 修改choices
- 限制可销售为 当前销售
urls.py
# 展示跟进 url(r'^consult_list/$', consult.ConsultList.as_view(), name='consult_list'), # 展示某个客户的跟进 url(r'^consult_list/(?P<customer_id>\d+)/$', consult.ConsultList.as_view(), name='one_consult_list'), url(r'^consult_add/', consult.consult_add, name='consult_add'), url(r'^consult_edit/(\d+)/', consult.consult_edit, name='consult_edit'),
consult.py
class ConsultList(View): def get(self, request, *args, **kwargs): q = self.search(['consultant__name', ]) customer_id=kwargs.get('customer_id') #打印某个用户传参if customer_id: # 某个客户的所有跟进 gep方式 all_consult = models.ConsultRecord.objects.filter(q,customer_id=customer_id,consultant=request.user_obj, delete_status=False).order_by('-date') else: # 当前销售的所有客户的跟进 all_consult = models.ConsultRecord.objects.filter(q, consultant=request.user_obj, delete_status=False).order_by('-date') page = Pagination(request.GET.get('page', 1), all_consult.count(), request.GET.copy(), 2) return render(request, 'consult_list.html', { 'all_consult': all_consult[page.start:page.end], 'page_html': page.page_html }) def search(self, field_list): query = self.request.GET.get('query', '') q = Q() q.connector = 'OR' for field in field_list: q.children.append(Q(('{}__contains'.format(field), query))) return q
# 添加跟进 def consult_add(request): # form_obj=ConsultForm()#自己实例化对象类似models传对象 obj = models.ConsultRecord(consultant=request.user_obj) form_obj = ConsultForm(instance=obj) # 交到form里面 if request.method == 'POST': form_obj = ConsultForm(request.POST, instance=obj) if form_obj.is_valid(): form_obj.save() next = request.GET.get('next') return redirect(next) # return redirect(reverse('consult_list')) return render(request, 'consult_add.html', {'form_obj': form_obj}) # 编辑跟进 def consult_edit(request, edit_id): obj = models.ConsultRecord.objects.filter(pk=edit_id).first() form_obj = ConsultForm(instance=obj) if request.method == 'POST': form_obj = ConsultForm(request.POST, instance=obj) if form_obj.is_valid(): form_obj.save() return redirect(reverse('consult_list')) return render(request, 'consult_edit.html', {'form_obj': form_obj})
consult_add.html
{% extends 'layout.html' %} {% block content %} <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title">添加跟进</h4> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2 " style="margin-top: 10px"> <form class="form-horizontal" novalidate method="post"> {% csrf_token %} {% for field in form_obj %} <div class="form-group {% if field.errors %}has-error{% endif %}"> <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {{ field }} <span class="help-block"> {{ field.errors.0 }}</span> </div> </div> {% endfor %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">保存</button> </div> </div> </form> </div> </div> </div> {% endblock %}
consult_edit.html
{% extends 'layout.html' %} {% block content %} <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title">编辑跟进</h4> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2 " style="margin-top: 10px"> <form class="form-horizontal" novalidate method="post"> {% csrf_token %} {% for field in form_obj %} <div class="form-group {% if field.errors %}has-error{% endif %}"> <label for="{{ field.id_for_label }}" class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {{ field }} <span class="help-block"> {{ field.errors.0 }}</span> </div> </div> {% endfor %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">保存</button> </div> </div> </form> </div> </div> </div> {% endblock %}
customer_list.html 显示 a标签
{% extends 'layout.html' %} {% block content %} {% load my_tags %} <div> <a class="btn btn-success btn-sm" style="margin: 3px" href="{% reverse_url request 'customer_add' %}"> <i class="fa fa-plus-square"></i> 添加 </a> </div> <form action="" method="get" class="form-inline pull-right"> <input type="text" name="query" class="form-control"> <button class="btn btn-sm btn-primary">搜索</button> </form> <form action="" method="post" class="form-inline"> {% csrf_token %} <select name="action" id="" class="form-control"> {% if request.path_info == '/crm/my_customer/' %} <option value="multi_pub"> 私户变公户</option> {% else %} <option value="multi_apply"> 公户变私户</option> {% endif %} <option value="multi_del"> 批量删除</option> </select> <button class="btn btn-sm btn-primary">提交</button> <table class="table table-bordered table-hover"> <thead> <tr> <th>选择</th> <th>序号</th> <th>QQ</th> <th>姓名</th> <th>性别</th> {# <th>出生日期</th>#} {# <th>电话</th>#} <th>客户来源</th> <th>咨询课程</th> <th>状态</th> <th>展示跟进</th> <th>最后跟进</th> <th>销售</th> <th>已报班级</th> <th>操作</th> </tr> </thead> <tbody> {% for customer in all_customer %} <tr> <td> <input type="checkbox" name="ids" value="{{ customer.pk }}"> </td> <td>{{ forloop.counter }}</td> <td>{{ customer.qq }}</td> <td>{{ customer.name|default:'未填写' }}</td> <td>{{ customer.get_sex_display }}</td> <td>{{ customer.get_source_display }}</td> <td>{{ customer.course }}</td> <td> {{ customer.show_status }} </td> <td><a href="{% url 'one_consult_list' customer.pk %}">查看</a></td> <td>{{ customer.last_consult_date }}</td> <td>{{ customer.consultant }}</td> {# <td>{{ customer.class_list.all }}</td>#} <td>{{ customer.show_class }}</td> <td> <a href="{% url 'customer_edit' customer.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> <a href="{% reverse_url request 'customer_edit' customer.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> </td> </tr> {% endfor %} </tbody> </table> </form> {% endblock %}
6. 报名记录管理
urls.py
# 展示报名表 Enrollment url(r'^enrollment_list/$', enrollment.EnrollmentList.as_view(), name='enrollment_list'), # 添加报名表 url(r'^enrollment_add/(?P<customer_id>\d+)/$', enrollment.enrollment_change, name='enrollment_add'), # 编辑报名表 url(r'^enrollment_edit/(?P<enrollment_id>\d+)/$', enrollment.enrollment_change, name='enrollment_edit'),
form.py
# 报名记录的form class EnrollmentForm(BSForm): class Meta: model = models.Enrollment fields = "__all__" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 限制客户为 customer_id 的客户 self.fields['customer'].choices = [(self.instance.customer_id, self.instance.customer)] # 客户 print(self.instance.customer.class_list.all()) # 限制报名班级为已报名的班级 self.fields['enrolment_class'].choices = [(i.pk, str(i)) for i in self.instance.customer.class_list.all()]
enrollment.py
from django.shortcuts import render, redirect, reverse, HttpResponse from crm import models from crm.form import EnrollmentForm from utils.pagination import Pagination from django.db.models import Q # 展示客户列表 CBV from django.views import View class EnrollmentList(View): def get(self, request, *args, **kwargs): q = self.search([]) # 当前这个销售 所有的客户 all_enrollment = models.Enrollment.objects.filter(q, customer__in=request.user_obj.customers.all()) page = Pagination(request.GET.get('page', 1), all_enrollment.count(), request.GET.copy(), 2) return render(request, 'enrollment_list.html', { 'all_enrollment': all_enrollment[page.start:page.end], 'page_html': page.page_html }) def search(self, field_list): query = self.request.GET.get('query', '') q = Q() q.connector = 'OR' for field in field_list: q.children.append(Q(('{}__contains'.format(field), query))) return q def enrollment_change(request, customer_id=None, enrollment_id=None): #有customer_id 报名 没有编辑 obj = models.Enrollment(customer_id=customer_id) if customer_id else models.Enrollment.objects.filter( pk=enrollment_id).first() title = '新增报名' if customer_id else '编辑报名' form_obj = EnrollmentForm(instance=obj) if request.method == 'POST': form_obj = EnrollmentForm(request.POST, instance=obj) if form_obj.is_valid(): form_obj.save() next = request.GET.get('next') return redirect(next) return render(request, 'form.html', {'form_obj': form_obj, "title": title})
enrollment_list.html 显示
{% extends 'layout.html' %} {% block content %} {% load my_tags %} <div> <a class="btn btn-success btn-sm" style="margin: 3px" href=""> <i class="fa fa-plus-square"></i> 添加 </a> </div> <form action="" method="get" class="form-inline pull-right"> <input type="text" name="query" class="form-control"> <button class="btn btn-sm btn-primary">搜索</button> </form> <form action="" method="post" class="form-inline"> {% csrf_token %} <select name="action" id="" class="form-control"> <option value="multi_del"> 批量删除</option> </select> <button class="btn btn-sm btn-primary">提交</button> <table class="table table-bordered table-hover"> <thead> <tr> <th>选择</th> <th>序号</th> <th>报名原因</th> <th>是否同意协议</th> <th>审核状态</th> <th>报名日期</th> <th>客户</th> <th>校区</th> <th>所报班级</th> <th>操作</th> </tr> </thead> <tbody> {% for enrollment in all_enrollment %} <tr> <td> <input type="checkbox" name="ids" value="{{ customer.pk }}"> </td> <td>{{ forloop.counter }}</td> <td>{{ enrollment.why_us }}</td> <td>{{ enrollment.contract_agreed}}</td> <td>{{ enrollment.contract_approved }}</td> <td>{{ enrollment.enrolled_date }}</td> <td>{{ enrollment.customer }}</td> <td>{{ enrollment.school }}</td> <td>{{ enrollment.enrolment_class }}</td> <td> <a href="{% reverse_url request 'enrollment_edit' enrollment.pk %}"> <i class="fa fa-pencil-square-o"></i> </a> </td> </tr> {% endfor %} </tbody> </table> </form> {% endblock %}
form.html显示
{% extends 'layout.html' %} {% block content %} <div class="panel panel-default"> <div class="panel-heading"> <h4 class="panel-title">{{ title }}</h4> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2 " style="margin-top: 10px"> <form class="form-horizontal" novalidate method="post"> {% csrf_token %} {% for field in form_obj %} <div class="form-group {% if field.errors %}has-error{% endif %}"> <label for="{{ field.id_for_label }}" class="col-sm-3 control-label">{{ field.label }}</label> <div class="col-sm-9"> {{ field }} <span class="help-block"> {{ field.errors.0 }}</span> </div> </div> {% endfor %} <p class="text-danger text-center"> {{ form_obj.non_field_errors.0 }} </p> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">保存</button> </div> </div> </form> </div> </div> </div> {% endblock %}
customer_list.html 中添加一行 做跳转
<th>添加报名</th>
<td><a href="{% reverse_url request 'enrollment_add' customer.pk %}">添加</a> </td>
不怕大牛比自己牛,就怕大牛比自己更努力