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/

逆风的方向最适合飞翔,我不怕千万人阻挡,只怕自己投降。
原文地址:https://www.cnblogs.com/daemon-czk/p/9746511.html