Django基础篇

Django是WEB框架的一种,相对于其他的WEB框架(如Tornado、Flash、Bottle)的优势为:大而全,框架本身集成了数据库操作的ORM、模型绑定、模板引擎、Session、缓存等功能。

如何配置一个简单的Django程序:

一、创建一个django程序

  可以通过终端创建,也可以通过编程工具PyCharm来创建

  • 终端创建:django-admin   startproject   sitename
  • 编程工具创建:File--->>New Project   本质上还是调用上面的命令创建

  其他常用的命令还有:

#启动django程序
python manage.py runserver 0.0.0.0

#创建一个app
python manage.py startapp appname

#同步数据库
python manage.py syncdb

#检查数据库并创建临时sql语句
python manage.py makemigrations

#创建数据库或更新数据库
python manage.py migrate

#对django程序的admin后台管理创建超级管理员
python manage.py createsuperuser

二、settings文件的配置:

1、数据库的配置

  在pycharm创建的工程默认的settings中的数据库为sqlite,可以设置成生产环境总的mysql数据库

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

但是这种mysql数据库配置只适合在python 2.x版本的可以使用,如果再python 3.x版本操作mysql数据库的话,仅仅这种配置就无法满足了,还应该在工程名下同工程名同名的文件夹下的__init__.py文件中添加如下代码:

# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
  
# 在与project同名的文件夹下的 __init__.py文件中配置
  
import pymysql
pymysql.install_as_MySQLdb() 

2、模板

  如果settings中如果没有模板的配置,可以在其中添加如下代码,这样一些前端的html文件才可以被调用。

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

3、静态文件

  这个一定要配置,因为一些静态文件(比如:css  js等)要放在此目录下

STATICFILES_DIRS = (
        os.path.join(BASE_DIR,'static'),
    )

路由系统

路由系统相当于中转枢纽,当客户发送url请求的时候,要经过路由系统转发到view处理,view处理操作数据库,对模板进行渲染返回给客户端。

1、单一路由

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

这里的url(r'^index$',views.index)也可以这样写url(r'^index/$',views.index)index后加了一个反斜线/,那么在其他地方引用这个url的时候也要加上/,如果没有的/,那么其他应用的地方也应该没有。

2、基于正则路由

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

注:这个url中带有参数,那么在view的对应的函数中也要加上参数如:

#url(r'^index/(\d*)', views.index),在view的对应的函数
def  index(request,num):
     pass 
    
#url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
def   manage(request,name,id):
     pass

3、url中添加额外的参数,这个参数作为view函数中参数的默认值

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

view中对应的函数为:

def   manage(request,id):
     pass

4、为路由映射设置名称

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

这个映射相当于给url起个别名,在模板中可以这样用:{% url 'h1' %}   {% url 'h2' 123 %}

那么view中也可通过这个name来获取url,这就要用到reverse()方式在view中获取url

在url中定义的路径如下:

url(r'^asdfasdfasdf/', views.index, name='i1'),
url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'),
url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'),

在view中获取url的方式为:

from django.urls import reverse
def func(request, *args, **kwargs):
        url1 = reverse('i1')                             
	url2 = reverse('i2', args=(1,2,))                
	url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) 
			

#那么通过reverse()生成的url分别为:
url1 = asdfasdfasdf/
url2 = yug/1/2/
url3 = buy/1/9/

在模板中使用

{% url "i1" %}                     # asdfasdfasdf/
{% url "i2" 1 2 %}                 # yug/1/2/
{% url "i3" pid=1 nid=9 %}         # buy/1/9/

还有在模板中也可以使用request.path_info来获取当前路径   {{ request.path_info }}

5、根据app对路由规则进行分类(多级路由)

当程序中有多个app的话,如果在一个总的url中添加多个app对应的路径,这样在后期维护的时候就会很乱,而且不好操作。这样就可以在每个app下创建一个子url,配置如下:

#比如在CMDB  app下创建一个子url
url(r'^cmdb/',include('cmdb.urls')),

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

模板

1、模板的执行过程

对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据通过模板语言插入到模版中,最后将信息渲染后返回给用户。

2、模板语言的书写方式:

#获取单一个值
{{ name }}

#获取对象内的值,如果对象是字典,用.健获取
{{ obj.name }}

#获取对象内的值,如果对象是列表,用.索引获取
{{ obj.0 }}

#for循环
{% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
#在for中可以使用一些方法
forloop.counter     forloop.first     forloop.last

#if...else判断
{% if 条件 %}  {% else %} {% endif %}

#当然可以在for循环中套if,也可以在if中套for循环

3、自定义simple_tag或filter

  (1)在app中创建templatetags模块

  (2)创建任意 .py 文件,如:xx.py

#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
   
register = template.Library()
   
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
   
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

       如果是filter的话,定义如下。需要注意的是:定义的filter函数只能定义两个参数

@register.filter
def my_filter(v1,v2):
    return  v1 + v2 

  这里的mark_safe()方法,表示从后台传到前台的html字符串是安全的,非xss攻击,那么这个html字符串经过mark_safe()处理后前台便可安全将此html代码解析成可读状态。

  (3)在使用自定义simple_tag或filter的html文件中导入之前创建的 xx.py 文件名

{% load xx %}

  (4)使用simple_tag或filter

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

#使用filter的方式
{{ "goser"|my_filter:"is a good man" }}

  (5)在settings中配置当前app,不然django无法找到自定义的simple_tag

  使用simple_tag和filter的优缺点:

  simple_tag:不能作为if条件,但参数可以任意多

  filter:最多两个参数,不能加空格。但能作为if条件(比如在html模板中参见if判断的条件{% if  "goser"|my_filter:"123" %}.......{% endif %})

4、模板的继承及include  

  定义母板master.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>
    <link rel="stylesheet" href="/static/commons.css" />
    <style>
        .pg-header{
            height: 50px;
            background-color: seashell;
            color: green;
        }
    </style>
    {% block css %} {% endblock %}
</head>
<body>
    <div class="pg-header">主机管理</div>
    <div>
        <a>asdf</a>
        <a id="">asdf</a>
        <a>asdf</a>
        <a>asdf</a>
        <a>asdf</a>
    </div>
    <script src='jquery-1.12.3.js'></script>
	{% block js %} {% endblock %}
</body>
</html>

  定义include模板tag.html

<li>{{ item }}</li>

  让userinfo.html继承模板和include模板

{% extends 'master.html' %}

{% block title %}用户管理{% endblock %}

{% block content %}
    <h1>用户管理</h1>
    <ul>
        {% for i in u %}
            <li>{{ i }}</li>
        {% endfor %}
    </ul>

    {% for i in u %}
        {% include 'tag.html' %}
    {% endfor %}

{% endblock %}

{% block css %}
    <style>
        body{
            background-color: red;
        }
    </style>
{% endblock %}

{% block js %}
    <script></script>
{% endblock %}

视图view

1、获取用户请求数据

#获取GET请求的数据
request.GET

#获取用户POST方式提交的数据
request.POST

#获取用户上传文件对象的方式
request.FILES

2、checkbox等多选的内容

#如果用户提交的数据是多选的,比如checkbox方式提交,那么在view中就要用到getlist()方式获取数据
request.POST.getlist()

3、上传文件的处理

def login(request):
    if request.method == "GET":
        return render(request, 'login.html')
    elif request.method == "POST":
        # radio
        # v = request.POST.get('gender')
        # print(v)
        # v = request.POST.getlist('favor')
        # print(v)
        # v = request.POST.get('fafafa')
        # print(v)
        obj = request.FILES.get('fafafa')
        print(obj,type(obj),obj.name)
        import os
        file_path = os.path.join('upload', obj.name)
        f = open(file_path, mode="wb")
        for i in obj.chunks():
            f.write(i)
        f.close()

        from django.core.files.uploadedfile import InMemoryUploadedFile
        return render(request, 'login.html')
    else:
        # PUT,DELETE,HEAD,OPTION...
        return redirect('/index/')

这里的上传的文件对象obj,要用到它的name属性(表示文件的名称)和chunks()(对文件进行分片的持续上传)

4、关于view中的FBV  CBV的书写方式

FBV的方式为:在view中以函数的方式处理前台发来的数据,在url中的方式为:url(r'^index/', views.index)

CBV的方式为:在view中以类的方式处理前台发来的数据,需要继承View类。在url中的体现按时为:url(r'^home/', views.Home.as_view())

CBV的示例如下:

from django.views import View
class Home(View):

    def dispatch(self, request, *args, **kwargs):
        # 调用父类中的dispatch
        print('before')
        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,'POST')
        return render(request, 'home.html')

在view中对可以用装饰器对用户登录做认证操作,这就要用cookie或session操作

def auth(func):
    def inner(reqeust,*args,**kwargs):
        v = reqeust.COOKIES.get('username111')
        if not v:
            return redirect('/login/')
        return func(reqeust, *args,**kwargs)
    return inner

@auth
def index(reqeust):
    # 获取当前已经登录的用户
    v = reqeust.COOKIES.get('username111')
    return render(reqeust,'index.html',{'current_user': v})

中间件

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

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

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',
)

自定义中间件

上面的中间件是创建工程后默认的中间件,当然也可以自定义中间件

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

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

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

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

1、创建中间件类

  这个类要继承MiddlewareMixin类,只有继承了这个类,自定义的类才可以使用中间件的方法,如process_request、process_view、process_response方法等。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Middleware1(MiddlewareMixin):
    def process_request(self,request):
        print('middleware1_request info....')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('middleware1_view  info....')

    def process_response(self, request, response):
        print('middleware1_response  info....')
        return response

class Middleware2(MiddlewareMixin):
    def process_request(self,request):
        print('middleware2_request info....')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('middleware2_view  info....')

    def process_response(self, request, response):
        print('middleware2_response  info....')
        return response

    def process_exception(self, request, exception):
        if isinstance(exception,ValueError):
            return HttpResponse('出现异常》。。')

2、注册中间件

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',
    'middleware.auth.AuthMiddleware1'
    'middleware.auth.AuthMiddleware2'
)

那么注册号中间件AuthMiddlware1和AuthMiddlware2后,运行程序,那么在控制台输出结果的顺序为:

middleware1_request info....
middleware2_request info....

middleware1_view  info....
middleware2_view  info....

middleware2_response  info....
middleware1_response  info....

 生命周期:

根据上面的中间件执行过程,下面来总结下django的生命周期是什么,如下图所示:

django后台admin配置

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

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

1、创建后台管理员

python manage.py createsuperuser

2、配置后台管理url

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

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

  a、在admin中执行如下配置

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、设置数据表名称

class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    class Meta:
        verbose_name = '用户类型'
        verbose_name_plural = '用户类型'

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

class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    def __unicode__(self):
        return self.name




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、为数据表添加搜索功能

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、添加快速过滤

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)

  

posted @ 2017-07-25 17:18  goser  阅读(171)  评论(0)    收藏  举报