功能篇之增删改查(包含公户、私户)
以django中的客户管理为例,包含公私户转换
settings中配置url
urlpatterns = [ # 公户 # 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'), # 增加客户 url(r'add_customer/', customer.add_customer, name='add_customer'), # url(r'add_customer/', customer.customer_change, name='add_customer'), # 编辑客户 url(r'edit_customer/(\d+)/', customer.edit_customer, name='edit_customer'), # url(r'edit_customer/(\d+)/', customer.customer_change, name='edit_customer'),]
models.py文件中
from django.db import models
from multiselectfield import MultiSelectField
from django.utils.safestring import mark_safe
class Customer(models.Model): """ 客户表 """ qq = models.CharField('QQ', max_length=64, unique=True, help_text='QQ号必须唯一') qq_name = models.CharField('QQ昵称', max_length=64, blank=True, null=True) name = models.CharField('姓名', max_length=32, blank=True, null=True, help_text='学员报名后,请改为真实姓名') sex_type = (('male', '男'), ('female', '女')) sex = models.CharField("性别", choices=sex_type, max_length=16, default='male', blank=True, null=True) birthday = models.DateField('出生日期', default=None, help_text="格式yyyy-mm-dd", blank=True, null=True) phone = models.BigIntegerField('手机号', blank=True, null=True) source = models.CharField('客户来源', max_length=64, choices=source_type, default='qq') introduce_from = models.ForeignKey('self', verbose_name="转介绍自学员", blank=True, null=True) course = MultiSelectField("咨询课程", choices=course_choices) class_type = models.CharField("班级类型", max_length=64, choices=class_type_choices, default='fulltime') customer_note = models.TextField("客户备注", blank=True, null=True, ) status = models.CharField("状态", choices=enroll_status_choices, max_length=64, default="unregistered", help_text="选择客户此时的状态") network_consult_note = models.TextField(blank=True, null=True, verbose_name='网络咨询师咨询内容') date = models.DateTimeField("咨询日期", auto_now_add=True) last_consult_date = models.DateField("最后跟进日期", auto_now_add=True) next_date = models.DateField("预计再次跟进时间", blank=True, null=True) network_consultant = models.ForeignKey('UserProfile', blank=True, null=True, verbose_name='咨询师', related_name='network_consultant') consultant = models.ForeignKey('UserProfile', verbose_name="销售", related_name='customers', blank=True, null=True, ) class_list = models.ManyToManyField('ClassList', verbose_name="已报班级", blank=True, ) def __str__(self): return "{} - {}".format(self.qq, self.name) def show_class(self): return ' '.join([str(i) for i in self.class_list.all()]) def show_status(self): """ (('signed', "已报名"), ('unregistered', "未报名"), ('studying', '学习中'), ('paid_in_full', "学费已交齐")) :return: """ color_dict = { 'signed': 'green', 'unregistered': 'red', 'studying': 'yellow', 'paid_in_full': '#2c356e', } return mark_safe('<span style="background-color: {};color: white;padding: 3px">{}</span>'.format( color_dict.get(self.status), self.get_status_display()))
views视图文件中:
from django.shortcuts import render, redirect, HttpResponse, reverse from crm import models from crm.forms import CustomerForm from django.http.request import QueryDict from crm.utils.pagination import Pagination from crm.utils.urls import reverse_url from django.db import transaction # 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}) from django.views import View from django.db.models import Q from django.conf import settings, global_settings class CustomerList(View): def get(self, request): # query = request.GET.get('query', '') # 'django.http.request.QueryDict' # dic = request.GET # dic._mutable = True # dic['page'] = 1 # print(dic) 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'), all_customer.count(), request.GET.copy(), 10) return render(request, 'consultant/customer_list.html', {'all_customer': all_customer[page.start:page.end], 'page_html': page.page_html}, ) def post(self, request): action = request.POST.get('action') if not hasattr(self, action): return HttpResponse('非法操作') ret = getattr(self, action)() if ret: return ret return self.get(request) def multi_apply(self): # 公户变私户 ids = self.request.POST.getlist('ids') # 方式一 # models.Customer.objects.filter(pk__in=ids).update(consultant=self.request.user_obj) # 当前销售私户的数量 + 申请的客户的数量 > 上限 if self.request.user_obj.customers.all().count() + len(ids) > settings.MAX_CUSTOMER_NUM: return HttpResponse('做人不要太贪心了,给别人留点') # 开启事务: with transaction.atomic(): queryset = models.Customer.objects.filter(pk__in=ids, consultant__isnull=True).select_for_update() # 加行锁 # 跟新 # 判断提交的数据数 和 查询的数据数 if len(ids) == queryset.count(): queryset.update(consultant=self.request.user_obj) return return HttpResponse('你的手速太慢,已经别别人掳走了') # 方式二 # self.request.user_obj.customers.add(*models.Customer.objects.filter(pk__in=ids)) def multi_pub(self): # 私户变公户 ids = self.request.POST.getlist('ids') # 方式一 # models.Customer.objects.filter(pk__in=ids).update(consultant=None) # 方式二 self.request.user_obj.customers.remove(*models.Customer.objects.filter(pk__in=ids)) def search(self, filed_list): query = self.request.GET.get('query', '') # q = Q(Q(qq__contains=query) | Q(name__contains=query)) q = Q() q.connector = 'OR' for field in filed_list: # q.children.append(Q(qq__contains=query)) q.children.append(Q(('{}__contains'.format(field), query))) return q def add_customer(request): # 创建一个没有数据的Form form_obj = CustomerForm() if request.method == 'POST': # 创建一个包含提交数据的Form form_obj = CustomerForm(request.POST) # 对数据进行校验 if form_obj.is_valid(): form_obj.save() # 新增 return redirect(reverse_url(request, 'customer_list')) return render(request, 'consultant/add_customer.html', {'form_obj': form_obj}) def edit_customer(request, edit_id): obj = models.Customer.objects.filter(pk=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() return redirect(reverse_url(request, 'customer_list')) return render(request, 'consultant/edit_customer.html', {'form_obj': form_obj}) # 新增和编辑客户 def customer_change(request, edit_id=None): obj = models.Customer.objects.filter(pk=edit_id).first() form_obj = CustomerForm(instance=obj) title = '编辑客户' if edit_id else '新增客户' if request.method == 'POST': # 有修改的数据和原始的数据 form_obj = CustomerForm(request.POST, instance=obj) if form_obj.is_valid(): form_obj.save() return redirect(reverse('customer_list')) return render(request, 'consultant/customer_change.html', {'form_obj': form_obj, 'title': title})
前端页面中
#customer_list {% extends 'layout.html' %} {% block content %} {% load my_tags %} <div class="panel panel-default" style="margin: 15px"> <div class="panel-heading"> <h3 class="panel-title">展示客户</h3> </div> <div class="panel-body"> <div> {% load rbac %} {% if request|has_permission:'add_customer' %} <a class="btn btn-sm btn-primary" style="margin-bottom: 5px" href="{% reverse_url request 'add_customer' %}">添加</a> {% endif %} </div> <form action="" 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/customer_list/' %} <option value="multi_apply">公户变私户</option> {% else %} <option value="multi_pub">私户变公户</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> {% if request|has_permission:'edit_customer' %} <th>操作</th> {% endif %} </tr> </thead> <tbody> {% for customer in all_customer %} <tr> <td> <input type="checkbox" value="{{ customer.pk }}" name="ids"> </td> <td>{{ forloop.counter }}</td> <td>{{ customer.qq }}</td> <td>{{ customer.name|default:'未填写' }}</td> <td>{{ customer.get_sex_display }}</td> {# <td>{{ customer.birthday }}</td>#} <td>{{ customer.source }}</td> <td>{{ customer.course }}</td> <td> {{ customer.show_status }} </td> <td>{{ customer.date }}</td> <td>{{ customer.consultant.name }}</td> <td>{{ customer.show_class }}</td> <td><a href="{% url 'consult_list' customer.pk %}">查看</a></td> <td><a href="{% url 'add_enrollment' customer.pk %}">添加</a></td> {% if request|has_permission:'edit_customer' %} <td> {# <a href="{% url 'edit_customer' customer.pk %}"><i#} {# class="fa fa-pencil-square-o"></i></a>#} <a href="{% reverse_url request 'edit_customer' customer.pk %}"><i class="fa fa-pencil-square-o"></i></a> </td> {% endif %} </tr> {% endfor %} </tbody> </table> </form> <nav aria-label="Page navigation"> <ul class="pagination"> {{ page_html }} </ul> </nav> </div> </div> {% endblock %}
#edit_customer {% extends 'layout.html' %} {% block content %} <div class="panel panel-default" style="margin: 15px"> <div class="panel-heading"> <h3 class="panel-title">编辑客户</h3> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2"> <form class="form-horizontal" action="" method="post" novalidate> {% 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 %}
#add_customer {% extends 'layout.html' %} {% block content %} <div class="panel panel-default" style="margin: 15px"> <div class="panel-heading"> <h3 class="panel-title">添加客户</h3> </div> <div class="panel-body"> <div class="col-lg-8 col-lg-offset-2"> <form class="form-horizontal" action="" method="post" novalidate> {% 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 %}