Web

Django--MTV

2018-12-17  本文已影响70人  Anatkh_7117

http协议简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文本的传送协议。

特点

 基于TCP/IP

 基于请求-响应模式

 无状态保存

 无连接

请求协议

请求协议.png

请求方式: get与post请求

响应协议

响应协议.png

协议格式:请求首航\r\n请求头\r\n\请求头....r\n\r\n请求体

其中:只有POST请求有请求体,GET请求的参数用&链接到请求首航的URL里

响应状态码


状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

1xx:指示信息--表示请求已接收,继续处理

2xx:成功--表示请求已被成功接收、理解、接受

3xx:重定向--要完成请求必须进行更进一步的操作

4xx:客户端错误--请求有语法错误或请求无法实现

5xx:服务器端错误--服务器未能实现合法的请求

常见状态码:

OK                        //客户端请求成功

Bad Request              //客户端请求有语法错误,不能被服务器所理解

Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用

Forbidden                //服务器收到请求,但是拒绝提供服务

Not Found                //请求资源不存在,eg:输入了错误的URL

Internal Server Error    //服务器发生不可预期的错误

Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

WSGI接口协议

封装了http请求协议解析数据的过程(切割\r\n进行拆分)和http响应协议封装数据的过程(拼接\r\n进行数据封装),让程序员专注于web业务开发。python根据wsgi协议开发了wsgiref模块使开发更加方便


from wsgiref.simple_server import make_server

def application(environ, start_response):

    """

    回调函数,当客户端链接时调用该函数

    :param environ: 按着http协议解析数据

    :param start_response: 按着http协议组装数据

    :return:

    """

    start_response('200 OK', [('Content-Type', 'text/html')])

    return [b'<h1>Hello, World!</h1>']

if __name__ == '__main__':

httpd = make_server('', 8080, application)  # 1:IP/2:端口/3:回调函数,当用户链接就调用回调函数

print('Serving HTTP on port 8000...')

# 等待用户链接,开始监听HTTP请求:conn,addr = socket.accept()

httpd.serve_forever()

如何给用户返回动态内容?

MTV模型

Django的MTV分别代表:

Django基础篇

基本配置及操作

01.查看Django版本python -m django --version

02.创建Django项目django-admin startproject mysite(cd到你要创建的文件下)

03.在mysite目录下创建应用python manage.py startapp appname

04.启动django项目python manage.py runserver 8080

05.两条数据库迁移命令即可在指定的数据库中创建表

python manage.py makemigrations

python manage.py migrate

pyhon manage.py syncdb

06.清空静态服务器python manage.py flush

07.创建超级用户python manage.py createsuperuser

08.修改用户密码可以用python manage.py changepassword username

09.导入导出数据

python manage.py dumpdata > proname.json

python manage.py loaddata proname.json

10.Django 项目环境终端:python manage.py shell

11.Django终端直接操作SQL语句python mange.py dbshell

12.查看所有命令python manage.py

配置文件

1.APPS注册


INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'blog',  # 注册自己的应用名到installed_apps里

]

2.数据库

Django默认使用sqlite进行存储数据,如果要使用其他数据库需要在settings中进行配置


DATABASES = {

    'default': {  # default为默认使用的数据库,可以在DATABASES中配置多个不同数据库

        'ENGINE': 'django.db.backends.mysql',

        'NAME': 'cnblog',

        'USER': 'root',

        'PASSWORD': 'xxxx',

        'HOST': '127.0.0.1',  # IP

        'POST': 3306  # 端口

    }

}

由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

如下设置放置的与project同名的配置__init__.py文件中


import pymysql

pymysql.install_as_MySQLdb()

3.静态文件


静态文件交由Web服务器处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例):

              URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx.

                            conf里的location

                        |---------->如果是静态文件,则由nginx直接处理

                        |---------->如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配

以上是部署到Web服务器后的处理方式(生产环境),为了便于开发,Django提供了在开发环境的对静态文件的处理机制,方法是这样

STATIC主要指的是如css,js,images这样文件


STATIC_URL = '/static/'      # 别名/引用名

STATICFILES_DIRS = (

            os.path.join(BASE_DIR,"static"),  #实际名 ,即实际文件夹的名字

        )

'''

注意点1:

django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找

        <script src="/statics/jquery-3.1.1.js"></script>

        ------error-----不能直接用,必须用STATIC_URL = '/static/':

        <script src="/static/jquery-3.1.1.js"></script>

注意点2:

STATICFILES_DIRS = (

    ("app01",os.path.join(BASE_DIR, "app01/statics")),

        )

<script src="/static/app01/jquery.js"></script>

'''

media配置


# in settings:

MEDIA_URL="/media/"  # 让用户能够访问到media文件夹的路径

MEDIA_ROOT=os.path.join(BASE_DIR,"app01","media","upload")  # 好像是Django2.0之前?

MEDIA_ROOT = os.path.join(BASE_DIR, "media")  # 2.0后配置?

# MEDIA_ROOT效果:一旦配置了media,Django将把文件下载到media文件夹里

# in urls:

from django.views.static import serve

re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),


        静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的:



        MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件。如果你定义



        MEDIA_ROOT=c:\temp\media,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c:\temp\media\abc

        eg:

            class blog(models.Model):

                  Title=models.charField(max_length=64)

                  Photo=models.ImageField(upload_to="photo")

          上传的图片就上传到c:\temp\media\photo,而在模板中要显示该文件,则在这样写

          在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写:

                BASE_DIR= os.path.abspath(os.path.dirname(__file__))

                MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/')

        MEDIA_URL是指从浏览器访问时的地址前缀,举个例子:

            MEDIA_ROOT=c:\temp\media\photo

            MEDIA_URL="/data/"

        在开发阶段,media的处理由django处理:

          访问http://localhost/data/abc/a.png就是访问c:\temp\media\photo\abc\a.png

          在模板里面这样写<img src="/media/abc/a.png">

          在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置,

          以便能让web服务器能访问media文件

          以nginx为例,可以在nginx.conf里面这样:

                location ~/media/{

                      root/temp/

                      break;

                    }

          具体可以参考如何在nginx部署django的资料。

路由系统

FBV


1、单一路由对应

re_path(r'^index$', views.index),

2、基于正则的路由,捕获到的参数永远转换成str

re_path(r'^index/(\d*)', views.index),

re_path(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),

3、添加额外的参数(了解即可)

re_path(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),

4、为路由映射设置名称(用于反向生成)

re_path(r'^home', views.home, name='h1'),

re_path(r'^index/(\d*)', views.index, name='h2'),

设置名称之后,可以在不同的地方调用,如:

01.模板中使用生成URL    {% url 'h2' 2012 %} 重定向name=h2的url,传参2012给url {% url 'xx' year%} 参数year为外层模板for循环进行循环传参

02.views.py函数中使用生成URL,导入from django.from django.shortcuts import reverse/from django.urls import reverse

reverse('h2', args=(2012,))/reverse('NewType.Detail', kwargs={'nid': self.id})

03.Model中使用获取URL  自定义get_absolute_url() 方法,使用reverse会自动调用该函数

# in models.py:

class NewType(models.Model):

    caption = models.CharField(max_length=16)

    def get_absolute_url(self):

        """

        为每个对象生成一个URL

        应用:在对象列表中生成查看详细的URL,使用此方法即可!!!

        :return:

        """

        # return '/%s/%s' % (self._meta.db_table, self.id)

        # 或

        from django.urls import reverse

        return reverse('NewType.Detail', kwargs={'nid': self.id})



# in templates:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

当模板语法通过循环获取每个标签的object时,为了不使用硬编码,让代码动态起来,也为了方便维护,而使用object.get_absolute_url

5、根据app对路由规则进行分类

re_path(r'^web/',include('app.urls')),

在app里创建urls.py,实现相似的urlpatterns列表

注意!在对应app的urlpatterns上方定义app_name=当前app名

6、命名空间,路由中有多个相同的name时,为了避免冲突,引入了namespace

    re_path(r'^a/', include('app01.urls', namespace='author-polls')),

    re_path(r'^b/', include('app01.urls', namespace='publisher-polls')),

使用namespace后,使用name生成URL时候,应该如下:

v = reverse('app01:detail', kwargs={'pk':11})

{% url 'app01:detail' pk=12 pp=99 %}

CBV


当类继承了View、APIView

from django.views import view

from rest_framework.views import APIView

re_path(r'^login.html$', views.Login.as_view()),

当类继承了ViewMixin

from rest_framework.viewsets import GenericViewSet, ViewSetMixin, ModelViewSet

re_path(r'^login.html$', views.Login.as_view({'get': 'list','post': 'create','delete':'destroy'})),

视图函数views

视图函数都接受request参数,request有多种属性


path:      请求页面的全路径,不包括域名

request.path

method:    请求中使用的HTTP方法的字符串表示。全大写表示。例如

              if  request.method=="GET":

                        do_something()

              elif request.method=="POST":

                        do_something_else()

GET:        包含所有HTTP GET参数的类字典对象

POST:      包含所有HTTP POST参数的类字典对象

注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:

request.POST.getlist("hobby")

COOKIES:    包含所有cookies的标准Python字典对象;keys和values都是字符串。

FILES:      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中

            name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:

request.FILES.get(input的name名) 获取前端传来的文件数据

request.FILES.get(name名称).name 获取文件名

            filename:      上传文件名,用字符串表示

            content_type:  上传文件的Content Type

            content:      上传文件的原始内容

user:      是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登陆:

            if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware

            时该属性才可用

session:    唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。

设置session:request.session["valid_code_str"] = valid_code_str

获取session:request.session.get('valid_code_str')

render函数

render(request, template_name,字典)

注意

        渲染工作在Django中执行完成后,字符串返回给浏览器。 

        但是:**js,css额外再发一次请求仅获取静态文件** 

redirect

参数可以是:

默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向


传递一个对象

将调用get_absolute_url() 方法来获取重定向的URL:

from django.shortcuts import redirect

def my_view(request):

    ...

    object = MyModel.objects.get(...)

    return redirect(object)



传递一个视图的名称

可以带有位置参数和关键字参数;将使用reverse() 方法反向解析URL:

def my_view(request):

    ...

    return redirect('some-view-name', foo='bar')



传递要重定向的一个硬编码的URL

def my_view(request):

    ...

    return redirect('/some/url/')



也可以是一个完整的URL:

def my_view(request):

    ...

    return redirect('http://example.com/')



默认情况下,redirect() 返回一个临时重定向。以上所有的形式都接收一个permanent 参数;如果设置为True,将返回一个永久的重定向:

def my_view(request):

    ...

    object = MyModel.objects.get(...)

    return redirect(object, permanent=True)

render和redirect的区别

1.render是渲染变量到模板中,而redirect是HTTP中的1个跳转的函数,一般会生成302状态码。

2.地址栏有区别:

模板层template

模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户

return render(request, 'xxx.html',{'str':data_str})

模板语法

views中

return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list})

以传数字/字符串/字典/date类型/列表/对象

template


<h4>{{s}}</h4>

<h4>列表:{{ l.0 }}</h4>

<h4>列表:{{ l.2 }}</h4>

<h4>字典:{{ dic.name }}</h4>

<h4>日期:{{ date.year }}</h4>

<h4>类对象列表:{{ person_list.0.name }}</h4>

注意:句点符也可以用来引用对象的方法(无参数方法)。

<h4>字典:{{ dic.name.upper }}</h4>

模板值过滤器 | :


default

如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:

{{ value|default:"nothing" }}

length

返回值的长度。它对字符串和列表都起作用。例如:

{{ value|length }}

如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。

filesizeformat

将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

date

如果 value=datetime.datetime.now()

{{ value|date:"Y-m-d" }}

slice

如果 value="hello world"

{{ value|slice:"2:-1" }}

truncatechars

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:要截断的字符数

例如:

{{ value|truncatechars:9 }}

如果value是“Joel 是 a >,输出将为“Joel i ...”。

safe

Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如:

value="<a href="">点击</a>"

{{ value|safe}}

模板标签


{% for person in person_list %}

    <p>{{ person.name }}</p>

{% empty %}  # 可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作

    <p>sorry,no person here</p>

{% endfor %}

forloop.counter

forloop.first

forloop.last


{% if num > 100 or num < 0 %}

    <p>无效</p>

{% elif num > 80 and num < 100 %}

    <p>优秀</p>

{% else %}

    <p>凑活吧</p>

{% endif %}


使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

{% with total=business.employees.count %}

    {{ total }} employee{{ total|pluralize }}

{% endwith %}

这个标签用于跨站请求伪造保护

母板base.html:{% block title %}{% endblock %}

子板:{% extends "base.html" %}

{% block title %}{% endblock %}

注意:子模板没有定义父模板的block,则沿用父模板的内容。父模版的 {% block %} 标签中的内容总是被用作备选内容

{{ item.event_start|date:"Y-m-d H:i:s"}}

{{ bio|truncatewords:"30" }}

{{ my_list|first|upper }}

{{ name|lower }}

自定义标签和过滤器

1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

2、在app中创建templatetags模块(模块名只能是templatetags)

3、创建任意 .py 文件,如:my_tags.py

自定义标签位置.png

from django import template

from django.utils.safestring import mark_safe

register = template.Library()  #register的名字是固定的,不可改变

@register.filter

def filter_multi(v1,v2):

    return  v1 * v2

<br>

@register.simple_tag

def simple_tag_multi(v1,v2):

    return  v1 * v2

<br>

@register.simple_tag

def my_input(id,arg):

    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)

    return mark_safe(result)

simple_tag和filter的使用


-------------------------------.html

{% load xxx %} 



# num=12

{{ num|filter_multi:2 }} #24

{{ num|filter_multi:"[22,333,4444]" }}

{% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中

{% simple_tag_multi num 5 %}

注意:filter可以用在if等语句后,simple_tag不可以


{% if num|filter_multi:30 > 100 %}

    {{ num|filter_multi:30 }}

{% endif %}

上一篇 下一篇

猜你喜欢

热点阅读