Django复习: MTV模型: manager启动服务→urls找到路径→(找到views视图函数或者做路由分发)→视图函数处理相关逻辑,返回一个模板或者是字符串: -------------------------------------------------------------------------------------------------------------------- URLS: -------起别名是为了反向解析 urlpattern = [ (正则表达式,include(分发路径)), (正则表达式,views视图函数), (?P<name>正则,views视图函数) ] -------------------------------------------------------------------------------------------------------------------- views: 客户端通过url路径找到要访问的视图函数, def func(request): return Httpresponse("string") def func(request): return render(request,"model",locals()) def func(request): return redirect("/url/") 浏览器返回的信息都在request里,可以通过request. 的方法获取到某一个值: -------------------------------------------------------------------------------------------------------------------- template: 模板(前端页面): ----->模板中的都是经过上下文处理的字符串 模板语法: {% url "/../" 参数 %} {{ locals }} {% for i in locals %} for循环体,循环传过来的上下文对象 {% endfor %}} {% if locals %} ....... {% endif %} {% with locals %} ....... {% endwith %} ------------------------------------------------------------------------------------------------------------------ 模板继承: 母版(base.html):被继承的模板,一般不在前端页面展示 (模板中的block可以看做你自己挖的坑,一块一个坑,为了区分就起了名字name) {{ block name }} 继承的内容 {{ endblock }} name:有可能要继承多个块,所以起名字会方便, 子板:要继承的模板,用户可以访问的页面 子板要继承模板的内容必须导入{{ extend "base.html" }} 接下来自己就可以填母版挖的坑了,当然不填也可以,不过会继承模板的所有,挖坑只是为了方便重写 (假如要展示的页面有成千上百个,但是大致的内容都一样,要是自己写难免太多重复代码,此时就有了继承,多个子页面继承base页面,到时候根据需求分别填坑 {{ block name }} .....重写的代码 {{ endblock }} 理论上来说一个endblock就已经够了,可是为了方便阅读就每个block加上一个endblock!) 静态文件的配置: -------------------------------------------------------------------------------------------------------------------------- model: 数据库处理相关: 用类的方法创建数据表:类名---->表名:属性---->字段名:数据---->实例化对象 插入数据: 普通字段: obj = 对象实例化 obj.save() --------->插入数据 models.表名.object.creat(key=value,) models.表名.object.bulk_creat(批量插入数据) 外键字段: 1、先获取到外键的对象,然后用一个变量接收,表名.object.creat(字段=数据) 2、直接用表名.objects.creat(表名=字段名,外键=。。) 多对多字段: 1、多对多的外键字段实例化得到两个对象; 2、用一个列表接收这两个对象; 3、表名.外键字段.add(2) 4、表名.外键字段.create() 解除关系: 对象.外键.remove() --------->去除 对象.外键.clear() --------->清空对象集合 更新数据: models.表名.object.filter(条件).update(key=value) 删除数据: models.表名.object.filter(条件).delete 查找数据: 13个查找相关的API: all() 查询所有的结果: filter(**kwargs) 过滤匹配到的对象 get(**kwargs) 获取到一个对象,没有结果报错 exclude(**kwargs) 与筛选结果不匹配的对象 values(*field) 可迭代的字典序列 values_list(*field) 返回的是一个元组序列-----可以循环取值 order_by(*field) 对查询的结果进行排序 reverse() 对查询结果进行反向排序 distinct() 去掉重复记录 count() 返回queryset集合的对象数量 first() 返回第一条记录 last() 返回最后一条记录 exists() 如果该集合包含数据就返回true,else:False ------------------------------------------------------------------------------------- QuerySet集合对象: models.表名.objects.all() models.表名.objects.filter(**kwargs) models.表名.objects.all().values(*args) models.表名.objects.all().values_list(*args) -------------------------------------------------------------------------------------- models.表名.objects.exclude(**kwargs) models.表名.objects.order_by(*args) models.表名.objects.distinct(*args) model对象: models.表名.objects.get(**kwargs) -------------------------------------------------------------------------------------- models.表名.objects.filter(**kwargs).first() models.表名.objects.filter(**kwargs).last() models.表名.objects.filter(**kwargs).count() models.表名.objects.filter(**kwargs).exist() --------------------------------------------------------------------------------------- 正向查询按字段直接.,反向查询按表名[当前表.关联表_set. ,] 双下划线单表查询: 当筛选条件里面要过滤出一个范围的时候,那些简单的查询就已经不够用了,此时就出来了双下划线: eg:models.table.object.filter(id__lt-10,id__gt=1) 过滤1<id<10的数据 (类似的:__in=[....],__contains,__icontains,大小写; __range= [start,end]) 双下划线的跨表查询: 表名.objects.filter(关联表__字段=“..”).values_list(查出来的数据,用户能看到的) 外键字段的表名.objects.filter(条件).values_list(被关联表__字段) 分组和聚合: aggregate是queryset的一个终止自居,返回包含键值对的字典,键的名称是标识符,值是计算出来的聚合值 聚合:aggregate(*args,**kwargs) Book.objects.all().aggregate(Avg("x")) 获取到所有的book值,求字段x的平均值 得到的结果是一个字典{"x__avg":num} 当然还可以为这个聚合值指定一个名称: Book.objects.aggregate(average_price=Avg('x')) 得到的结果是:{"average_price":num} 分组:annotate() 为每一个对象生成一个独立的汇总值,和MySQL数据库的分组类似 booklist = Book.objects.annotate(authorNum = Count("x")) 得到的对象是一个queryset集合,,可以用for循环遍历,,便利的结果可以同.字段名的方式取值 annotate的返回值是queryset对象,如果不想遍历可以用valuelist接收 F查询与Q查询: F查询: 当两个字段需要做比较的时候就会用到: F() 与 F() 可以进行加减乘除和取模操作: Q查询: Q对象可以使用&与|操作符组合起来,当一个操作符在两个Q对象之间使用将返回一个新的Q对象; Q 对象还可以使用~去反操作 【Book.objects.filter(Q(authors__name="Mr_zhang")|Q(authors__name="egon"))==where name="Mr_zhang" or name="egon"】 过滤器: cookie和session cookie:数据存在客户端,不安全 session:数据存在服务器,安装 1、在登录页面设置cookie或者谁session 2、在需要验证的页面校验cookie或者是session 3、为了少写代码,直接写获取值的auth装饰器 auth 模块 auth模块完成的是就是cookie和session的事 user = authenticate(username=username,password=password) 当user获取到值说明验证通过了, login(request,user) ----------------自动帮你设置session logout:在函数内部logout(request) ----------直接注销登录 对于验证我们为了简单早就写了弍模块: @login_required 当把这个装饰器加到需要验证的页面,这个页面不可以直接访问,,而要通过验证才可以: 登录验证(user) is_authenticated() --验证通过,返回Trun 创建用户: user User.objects.creat_user(。。。。。。。。。) 修改密码:要输入原来的密码才让修改: user = User.objects.get(username="") user.set_password(password="new_password") user.save ---------不写save不会保存在数据库中 分页器: 有时候数据库的数据太多的话所有的数据都展示在同一个页面上,不方便浏览,也不利于管理: 此时就出来了一个叫做分页器的概念: 导入模块:from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 先查询一下所有的书:book_list = Book.object.all() paginator = Paginator(book_list,10) #每页显示10行数据 paginator.count ------------->总的数据有多少行 paginator.num_pages ---------->得到总的页数 paginator.page_range -----------页码的列表 page1 = paginator.page(1) -----获取到第一页的page对象 page1 可以遍历,,得到的结果就是这个页面上的10条数据 page1.object_list() -------得到第一页的所有数据 --------------------------------------------------------------------------------- page2 = paginator.page(2) ---------拿到第二页 page2.has_next() -------------判断是否有下一页 page2.next_page_number() ---------------下一页的页面 page2.has_previous() ---------判断是否有上一页 page2.previous_page_number() --------------上一页的页码 ps:page不到数据的时候或者page的数据是错误的话会抛错 前端处理数据: 上一页 中间页 下一页 判断booklist有没有上一页 for循环中间页 判断booklist有没有下一页