crm项目04--添加,编辑客户,公户和私户的展示,公户和私户的转化

 

这篇博客主要用来实现这样的效果

 

templateresponse

本文实现功能(共4个)

  1. 添加客户

  2. 编辑客户

  3. 公户和私户的展示,公户就是所有用户都可以看到的客户,私户就是用户自己的客户

  4. 公户和私户的转化

实现需求的整体思路

1.添加客户

添加客户用django的form组件来对前端进行渲染, 设立一个前端模版,从后端传递一个查询出的queryset对象,通过render({“form_obj”:form_obj})的方式传到html页面,在页面中使用for进行遍历进而显示所需要添加的图片

要点

 

  1. 视图函数特别多,可以建立一个views文件夹 ,里面存放对不同对象操作的views.py,原有的单个views.py文件就不需要了,删掉即可,或者迁移到views文件夹下面

 

  1. 前端直接遍历传过去的form_obj对象即可,使用for循环生成表单

    {% extends 'layout.html' %}
    {% block content %}
    
        <div class="panel panel-default">
            <div class="panel-heading">添加</div>
            <div class="panel-body">
                <form class="form-horizontal" novalidate method="post" action="{% url 'customer_add' %}">
                    {% csrf_token %}
                    {% for customer in form_obj %}
                        <div class="form-group {% if customer.errors.0 %}has-error{% else %}{% endif %}">
                            <label for="{{ customer.id_for_label }}"
                                   class="col-sm-2 control-label">{{ customer.label }}</label>
                            <div class="col-sm-10">
                                {{ customer }}
                                <span></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>
    
    
    {% endblock %}
    View Code
  2. 在form表单中,为了保证页面的样式同一,每个自定义form都一个个添加样式非常繁琐,可以将使用到的提出来,变成一个父类,让其他的类继承它.

    from django import forms
    from app01 import models
    import hashlib
    from django.core.exceptions import ValidationError
    
    
    # 定义Boostrap表单样式的类
    class BootstrapForm(forms.ModelForm):
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
            for field in self.fields.values():
                field.widget.attrs.update({'class':'form-control'})
    
    
    #  注册表单
    class RegForm(BootstrapForm):
        password = forms.CharField(widget=forms.PasswordInput,label='密码',min_length=3)
        re_password = forms.CharField(widget=forms.PasswordInput,label='确认密码',min_length=3)
    
        class Meta:
            model = models.UserProfile
            fields = "__all__"
            exclude = ['is_active']
            labels = {
                'username':'用户名',
    
    
            }
    
            # widgets = {
            #     "password": forms.widgets.PasswordInput(attrs={"class":"form-control"})
            # }
    
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args,**kwargs)
            print(self.fields)
            for field in self.fields.values():
                field.widget.attrs.update({'class':'form-control'})
    
        def clean(self):
            print(self.cleaned_data)
            pwd = self.cleaned_data.get('password','')
            re_pwd = self.cleaned_data.get('re_password','')
            if pwd == re_pwd:
                # md5验证
                s = hashlib.md5()
                s.update(pwd.encode('utf-8'))
                ret = s.hexdigest()
                self.cleaned_data['password'] = ret
                return self.cleaned_data
            else:
                self.add_error('re_password','两次密码输入不一致')
                raise ValidationError('两次密码输入不一致')
    
    
    # Customer添加表单
    class CustomerForm(BootstrapForm):
        class Meta:
            model = models.Customer
            fields = "__all__"
    
    
        def __init__(self,*args,**kwargs):
            super().__init__(*args,**kwargs)
            self.fields["course"].widget.attrs.pop('class')
    View Code

     

  3. 在样式框中,想让输入框报错显示一个红色框体,可以这样写,这样

     

  4. <div class="form-group {% if customer.errors.0 %}has-error{% else %}{% endif %}">

2.编辑客户

编辑客户同样使用到form组件,需要注意的是django的form组件已经为我们提供了将值直接传给表单的功能,

要点

  1. 使用form组件的表单功能,form_obj = CustomerForm(instance=obj)直接可以生成包含有原始数据的编辑表单.

    # 编辑客户
    def customer_edit(request, edit_id):
        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表单
            form_obj = CustomerForm(instance=obj)
        return render(request, 'customer_edit.html', {"form_obj": form_obj})
    View Code
  2. 编辑客户和添加客户功能重复,视图函数可以合并成为一个,前端页面也可以合成一个,不过在前端页面中,显示页头 编辑/添加 时可以在后端判断完成后传递给前端 title = '编辑' if edit_id else '添加' 即可

    {% extends 'layout.html' %}
    {% block content %}
    
        <div class="panel panel-default">
            <div class="panel-heading">{{ title }}</div>
            <div class="panel-body">
                <form class="form-horizontal" novalidate method="post">
                    {% csrf_token %}
                    {% for customer in form_obj %}
                        <div class="form-group {% if customer.errors.0 %}has-error{% else %}{% endif %}">
                            <label for="{{ customer.id_for_label }}"
                                   class="col-sm-2 control-label">{{ customer.label }}</label>
                            <div class="col-sm-10">
                                {{ customer }}
                                <span></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>
    
    
    {% endblock %}
    View Code

     简化代码后的change功能

    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 '添加客户'
    
        obj = HttpResponse('xxx')
    
    
        return render(request, 'customer_change.html', {'title': title, 'form_obj': form_obj})

     

    简化后的前端页面

{% 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-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 %}

 

    

3.私户和公户的转化

可以在视图函数中使用CBV的方式,再利用反射,实现功能

orm操作:

1. 公户变私户
        # 方式一  查询的客户
     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))

 

2. 私户变公户
        
        # 方式一  查询的客户
        models.Customer.objects.filter(pk__in=ids).update(consultant=None)

        # 方式二 查用户
        # self.request.user_obj.customers.remove(*models.Customer.objects.filter(pk__in=ids))

 

代码实现:

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))

 

4.识别用户公户和私户的身份

采用中间件的方式进行认证,在login函数中,判定成功时加入session,使用对象的主键pk即可

中间件中这样验证, 采用白名单的形式

from django.utils.deprecation import MiddlewareMixin
from crm import models
from django.shortcuts import redirect, reverse


class AuthMiddleware(MiddlewareMixin):

    def process_request(self, request):

        if request.path_info in [reverse('login'), reverse('reg')]:
            return

        if request.path_info.startswith('/admin/'):
            return

        pk = request.session.get('pk')

        user = models.UserProfile.objects.filter(pk=pk).first()
        # 没有登录 跳转至登录页面
        if not user:
            return redirect(reverse('login'))

        request.user_obj = user

 

 

前端页面这样写

{% 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 %}

 

 

 

5.其他

视图函数中,使用form表单时用到form_obj = MyForm(request,instance=obj)

由于视图函数文件中函数代码太多,所以在app中建一个views文件夹,里面放不同的py文件.原有的views.py文件删除

urls.py中添加编辑和新增的url

forms.py文件中添加需要用的表单,其中BootstrapForm类是因为方便统一为form组件的样式加入bootstap样式建立的,让其他表单继承这个类,将attrs属性加入这个类的__init__方法,其他的类只要继承就可以了,省下不少代码

# 定义Boostrap表单样式的类
class BootstrapForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({'class':'form-control'})

# Customer添加表单
class CustomerForm(BootstrapForm):
    class Meta:
        model = models.Customer
        fields = "__all__"


    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.fields["course"].widget.attrs.pop('class')

现在将所有的有关用户的方法放进customer.py文件, 其中有新写的编辑,添加功能

form_obj = CustomerForm(request.POST,instance=obj)

上面这段代码是用来放进编辑功能的,私用instance=obj的方法可以将这个字段的数据直接放入表单,非常方便

customer.py

# 添加客户信息
def customer_add(request):
    form_obj = CustomerForm()
    if request.method == "POST":
        form_obj = CustomerForm(request.POST)
        print(form_obj.is_valid())
        if form_obj.is_valid():
            form_obj.save()
            return redirect(reverse('customer_list'))

    return render(request,"customer_add.html",{"form_obj": form_obj})


# 编辑客户
def customer_edit(request, edit_id):
    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表单
        form_obj = CustomerForm(instance=obj)
    return render(request, 'customer_edit.html', {"form_obj": form_obj})

 

posted @ 2019-03-14 20:50  robertx  阅读(305)  评论(0)    收藏  举报