zoukankan      html  css  js  c++  java
  • django-(创建工程项目的基本配置、url路由系统详解、中间件&请求生命周期、admin介绍、FBV和CBV装饰器实现用户登陆认证)

      Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

    基本配置

    跨文件导入模型注意事项:

    1、当从其他应用的model导入模型时,会遇到循环导入错误。可以django.db.models.loading.get_model用来解决这个问题。

    from django.db.models.loading import get_model
    
    Libro = get_model('libros', 'Libro')
    class Perfil(models.Model):
        usuario = models.OneToOneField(User, null=True)
        actualmente_leyendo = models.ForeignKey(Libro, related_name="actualmente_leyendo")
    

    或者更好的是,不要导入模型,只需<app>.<model_name>在引用其他应用程序中的模型时传递带有格式的字符串

    class Perfil(models.Model):
        usuario = models.OneToOneField(User, null=True)
        actualmente_leyendo = models.ForeignKey('libros.Libro', related_name="actualmente_leyendo

    2、makemigrations,migrate的时候指定app名(先执行带有user模块的app模型),如:python manage.py makemigrations appname,python manage.py migrate appname

    3、再执行一遍python manage.py migrate

    一、创建django程序

    • 添加环境变量,python中有个script文件夹
    • 终端命令:django-admin startproject sitename
    • IDE创建Django程序时,本质上都是自动执行上述命令
    • 进入创建的工程名字文件夹
    • 执行:python manage.py runserver ip:端口(例如:127.0.0.1:8800)

    例如:
      wsgi是一套规则,一个接口,
      mysite
        -mysite
          - -init-.py
          - settings.py 配置文件:支持缓存,连接数据库,做静态文件处理,找模板,加密的加严都是这个文件
          - urls.py url对应关系,用户访问django程序,进行匹配,如果有就去提取,
          - wsgi.py 遵循WSGI规范,以后上线的时候会变成uwsgi+nginx才能跑起来,wsgi是一套规则,一个接口,
          -db.sqlite3
        -manage.py 管理Django程序

    其他管理Django的常用命令:

      python manage.py runserver 0.0.0.0
      python manage.py startapp appname
      python manage.py syncdb
      python manage.py makemigrations
      python manage.py migrate

      python manage.py createsuperuser

      python manage.py
      python manage.

    网站设计模型:
    -抽屉网
      -配置、数据库
      -主站app
      -后台管理app

    创建app
      python manage.py startapp cmdb
      python manage.py startapp openstack
    .

    创建完app之后,可以把自己写的函数放在相关app文件夹下面的view.py文件里面

    二、程序目录

    wsgi:帮助django自动创建socket,其实是一套规则接口,其可以适应多种socket服务:django系统内部就是调用的wsgiref模块,一般上线的时候会变成uwgi第三方模块,需要自己安装,现在只是在测试调试阶段,namewsgi支持一下服务:

    server_names = {

        'cgi': CGIServer,
        'flup': FlupFCGIServer,
        'wsgiref': WSGIRefServer,
        'waitress': WaitressServer,
        'cherrypy': CherryPyServer,
        'paste': PasteServer,
        'fapws3': FapwsServer,
        'tornado': TornadoServer,
        'gae': AppEngineServer,
        'twisted': TwistedServer,
        'diesel': DieselServer,
        'meinheld': MeinheldServer,
        'gunicorn': GunicornServer,
        'eventlet': EventletServer,
        'gevent': GeventServer,
        'geventSocketIO':GeventSocketIOServer,
        'rocket': RocketServer,
        'bjoern' : BjoernServer,
        'auto': AutoServer,

    app里面的文件详解:
      1、配置作用的文件:
        -migrations文件夹:数据库操作记录,在django创建修改数据库的时候,就会在这个文件生成记录,记录操作,只记录修改表结构的记录
        -admin django为我们提供的后台管理
        -app 配置当前app
        -models 创建数据库表ORM,写指定的类,再通过命令执行可以创建数据库结构
        -tests 单元测试
      2、写代码的文件:
        -views 写对app管理的业务代码

    三、配置文件,当创建了工程的时候就要先执行下面的操作

    1、数据库

    1、数据库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DATABASES = {
        'default': {
        'ENGINE''django.db.backends.mysql',
        'NAME':'dbname',
        'USER''root',
        'PASSWORD''xxx',
        'HOST': '',
        'PORT': '',
        }
    }
    1
    2
    3
    4
    5
    6
    # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
      
    # 如下设置放置的与project同名的配置的 __init__.py文件中
      
    import pymysql
    pymysql.install_as_MySQLdb() 

    2、模版

    1
    2
    3
    TEMPLATE_DIRS = (
            os.path.join(BASE_DIR,'templates'),
        )

    3、静态文件(在settings文件的最下面行设置)

    1
    2
    3
    STATICFILES_DIRS = (
            os.path.join(BASE_DIR,'static'),
        )  #记得后面加逗号,不加会报错

    下面是提示用户输入信息错误出现提示信息实例:

    工程文件显示图片实例:

    views文件代码:

    from __future__ import unicode_literals
    # from django.shortcuts import render
    from django.shortcuts import redirect
    # Create your views here.
    from django.shortcuts import render
    def login(request):
    # 先指定error_msg为空,这样就不会显示要提示的信息
    error_msg= ''
    if request.method=='POST':
    user=request.POST.get('user',None)
    pwd=request.POST.get('pwd',None)
    if user=='root' and pwd=='123':
    return redirect('https://www.baidu.com') #重定向用redirect方法
    else:
    error_msg='用户名密码错误'
    # 第三个参数是用来和html文件里面的span标签对应,用户密码错误的时候,在客户端浏览器提示信息,用来替换需要输出给屏幕的信息
    return render(request,'login.html',{'error_msg':error_msg})

    urls文件代码:

    from django.conf.urls import url
    from django.contrib import admin
    from cmdb import views
    urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login', views.login), #注意,这里的r"^login"后面没有/,因为django会自动添加,如果这里后面添加了/,
    那么在login.html文件的<form action="/login" method="post"> 中的action参数后面也要加上/变成"/login/".
    ]

    templates下面的login.html文件代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/comments.css">
    <style>
    lable{
    text-align: right;
    display: inline-block;
    80px;
    }
    </style>
    </head>
    <body>
    <form action="/login" method="post">  
        <p>
    <lable for="username">用户名:</lable>
    {    #提交表单的时候,input表单必须制定name,不然POST的时候无法获取对应信息#}
    <input id='username' type="text" name="user" />
    </p>
    <p>
    <lable for="lpassword">密码:</lable>
    <input id='password' type="password" name="pwd" />
    <input type="submit" value="提交">
    {    #下面标签用的两个{}是为了在客户端调用网页的时候,login函数可以调用并替换其内容#}
    <span style="color: red">{{ error_msg }}</span>
    </p>
    </form>
    <script src="/static/jquery-3.3.1.min.js"></script>
    </body>
    </html>

     知识梳理:

    对于文件的接收,用request.FILES.get('file标签的name'),注意:form标签要做特殊设置

    obj=request.FILES.get('文件名')

    boj.name

    f=open(obj.name,mode='wb')

    for item in obj.chunks():

      f.write(item)

    f.close

    对于checkbox等多选的内容,用request.getlist(),

     

    变量里面如果有字典和字符串等,字典就用.key,字符串就用.下标(.0/.1)这种形式

    if语句也可以嵌套在for循环里面用

    4、FBV和CBV,今后的工程开发中,两种方法都可以使用;

      FBV: function base view 通过函数实现
        url.py
        index-->函数名
        view.py
        def 函数(request):
          ...


    CBV:通过类class实现

     urls中的代码:  

    from app001 import views
    urlpatterns = [
    url(r'^home', views.Home.as_view()), #固定格式,必须这么写
    ]

    views中的代码:

    from django.views import View
    class Home(View):
    '''
    类的执行过程:首先urls里面的是home选择的话,先执行View里面的dispatch方法,然后选择http_method_names里面的方法(比如get和post)执行,
    将执行的结果再通过dispatch给返回,所以和浏览器客户交流的数据其实是通过dispatch中间调度来通信的。
    '''''
    # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 其实view里面有这么多调用方法
    #下面是自己来定义dispatch方法,可以自己添加某些功能,这里实例中没有做什么功能的修改,只是作为演示。
        def dispatch(self, request, *args, **kwargs):
    print('before')
    # 调用父类中的dispatch方法,
    result=super(Home,self).dispatch(request, *args, **kwargs)
    print('after')
    return result

    def get(self,request):
    print(request.method)
    return render(request,'home.html')
    def post(self,request):
    print(request.method)
    return render(request, 'home.html')

       

     5、装饰器知识点:其他:在循环字典的时候,在html中有key,values,items方法来循环,注意这里和python不一样的是后面不需要加( ),

    6、装饰器实现用户登陆认证(结合cookie):

    路由系统,url

    1、单一路由对应

    1
    url(r'^index$', views.index),

    2、基于正则的路由

      url代码:

    1
    2
    url(r'^index/(d*)', views.index),
    url(r'^manage/(?P<name>w*)/(?P<id>d*)', views.manage),#这种方式是按照位置参数传递值的,推荐用这种方式

      views代码:

    def detail(request,nid):
    # n=request.GET.get('nid')
    # info=USER_LIST[n]
    # # return HttpResponse(n)
    # return render(request,'detail.html',{'info':info})
    a=USER_LIST[nid]
    return render(request,'detail.html',{"info":a})

      

    3、添加额外的参数

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

    4、为路由映射设置名称

    1
    2
    url(r'^home', views.home, name='h1'),
    url(r'^index/(d*)', views.index, name='h2'),

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

    • 模板中使用生成URL     {% url 'h2' 2012 %}
    • 函数中使用生成URL     reverse('h2', args=(2012,))      路径:django.urls.reverse
    • Model中使用获取URL  自定义get_absolute_url() 方法

      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})

      复制代码
      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})
      复制代码

    获取请求匹配成功的URL信息:request.resolver_match

    补充:

    name
      对url路由的关系进行命名,以后可以根据名称生成自己想要的url
      url(r'^sdfas/', views.detail,name='i1')
      url(r'^sdfas/(d+)/(d+)/', views.detail,name='i2')
      url(r'^sdfas/(?p<nid>d+)/(?p<nid>d+)/', views.detail,name='i3')

      def func(request,*args,**kwargs):
        from django.urls import reverse
        url1=reverse('i1') #相当于sdfas/
        url1=reverse('i1',args=(1,2)) #相当于sdfas/1/2
        url1=reverse('i1',kwargs={'pid':1,'nid':2}) #相当于sdfas/1/9
        xxx.html模板语言action=:
        {% url "i1" %} #相当于sdfas/
        {% url "i2" 1 2 %} #相当于sdfas/1/2
        {% url "i2" pid=1 nid=9 %} #相当于sdfas/1/9
    注意:
    当前的URL:request.path_info

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

    1
    url(r'^web/',include('web.urls')),

    6、命名空间

    a. project.urls.py

    1
    2
    3
    4
    5
    6
    from django.conf.urls import url,include
     
    urlpatterns = [
        url(r'^a/', include('app01.urls', namespace='author-polls')),
        url(r'^b/', include('app01.urls', namespace='publisher-polls')),
    ]

    b. app01.urls.py

    1
    2
    3
    4
    5
    6
    7
    from django.conf.urls import url
    from app01 import views
     
    app_name = 'app01'
    urlpatterns = [
        url(r'^(?P<pk>d+)/$', views.detail, name='detail')
    ]

    c. app01.views.py

    1
    2
    3
    def detail(request, pk):
        print(request.resolver_match)
        return HttpResponse(pk)

    以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

    • v = reverse('author-polls:detail', kwargs={'pk':11})
    • {% url 'author-polls:detail' pk=12 pp=99 %}

    django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

    注意,一般namespace主要用在不同页面要用到同一个app的同一个视图函数,而name主要用在同一个app不同的视图函数,这是两者的主要应用却别;

     

    中间件

    django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

    在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

    与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

     

    里面的def定义的requeset和response名称是不能变的,类继承的类名也不能变;

    这种操作适合对所有操作,也能进行黑名单、ip过滤的操作;

    处了自定义上面2个方法,还可以加上下面4个方法

    中间件中可以定义四个方法,分别是:

      • process_request(self,request)  #重要
      • process_view(self, request, callback, callback_args, callback_kwargs)  #重要   callback就是view函数,后面的args和kwargs就是view函数的参数
    • process_template_response(self,request,response)   如果有render函数返回,才执行这条,例如下面:
    • process_exception(self, request, exception)    如果views函数返回有错误,就会执行,然后再继续response,返回给用户,exception是异常信息
    • process_response(self, request, response)    #重要

    以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

    自定义中间件

    1、创建中间件类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class RequestExeute(object):
          
        def process_request(self,request):
            pass
        def process_view(self, request, callback, callback_args, callback_kwargs):
            =1
            pass
        def process_exception(self, request, exception):
            pass
          
        def process_response(self, request, response):
            return response

    2、注册中间件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'wupeiqi.middleware.auth.RequestExeute',
    )

     中间件执行流程(程序请求声明周期):

    1、当用户发送请求的时候,先经过中间件的process_request(按照settings配置的中间件顺序执行),拿到客户端发送过来的request信息一层一层的传递;

    2、在传递到最后一层中间件后,先做了urls关系映射的处理,然后中间件里面如果有process_view函数,就会转到process_vies函数里面也是一层一层的执行(这里就可以做参数错误处理、黑名单、ip过滤操作);

    3、当中间件的所有process_view执行完了之后就会到达视图views执行相应的函数;

    4、在服务端向客户端返回信息的时候,再经过process_exception,判断视图函数是否出现了执行错误,如果出现了执行错误,捕捉错误,返回给最靠近视图view的中间件的process_response函数(这里可以做抛出页面丢失、或者403等界面的处理),改变了process_response返回的信息后一层一层传递到客户端;

    5、如果中间件没有定义process_exception函数,那么视图函数返回的信息就会直接经过中间件的process_response一层一层的向最外层传递信息,也可以在函数里面做操作,返回给用户自定义的字符串等信息,最后,信息一层一层传回给客户端的浏览器。

      另外一个不重要的中间件函数是process_template_response(self,request,response)   如果有render函数返回,才执行这条,而且要render response,不然客户端接受不到数据,

    admin

    django amdin是django提供的一个后台管理页面,该管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

    • 创建后台管理员
    • 配置url
    • 注册和配置django admin后台管理页面

    1、创建后台管理员

    1
    python manage.py createsuperuser

    2、配置后台管理url

    1
    url(r'^admin/', include(admin.site.urls))

    3、注册和配置django admin 后台管理页面

    a、在admin中执行如下配置

    1
    2
    3
    4
    5
    6
    7
    8
    from django.contrib import admin
      
    from app01 import  models
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    b、设置数据表名称

    1
    2
    3
    4
    5
    6
    class UserType(models.Model):
        name = models.CharField(max_length=50)
      
        class Meta:
            verbose_name = '用户类型'
            verbose_name_plural = '用户类型'

    c、打开表之后,设定默认显示,需要在model中作如下配置

    1
    2
    3
    4
    5
    class UserType(models.Model):
        name = models.CharField(max_length=50)
      
        def __unicode__(self):
            return self.name
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username''password''email')
      
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    d、为数据表添加搜索功能

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username''password''email')
        search_fields = ('username''email')
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    e、添加快速过滤

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username''password''email')
        search_fields = ('username''email')
        list_filter = ('username''email')
          
      
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    更多:http://docs.30c.org/djangobook2/chapter06/

    逆风的方向最适合飞翔,我不怕千万人阻挡,只怕自己投降。
  • 相关阅读:
    L3-028 森森旅游 题解(最短路)
    Codeforces Round #717 (Div. 2) 题解(A-D)
    大爽Python入门教程 总目录
    Django笔记&教程 2-4 视图常用
    python一对一教程:Computational Problems for Physics chapter 1-B Code Listings 1.7
    python一对一教程:Computational Problems for Physics chapter 1 Code Listings
    b站个人直播年报【大爽歌作】 介绍与演示
    架构漫谈阅读笔记03
    架构漫谈阅读笔记02
    架构漫谈阅读笔记01
  • 原文地址:https://www.cnblogs.com/daemon-czk/p/9746511.html
Copyright © 2011-2022 走看看