Django学习

一 什么叫Django

  Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。

  

  MVC框架:

  MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
  MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
  

 二 Django的简单介绍

  Django是一个基于MVC构造的框架。但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),称为 MTV模式。它们各自的职责如下:
  
  从以上表述可以看出Django 视图不处理用户输入,而仅仅决定要展现哪些数据给用户,而Django 模板 仅仅决定如何展现Django视图指定的数据。或者说, Django将MVC中的视图进一步分解为 Django视图 和 Django模板两个部分,分别决定 “展现哪些数据” 和 “如何展现”,使得Django的模板可以根据需要随时替换,而不仅仅限制于内置的模板。
至于MVC控制器部分,由Django框架的URLconf来实现。URLconf机制是使用正则表达式匹配URL,然后调用合适的Python函数。URLconf对于URL的规则没有任何限制,你完全可以设计成任意的URL风格,不管是传统的,RESTful的,或者是另类的。框架把控制层给封装了,无非与数据交互这层都是数据库表的读,写,删除,更新的操作。在写程序的时候,只要调用相应的方法就行了,感觉很方便。程序员把控制层东西交给Django自动完成了。 只需要编写非常少的代码完成很多的事情。所以,它比MVC框架考虑的问题要深一步,因为我们程序员大都在写控制层的程序。现在这个工作交给了框架,仅需写很少的调用代码,大大提高了工作效率。

  

  工作机制: 

  1.用manage .py runserver 启动Django服务器时就载入了在同一目录下的settings .py。该文件包含了项目中的配置信息,如前面讲的URLConf等,其中最重要的配置就是ROOT_URLCONF,它告诉Django哪个Python模块应该用作本站的URLConf,默认的是urls .py
  2.当访问url的时候,Django会根据ROOT_URLCONF的设置来装载URLConf。
  3.然后按顺序逐个匹配URLConf里的URLpatterns。如果找到则会调用相关联的视图函数,并把HttpRequest对象作为第一个参数(通常是request)
  4.最后该view函数负责返回一个HttpResponse对象。
   

   

  

  模型:M

  模型是你的数据的唯一的、权威的信息源。它包含你所储存数据的必要字段和行为。通常,每个模型对应数据库中唯一的一张表。

  基础:

  • 每个模型都是django.db.models.Model 的一个Python 子类。
  • 模型的每个属性都表示为数据库中的一个字段。
  • Django 提供一套自动生成的用于数据库访问的API

  

 三 Django文档

  1 视图层

    1)Request对象和Response对象

    Django 使用Request 对象和Response 对象在系统间传递状态。

    当请求一个页面时,Django会建立一个包含请求元数据的 HttpRequest 对象。 当Django 加载对应的视图时,HttpRequest 对象将作为视图函数的第一个参数。每个视图会返回一个HttpResponse 对象。

     HttpRequest对象  

    属性   

    HttpRequest.method   
    HttpRequest.GET    类似字典的对象
    HttpRequest.POST  类似字典的对象
    HttpResponse对象
    与由Django自动创建的HttpRequest 对象相比,HttpResponse 对象由程序员创建.你创建的每个视图负责初始化实例,填充并返回一个 HttpResponse.
    用法
    传递字符串
    典型的应用是传递一个字符串作为页面的内容到HttpResponse 构造函数:
>>> from django.http import HttpResponse
>>> response = HttpResponse("Here's the text of the Web page.")
>>> response = HttpResponse("Text only, please.", content_type="text/plain")
  2 render()
  help文档中描述如下: 

  render(request, template_name, context=None, content_type=None, status=None, using=None)

 

  Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments.

 

  此方法的作用---结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。

 

  通俗的讲就是把context的内容, 加载进templates中定义的文件, 并通过浏览器渲染呈现.

参数讲解:

request: 该request用于生成response

template_name: templates 中定义的文件, 要注意路径名. 比如'templatespollsindex.html', 参数就要写‘pollsindex.html’

context: 要传入文件中用于渲染呈现的数据, 默认是字典格式

content_type: 生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值。

status: http的响应代码,默认是200.

using: 用于加载模板使用的模板引擎的名称。

  示例:
  
    from django.shortcuts import render  
      
    def my_view(request):  
        # View code here...  
        return render(request, 'myapp/index.html', {  
            'foo': 'bar',  
        }, content_type='application/xhtml+xml')  
  3 redirect()重定向
  实际上是经历了两次请求和响应。
  以login为例
    第一次请求,method是GET,没有数据。 /login/--->views.login--->login()
    第二次请求,method是POST,提交数据,字典格式。/login/--->views.login--->login()   。return redirect('/index/')。通知浏览器在发送 '/index/'
          请求url  ..../index/,method是GET, 没有数据。/index/-->views.index-->index(),响应一个index.html页面、
  
  PS :render与redirect的应用场景:

    如果验证成功要用redirect跳转,不然你实际页面是发生了变化,但是URL还是没有变!~

    render()只是对当前访问模板的加载与渲染,记住!是当前!并不能跳转!

  4 编写视图

  一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西都可以。无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。

  一个简单的视图

    下面是一个返回当前日期和时间作为HTML文档的视图:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

让我们逐行阅读上面的代码:

  • 首先,我们从 django.http模块导入了HttpResponse类,以及Python的datetime库。

  • 接着,我们定义了current_datetime函数。它就是视图函数。每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request

    注意,视图函数的名称并不重要;不需要用一个统一的命名方式来命名,以便让Django识别它。我们将其命名为current_datetime,是因为这个名称能够精确地反映出它的功能。

  • 这个视图会返回一个HttpResponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象。

四  cmd相关的指令。

  命令行创建Django项目

  在指定的文件夹下 django-admin startproject XXX

  启动Django项目

  在指定文件夹下  python manage.py runserver

五 模板

  模板层

  模板是一个文本,用于分离文档的表现形式和内容。

  使用模板来输出数据,从而实现数据与视图分离。

  在 Django 模板中遍历复杂数据结构的关键是句点字符。非常灵活。列表的索引值,字典的key值,类的静态属性,类的动态属性,都可以是 . 取到。美中不足的是类的动态属性不能传参。

  

  点号(.)用来访问变量的属性。

  从技术上来说,当模版系统遇到点("."),它将以这样的顺序查询:

  • 字典查询(Dictionary lookup)
  • 属性或方法查询(Attribute or method lookup)
  • 数字索引查询(Numeric index lookup)

  如果计算结果的值是可调用的,它将被无参数的调用。调用的结果将成为模版的值。 -----官方文档(1.8.2)

  

  模版是纯文本文件。它可以产生任何基于文本的的格式(HTML,XML,CSV等等)。

  模版包括在使用时会被值替换掉的 变量,和控制模版逻辑的 标签

  模板继承

  {{ block.super }}继承模板中原有的内容。

  模板变量用双括号表示。

  模板标签

  if/else 标签

{% if condition %}
     ... display
{% endif %}

   for/empty标签

  for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

   

  csrf_token 标签

  原文博客地址:http://blog.csdn.net/wjtlht928/article/details/46563809

  PS :跨域

    参考博客 :https://segmentfault.com/a/1190000000718840

  CSRF的攻击原理

  CSRF攻击原理比较简单,如图1所示。其中Web A为存在CSRF漏洞的网站,Web B为攻击者构建的恶意网站,User C为Web A网站的合法用户。

1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;

2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;

3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;

4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;

5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

  预防措施

  1)在请求地址中添加token并验证

CSRF攻击之所以能够成功,是因为攻击者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此攻击者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF攻击的关键在于:在请求中放入攻击者所不能伪造的信息,并且该信息不存在于Cookie之中。鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。 

2)在HTTP头中自定义属性并验证  

自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到HTTP头中自定义的属性里。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中。这样解决了前一种方法在请求中加入token的不便,同时,通过这个类请求的地址不会被记录到浏览器的地址栏,也不用担心token会通过Referer泄露到其他网站。 

六 django的请求生命周期

  首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串.

  在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中.

  Django的请求生命周期是指当用户在浏览器上输入url到用户看到网页的这个时间段内,Django后台所发生的事情

  而Django的生命周期内到底发生了什么呢??

1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端
请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者post,体现在url之中.

2. url经过Django中的wsgi,再经过Django的中间件,最后url到过路由映射表,在路由中一条一条进行匹配,
一旦其中一条匹配成功就执行对应的视图函数,后面的路由就不再继续匹配了.
3. 视图函数根据客户端的请求查询相应的数据.返回给Django,然后Django把客户端想要的数据做为一个字符串返回给客户端.
4. 客户端浏览器接收到返回的数据,经过渲染后显示给用户.

  视图函数根据客户端的请求查询相应的数据后.如果同时有多个客户端同时发送不同的url到服务端请求数据

  服务端查询到数据后,怎么知道要把哪些数据返回给哪个客户端呢??

  因此客户端发到服务端的url中还必须要包含所要请求的数据信息等内容.

  例如,http://www.aaa.com/index/?nid=user这个url中,
  客户端通过get请求向服务端发送的nid=user的请求,服务端可以通过request.GET.get("nid")的方式取得nid数据

  客户端还可以通过post的方式向服务端请求数据.

  当客户端以post的方式向服务端请求数据的时候,请求的数据包含在请求体里,这时服务端就使用request.POST的方式取得客户端想要取得的数据

  需要注意的是,request.POST是把请求体的数据转换一个字典,请求体中的数据默认是以字符串的形式存在的.

  

七 django UR调度器

  视图层

  文档网址:http://python.usyiyi.cn/documents/django_182/topics/http/urls.html

  1()位置传参

  2(?P<x>)关键字传参

  3  URL的反向解析

    在模板中使用 url模板标签

    urlpatterns=[r'login.html',view.login,name='mylogin']

    模板html文件中

    [form action='{% url 'mylogin'%}']

     <a href='{%url 'myurl'%}'>
 
八 过滤器
  模板层
  Django提供了大约六十个内置的模版过滤器。你可以在 内置过滤器手册中阅读全部关于它们的信息。为了体验一下它们的作用,这里有一些常用的模版过滤器。
  内置模板标签和过滤器官方文档:http://python.usyiyi.cn/documents/django_182/ref/templates/builtins.html#ref-templates-builtins-filters
  常用的有default,filesizeformat,safe等等
 
九 中间件
  在有些场合,需要对Django处理的每个request都执行某段代码。 这类代码可能是在view处理之前修改传入的request,或者记录日志信息以便于调试,等等。

这类功能可以用Django的中间件框架来实现。

  W3C介绍网址:https://www.w3cschool.cn/django/mrxdfozt.html

十 Q查询

  Q 对象是 django.core.meta.Q 的实例, 用来装载一系列关键字参数. 这些关键字参数就象指定给 get() 和 filter() 函数的关键字参数一样.举例来说:

  Q(question__startswith='What') 

  Q 对象可以使用 & 和 | 运算符进行组合. 当两个Q对象进行 & 或 | 运算时,会生成一个新的Q对象.举例来说语句:

  Q(question__startswith='Who') | Q(question__startswith='What')

  生成一个新的 Q 对象表示这两个 "question__startswith" 查询条件的 "OR" 关系. 等同于下面的 SQL WHERE 子句:

  WHERE question LIKE 'Who%' OR question LIKE 'What%'

  示例:

from django.db.models import Q,F
book_list=models.Book.objects.filter(Q(publish__id=2)|Q(price__gt=70))

十一  F查询

  应用场景 :商品在原价格的基础上涨价10元

models.Book.objects.update(price=F('price')+10)

十二 中介模型

  文档官方网址:http://python.usyiyi.cn/documents/django_182/topics/db/models.html

  中介模型解决的是当Django帮你建好的多对多模型,并不能够满足,需要添加额外的字段。

  比如Student表,Course表,属于多对多关系。在Studnet2Course中,想添加一个score字段。

  怎么解决呢?通过through参数,来告诉Django我自己来建表。

class Student(models.Model):
    name=models.CharField(max_length=10)
    courese=models.ManyToManyField('Course',through='student2course')
    
class Course(models.Model):
    name=models.CharField(max_length=10)
    
class student2course(models.Model):
    student_id=models.ForeignKey('Student')
    course_id=models.ForeignKey('Course')
    score=models.DecimalField(max_digits=4,decimal_places=2)

   

  中介模型有一些限制:

  1 中介模型必须有且只有一个外键关联到源模型上,否则,必须通过manytomanyfield.through_fields()来显示指定Django 应该在关系中使用的外键。

  示例:

  Article与Tag建立多对多 中介模型

class Article(models.Model):

    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=50, verbose_name='文章标题')
    desc = models.CharField(max_length=255, verbose_name='文章描述')

    comment_count= models.IntegerField(default=0)

    homeCategory = models.ForeignKey(to='HomeCategory', to_field='nid', null=True)
    user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid')
    tags = models.ManyToManyField(
        to="Tag",
        through='Article2Tag',
        through_fields=('article', 'tag'),
    )


在这个中介模型中,有两个外键,怎么办呢,用through_fields参数。
class Tag(models.Model):

    nid = models.AutoField(primary_key=True)
    title = models.CharField(verbose_name='标签名称', max_length=32)
    blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid')
class Article2Tag(models.Model):
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid')
    tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid')

    class Meta:
        unique_together = [
            ('article', 'tag'),
        ]
  设置联合唯一。

十三 <QuerySet>转变为生成器

  只需调用.iterator()方法

def index(request):
    obj = models.Student.objects.all()
    print(obj, type(obj))
    print(obj.iterator(),type(obj.iterator()))
    return HttpResponse('ok')

  输出:

<QuerySet [<Student: Student object>, <Student: Student object>]> <class 'django.db.models.query.QuerySet'>
<generator object ModelIterable.__iter__ at 0x000002538633DBA0> <class 'generator'>

十四 bulk_create 整体插入

  bulk 大量

  如果插入10000条数据,这样的方法是不明智的,不合适的

def create(request):
    for i in range(10000):
        User.objects.create_user('user-%s' %i)
    return HttpResponse('ok')

  尽量少的避免数据的链接与断开

  推荐这种方法

def create(request):
    l=[]
    for i in range(10000):
        l.append('user-%s' %i)
    User.objects.bulk_create(l)
    return HttpResponse('ok')

十五 verbose_name

  自述名

  应用场景:后台显示,admin?

  一个字段的可读性更高的名称。如果用户没有设定冗余名称字段,Django会自动将该字段属性名中的下划线转换为空格,并用它来创建冗余名称。

  ForeignKeyManyToManyField 和 OneToOneField 之外,每个字段类型都接受一个可选的位置参数(在第一的位置) —— 字段的自述名。如果没有给定自述名,Django 将根据字段的属性名称自动创建自述名 —— 将属性名称的下划线替换成空格。

  官方文档地址:http://python.usyiyi.cn/documents/django_182/topics/db/models.html#verbose-field-names

  

原文地址:https://www.cnblogs.com/654321cc/p/7891993.html