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>