Django学习笔记1

Django

  1. 特点
  • 快速开发:Django的宗旨在于帮助开发人员快速从概念到完成应用程序。
  • 安全可靠:Django认真对待安全性,帮助开发人员避免许多常见的安全错误。
  • 超可伸缩性: Web上的一些最繁忙的网站利用了Django快速灵活扩展的能力。
  1. 入门

MVC 设计模式

目标:程序的解耦

在行业内普遍存在的设计模式

M  ==>  Model       模型    ==> 数据层   ==> 针对数据的操作 ===>转化成对数据库的操作 (sql)  映射关系

V  ==>  view        视图    ==> 展示层  ==> 展示页面(页面中会有数据)  里面加载的是 模板(html文件)

C  ==>  Controller  控制器  ==> 逻辑层  ==> 业务逻辑  根据用户的请求去调用模型,获取数据后交给视图去展示数据
复制代码

MVT 设计模式

目标:程序的解耦

仅限于Django中的设计模式

M ==> Model 模型(对数据的操作)
V ==> view  视图(业务逻辑)
T ==> Template 模板(页面的展示)
复制代码

路由

负责请求地址的匹配,并交给指定的视图函数进行处理

如:www.pyweb.com/yichuan/p/123457/
前面到com都为域名,后面的yichuan/p/123457/这是就是url地址
在路由的url函数中可以写正则表达式进行匹配,例如:
url(r'^address/2003/$', views.year)
复制代码
  1. 项目的搭建
  • 执行命令:django-admin startproject 项目名
  • 系统会创建一系列文件和文件夹,其中项目名下有一个文件夹与项目同名
  • 项目的总目录可以重命名,但是其中的文件尽量不要重命名,否则需要修改配置

创建应用

启动项目 ⭐⭐⭐

输出一个 Hello World 的过程

  1. 创建应用:python3 manage.py startapp myhome

  2. 在应用文件夹中找到视图函数 views.py

  3. 定义视图函数

    def hello(request): return HttpResponse('hello world')

  4. 注意:需要导入 HttpResponse:from django.http import HttpResponse

  5. 定义路由规则

    1. 先到根路由urls.py文件中定义规则,交给自定义应用的子路由url(r'^', include('myhome.urls'))
    2. 定义子路由器,在自定义应用中创建一个urls.py文件,并添加路由规则url(r'^', views.hello),其中url函数三个参数,第一个为路由规则,第二个为指定的视图函数
  6. 启动服务,开始访问

请求、访问过程

1. 当用户在浏览器中访问url地址时,服务器接收请求
2. --> 交给根路由进行匹配
3. --> 交给子路由进行url地址匹配
4. --> 子路由调用相应的视图函数
5. --> 视图函数进行执行,开始响应
复制代码
  1. 使用模板

  2. 配置模板引擎

    1. 找到项目配置文件 settings.py
    2. 修改templates的配置项中的DIRS为:'DIRS':[os.path.join(BASE_DIR,'templates')]
  3. 在manage.py文件的同级目录下创建一个templates的文件夹,里面放置模板文件,即html文件

  4. 在视图函数中使用render函数加载模板

    def tmp(request): return render(request,'t.html')

    其中render函数有三个参数,1-请求对象,为固定写法;2-模板路径;3-传入模板的数据(字典类型)

  5. 路由规则 ⭐⭐⭐

基本规则

  1. 路由按照从上至下的顺序执行

  2. 路由中可以使用()来捕获 url 请求中的一部分作为参数来使用,例如

    请求路径:http://127.0.0.1:9000/articles/2014/

    路由规则

    url(r'^articles/([0-9]{4})/$', views.year_archive),

    视图函数

    def year_archive(request,y): print(y) return HttpResponse('year_archive')

注意:在有()的正则路由规则中,对应的视图函数中必须用形参来接收()中的传入的参数

正则表达式命名组

以上的路由规则中,对视图函数的接收没有命名要求,形参的名字可以随意更改,但是命名组规则要求视图函数中接收参数的形参必须为规定的名称,例如

# 路由规则
url(r'^abc/(?P<year>[0-9]{4})/$', views.abc_2003),

# 视图函数
def abc_2003(request,year):
        print(year)
        return HttpResponse('abc_2003')
复制代码

默认值参数

使用两个路由规则,指向同一个视图函数

# 路由规则
url(r'^user/list/$', views.userlist),
url(r'^user/list/(?P<page>[0-9]+)/$', views.userlist),

# 视图函数
def userlist(request,page=1):
    print(page)
    return HttpResponse('userlist')
复制代码

url的反向解析 ⭐⭐⭐⭐⭐

通过路由规则的名(name),动态解析路由的地址

如果在视图、模板中使用硬编码(直接写死请求地址)的链接,在你url发生改变时,维护是意见非常麻烦的事情

# 为了能够动态的解析url的规则,可以在定义路由规则时,给路由器起一个名字(name)
# 路由规则
url(r'^goods/list/$', views.goodslist,name='glist'),

# 然后可以在视图和模板中通过反向解析动态的获取路由解析地址
# 视图函数
def hello(request):
    # 视图函数中进行反向解析,获取url地址,需要提前导入reverse
    # from django.core.urlresolvers import reverse
    r1 = reverse('goods')
    r2 = reverse('order')
    print(r1,r2)
    return render(request, 't.html')

# 模板
<a href="{% url 'glist' %}">商品列表:反向解析格式</a>
复制代码

注意:路由规则中如果有参数要求,那么模板中在使用url进行反向解析时,必须给参数

<a href="{% url 'olist' 100 %}">订单列表:反向解析格式</a>
复制代码

反向解析是路由中的重中之重,必须要搞清楚!

  1. 模型关系 ⭐⭐⭐⭐

一对一(人对应身份证)

定义

一对一关系指模型的关系时一一对应的,例如:

  • 一个用户对应一条用户详细信息
  • 一个身份证对应一个人
  • 一个微信号对应一个用户

二者一一对应,如果有一个用户的详细信息,必对应一个用户

创建模型

  • 在建立模型时建立两个模型,在其中一个模型中加入外键

  • 在模型中使用models.OneToOneField(关联的模型名,是否关联删除)来建立外键,没有外键的为主数据,有外键的为副数据

    模型关系 一对一

    用户模型

    class User(models.Model): username = models.CharField(max_length=50) age = models.IntegerField()

    用户详情

    class UserInfo(models.Model): # 此语句为创建外键 uid = models.OneToOneField(User,on_delete=models.CASCADE) xueli = models.CharField(max_length=50) yuanxiao = models.CharField(max_length=5)

增删查

  1. 增加 一对一模型进行增加时不需要特殊注意,直接进行增加,Django框架会自动将两个模型创建的数据进行关联

  2. 删除 一对一模型在进行数据删除时,如果删除的是主数据,则副数据也会被删除;如果副数据被删除,主数据则不会被删除

  3. 查询 一对一模型在进行数据查询时有两种方法:

    • 通过主数据查找副数据:主数据对象.副数据类名(小写).查询的属性名
    • 通过副数据查找主数据:副数据对象.外键名.查询的属性名

    模型关系:一对一

    def one(request): # 添加 # # 创建用户 data = {'username':'燕小六','age':20} user = User.objects.create(**data) # 创建详情 infodata = {'uid':user,'xueli':'本科','yuanxiao':'家里蹲'} info = UserInfo.objects.create(**infodata)

     # 删除
     # 删除用户时会关联删除对应的详情数据
     user = User.objects.first()
     user.delete()
     # 删除详细信息,用户不会被删除
     ui = UserInfo.objects.first()
     ui.delete()
    
     # 查询
     # 根据用户获取详细信息
     user = User.objects.first()
     print(user.username)
     print(user.userinfo.xueli)
     # # 根据详细信息获取用户信息
     ui = UserInfo.objects.first()
     print(ui.xueli)
     print(ui.uid.username)
    
     return HttpResponse('<h1>模型关系:一对一<h1>')
    复制代码

一对多(商品分类对应分类下的商品) ⭐⭐⭐⭐

定义

  • 一个商品分类对应多个商品
  • 一个班级对应多个学生
  • 一个国家对应多个城市

创建模型

  • 在建立模型时建立两个模型,在商品中加入外键

  • 在模型中使用models.ForeignKey(关联的模型名)来建立外键

    模型关系:一对多

    商品类别

    class Classify(models.Model): name = models.CharField(max_length=50)

    商品

    class Goods(models.Model): # 设置外键,第二个参数为可选 cid = models.ForeignKey(to="Classify", to_field="id") title = models.CharField(max_length=50) price = models.IntegerField()

      def __str__(self):
          return self.title
    复制代码

增删查

  1. 增加 增加时不需要特殊注意,直接进行增加,Django框架会自动将两个模型创建的数据进行关联

  2. 删除 如果删除的是商品分类,则分类下的商品也会被删除;如果分类下的商品被删除,商品分类则不会被删除

  3. 查询 一对一模型在进行数据查询时有两种方法:

    • 获取商品分类下所有商品:商品分类.商品类名(小写)_set.all()
    • 获取商品所属分类:商品对象.外键名.查找的属性

    模型关系:一对多

    def two(request): # 添加 # 创建商品分类 c = Classify.objects.create({'name':'手机'}) # 创建商品 g1 = Goods.objects.create({'cid':c,'title':'小米8','price':'2399'}) g1 = Goods.objects.create({'cid':c,'title':'华为P20','price':'4399'}) g1 = Goods.objects.create({'cid':c,'title':'OPPO Find X','price':'4999'})

     # 删除
     c = Classify.objects.last()
     c.delete()
    
     # 查询
     # 根据分类获取下面所有的商品
     c = Classify.objects.first()
     print(c.name)
     print(c.goods_set.all())
     # 根据商品获取其分类
     g = Goods.objects.first()
     print(g.title)
     print(g.cid.name)
     return HttpResponse('模型关系:一对多')
    复制代码

多对多(一本书对应多个标签,一个标签对应多本书) ⭐⭐⭐⭐

定义

  • 一本书对应多个标签,一个标签对应多本书
  • 一个老师对应多个班级,一个班级对应多个老师

创建模型

  • 需要用到第三张表,而不是单单在表中添加外键

  • 第三张表用来记录书和标签互相的关系

  • 在模型中使用models.ManyToManyField(关联的模型名)来建立对多对关系,且定义在任意模型中即可

    模型关系:多对多

    class Books(models.Model): title = models.CharField(max_length=50)

      def __str__(self):
          return self.title
    复制代码

    class Tags(models.Model): name = models.CharField(max_length=50) # 设置关系语句 bid = models.ManyToManyField(to="Books")

      def __str__(self):
          return self.name
    复制代码

增删查

  1. 增加 增加时需要进行关系声明,且方式取决于关系语句设置在哪个模板中,以上面代码为例

    • 给书添加标签:书对象.tags_set.set([标签对象1,标签对象2,...])
    • 给标签添加书:标签对象.bid.add(书对象1,书对象2,...)
    • 多对多关系设置方法:
      • .set([对象1,对象2,...]) 添加关系
      • .add(对象1,对象2,...) 添加关系
      • .clear() 清空关系
  2. 删除

    • 无论删除书或标签,表3中相应的关系记录都会关联删除
    • .clear() 清空指定对象的所有关系
  3. 查询

    • 获取一本书的所有标签:书对象.tags_set.all()
    • 获取一个标签下的所有书:标签对象.bid.all()
  4. 模型查询

  5. 查询集

  • 在管理器上调用过滤器方法会返回查询集,查询集表示从数据库中获取的对象集合

  • 查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤

  • 惰性执行:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库

  • 何时对查询集求值:迭代,序列化,与if合用

  • 返回查询集的方法,称为过滤器

  • all(): 获取所有的返回值

  • filter(): 过滤掉不符合条件的值 filter(键1=值1,键2=值2) == filter(键1=值1).filter(键2=值2)

  • exclude(): 获取除了满足条件之外的值

  • order_by(): 分组返回值根据条件进行排序

  • values(): 一个对象构成一个字典,然后构成一个列表返回

返回单个值

  • get(): 返回单个满足条件的对象
    • 如果未找到则引发模型类.DoesNotExist异常
    • 如果返回多条,会引发"模型类.MultipleObjectsReturned"异常
  • count(): 返回当前查询的总条数
  • first(): 返回第一个对象
  • last(): 返回最后一个对象
  • exists(): 判断查询集中是否有数据,如果有返回True,反之返回False

限制查询集

  • 查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句

  • 注意:不支持负数索引

  • 使用下标后返回一个新的查询集,不会立即执行查询

  • 如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常

    #这会返回前5个对象 LIMIT 5 Entry.objects.all()[:5] #这将返回第六个到第十个对象 OFFSET 5 LIMIT 5 Entry.objects.all()[5:10]

  1. 字段查询
  • 实现where子名,作为方法filter()、exclude()、get()的参数
  • 语法:属性名称__比较运算符=值
  • 表示两个下划线,左侧是属性名称,右侧是比较类型
  • 对于外键,使用“属性名_id”表示外键的原始值
  • 转义:like语句中使用了%与,匹配数据中的%与,在过滤器中直接写,例如:filter(title__contains="%")=>where title like '%%%',表示查找标题中包含%的

比较运算符

  1. exact:判断等,区分大小写;如果没有写'比较运算符',表示判断等

    filter(isDelete=False)

  2. contains:是否包含,区分大小写

    exclude(btitle__contains='传')

  3. startwith\endswith:以value开头或结尾,区分大小写

    exclude(btitle__endswith='传')

  4. isnull\isnotnull:判断是否为null

    filter(btitle__isnull=False)

  5. 在前面加个i表示不区分大小写,如iexact、icontains、istarswith、iendswith

  6. in:是否包含在范围内

    filter(pk__in=[1, 2, 3, 4, 5])

  7. gt、gte、lt、lte:大于、大于等于、小于、小于等于

    filter(id__gt=3)

  8. year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算

    filter(bpub_date__year=1980) filter(bpub_date__gt=date(1980, 12, 31))

8.View视图

  1. GET\POST

一键一值

# 这种方式当键不存在或多个键时会报错
request.GET['name']
# 这种方式None为默认值,如果数据不存在则返回默认值
request.GET.get('name',None)

request.POST['name']
request.POST.get('name',None)
复制代码

一键多值

# 返回值为一个列表
request.GET.getlist('name',None)
request.POST.getlist('name',None)
复制代码
  1. HttpResponse对象

  2. 在django.http模块中定义了HttpResponse对象的API

  3. HttpRequest对象由Django自动创建,HttpResponse对象由程序员创建

  4. 在每一个视图函数中必须返回一个HttpResponse对象,当然也可以是HttpResponse子对象

  5. HttpResponse

  • 不使用模板,直接返回数据

  • 返回数据类型为字符串

  • 如果字符串中是标签,浏览器可以进行解析

    return HttoResponse('你好')

  1. render
  • 调用模板返回数据

  • 参数1:request,固定形式

  • 参数2:'模板路径',即html文件的路径

  • 参数3:字典类型的数据,用于传入模板中

    return render(request,'user/edit.html',{'info':'你好'})

  1. 子类 HttpResponseRedirect
  • 重定向,服务器端跳转

  • 构造函数的第一个参数用来指定重定向的地址

  • 可以简写为 redirect

    return redirect(reverse('myindex')

  1. 子类 JsonResponse
  • 返回json书,一般用于异步请求

  • 帮助用户创建JSON编码的响应

  • JsonResponse的默认类型为application/json

  • 参数1:字典类型数据

  • 参数2:safe=True/False,默认为True,False表示关闭数据安全,参数1可以传入非字典类型

    return JsonResponse([{'list': 'abc'},{'d': 'ac'}],safe=False)

  1. set_cookie 方法
  • Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。
  • 服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。
  • Cookies最典型的应用是判定注册用户是否已经登录网站
  1. 设置cookie

    设置cookie

    def setcok(request): # 获取当前的 响应对象 res = HttpResponse('设置cookie') # 使用响应对象进行cookie的设置 res.set_cookie('a', 'abcd') # 返回响应对象 res.set_cookie('c', 'cdef') return res

  2. 获取cookie

    获取cookie

    def getcok(request): cok = request.COOKIES.get('a', None) return HttpResponse(cok)

  3. set_session 方法

  • sesison方式所有数据存储在服务器端,在客户端cookie中存储唯一的身份标识
  • 当用户进行请求时,判断cookie中的唯一标识符是否与用户请求中携带的唯一标识符相同
  • 认证成功后页面可以调用session中的所有内容
  • 向对于cookie更加安全,信息不容易被截获
  • 存储的内容比cookie更加丰富
  1. 开启session
  • 使用django-admin startproject创建的项目默认启用

  • 禁用会话:删除下面指定的两个值,禁用会话将节省一些性能消耗

  • Django 中session需要依赖数据库,因此需要确认数据库中是否存在 与session相关的 表

  • 在settings.py文件中

    • 向INSTALLED_APPS列表中添加:

    • 'django.contrib.sessions',

    • 项MIDDLEWARE_CLASSES列表中添加:

    • 'django.contrib.sessions.middleware.SessionMiddleware',

  1. 设置session

    设置session

    def setsess(request): # 设置session request.session['user'] = {'username':'李四','userid':'12314','age':20} request.session['vip'] = {'username':'王五','userid':'12314','age':20} return HttpResponse('设置session')

  2. 获取session

    获取session

    def getsess(request): res = request.session.get('user',None) if res: return HttpResponse('欢迎'+res['username']) else: return HttpResponse('请登录')

  3. 删除session

    删除session

    def outsess(request): # 删除会话中的一个key;注意:删除时,如果不存在,则报错 # del request.session['user']

     # 清除所有会话信息,但不会删除会话记录,会话依然存在
     # request.session.clear()
    
     # 删除当前的会话所有的数据及记录
     # request.session.flush()
     return HttpResponse('退出')
    复制代码
  4. session配置

    settings.py 文件中进行设置:

    session 设置

    SESSION_COOKIE_AGE = 60 * 30 # 30分钟 SESSION_SAVE_EVERY_REQUEST = True #如果SESSION_SAVE_EVERY_REQUEST是True,会话cookie将在每个请求中发送 SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器,则COOKIE失效

    #来自 docs.djangoproject.com/en/1.11/top…

    以下设置为:10秒后过期

    request.session['abc'] = 'abcdef'

    request.session.set_expiry(10)

Ajax 实例

四级城市联动 - 思路

前提:
    创建模型
    填充数据
    配置静态文件

1. 定义路由,获取一级城市数据,返回城市联动的html页面
2. 在html页面中循环并显示一级城市数据
3. 定义一个路由,接收ajax请求
4. 在视图函数中接收页面传回的选项id,回去下一级数据,并返回json格式
5. 在html的页面中动态绑定change事件,获取id,发送ajax请求
6. 在ajax中判断是否有返回数据:如果有,返回数据,并动态创建下拉框,添加数据
注意:
    最后一级没有数据,但是创建选框;解决:在返回数据时进行判断

    每次选择元素都创建新的选项框,不会删除原来的选项框
    解决:当选中元素时,移除当前元素之后的所有元素
复制代码

转载于:https://juejin.im/post/5bc19c436fb9a05cdb105eb0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值