引入三个表:用户表,客户表,校区表,班级表,梳理逻辑关系并迁移数据库,生成表。javascript
使用admin插入数据,admin是Django提供的web形式的后台数据管理页面,它是和用户认证组件相通的,使用超级用户便可登陆admin后台,并管理本身的数据库。java
作出所有客户列表页面和个人客户列表页面。python
在python中,装饰器以及前面讲到的迭代器,生成器都是十二分重要的高级函数。要想理解装饰器,首先要掌握如下几点准备知识:web
在python的世界里,函数和咱们以前的[1,2,3],'abc',8等同样都是对象,并且函数是最高级的对象(对象是类的实例化,能够调用相应的方法,函数是包含变量对象的对象)数据库
def foo(): print('i am the foo') bar() def bar(): print('i am the bar') foo() # def bar(): # bar函数定义放到foo()后边会报错 # print('i am the bar')
带着上面的问题,咱们看看函数在内存的存储状况,以下图:django
既然函数是对象,那么天然知足下面两个条件:函数对象的调用仅仅比其余对象多了一个()而已!foo,bar与a,b同样都是个变量名。那么上面示例的报错问题也就解决了,由于只有函数加载到内存才能够被调用。编程
1)函数能够被赋给其余变量缓存
def foo(): print('foo') bar=foo bar() foo() print(id(foo),id(bar)) #4321123592 4321123592
2)函数能够被定义在另一个函数内(做为参数&做为返回值),相似于整型,字符串等对象闭包
#*******函数名做为参数********** def foo(func): print('foo') func() def bar(): print('bar') foo(bar) #*******函数名做为返回值********* def foo(): print('foo') return bar def bar(): print('bar') b=foo() b()
注意:这里说的函数都是指函数名,好比foo;而foo()表示已经执行函数了,foo()是什么类型取决于return的内容是什么类型!!!另外,若是你理解不了对象,那么就将函数理解成变量,由于函数对象总会由一个或多个变量引用,好比foo,bar。app
python容许建立嵌套函数,经过在函数内部def的关键字再声明一个函数即为嵌套。先看下面这个函数嵌套的示例,分析可否正常执行:
def foo(): print('foo') def bar(): print('bar') # bar() bar() # 报错缘由:找不到这个引用变量 # 分析:没错,bar就是一个变量名,有本身的做用域的,所以bar()不能执行。
再看下面一个函数嵌套的示例,并思考执行inner函数的两种方法有什么区别:
def outer(): x = 1 def inner(): print (x) # inner() # 方式一 return inner # 方式二 # outer() # 方式一 in_func=outer() # 方式二:这里其实就是一个变量赋值,将inner的引用对象赋值给in_func,相似于a=5,b=a同样 in_func()
分析:两种调用方式有区别吗,不都是在外面调用inner吗?按照方式二调用后,inner()已经加载到内存了!
回顾闭包的概念:若是在一个内部函数里,对在外部做用域(但不是在全局做用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
如上示例,inner就是内部函数,inner里引用了外部做用域的变量x(x在外部做用域outer里面,不是全局做用域),则这个内部函数inner就是一个闭包。
说了这么多,终于到装饰器了。装饰器本质上是一个函数,该函数用来处理其余函数,它可让其余函数在不须要修改代码的前提下增长额外的功能,装饰器的返回值也是一个函数对象。它常常用于有切面需求的场景,好比:插入日志、性能测试、事务处理、缓存、权限校验等应用场景。装饰器是解决这类问题的绝佳设计,有了装饰器,咱们就能够抽离出大量与函数功能自己无关的雷同代码并继续重用。归纳的讲,装饰器的做用就是为已经存在的对象添加额外的功能。
好比,业务生产中有以下一个大量调用的函数:
def add(): for i in range(30000000): ret+=i print(ret) add()
如今有一个新的需求,但愿能够记录下函数的执行时间,因而在函数中添加日志代码:
总结:虽然实现了需求,可是这样作违反了开发的开放封闭原则的封闭原则,即不要轻易去改已经写好方法!并且若是要给其余函数也要加记录时间的代码,再用以上方法会形成代码冗余,因此想想有没有其余方法。你可能会想到单独定义一个记录时间的函数,以下:
import time def show_time(func): start_time=time.time() func() end_time=time.time() print('spend %s'%(end_time-start_time)) def add(): for i in range(30000000): ret+=i print(ret) show_time(add)
上面示例从逻辑上不难理解,并且运行正常。可是这样的话,以前执行业务逻辑时,执行运行add(),可是如今不得不改为show_time(add),这种方式就违反了开发的开放封闭原则的开放原则,即不要改动以前已有的调用方式。那么有没有更好的方式的呢?固然有,答案就是装饰器。
若是,能够将上例中的add()=show_time(add),那么就能够在不违反开放封闭原则前提下完成需求了,因此,咱们须要show_time(add)返回一个函数对象,而这个函数对象内则是核心业务函数:执行func()与装饰函数时间计算,修改以下:
import time def show_time(func): def inner(): start_time=time.time() func() end_time=time.time() print('spend %s'%(end_time-start_time)) return inner def add(): for i in range(30000000): ret+=i print(ret) add=show_time(add) add()
分析:函数show_time就是装饰器,它把真正的业务方法func包裹在函数里面,看起来像add被上下时间函数装饰了。在这个例子中,函数进入和退出时 ,被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。
@符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操做,以下示例:
import time def show_time(func): def inner(): start_time=time.time() func() end_time=time.time() print('spend %s'%(end_time-start_time)) return inner @show_time # add=show_time(add) def add(): for i in range(30000000): ret+=i print(ret) @show_time # bar=show_time(bar) def bar(): print('in the bar') time.sleep(2) add() bar()
如上所示,这样咱们就能够省去add = show_time(add)这一句了,直接调用add()便可获得想要的结果。若是咱们有其余的相似函数,咱们能够继续调用装饰器来修饰函数,而不用重复修改函数或者增长新的封装。这样,咱们就提升了程序的可重复利用性,并增长了程序的可读性。
这里须要注意:add=show_time(add)实际上是把inner引用的对象引用给了add,而inner里的变量func之因此能够用,就是由于inner是一个闭包函数。
@show_time帮咱们作的事情就是当咱们执行业务逻辑foo()时,执行的代码由粉框部分转到蓝框部分,仅此而已!装饰器在Python使用如此方便都要归因于Python的函数能像普通的对象同样能做为参数传递给其余函数,能够被赋值给其余变量,能够做为返回值,能够被定义在另一个函数内。
import time def show_time(func): def inner(a,b): start_time=time.time() func(a,b) end_time=time.time() print('spend %s'%(end_time-start_time)) return inner @show_time # add=show_time(add) def add(a,b): time.sleep(1) print(a+b) add(2,4)
import time def show_time(func): def inner(a,b): start_time=time.time() ret=func(a,b) end_time=time.time() print('spend %s'%(end_time-start_time)) return ret # 若被装饰函数有返回值,则inner函数也必定要返回func(a,b)的结果 return inner @show_time # add=show_time(add) def add(a,b): time.sleep(1) return a+b print(add(2,5))
Django为咱们提供了一个装饰器函数login_required,当咱们只想限制少许页面登陆才能访问时,就可使用装饰器函数,而没有必要加中间件。
1)首先,在admin.py中配置以下信息:
from django.contrib import admin # Register your models here. from app01.models import * # 将models模块中的全部类(表)引入 admin.site.register(UserInfo) # 括号中是model中的类(表),下面也如此 admin.site.register(Customer) admin.site.register(Campuses) admin.site.register(ClassList)
2)建立超级用户
python manage.py createsuperuser
3)以超级用户登陆admin后台,开始录入数据
方式一:
pip3 install multiselectfield
方式二:pycharm软件上按以下操做
file -> settints -> Project:xxx -> Project Interpreter -> 右侧绿色加号 -> 搜索multiselectfield ->Install Package
解释:咱们以前学过gender=models.CharField(choices=(('male','男')('female','女'))),使用modelform会渲染成多个type为radio的input标签,model中定义course = MultiSelectField("咨询课程", choices=(('Linux', 'Linux中高级'),('PythonFullStack', 'Python高级全栈开发'),), blank=True, null=True),使用modelform会渲染成多个type为checkbox的input标签。
qq_name = models.CharField('QQ昵称', max_length=64, blank=True, null=True)
解释:null=True表示数据库中不能为空,blank=True表示使用modelform组件中校验该字段输入时不能为空,而只写null=True则不能校验。Django的admin也是基于modelform实现的,因此使用admin提交表单数据时,只写了null=True而没有写blank=True的则必须输入值,不能为空。
search 属性是一个可读可写的字符串,可设置或返回当前 URL 的查询部分(即问号 ? 以后的部分)。
语法:string.slice(start,end)
解释:提取字符串的某个部分,并以新的字符串返回被提取的部分,索引从0开始,顾头不顾尾。