第十九 django继续及CRM

 1.创建新项目

2.设计数据库表

 

from django.db import models

# Create your models here.
from django.contrib.auth.models import User

course_type_choices = (('online', '网络班'),
                       ('offline_weekend', '面授班(周末'),
                       ('offline_fulltime', '面授班(脱产)'),
                       )

class School(models.Model):
    name = models.CharField(max_length=128,unique=True)
    city = models.CharField(max_length=64)
    addr = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class UserProfile(models.Model):
    User = models.OneToOneField(User)
    name = models.CharField(max_length=64)
    school = models.ForeignKey('School')

    def __unicode__(self):
        return self.name

class Customer(models.Model):
    qq = models.CharField(max_length=64,unique=True)
    name = models.CharField(max_length=32,blank=True,null=True)
    phone = models.BigIntegerField(blank=True,null=True)
    course = models.ForeignKey('Course')
    course_type = models.CharField(max_length=64,choices=course_type_choices,default='offline_weekend')
    consult_memo = models.TextField()
    source_type_choices = (('qq','qq群'),
                           ('referral','内部转介绍'),
                           ('agent',''),
                           ('others','其它'),
                           )
    source_type = models.CharField(max_length=64,choices=source_type_choices,default='qq')
    referral_from = models.ForeignKey('self',blank=True,null=True)
    status_choices = (('signed','已报名'),
                      ('unregistered','未报名'),
                      ('graduated','已毕业'),
                      ('drop-off','退学'),
                      )
    status = models.CharField(max_length=64,choices=status_choices,default='signed')
    consultant = models.ForeignKey('UserProfile')
    class_list = models.ManyToManyField('ClassList',blank=True)
    date = models.DateField('咨询日期',auto_now_add=True)

    def __unicode__(self):
        return "%s (%s)" %(self.qq,self.name)


class CustomerTrackRecord(models.Model):
    customer = models.ForeignKey(Customer)
    track_record = models.TextField('跟踪记录')
    track_date = models.DateField()
    follower = models.ForeignKey(UserProfile)
    status_choices = ((1,'近期无报名计划'),
                      (2,'2个月内报名计划'),
                      (3,'1个月内报名计划'),
                      (4,'2周内报名计划'),
                      (5,'1周内报名计划'),
                      (6,'2天内报名'),
                      (7,'已报名'),
                      )
    status = models.IntegerField('状态',choices=status_choices,help_text='选择此客户的原因')

    def __unicode__(self):
        return self.customer

class Course(models.Model):
    name = models.CharField(max_length=64,unique=True)
    online_price = models.IntegerField()
    offline_price = models.IntegerField()
    introduction = models.TextField()

    def __unicode__(self):
        return self.name

class ClassList(models.Model):
    course = models.ForeignKey(Course,verbose_name='课程')
    semester = models.IntegerField(verbose_name='学期')
    course_type = models.CharField(max_length=64, choices=course_type_choices, default='offline_weekend')
    teachers = models.ManyToManyField(UserProfile)
    start_date = models.DateField()
    graduate_date = models.DateField()

    def __unicode__(self):
        return "%s(%s) %s" %(self.course.name,self.course_type,self.semester)

    class Meta:
        unique_together = ('course','semester','course_type')

class CourseRecord(models.Model):
    class_obj = models.ForeignKey(ClassList)
    day_num = models.IntegerField("第几节课")
    course_date = models.DateField(auto_now_add=True,verbose_name='上课时间')
    teacher = models.ForeignKey(UserProfile)

    def __unicode__(self):
        return self.class_obj,self.day_num

    class Meta:
        unique_together = ('class_obj','day_num')

class StudyRecord(models.Model):
    course_record = models.ForeignKey(CourseRecord)
    student = models.ForeignKey(Customer)
    record_choices = (('checked','已签到'),
                      ('late','迟到'),
                      ('noshow','缺勤'),
                      ('leave_early','早退')
                      )
    record = models.CharField("状态",choices=record_choices,max_length=64)
    score_choices = ((100,'A+'),
                     (90,'A'),
                     (80,'A-'),
                     (70,'B+'),
                     (60,'B'),
                     (50,'C'),
                     (40,'C-'),
                     (0,'D'),
                     (-1,'N/A'),
                     (-100,'COPY'),
                     (-1000,'FAIL')
                     )
    score = models.IntegerField("本节成绩",choices=score_choices,default=-1)
    date = models.DateTimeField(auto_now_add=True)
    note = models.CharField('备注',max_length=255,blank=True,null=True)

    def __unicode__(self):
        return "%s %s %s" %(self.course_record,self.student,self.record)

3.生成表

3.1.配置引入mysql

import pymysql
pymysql.install_as_MySQLdb()

3.2.配置数据库连接文件

....
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'cklcrm.apps.CklcrmConfig',
]
....
DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.sqlite3',
    #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    # }
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'cklcrm',
        'HOST': '192.168.1.80',
        'PORT': '',
        'USER': 'sayyou',
        'PASSWORD': 'what@F893',
    }
}
....

3.3.生成表

4.创建admin

4.1.admin创建登录用户

4.2.注册表到admin

from django.contrib import admin
import cklcrm.models
# Register your models here.

admin.site.register(cklcrm.models.UserProfile)
admin.site.register(cklcrm.models.Customer)
admin.site.register(cklcrm.models.CustomerTrackRecord)
admin.site.register(cklcrm.models.ClassList)
admin.site.register(cklcrm.models.Course)
admin.site.register(cklcrm.models.CourseRecord)
admin.site.register(cklcrm.models.StudyRecord)
admin.site.register(cklcrm.models.School)

4.3.启动服务

4.4.登录admin

 5.配置静态资源

5.1.添加静态目录

5.2.添加bootstrap资源

这里是bootstrap-3.3.7

5.3.保存框架页面

https://v3.bootcss.com/examples/dashboard/

加入到templates里,重命名为base并作为基准页面。

 6.配置项目访问

6.1.配置全局访问url

"""s19crm URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^cklcrm/',include('cklcrm.urls'))
]

6.2.配置cklcrm url

from django.conf.urls import url,include
from django.contrib import admin
from cklcrm import views

urlpatterns = [
    url(r'^$',views.dashboard),
]

6.3.配置views里的方法

from django.shortcuts import render

# Create your views here.

def dashboard(request):
    return render(request,'cklcrm/dashboard.html')

6.4.配置dashboard.html

文件内容继承base

{% extends 'base.html' %}

6.5.配置静态文件的路径

STATIC_URL = '/static/'   #别名

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "statics"),  #实际路径
    # '/var/www/static/',
]

6.6.启动服务,访问页面

6.7.页面静态文件路径必须修改

诸如此类的路径,必须修改为别名

查看修改后页面

 7.精简基页,引用基本页

7.1.精简基本页

7.2.修改基本base.html引用block

        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
          <h1 class="page-header">{% block page-header %}You page{% endblock %}</h1>
         {% block page-content %}
          Your page haha
         {% endblock %}
      </div>

7.3.修改dashboard.html

{% extends 'base.html' %}
{% block page-header %}
     CKL dashboard
{% endblock %}

查看页面:

 8.添加客户管理信息表

8.1.新增views方法

from django.shortcuts import render
from cklcrm import models
# Create your views here.

def dashboard(request):
    return render(request,'cklcrm/dashboard.html')

def customers(request):
    customers_list = models.Customer.objects.all()
    return render(request,'cklcrm/customers.html',{'customers_list':customers_list})

8.2.新增返回页面

{% extends 'base.html' %}
{% block page-header %}
     客户管理信息列表
{% endblock %}

{% block page-content %}
    {{ customers_list }}
{% endblock %}

8.4.查看返回页面

 

 8.5.新增数据

 8.5.1.新增课程

8.5.2.新增讲师

8.5.3.新增客户

8.5.4.查看页面

 9.添加表格展示

9.1.修改返回customer.html

{% extends 'base.html' %}
{% block page-header %}
     客户管理信息列表
{% endblock %}

{% block page-content %}
    {{ customers_list }}
    <table class="table table-hover">
        <thead>
            <tr>
                <th>ID</th>
                <th>QQ</th>
                <th>姓名</th>
                <th>渠道</th>
                <th>咨询课程</th>
                <th>课程类型</th>
                <th>客户备注</th>
                <th>状态</th>
                <th>课程顾问</th>
                <th>日期</th>
            </tr>
        </thead>
        <tbody>
            {% for customer in customers_list %}
                <tr>
                    <td>{{ customer.id }}</td>
                    <td>{{ customer.qq }}</td>
                    <td>{{ customer.name }}</td>
                    <td>{{ customer.source_type }}</td>
                    <td>{{ customer.course }}</td>
                    <td>{{ customer.course_type }}</td>
                    <td>{{ customer.consult_memo }}</td>
                    <td>{{ customer.status }}</td>
                    <td>{{ customer.consultant }}</td>
                    <td>{{ customer.date }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
{% endblock %}

查看结果:

 9.2.字段名称显示中文

修改html

               <tr>
                    <td>{{ customer.id }}</td>
                    <td>{{ customer.qq }}</td>
                    <td>{{ customer.name }}</td>
                    <td>{{ customer.source_type }}</td>
                    <td>{{ customer.course }}</td>
                    <td>{{ customer.get_course_type_display }}</td>
                    <td>{{ customer.consult_memo }}</td>
                    <td>{{ customer.get_status_display }}</td>
                    <td>{{ customer.consultant }}</td>
                    <td>{{ customer.date }}</td>
                </tr>

查看修改结果:

 10.为状态增加颜色

10.1.新增颜色css

.signed {
    background-color: #4cae4c;
}

.unregistered {
    background-color: #ff6f06;
}

.graduated {
    background-color: #9d9d9d;
}

.drop-off {
    background-color: red;
}

10.2.新增静态引用

10.3.增加显示样式

               <td>{{ customer.id }}</td>
                    <td>{{ customer.qq }}</td>
                    <td>{{ customer.name }}</td>
                    <td>{{ customer.source_type }}</td>
                    <td>{{ customer.course }}</td>
                    <td>{{ customer.get_course_type_display }}</td>
                    <td>{{ customer.consult_memo|truncatewords:10 }}</td>
                    <td class="{{ customer.status }}">{{ customer.get_status_display }}</td>
                    <td>{{ customer.consultant }}</td>
                    <td>{{ customer.date }}</td>

查看结果:

11.分页

11.1.django分页模块

https://docs.djangoproject.com/en/2.0/topics/pagination/

11.2.新增数据

 11.3.配置分页

11.3.1.配置后端返回

from django.shortcuts import render
from cklcrm import models
# Create your views here.
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger

def dashboard(request):
    return render(request,'cklcrm/dashboard.html')

def customers(request):
    customers_list = models.Customer.objects.all()
#返回每页显示的条数 paginator
= Paginator(customers_list,3) page = request.GET.get('page') try: customer_pages = paginator.page(page) except PageNotAnInteger:
#如果输入的页数不存在,默认返回第一页 customer_pages
= paginator.page(1) except EmptyPage:
#如果页数超出,则返回最后一页 customer_pages
= paginator.page(paginator.num_pages) # return render(request,'cklcrm/customers.html',{'customers_list':customers_list}) return render(request, 'cklcrm/customers.html', {'customers_list': customer_pages})

 11.3.2.配置前端返回

在表格下面新增如下:

 <div class="pagination">
        <span class="step-links">
                {% if customers_list.has_previous %}
                    <a href="?page=1">&laquo; first</a>
                    <a href="?page={{ customers_list.previous_page_number }}">previous</a>
                {% endif %}

                <span class="current">
                    Page {{ customers_list.number }} of {{ customers_list.paginator.num_pages }}.
                </span>

                {% if customers_list.has_next %}
                    <a href="?page={{ customers_list.next_page_number }}">next</a>
                    <a href="?page={{ customers_list.paginator.num_pages }}">last &raquo;</a>
                {% endif %}
        </span>
    </div>

11.3.查看页面

 11.4.分页优化一

11.4.1.增加如下样式

https://v3.bootcss.com/components/#pagination

11.4.2.前端展示增加

    <nav aria-label="">
      <ul class="pagination">
          <!-- 如果还有上一页,则增加想做的箭头 -->
          {% if customers_list.has_previous %}
                    <li class=""><a href="?page={{ customers_list.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
          {% endif %}

          <!-- 循环页码,展示所有页码 -->
          {% for page_num in customers_list.paginator.page_range %}
              <!-- 如果循环页码等于当前页码,则增加样式 -->
              {% if page_num == customers_list.number %}
                    <li class="active"><a href="?page={{ page_num }}">{{ page_num }} <span class="sr-only">(current)</span></a></li>
              {% else %}
                    <li class=""><a href="?page={{ page_num }}">{{ page_num }} <span class="sr-only">(current)</span></a></li>
              {% endif %}
          {% endfor %}

          <!-- 如果还有下一页,则增加向右的箭头 -->
          {% if customers_list.has_next %}
            <li class=""><a href="?page={{ customers_list.next_page_number }}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
          {% endif %}
      </ul>
    </nav>

 

11.4.3.查看结果

 11.5.增加页码缩减

11.5.1.如果页码很多,就没办法全部显示

11.5.2.优化办法,只显示当前页的最近两三页

思路:获取当前页码号码,然后取当前页 减去 循环的页数,如果小于等于2则正确

abs(current_page - i_page )

比如当前是10

abs(10 - 8)

abs(10 - 12)

但是,没有这个方法,所以需要自定义

11.5.3.自定义返回前端页码方法

https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

11.5.4.方法演示

11.5.4.1.新增包

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django import template

register = template.Library()

@register.filter
def ckl_upper(val):
    print("-- from my temp:")
    return val.upper()

11.5.4.2.前端返回引用

 前端引用自定义方法

将渠道信息转为大写:

查看结果:

 11.6.自定义返回方法

11.6.1.定义自定义方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django import template
from django.utils.html import format_html
register = template.Library()

@register.filter
def ckl_upper(val):
    print("-- from my temp:")
    return val.upper()


#传入多个参数使用如下
@register.simple_tag
def neb_page(current_num,loop_num):
    #获取当前页及循环页的偏移量
    offset = abs(current_num - loop_num)
    #如果小于3则
    if offset < 3:
        #如果循环页等于当前页,就给页码加色
        if loop_num == current_num:
            page_ele = '''<li class="active"><a href="?page=%s">%s<span class="sr-only">(current)</span></a></li>''' %(loop_num,loop_num)
        else:
            page_ele = '''<li class=""><a href="?page=%s">%s<span class="sr-only">(current)</span></a></li>''' % (loop_num, loop_num)
        return format_html(page_ele)
    else:
        return ""

11.6.2.前端返回定义

{% extends 'base.html' %}
{% load custom_page %}
{% block page-header %}
     客户管理信息列表
{% endblock %}

{% block page-content %}
    <table class="table table-hover">
        <thead>
            <tr>
                <th>ID</th>
                <th>QQ</th>
                <th>姓名</th>
                <th>渠道</th>
                <th>咨询课程</th>
                <th>课程类型</th>
                <th>客户备注</th>
                <th>状态</th>
                <th>课程顾问</th>
                <th>日期</th>
            </tr>
        </thead>
        <tbody>
            {% for customer in customers_list %}
                <tr>
                    <td>{{ customer.id }}</td>
                    <td>{{ customer.qq }}</td>
                    <td>{{ customer.name }}</td>
                    <td>{{ customer.source_type | ckl_upper}}</td>
                    <td>{{ customer.course }}</td>
                    <td>{{ customer.get_course_type_display }}</td>
                    <td>{{ customer.consult_memo|truncatechars:30 }}</td>
                    <td class="{{ customer.status }}">{{ customer.get_status_display }}</td>
                    <td>{{ customer.consultant }}</td>
                    <td>{{ customer.date }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <nav aria-label="">
      <ul class="pagination">
          <!-- 如果还有上一页,则增加想做的箭头 -->
          {% if customers_list.has_previous %}
                    <li class="">
                        <a href="?page={{ customers_list.previous_page_number }}" aria-label="Previous">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
          {% endif %}

          <!-- 循环页码,展示所有页码 -->
          {% for page_num in customers_list.paginator.page_range %}
              <!-- 返回自定义方法的结果 -->
              {% neb_page customers_list.number page_num %}
          {% endfor %}

          <!-- 如果还有下一页,则增加向右的箭头 -->
          {% if customers_list.has_next %}
            <li class="">
                <a href="?page={{ customers_list.next_page_number }}" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
          {% endif %}
      </ul>
    </nav>
    <div class="pagination">
        <span class="step-links">
                {% if customers_list.has_previous %}
                    <a href="?page=1">&laquo; first</a>
                    <a href="?page={{ customers_list.previous_page_number }}">previous</a>
                {% endif %}

                <span class="current">
                    Page {{ customers_list.number }} of {{ customers_list.paginator.num_pages }}.
                </span>

                {% if customers_list.has_next %}
                    <a href="?page={{ customers_list.next_page_number }}">next</a>
                    <a href="?page={{ customers_list.paginator.num_pages }}">last &raquo;</a>
                {% endif %}
        </span>
    </div>
{% endblock %}

查看结果:

 12.选择查看详细信息

12.1.点击id进入详细信息

12.1.1.添加a标签,点击a标签进入详细页

思路:当前页面是:http://127.0.0.1:8000/cklcrm/customers/?page=1

希望点击id,进入:http://127.0.0.1:8000/cklcrm/customers/1/  此处是详细信息

12.1.2.增加url

from django.conf.urls import url,include
from django.contrib import admin
from cklcrm import views

urlpatterns = [
    url(r'^$',views.dashboard),
    url(r'^customers/$',views.customers),
    url(r'^customers/(\d+)/$',views.customsers_detail)
]

12.1.3.使用modelfrom

新增forms

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.forms import Form,ModelForm
from cklcrm import models

class CustomerModelForm(ModelForm):
    class Meta:
        model = models.Customer
        exclude = ()

12.1.4.配置views方法

from django.shortcuts import render
from cklcrm import models
#导入forms
from cklcrm import forms # Create your views here. from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger def dashboard(request): return render(request,'cklcrm/dashboard.html') def customers(request): customers_list = models.Customer.objects.all() paginator = Paginator(customers_list,3) page = request.GET.get('page') try: customer_pages = paginator.page(page) except PageNotAnInteger: customer_pages = paginator.page(1) except EmptyPage: customer_pages = paginator.page(paginator.num_pages) # return render(request,'cklcrm/customers.html',{'customers_list':customers_list}) return render(request, 'cklcrm/customers.html', {'customers_list': customer_pages})
#返回forms结果
def customsers_detail(request,customer_id): customer_obj = models.Customer.objects.get(id=customer_id) form = forms.CustomerModelForm() return render(request,'cklcrm/customers_detail.html',{'customer_form':form})

12.1.5.添加静态文件

查看文件内容:

{% extends 'base.html' %}
{% load custom_page %}
{% block page-header %}
     客户详细信息
{% endblock %}

{% block page-content %}
    {{ customer_form }}
{% endblock %}

12.1.6.点击id查看内容

内容为空:

 12.1.7.列表没有内容,需要增加内容

def customsers_detail(request,customer_id):
    customer_obj = models.Customer.objects.get(id=customer_id)
    form = forms.CustomerModelForm(instance=customer_obj)
    return render(request,'cklcrm/customers_detail.html',{'customer_form':form})

再次查看:

 12.1.8.给某个字段加样式

比如让qq这个字段

修改forms

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.forms import Form,ModelForm
from cklcrm import models

class CustomerModelForm(ModelForm):
    class Meta:
        model = models.Customer
        exclude = ()

    def __init__(self,*args,**kwargs):
        super(CustomerModelForm,self).__init__(*args,**kwargs)
        self.fields['qq'].widget.attrs["class"] = "form-control"

查看结果:

12.1.9.给所有字段加样式

修改forms

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from django.forms import Form,ModelForm
from cklcrm import models

class CustomerModelForm(ModelForm):
    class Meta:
        model = models.Customer
        exclude = ()

    def __init__(self,*args,**kwargs):
        super(CustomerModelForm,self).__init__(*args,**kwargs)
        #self.fields['qq'].widget.attrs["class"] = "form-control"

#循环所有字段 for filed_name in self.base_fields: filed = self.base_fields[filed_name] filed.widget.attrs.update({'class':'form-control'})

查看结果:

 12.2.提交修改内容

12.2.1.页面增加样式

https://v3.bootcss.com/css/#forms

页面希望修改如下:

 12.2.2.修改返回页面

{% extends 'base.html' %}
{% load custom_page %}
{% block page-header %}
     客户详细信息
{% endblock %}

{% block page-content %}
    <!-- 新增提交form -->
    <form class="form-horizontal" method="post">
        <!-- 循环每个字段,增加样式 -->
        {% for filed in customer_form %}
            <div class="form-group">
                <label for="inputEmail3" class="col-sm-2 control-label">{{ filed.label }}</label>
                <div class="col-sm-10">
                    {{ filed }}
                </div>
            </div>
        {% endfor %}
        <!-- 按钮样式 -->
        <div class="col-sm-12">
            <input class="btn btn-success pull-right" type="submit" value="Save">
        </div>
    </form>
{% endblock %}

 

12.3.提交修改

12.3.1.修改views方法

from django.shortcuts import render,redirect
from cklcrm import models
from cklcrm import forms
# Create your views here.
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger

def dashboard(request):
    return render(request,'cklcrm/dashboard.html')

def customers(request):
    customers_list = models.Customer.objects.all()
    paginator = Paginator(customers_list,3)
    page = request.GET.get('page')
    try:
        customer_pages = paginator.page(page)
    except PageNotAnInteger:
        customer_pages = paginator.page(1)
    except EmptyPage:
        customer_pages = paginator.page(paginator.num_pages)

    # return render(request,'cklcrm/customers.html',{'customers_list':customers_list})
    return render(request, 'cklcrm/customers.html', {'customers_list': customer_pages})

def customsers_detail(request,customer_id):
    customer_obj = models.Customer.objects.get(id=customer_id)
    if request.method == "POST":
        #不加instance=customer_obj,就是创建一条新记录,而不是更新数据
        form = forms.CustomerModelForm(request.POST,instance=customer_obj)
        if form.is_valid():
            form.save()
            #获取到首页的url,并返回
            base_url = "/".join(request.path.split("/")[0:-2])
            return redirect(base_url)
    else:
        form = forms.CustomerModelForm(instance=customer_obj)
    return render(request,'cklcrm/customers_detail.html',{'customer_form':form})

提交内容:

查看结果:

 12.4.增加验证及显示必填

{% extends 'base.html' %}
{% load custom_page %}
{% block page-header %}
     客户详细信息
{% endblock %}

{% block page-content %}
    <!-- 新增提交form -->
    <form class="form-horizontal" method="post">{% csrf_token %}
        <!-- 循环每个字段,增加样式 -->
        {% for filed in customer_form %}
            <div class="form-group">
                <!-- 如果字段比填 -->
                {% if filed.field.required %}
                    <!-- 字段前面加* -->
                    <label for="inputEmail3" class="col-sm-2 control-label">*{{ filed.label }}</label>
                {% else %}
                    <!-- 非必须,则不加,此外字体变细 -->
                    <label style="font-weight: normal" for="inputEmail3" class="col-sm-2 control-label">{{ filed.label }}</label>
                {% endif %}
                <div class="col-sm-10">
                    {{ filed }}
                    {% if filed.errors %}
                        <ul>
                            {% for err in filed.errors %}
                                <li style="color: #ff0e2e">{{ err }}</li>
                            {% endfor %}
                        </ul>
                    {% endif %}
                </div>
            </div>
        {% endfor %}
        <!-- 按钮样式 -->
        <div class="col-sm-12">
            <input class="btn btn-success pull-right" type="submit" value="Save">
        </div>
    </form>
{% endblock %}

查看结果:

 13.权限管理

13.1.增加表字段

表字段,临时随机找的表增加

class UserProfile(models.Model):
    User = models.OneToOneField(User)
    name = models.CharField(max_length=64)
    school = models.ForeignKey('School')

    def __str__(self):
        return self.name

    class Meta:
        permissions = (
                       ('view_customer_list','可以查看客户列表'),
                       ('view_customer_info','查看客户详细信息'),
                       ('edit_own_customer_info','可以修改自己客户信息'),
                       )

13.2.运行添加

13.3.先说URL别名

13.3.1.django的url别名很灵活

如果要访问:http://127.0.0.1:8000/cklcrm/customers/2/

后面的 2 如果写死就不好了,无法匹配到后面的3,4 ..等

from django.conf.urls import url,include
from django.contrib import admin
from cklcrm import views

urlpatterns = [
    url(r'^$',views.dashboard),
    url(r'^customers/$',views.customers),
    url(r'^customers/(\d+)/$',views.customsers_detail,name="customer_detail"), #此处使用了别名
]

13.3.2.返回页面修改访问url

原:

 <td><a href="/cklcrm/customers/{ customer.id }}">{ customer.id }}</a></td>

现:

<td><a href="{% url 'customer_detail' customer.id %}">{{ customer.id }}</a></td>

url 是调用路径

'customer_detail' 是调用的url别名

customer.id 是url的id

13.3.3.查看元素

 13.4.继续接 13.2.

增加url别名

from django.conf.urls import url,include
from django.contrib import admin
from cklcrm import views

urlpatterns = [
    url(r'^$',views.dashboard),
    url(r'^customers/$',views.customers,name="customer_list"),
    url(r'^customers/(\d+)/$',views.customsers_detail,name="customer_detail"),
]

 13.5.权限认证部分

新建文件:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.core.urlresolvers import resolve
from django.shortcuts import render,redirect

perm_dic = {
    'view_customer_list': ['customer_list','GET',[]],
    'view_customer_info': ['customer_detail','GET',[]],
    'edit_own_customer_info': ['customer_detail','POST',['test']],
}

def perm_check(*args,**kwargs):
    request = args[0]
    #resolve将路径封装成返回的url别名
    url_resovle_obj = resolve(request.path_info)
    #查找url,是否匹配成功
    current_url_namespace = url_resovle_obj.url_name
    #app_name = url_resovle_obj.app_name #use this name later
    print("url namespace:",current_url_namespace)
    #设置一个变量,默认为false
    matched_flag = False
    matched_perm_key = None
    #必须设置url别名
    if current_url_namespace is not None:#if didn't set the url namespace, permission doesn't work
        print("find perm...")
        #循环字典加入新的字典
        for perm_key in perm_dic:
            perm_val = perm_dic[perm_key]
            #字典长度必须大于3
            if len(perm_val) == 3:#otherwise invalid perm data format
                url_namespace,request_method,request_args = perm_val
                print(url_namespace,current_url_namespace)
                #判断url
                if url_namespace == current_url_namespace:
                    #判断方法
                    if request.method == request_method:
                        #如果参数为空,则匹配到权限
                        if not request_args:#if empty , pass
                            matched_flag = True
                            matched_perm_key = perm_key
                            print('mtched...')
                            break #no need looking for  other perms
                        else:
                            #如果参数不为空,则循环参数
                            for request_arg in request_args: #might has many args
                                request_method_func = getattr(request,request_method) #get or post mostly
                                #print("----->>>",request_method_func.get(request_arg))
                                if request_method_func.get(request_arg) is not None:
                                    matched_flag = True # the arg in set in perm item must be provided in request data
                                else:
                                    matched_flag = False
                                    print("request arg [%s] not matched" % request_arg)
                                    break #no need go further
                            if matched_flag == True: # means passed permission check ,no need check others
                                print("--passed permission check--")
                                matched_perm_key = perm_key
                                break

    else:#permission doesn't work
        return True

    if matched_flag == True:
        #pass permission check
        perm_str = "crm.%s" %(matched_perm_key)
        if request.user.has_perm(perm_str):
            print("\033[42;1m--------passed permission check----\033[0m")
            return True
        else:
            print("\033[41;1m ----- no permission ----\033[0m")
            print(request.user,perm_str)
            return False
    else:
        print("\033[41;1m ----- no matched permission  ----\033[0m")


def check_permission(func):
    def wrapper(*args,**kwargs):
        print("--start check permission --")
        if perm_check(*args,**kwargs) is not True:
            return render(args[0],'cklcrm/403.html')
        return func(*args,**kwargs)
    return wrapper

13.6.装饰器应用views.py

from django.shortcuts import render,redirect
from cklcrm import models
from cklcrm import forms
# Create your views here.
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
from cklcrm.permissions import check_permission

def dashboard(request):
    return render(request,'cklcrm/dashboard.html')

@check_permission
def customers(request):
    customers_list = models.Customer.objects.all()
    paginator = Paginator(customers_list,3)
    page = request.GET.get('page')
    try:
        customer_pages = paginator.page(page)
    except PageNotAnInteger:
        customer_pages = paginator.page(1)
    except EmptyPage:
        customer_pages = paginator.page(paginator.num_pages)

    # return render(request,'cklcrm/customers.html',{'customers_list':customers_list})
    return render(request, 'cklcrm/customers.html', {'customers_list': customer_pages})

@check_permission
def customsers_detail(request,customer_id):
    customer_obj = models.Customer.objects.get(id=customer_id)
    if request.method == "POST":
        #不加instance=customer_obj,就是创建一条新记录,而不是更新数据
        form = forms.CustomerModelForm(request.POST,instance=customer_obj)
        if form.is_valid():
            form.save()
            #获取到首页的url,并返回
            base_url = "/".join(request.path.split("/")[0:-2])
            return redirect(base_url)
    else:
        form = forms.CustomerModelForm(instance=customer_obj)
    return render(request,'cklcrm/customers_detail.html',{'customer_form':form})

13.7.配置返回页面

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>403</title>
</head>
<body>
    <h1 style="font-size: 100px">403</h1>
    <h2>You cannot access this page,check your permission !</h2>
</body>
</html>

 

13.8.普通用户登录

进入访问页面:

13.8.添加列表访问权限

 

posted @ 2018-01-30 09:17  ckl893  阅读(202)  评论(0编辑  收藏  举报