Django~1_yuan_liu

前言

框架必须的会底层可以不会,但是必须的会用框架我们是做后端开发的,所以一定要把精力放在后端,你必须的看懂前端。用框架去写。不要什么都会,什么都会,你最后什么也不会。

术业要有专攻

前端有专业的框架目前最常用的web服务器:ngix或者  apaqi 

web 框架 :flask 、Django、 tadal

 

 

一 什么是web框架?

有关Django的三个网址:

https://blog.csdn.net/shelldawn/article/details/70316073
https://blog.csdn.net/weixin_42305814/article/details/80742090
http://www.cnblogs.com/ALADL/p/9762262.html

框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。

对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

import socket

def handle_request(client):

    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8001))
    sock.listen(5)

    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':

    main()
View Code

 

      最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

      正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

这个接口就是WSGI:Web Server Gateway Interface。

-----------------------------Do a web  framework ourselves---------------------------

step 1:

from wsgiref.simple_server import make_server


def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']


httpd = make_server('', 8080, application)

print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
View Code

注意:

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,
我们只负责在更高层次上考虑如何响应请求就可以了。

application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。

Python内置了一个WSGI服务器,这个模块叫wsgiref    
    
    
application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

        //environ:一个包含所有HTTP请求信息的dict对象;
        
        //start_response:一个发送HTTP响应的函数。

在application()函数中,调用:

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

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每
个Header用一个包含两个str的tuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值b'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,
通过start_response()发送Header,最后返回Body。
View Code

step 2

print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])
    f1=open("index1.html","rb")
    data1=f1.read()
    f2=open("index2.html","rb")
    data2=f2.read()

    if path=="/yuan":
        return [data1]
    elif path=="/alex":
        return [data2]
    else:
        return ["<h1>404</h1>".encode('utf8')]
View Code

step3

from wsgiref.simple_server import make_server

def f1():
    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2():
    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    if path=="/yuan":
        return f1()

    elif path=="/alex":
        return f2()

    else:
        return ["<h1>404</h1>".encode("utf8")]


httpd = make_server('', 8502, application)

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

# 开始监听HTTP请求:
httpd.serve_forever()
View Code

step4

from wsgiref.simple_server import make_server


def f1(req):
    print(req)
    print(req["QUERY_STRING"])

    f1=open("index1.html","rb")
    data1=f1.read()
    return [data1]

def f2(req):

    f2=open("index2.html","rb")
    data2=f2.read()
    return [data2]

import time

def f3(req):        #模版以及数据库

    f3=open("index3.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
    data3=str(data3,"utf8").replace("!time!",str(times))


    return [data3.encode("utf8")]


def routers():

    urlpatterns = (
        ('/yuan',f1),
        ('/alex',f2),
        ("/cur_time",f3)
    )
    return urlpatterns


def application(environ, start_response):

    print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')])


    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server('', 8518, application)

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

# 开始监听HTTP请求:

httpd.serve_forever()
View Code

伙计们,不知不觉我们自己已经写出一个web框架啦!

案列:

1、网址输入:http://127.0.0.1:8080/,返回一个hello word界面

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from wsgiref.simple_server import make_server
# environ 服务器封装好的对象
def application(environ, start_response):
    print(environ)  #打印出解析的对象内容,是一个大字典。是一个对象
    start_response('200 OK', [('Content-Type', 'text/html')]) #start_response  设置请求头
    return [b'<h1>Hello, web!</h1>'] #返回的页面信息,返回的是字节
httpd = make_server('127.0.0.1', 8080, application) #IP地址,端口,函数名
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
一个简单的页面信息

2、根据网址的输入,界面返回指定信息:

如:输入 http://127.0.0.1:8080/alexsd  返回404

       输入 http://127.0.0.1:8080/alex  返回hello,alex

  输入 http://127.0.0.1:8080/jack  返回hello,jack

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from wsgiref.simple_server import make_server
# environ 服务器封装好的对象
def application(environ, start_response):
    # print(environ)  #打印出解析的对象内容,是一个大字典。是一个对象
    print("path",environ['PATH_INFO'])
    path = environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')]) #start_response  设置请求头
    if path == '/alex':
        return [b'<h1>hello ,alex</h1>'] #返回的页面信息,返回的是字节
    elif path == '/jack':
        return [b'<h1>hello ,jack</h1>']
    else:
        return [b'404']
httpd = make_server('127.0.0.1', 8080, application) #IP地址,端口,函数名
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
View Code

3、根据网址的输入,通过函数读取指定的HTML文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是index1,hello alex</h1>
</body>
</html>
index1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>我是index2,hello jack</h1>
</body>
</html>
index2.html

输入 http://127.0.0.1:8080/alex 读取index1.html文件并返回界面

输入 http://127.0.0.1:8080/jack 读取index2.html文件并返回界面

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from wsgiref.simple_server import make_server
def foo2():
    f = open('index2.html','rb')
    data = f.read()
    return data
def foo1():
    with open('index1.html','rb') as f:
        data = f.read()
        return data

# environ 服务器封装好的对象
def application(environ, start_response):
    # print(environ)  #打印出解析的对象内容,是一个大字典。是一个对象
    print("path",environ['PATH_INFO'])
    path = environ['PATH_INFO']
    start_response('200 OK', [('Content-Type', 'text/html')]) #start_response  设置请求头
    if path == '/alex':
        # return [b'<h1>hello ,alex</h1>'] #返回的页面信息,返回的是字节
        return [foo1()]
    elif path == '/jack':
        return [foo2()]
    else:
        return [b'404']
httpd = make_server('127.0.0.1', 8080, application) #IP地址,端口,函数名
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
View Code

 4、自己写一个router路由分发函数,根据输入的信息返回相应的值

如:输入http://127.0.0.1:8080/alex   就执行alex函数

  输入 http://127.0.0.1:8080/jack  就执行jack 函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我是index1,hello alex</h1>
    <h1>我是jack,我是一个函数</h1>
</body>
</html>
index1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>时间:{{time}}</h1>
</body>
</html>
show_time.html
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from wsgiref.simple_server import make_server
import time
def login(req):
    return b'wo shi  login func'
def alex(req):
    return b'wo shi alex func'
def jack(req):
    f = open('index1.html','rb')
    ret = f.read()
    ret = ret.decode('utf-8') #转换成汉子
    return ret.encode('utf-8')
def show_time(req):
    print('req函数',req['PATH_INFO'])  #这里的req就是environ
    times = time.ctime()
    f = open('show_time.html','rb')
    data = f.read()
    data = data.decode('utf-8')  #转换成汉子
    data = data.replace("{{time}}",str(times)) #用一个特殊符替换到,两个大括号被定义成一个语法
    return data.encode('utf-8')
def router(): #路径分发函数,一个路径对应一个函数
    url_partitions = [
        ('/login',login),
        ('/jack',jack),
        ('/alex',alex),
        ('/show_time', show_time),
    ]
    return url_partitions
# environ 服务器封装好的对象
def application(environ, start_response):
    print(environ)  #打印出解析的对象内容,是一个大字典。是一个对象
    print(environ['PATH_INFO'])
    path = environ['PATH_INFO']  #打印出后缀信息
    start_response('200 OK', [('Content-Type', 'text/html')]) #start_response  设置请求头
    # return [b'<h1>Hello, web!</h1>'] #返回的页面信息,返回的是字节
    func = None
    url_list = router()
    for item in url_list:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return [func(environ)] #把environ当做形参传入,方便从里面提取相关信息,如登录信息
    else:
        return [b'404 le ya']

httpd = make_server('127.0.0.1', 8080, application) #IP地址,端口,函数名
print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
View Code

 

二 MVC和MTV模式

著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。

模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。

                   

Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:

       Model(模型):负责业务对象与数据库的对象(ORM)

       Template(模版):负责如何把页面展示给用户

       View(视图):负责业务逻辑,并在适当的时候调用Model和Template

       此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

 三 django的流程和命令行工具

django实现流程

django
    #安装: pip3 install django

          添加环境变量

    #1  创建project
       django-admin startproject mysite  (这个mysite是项目名称)

       ---mysite   mysite下面还会有一个mysite文件夹

          ---settings.py   配置文件
          ---url.py              路由  用来分发的功能,默认有一个admin
          ---wsgi.py          协议

       ---- manage.py(启动文件)  

    #2  创建APP          创建一个新的应用 ,名称叫app01 
       python manage.py startapp  app01 (app01是给项目起个名称)
           
           app01文件里的内容
                views.py    用来存放函数
                models.py   用来操作数据库
                apps.py     不用
                test.py     是测试
                admin.py    是后台管理系统

    #3  settings配置
    
       TEMPLATES

       STATICFILES_DIRS=(
            os.path.join(BASE_DIR,"statics"),
        )

       STATIC_URL = '/static/' 
       #  我们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找
       #4  根据需求设计代码
           url.py
           view.py

    #5  使用模版
       render(req,"index.html")   

    #6  启动项目
       python manage.py runserver  127.0.0.1:8090

    #7  连接数据库,操作数据
       model.py
View Code

django的命令行工具

django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每一个Django Project里都会有一个mannage.py。

<1> 创建一个django工程 : django-admin.py startproject mysite

        当前目录下会生成mysite的工程,目录结构如下:

        

  • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
  • urls.py ----- 负责把URL模式映射到应用程序。

<2>在mysite目录下创建blog应用: python manage.py startapp blog

        

<3>启动django项目:python manage.py runserver 8080

       这样我们的django就启动起来了!当我们访问:http://127.0.0.1:8080/时就可以看到:

       

<4>生成同步数据库的脚本:python manage.py makemigrations  

                     同步数据库:  python manage.py migrate   

       注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法是把migrations目录下

                的脚本(除__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。            

<5>当我们访问http://127.0.0.1:8080/admin/时,会出现:

       

       所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser设置好用户名和密码后便可登录啦!

<6>清空数据库:python manage.py  flush

<7>查询某个命令的详细信息: django-admin.py  help  startapp

       admin 是Django 自带的一个后台数据库管理系统。

<8>启动交互界面 :python manage.py  shell

     这个命令和直接运行 python 进入 shell 的区别是:你可以在这个 shell 里面调用当前项目的 models.py 中的 API,对于操作数据,还有一些小测试非常方便。

<9> 终端上输入python manage.py 可以看到详细的列表,在忘记子名称的时候特别有用

使用pycharm创建Django项目      location:后面跟的是路径  、application name  是应用名称,也就是新创建的app名称

截图如下:

 Django常用方法总结

1. Urls.py 路由系统:
    
        正则
            分组匹配     --> 位置参数
            分组命名匹配 --> 关键字参数
        
        分级路由
            include
        
        给路由起别名
            name="xx"
            
        反向解析url
            view
                from django.urls import reverse
                
                reverse("xx", args=[1, 2, 3])
                reverse("xx", args=(year,month,))
                reverse("xx", kwargs={”k": "v"})        
        
    2. 视图 views.py
        request
            request.method
            request.GET     --> URL里面的参数
            request.POST    --> post请求的数据
            
            request.path_info        --> 路径
            request.get_full_path()  --> 路径加路径的参数
        
        response
            新手必备3件套
            render(request, "xx.html", {“k”: "v", ...})
            HttpResponse("响应")
            redirect("/index/")
            redirect("http://www.luffycity.com")
            
            from django.http import JsonResponse
            JsonResponse()
            
            FBV和CBV
            
            函数装饰器和方法装饰器的区别
            
    3. 模板
        
        filter
            内置的filter方法
            自定义的filter方法
            
        tag
            内置的tag
            自定义的simpleTag
            自定义的inclusionTag
            
        母版和继承
        
        {% extends ‘base.html’ %}
        
        {% block page-main %}
            {% block small %}
            {% endblock small %}
        {% endblock page-main %}
        
        
        组件 {% include nav %}
        
        
        静态文件相关的tag
        
        在模板语言里面反向解析url
        
            {% url 'url的别名' xx %}
4、多对多时 getlist,set,add的使用
author_pk_list=request.POST.getlist("author_pk_list") # [1,2]  getlist获取多条数据,得到一个列表
book_obj=Book.objects.create(title=title,price=price,date=date,publish_id=publish_id)
book_obj.authors.add(*author_pk_list) #多对多添加 book_obj.authors.add(),因为一本书可能对用多个作者

author_pk_list=request.POST.getlist("author_pk_list") # [1,2]
Book.objects.filter(pk=edit_book_id).update(title=title,price=price,date=date,publish_id=publish_id)
book_obj=Book.objects.filter(pk=edit_book_id).first()
# 用 set重置,set重置无需加*号,因为一本书可能对应多个作者,所以用set
book_obj.authors.set(author_pk_list)

5、使用widgets增加属性

from django import forms
from django.forms import widgets
class BookForm(forms.Form):
title = forms.CharField(max_length=32,label="书籍名称")
price = forms.DecimalField(max_digits=8, decimal_places=2,label="价格") # 999999.99
date = forms.DateField(label="日期",
#因为日期类型,在html用form进行渲染的时候,会给改成text类型,所以用widget进行属性 修改,改成date类型
widget=widgets.TextInput(attrs={"type":"date"})
)

 Django实现流程

 

Django项目案列

注意:settings 配置文件 

MIDDLEWARE_CLASSES 下的    'django.middleware.csrf.CsrfViewMiddleware' 可以先注释掉,否则可能报错,它是校验安全性的
#static静态文件有的是一个应用放一个static文件
"""
Django settings for django_lesson project.

Generated by 'django-admin startproject' using Django 1.10.5.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '@jm-+mpxpv-@3%=o^fij9w+dtsil=18&6bpt*akkv+=422-vsl'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'django_lesson.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'django_lesson.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'  #别名  代替下面的


# STATICFILES_DIRS=(
#     os.path.join(BASE_DIR,"statics"),
# )

#static静态文件有的是一个应用放一个static文件
STATICFILES_DIRS=(
    os.path.join(BASE_DIR,"blog","statics"),
)
settings配置文件
 return render(requset,"index.html")  用于返回一个HTML界面
return HttpResponse("hello")  HttpResponse发回去的对象,返回给前端的一个对象,一定是一个httpResponse对象

1、一个简单的项目   

urls路由文件增加了url(r'^show_time/', views.show_time),   这是一个正则表达式

views 函数文件增加了 show_time函数

在terminal启动项目:python manage.py runserver  127.0.0.1:8080

截图如下:

输入网址:http://127.0.0.1:8080/show_time/  出来相关信息

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
]
urls.py
from django.shortcuts import render,HttpResponse
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    return render(requset,'show_time.html')  #request必须和形参一致,如果是读取html文件用这种格式
# Create your views here.
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello yuan</h1>
</body>
</html>
show_time.html

 2、根据输入网址  返回年和月   无名分组

如:http://127.0.0.1:8080/aricles_year/2018/12   返回:years:2018 months:12

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
    # url(r'^aricles_year/', views.aricles_year),
    url(r'^aricles_year/(\d{4})/(\d{2})', views.aricles_year),
]
urls.py
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    return render(requset,'show_time.html')  #request必须和形参一致,如果是读取html文件用这种格式

def aricles_year(request,year,month):
    # return HttpResponse(year)
    return  HttpResponse("years:%s months:%s" %(year,month))
views.py

3、、根据输入网址  返回年和月   有名分组

如:http://127.0.0.1:8080/aricles_year/2018/12   返回:years:2018 months:12

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
    # url(r'^aricles_year/', views.aricles_year),
    # url(r'^aricles_year/(\d{4})/(\d{2})', views.aricles_year),
    #因为下面是有名分组 所以article_year_newvie函数的入参必须和正则的入参一致
    url(r'^aricles_year/(?P<my_year>\d{4})/(?P<my_months>\d{2})', views.article_year_newview),
]
urls.py
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    return render(requset,'show_time.html')  #request必须和形参一致,如果是读取html文件用这种格式

def aricles_year(request,year,month):
    # return HttpResponse(year)
    return  HttpResponse("years:%s months:%s" %(year,month))

def article_year_newview(request,my_year,my_months):
    return  HttpResponse("years:%s months:%s" %(my_year,my_months))
views.py

4、用render返回html文件

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
]
urls.py
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    t = time.ctime()
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    #times对应的是 show_time.html 里的times。{'times':t} 就是把t变量赋值给times
    return render(requset,'show_time.html',{'times':t})  #request必须和形参一致,如果是读取html文件用这种格式
views.py

5、get模式,根据前台页面的注册,返回相关后台信息

from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    t = time.ctime()
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    #times对应的是 show_time.html 里的times。{'times':t} 就是把t变量赋值给times
    return render(requset,'show_time.html',{'times':t})  #request必须和形参一致,如果是读取html文件用这种格式

def register(request):
    print(request.GET)
    print(request.GET.get('user'))  #通过键提取
    print(request.GET.get('age'))
    print(request.GET.get('hoby'))
    return render(request, "register.html") #返回界面
views.py
"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register ),
]
urls.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>学生注册界面</h1>
<form action="http://127.0.0.1:8080/register/"  method="get">
    <p>姓名:<input type="text" name="user"></p>
    <p>年龄:<input type="text" name="age"></p>
    <p>爱好:<input type="checkbox" name="hoby" value="lanqiu">篮球
        <input type="checkbox" name = "hoby" value="zuqiu">足球
        <input type="checkbox" name = "hoby" value="pingpang">乒乓球
    </p>
    <p><input type="submit">提交啊</p>
</form>

</body>
</html>
register.html

 6、post模式:

流程:界面输入:http://127.0.0.1:8080/register/   ---》到路由urls.py文件执行第一次执行register 函数 函数执行结果是返回register.html界面(走的是get模式)

----》在界面输入相关信息如:姓名、年龄等点击提交  走的是POST模式 再次执行第二次执行register函数 

---》因为做了判断如果是post模式返回值是   success liu!

注意:settings 配置文件 

MIDDLEWARE_CLASSES 下的    'django.middleware.csrf.CsrfViewMiddleware' 可以先注释掉,否则可能报错,它是校验安全性的
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    t = time.ctime()
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    #times对应的是 show_time.html 里的times。{'times':t} 就是把t变量赋值给times
    return render(requset,'show_time.html',{'times':t})  #request必须和形参一致,如果是读取html文件用这种格式
#因为浏览器默认
def register(request):
    if request.method == "POST": #判断请求方式, 当第二次进来的时候走这个
        print(request.POST.get('user')) #通过键提取
        print(request.POST.get('age'))
        return HttpResponse("success  liu!")
    return render(request, 'register.html') #返回界面  这个是第一次进来时
views.py
"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register ),
]
urls.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>学生注册界面</h1>
<form action="http://127.0.0.1:8080/register/"  method="POST">
    <p>姓名:<input type="text" name="user"></p>
    <p>年龄:<input type="text" name="age"></p>
    <p>爱好:<input type="checkbox" name="hoby" value="lanqiu">篮球
        <input type="checkbox" name = "hoby" value="zuqiu">足球
        <input type="checkbox" name = "hoby" value="pingpang">乒乓球
    </p>
    <p><input type="submit">提交啊</p>
</form>

</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>时间:{{ times }}</h1>
</body>
</html>
show_time.html

7、最常用的提交方式  使用别名

 {% load staticfiles %}

<form action="{% url 'regi' %}" method="post">

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register ,name='regi'),#regi是别名
]
urls.py
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    t = time.ctime()
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    #times对应的是 show_time.html 里的times。{'times':t} 就是把t变量赋值给times
    return render(requset,'show_time.html',{'times':t})  #request必须和形参一致,如果是读取html文件用这种格式
#因为浏览器默认
def register(request):
    if request.method == "POST": #判断请求方式, 当第二次进来的时候走这个
        print(request.POST.get('user2')) #通过键提取
        print(request.POST.get('age2'))
        return HttpResponse("success10  liu!")
    return render(request, 'register.html') #返回界面  这个是第一次进来时
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>时间:{{ times }}</h1>
</body>
</html>
show_time.html
<!DOCTYPE html>
<html lang="en">
<head>
     {% load staticfiles %}
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>学生注册界面</h1>
{#regi是别名 在路由文件urls.py里name=‘regi’  --》 url(r'^register/', views.register ,name='regi')#}
<form action="{% url 'regi' %}" method="post">
{#<form action="http://127.0.0.1:8080/register/"  method="POST">#}
    <p>姓名:<input type="text" name="user2"></p>
    <p>年龄:<input type="text" name="age2"></p>
    <p>爱好:<input type="checkbox" name="hoby" value="lanqiu">篮球
        <input type="checkbox" name = "hoby" value="zuqiu">足球
        <input type="checkbox" name = "hoby" value="pingpang">乒乓球
    </p>
    <p><input type="submit">提交啊</p>
</form>

</body>
</html>
register.html

form表单提交的两种方式

方法一 推荐使用 使用别名
<form method="post" action="{% url 'sh_t' %}">    //sh_t是起的别名
#在head 里增加  {% load staticfiles %}
<head>
    {% load staticfiles %}
    <meta charset="UTF-8">
    <title>Title</title>
</head>
#路由系统 name='sh_t' 设置别名  这样如果需要改动,只要别名不动就行
 url(r'^show_time/', views.show_time, name='sh_t'),
  
方法二、
路由系统不设置别名
 url(r'^show_time/', views.show_time ),
form表单直接写路径
<form method="post" action="show_time/">

 引入static文件的两种方式

方法一
<script src="/static/jquery-1.12.4.js"></script>  
方法二
<script src="{% static 'jquery-1.12.4.js' %}"></script>

都需要设置:
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

 

8、urls分发系统文件一般在每一个应用里都应该有一个分发,由总分发分发文件进行分发

url(r'^blog/', include('blog.urls')), 表示所有与blog有关的网址去blog.urls里查找
url 后面跟的是一个正则表达式

如:当再访问register函数时     http://127.0.0.1:8080/blog/register/  需要加上blog

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^blog/', include('blog.urls')),
]
总urls分发文件
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register ,name='regi'),#regi是别名
]
blog应用下的urls文件
from django.shortcuts import render,HttpResponse
# Create your views here.
#django 会先运行setting文件,settings文件已经给你写好了,所以无需重启,就会被找到
import time
def show_time(requset): #requset 形参,随便命名必须有,它是看客户端发过来的信息,进行打包成的对象
    t = time.ctime()
    # return  HttpResponse('hello ya') #这个是返回给前端的一个对象
    # render是渲染的意思,浏览器只认识HTML文件,第一个参数是形参,也就是requset
    #times对应的是 show_time.html 里的times。{'times':t} 就是把t变量赋值给times
    return render(requset,'show_time.html',{'times':t})  #request必须和形参一致,如果是读取html文件用这种格式
#因为浏览器默认
def register(request):
    if request.method == "POST": #判断请求方式, 当第二次进来的时候走这个
        print(request.POST.get('user2')) #通过键提取
        print(request.POST.get('age2'))
        return HttpResponse("success10  liu!")
    return render(request, 'register.html') #返回界面  这个是第一次进来时
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>时间:{{ times }}</h1>
</body>
</html>
show_time.html
<!DOCTYPE html>
<html lang="en">
<head>
     {% load staticfiles %}
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>学生注册界面</h1>
{#regi是别名 在路由文件urls.py里name=‘regi’  --》 url(r'^register/', views.register ,name='regi')#}
<form action="{% url 'regi' %}" method="post">
{#<form action="http://127.0.0.1:8080/register/"  method="POST">#}
    <p>姓名:<input type="text" name="user2"></p>
    <p>年龄:<input type="text" name="age2"></p>
    <p>爱好:<input type="checkbox" name="hoby" value="lanqiu">篮球
        <input type="checkbox" name = "hoby" value="zuqiu">足球
        <input type="checkbox" name = "hoby" value="pingpang">乒乓球
    </p>
    <p><input type="submit">提交啊</p>
</form>

</body>
</html>
register.html

 9、静态文件的配置   创建static文件夹  static文件夹和templates同级

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

 10、 阻止url自动增加斜杠

在settings里增加APPEND_SLASH = False 默认是TRUE  可以阻止url自动增加/ 斜杠

实例练习1-提交数据并展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>创建个人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性别</td>
        <td>邮箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


-----------------------url.py---------------------------------------
url(r'^userInfor/', views.userInfor)

-----------------------views.py--------------------------------------

info_list=[]

def userInfor(req):

    if req.method=="POST":
        username=req.POST.get("username",None)
        sex=req.POST.get("sex",None)
        email=req.POST.get("email",None)

        info={"username":username,"sex":sex,"email":email}
        info_list.append(info)

    return render(req,"userInfor.html",{"info_list":info_list})
View Code

实例练习2-提交数据并展示(数据库)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>创建个人信息</h1>

<form action="/userInfor/" method="post">

    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性别</td>
        <td>邮箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


----------------------------------------------models.py
from django.db import models

# Create your models here.


class UserInfor(models.Model):

    username=models.CharField(max_length=64)
    sex=models.CharField(max_length=64)
    email=models.CharField(max_length=64)

----------------------------------------------views.py

from django.shortcuts import render

from app01 import models
# Create your views here.


def userInfor(req):

    if req.method=="POST":
        u=req.POST.get("username",None)
        s=req.POST.get("sex",None)
        e=req.POST.get("email",None)


       #---------表中插入数据方式一
            # info={"username":u,"sex":e,"email":e}
            # models.UserInfor.objects.create(**info)

       #---------表中插入数据方式二
        models.UserInfor.objects.create(
            username=u,
            sex=s,
            email=e
        )

        info_list=models.UserInfor.objects.all()

        return render(req,"userInfor.html",{"info_list":info_list})

    return render(req,"userInfor.html")
View Code

四 Django的配置文件(settings)

静态文件设置:

一、概述:

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

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

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

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

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

    #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles',

    #2、在urls.py里面加入
       if settings.DEBUG:  
           urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 
           'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),   
            url(r'^static/(?P<path>.*)$',
          'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), )  

    # 3、这样就可以在开发阶段直接使用静态文件了。

二、MEDIA_ROOT和MEDIA_URL

        #而静态文件的处理又包括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_URL}}abc/a.png">

        #    在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置,
        #  以便能让web服务器能访问media文件
        #    以nginx为例,可以在nginx.conf里面这样:

                 location ~/media/{
                       root/temp/
                       break;
                    }

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

三、STATIC_ROOT和STATIC_URL、
    STATIC主要指的是如css,js,images这样文件,在settings里面可以配置STATIC_ROOT和STATIC_URL,
    配置方式与MEDIA_ROOT是一样的,但是要注意

    #STATIC文件一般保存在以下位置:

    #1、STATIC_ROOT:在settings里面设置,一般用来放一些公共的js,css,images等。

    #2、app的static文件夹,在每个app所在文夹均可以建立一个static文件夹,然后当运行collectstatic时,
    #    Django会遍历INSTALL_APPS里面所有app的static文件夹,将里面所有的文件复制到STATIC_ROOT。因此,
    #   如果你要建立可复用的app,那么你要将该app所需要的静态文件放在static文件夹中。

    # 也就是说一个项目引用了很多app,那么这个项目所需要的css,images等静态文件是分散在各个app的static文件的,比
    #  较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT。

    #3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。
    #  STATIC_URL的含义与MEDIA_URL类似。

    # ----------------------------------------------------------------------------
    #注意1:
        #为了后端的更改不会影响前端的引入,避免造成前端大量修改

        STATIC_URL = '/static/'               #引用名
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR,"statics")  #实际名 ,即实际文件夹的名字
        )

        #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找
        #<script src="/statics/jquery-3.1.1.js"></script>
        #------error-----不能直接用,必须用STATIC_URL = '/static/':
        #<script src="/static/jquery-3.1.1.js"></script>

    #注意2(statics文件夹写在不同的app下,静态文件的调用):

        STATIC_URL = '/static/'

        STATICFILES_DIRS=(
            ('hello',os.path.join(BASE_DIR,"app01","statics")) ,
        )

        #<script src="/static/hello/jquery-1.8.2.min.js"></script>

    #注意3:
        STATIC_URL = '/static/'
        {% load staticfiles %}
       # <script src={% static "jquery-1.8.2.min.js" %}></script>
View Code

其它重要参数设置:

APPEND_SLASH
       Default: True
       When set to True, if the request URL does not match any of the patterns in the URLconf and it 
doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note
that the redirect may cause any data submitted in a POST request to be lost.

五 Django URL (路由系统)

     URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

urlpatterns = [
    url(正则表达式, views视图函数,参数,别名),
]

  

参数说明:

  • 一个正则表达式字符串
  • 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 可选的要传递给视图函数的默认参数(字典形式)
  • 一个可选的name参数

5.1 Here’s a sample URLconf:

复制代码
from django.conf.urls import url
from django.contrib import admin

from app01 import views

urlpatterns = [

    url(r'^articles/2003/$', views.special_case_2003),

    #url(r'^articles/[0-9]{4}/$', views.year_archive),

    url(r'^articles/([0-9]{4})/$', views.year_archive),  #no_named group

    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),

    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),

]
复制代码

Note:

#1   There’s no need to add a leading slash, because every URL has that. For
#    example, it’s ^articles, not ^/articles.

#2   A request to /articles/2005/03/ would match the third entry in the list.
#    Django would call the function views.month_archive(request, '2005', '03').

#3   /articles/2005/3/ would not match any URL patterns

#4   /articles/2003/ would match the first pattern in the list, not the second one

#5   /articles/2003/03/03/ would match the final pattern. Django would call the
#    functionviews.article_detail(request, '2003', '03', '03').
View Code

5.2 Named groups

      The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

       In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here’s the above example URLconf, rewritten to use named groups:

import re

ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')

print(ret.group())
print(ret.group('id'))
print(ret.group('name'))
ready
复制代码
from django.conf.urls import url
  
from . import views
  
urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
复制代码

       This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments.

5.3  Passing extra options to view functions

       URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.

The django.conf.urls.url() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

For example:

from django.conf.urls import url
from . import views
  
urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

       In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year='2005',foo='bar').

This technique is used in the syndication framework to pass metadata and options to views.

Dealing with conflicts

       It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.

5.4 name param

urlpatterns = [
    url(r'^index',views.index,name='bieming'),
    url(r'^admin/', admin.site.urls),
    # url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登陆成功")



    return render(req,'index.html')

#####################

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'bieming' %}" method="post">
         用户名:<input type="text" name="username">
         密码:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


#######################
View Code

5.5 Including other URLconfs

复制代码
#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),
]
复制代码

URL通过别名反向解析

无参数的情况下案列:

from django.shortcuts import render
from django.urls import reverse
def login(request):
    return render(request,'login.html')
def index(request):
    print('结果',reverse("index"))  #反向解析,无参数的时候
    return render(request,'index.html')
# Create your views here.
views.py
"""django11_6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app1 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login  ),
    url(r'^index/', views.index,name='index'),
]
url.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是h1 index界面</h1>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是login界面</h1>
{#<a href="/index/">跳转到index界面</a>#}
<a href={% url 'index' %}>跳转到index界面</a>
</body>
</html>
login.html

有参数的情况下:

from django.shortcuts import render
from django.urls import reverse
def login(request):
    return render(request,'login.html')
def index(request,year,mon):
    print('结果',year,mon)
    print('结果',reverse("index",args=(year,mon,)))  #反向解析,有参数的时候
    print('结果',reverse("reg",kwargs={"new_date":2019,'new_name':'hello'}))  #反向解析,有参数的时候,如果url正则表达式有命名,则需要字典方式传入
    return render(request,'index.html')
def register(request,new_date,new_name):
    print('结果',new_date,new_name)
    return render(request,'register.html')
# Create your views here.
views.py
"""django11_6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app1 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login  ),
    url(r'^index3434/(\d+)/(\d+)/', views.index,name='index'),
    url(r'^register/(?P<new_date>\d+)/(?P<new_name>[a-zA-Z]+)/', views.register,name='reg' ),
]
urls.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是注册9界面</h1>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是h1 index界面</h1>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是login界面</h1>
{#<a href="/index/">跳转到index界面</a>#}
<a href={% url 'index' 2238 12 %}>跳转到index界面</a>
{#<a href="/register/3000/what">跳转到register界面</a>#}
<a href={% url 'reg' 300 'zhongguo' %}>跳转到register界面</a>
</body>
</html>
login.html

 

六 Django Views(视图函数)

http请求中产生两个核心对象:

        http请求:HttpRequest对象

        http响应:HttpResponse对象

所在位置:django.http

之前我们用到的参数request就是HttpRequest    检测方法:isinstance(request,HttpRequest)

1 HttpRequest对象的属性和方法:

# path:       请求页面的全路径,不包括域名
#
# method:     请求中使用的HTTP方法的字符串表示。全大写表示。例如
#
#                    if  req.method=="GET":
#
#                              do_something()
#
#                    elseif req.method=="POST":
#
#                              do_something_else()
#
# GET:         包含所有HTTP GET参数的类字典对象
#
# POST:       包含所有HTTP POST参数的类字典对象
#
#              服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
#              HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
#              if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
#
#
#
# COOKIES:     包含所有cookies的标准Python字典对象;keys和values都是字符串。
#
# FILES:      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中                     name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
#
#             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支持时该属性才可用。

#方法
get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
req.path:/index33
View Code

注意一个常用方法:request.POST.getlist('')

2 HttpResponse对象:

  对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。

  HttpResponse类在django.http.HttpResponse

  在HttpResponse对象上扩展的常用方法:

页面渲染:         render()(推荐)<br>                 render_to_response(),
页面跳转:         redirect("路径")
locals():    可以直接将函数中所有的变量传给模板

案列:

1、render 和  render_to_response 的区别:

from django.shortcuts import render,HttpResponse,render_to_response
import time
# Create your views here.
def show_time(req):
    times = time.ctime()
    names = 'yuan2'
    return render(req, "show_time.html", {"times": t})  # 用render返回
    return render_to_response("show_time.html", {
    "times": t})  # render_to_response 和render的区别就是不用写request,推荐大家用render,用render_to_response可能出问题,render肯定不会有问题
View Code

2、locals(): 可以直接将函数中所有的变量传给模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我的w名字是{{ names }}现在时间:{{ times }}哈哈</h1>
</body>
</html>
show_time.html

当需要传入多个变量时可以这样写: 方法一

def show_time(req):
    t = time.ctime()
    name = 'yuan'
    return render(req,"show_time.html",{"times":t,"names":name})

方法二、推荐这样用,是用locals

 show_tiime.html的变量名称要和show_time的函数变量名称一样,否则无法找不到

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>我的w名字是{{ names }}现在时间:{{ times }}哈哈</h1>
</body>
</html>
show_time.html
from django.shortcuts import render,HttpResponse,render_to_response
import time
# Create your views here.
def show_time(req):
    times = time.ctime()
    names = 'yuan2'
    return  render(req,"show_time.html",locals())
views.py

 3、页面跳转: redirect("路径")

注意需注释掉settings.py文件里的 MIDDLEWARE_CLASSES 下的  # 'django.middleware.csrf.CsrfViewMiddleware',这是验证安全性的,先去掉

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
# Create your views here.
def show_time(req):
    times = time.ctime()
    names = 'yuan2'
    # return render(req, "show_time.html", {"times": t})  # 用render返回
    # return render_to_response("show_time.html", { "times": t})  # render_to_response 和render的区别就是不用写request,推荐大家用render,用render_to_response可能出问题,render肯定不会有问题
    return render(req,'show_time.html',locals())

def articles(req,year,mon):
    return HttpResponse("years: %s  months:%s" %(year,mon))
def login(req):
    user = 'yuan'
    return render(req,'login.html',locals())
def register(req):
    # print(req.path) #就是一个路径名称
    # print(req.get_full_path()) #带着数据的一个路径
    if req.method == 'POST':
        print(req)
        print(req.POST)
        print(req.POST.get('user'))
        user = req.POST.get('user')
        print(req.POST.get('paswd'))
        print(req.POST.get('hoby'))
        if user == 'yuan':
            print('123yuan')
            # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
            return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
        return HttpResponse('success ok l ')
    return render(req,'register.html')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#req里的所有东西都能拿到,因为它是局部变量之一#}
    <h1>我的w名字是{{ names }}现在时间:{{ times }}哈3哈{{ req.method }}</h1>
</body>
</html>
show_time.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>{{ user }}成功跳转到登录页面</h1>
    <p>用户名:<input type="text" name = "user"></p>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    {% load staticfiles %}
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>学生注册系统</h1>
{#    <form action="http://127.0.0.1:8080/register/" method="POST">#}
    <form action="{% url 'regi' %}" method="POST">
        <p>姓名:<input type="text" name = "user"></p>
        <p>密码:<input type="text" name="paswd"></p>
        <p>爱好:<input type="checkbox" name="hoby" value="lanqiu">篮球
                <input type="checkbox" name="hoby" value="yumaoqiu">羽毛球
                <input type="checkbox" name="hoby" value="zuqiu">足球
        </p>
        <p><input type="submit">提交</p>
    </form>
</body>
</html>
register.html
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # url(r'^register/', include('blog.urls')),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login),
]
urls.py

 

补充:

-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>用户{{ name }}你好</h1>

#总结: render和redirect的区别:
#   1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分
#     除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦.

#   2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后
#     又得重新登录.
View Code

七 Template基础 

模板系统的介绍

你可能已经注意到我们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python代码之中。

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

尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意。 让我们来看一下为什么:

  • 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。

  • Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。

  • 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式,这就是本章要具体讨论的问题。

------------------------------------------------------------------模板语法------------------------------------------------------------------

一模版的组成

组成:HTML代码+逻辑控制代码

二 逻辑控制代码的组成

1  变量(使用双大括号来引用变量):

语法格式:       {{var_name}}

------Template和Context对象————-这俩个都是类

>>> python manange.py shell  (进入该django项目的环境)
>>> from django.template import Context, Template
>>> t = Template('My name is {{ name }}.')
>>> c = Context({'name': 'Stephane'})
>>> t.render(c)
'My name is Stephane.'


# 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
# 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
# 更为高效:
# Low
for name in ('John', 'Julie', 'Pat'):
    t = Template('Hello, {{ name }}')
    print t.render(Context({'name': name}))

# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
    print t.render(Context({'name': name}))
View Code

 Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。

from django.shortcuts import render,HttpResponse
from django.template.loader import get_template #记得导入
# Create your views here.


import datetime
from django.template import Template,Context

# def current_time(req):
    #原始的视图函数
    # now=datetime.datetime.now()
    # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now
    # return HttpResponse(html)



# def current_time(req):

      #django模板修改的视图函数
#     now=datetime.datetime.now()
#     t=Template('<html><body>现在时刻是:<h1 style="color:red">{{current_date}}</h1></body></html>')
      #t=get_template('current_datetime.html')
#     c=Context({'current_date':now})
#     html=t.render(c)
#     return HttpResponse(html)

#另一种写法(推荐)

def current_time(req):

    now=datetime.datetime.now()

    return render(req, 'current_datetime.html', {'current_date':now})
推荐方式

------深度变量的查找(万能的句点号)

在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。

在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

#最好是用几个例子来说明一下。
# 首先,句点可用于访问列表索引,例如:

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'

#假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点:
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.'

#同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有
#year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> d.year
>>> d.month
>>> d.day
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)
'The month is 5 and the year is 1993.'

# 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适
# 用于任意的对象。
>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...         self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
'Hello, John Smith.'

# 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit()
# 方法,你在模板中可以使用同样的句点语法来调用它们:
>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 -- 123 -- True'

# 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
# 方法。
View Code

案列如下:

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
import datetime
# Create your views here.
def show_time(req):
    times = time.ctime()
    # return render(req,'show_time.html',{"times":t}
    return render(req,'show_time.html',locals())
def articles(req,year,mon):
    return HttpResponse("years: %s  months:%s" %(year,mon))
def login(req):
    user = 'yuan'
    return render(req,'login.html',locals())
def register(req):
    # print(req.path) #就是一个路径名称
    # print(req.get_full_path()) #带着数据的一个路径
    if req.method == 'POST':
        print(req)
        print(req.POST)
        print(req.POST.get('user'))
        user = req.POST.get('user')
        print(req.POST.get('paswd'))
        print(req.POST.get('hoby'))
        if user == 'yuan':
            print('123yuan')
            # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
            return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
        return HttpResponse('success ok l ')
    return render(req,'register.html')
class Animal:
    def __init__(self,name,sex):
        self.name =name
        self.sex = sex
def query(req):
    str_s = 'alex'
    date_d = datetime.date(1993,5,2)
    # L = ['alex','jack','张三','李四']
    action_list = ['alex', 'jack', '张三', '李四']
    d = {"name":'闫学晶','sex':'女','zhiye':'演员'}
    c_class = Animal('赵四','男')
    # return render(req,'query.html',{"action_list":L})
    return render(req,'query.html',locals())
views.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # url(r'^register/', include('blog.urls')),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#访问列表里的数据,#}
    <h1>hello {{ action_list }}</h1>
    <h1>hello {{ action_list.0 }}</h1>
    <h1>hello {{ action_list.1 }}</h1>
     <h1>hello {{ action_list.2 }}</h1>
{##访问字典#}
<h1>hello {{ d }}</h1>
<h1>hello {{ d.name }}</h1>
<h1>hello {{ d.sex }}</h1>
<h1>hello {{ d.zhiye }}</h1>
{##访问类#}
<h1>hello {{ c_class }}</h1>
<h1>hello {{ c_class.name }}</h1>
<h1>hello {{ c_class.sex}}</h1>
{##访问日期#}
<h1>hello {{ date_d }}</h1>
<h1>hello {{ date_d.year }}</h1>
<h1>hello {{ date_d.month }}</h1>
<h1>hello {{ date_d.day }}</h1>
{##访问字符串#}
<h1>hello {{ str_s }}</h1>
<h1>hello {{ str_s.upper }}</h1>
<h1>hello {{ str_s.isdigit }}</h1>
</body>
</html>
query.html

------变量的过滤器(filter)的使用

语法格式:      {{obj|filter:param}}
# 1  add          :   给变量加上相应的值
   #
   # 2  addslashes   :    给变量中的引号前加上斜线
   #
   # 3  capfirst     :    首字母大写
   #
   # 4  cut          :   从字符串中移除指定的字符
   #
   # 5  date         :   格式化日期字符串
   #
   # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
   #
   # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值


#实例:

#value1="aBcDe"
{{ value1|upper }}<br>

#value2=5
{{ value2|add:3 }}<br>

#value3='he  llo wo r ld'
{{ value3|cut:' ' }}<br>

#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br>

#value5=[]
{{ value5|default:'空的' }}<br>

#value6='<a href="#">跳转</a>'

{{ value6 }}

{% autoescape off %}
  {{ value6 }}
{% endautoescape %}

{{ value6|safe }}<br>

{{ value6|striptags }}

#value7='1234'
{{ value7|filesizeformat }}<br>
{{ value7|first }}<br>
{{ value7|length }}<br>
{{ value7|slice:":-1" }}<br>

#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}<br>
    value9='hello I am yuan'
View Code

案列:

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
import datetime
# Create your views here.
def show_time(req):
    times = time.ctime()
    # return render(req,'show_time.html',{"times":t}
    return render(req,'show_time.html',locals())
def articles(req,year,mon):
    return HttpResponse("years: %s  months:%s" %(year,mon))
def login(req):
    user = 'yuan'
    return render(req,'login.html',locals())
def register(req):
    # print(req.path) #就是一个路径名称
    # print(req.get_full_path()) #带着数据的一个路径
    if req.method == 'POST':
        print(req)
        print(req.POST)
        print(req.POST.get('user'))
        user = req.POST.get('user')
        print(req.POST.get('paswd'))
        print(req.POST.get('hoby'))
        if user == 'yuan':
            print('123yuan')
            # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
            return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
        return HttpResponse('success ok l ')
    return render(req,'register.html')
class Animal:
    def __init__(self,name,sex):
        self.name =name
        self.sex = sex
def query(req):
    d = {"name":'wusir','age':13}
    str1 = 'w 4 6 h2 a t'
    str2 = 'good'
    date5 = datetime.datetime.now()
    e = []
    a = "<a href =''>click</a>"
    return render(req,'query.html',locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{##访问字典#}
<h1>hello {{ d }}</h1>
<h1>hello {{ d.age }}</h1>
{#1  add          :   给变量加上相应的值#}
<h1>张可的真实年龄是:{{ d.age}}</h1>
<h1>张可的真实年龄加上3岁后是:{{ d.age|add:3 }}</h1>
{#cut          :   从字符串中移除指定的字符#}
<h1>hello {{ str1 }}</h1>
<h1>hello {{ str1|cut:" " }}</h1>
{# capfirst     :    首字母大写<h1>hello {{ str2 }}</h1>#}
<h1>hello {{ str2 }}</h1>
<h1>hello {{ str2|capfirst}}</h1>
{# 5  date         :   格式化日期字符串#}
<h1>hello {{ date5 }}</h1>
<h1>hello {{ date5|date:'Y-m-d' }}</h1>
{#6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值#}
<h1>hello {{ e }}</h1>
<h1>hello {{ e|default:'空列表' }}</h1>
{#如果想渲染需要加上safe,默认没有渲染#}
<h1>hello {{ a }}</h1>
<h1>hello {{ a|safe }}</h1>
{##就是把自己加的安全机制去掉去显示 和safe类似 #}
{% autoescape off%}
    <h1>hello {{a}}</h1>
{% endautoescape %}
</body>
</html>
query.html
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # url(r'^register/', include('blog.urls')),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py

2 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

{% tags %}

------{% if %} 的使用 

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

{% if num >= 100 and 8 %}

    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}

{% elif num < 100%}
    <p>num小于100</p>

{% else %}
    <p>num等于100</p>

{% endif %}



{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{% if obj1 and obj2 or obj3 %}
View Code

案列:

1、if 语句

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
import datetime
# Create your views here.
def show_time(req):
    times = time.ctime()
    # return render(req,'show_time.html',{"times":t}
    return render(req,'show_time.html',locals())
def articles(req,year,mon):
    return HttpResponse("years: %s  months:%s" %(year,mon))
def login(req):
    user = 'yuan'
    return render(req,'login.html',locals())
def register(req):
    # print(req.path) #就是一个路径名称
    # print(req.get_full_path()) #带着数据的一个路径
    if req.method == 'POST':
        print(req)
        print(req.POST)
        print(req.POST.get('user'))
        user = req.POST.get('user')
        print(req.POST.get('paswd'))
        print(req.POST.get('hoby'))
        if user == 'yuan':
            print('123yuan')
            # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
            return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
        return HttpResponse('success ok l ')
    return render(req,'register.html')
class Animal:
    def __init__(self,name,sex):
        self.name =name
        self.sex = sex
def query(req):
    d = {"name":'jack','age':16}
    return render(req,'query.html',locals())
views.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # url(r'^register/', include('blog.urls')),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello {{ d }}</h1>
{% if d.age > 30 %}
    <h1>{{ d.name }} 年龄大于30岁</h1>
    {% elif d.age > 20 %}
    <h1>{{ d.name }} 年龄大于20小于30岁</h1>
    {% else %}
    <h1>{{ d.name }}年龄是未成年</h1>
{% endif %}
</body>
</html>
query.html

2、if嵌套

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
import datetime
# Create your views here.
def show_time(req):
    times = time.ctime()
    # return render(req,'show_time.html',{"times":t}
    return render(req,'show_time.html',locals())
def articles(req,year,mon):
    return HttpResponse("years: %s  months:%s" %(year,mon))
def login(req):
    user = 'yuan'
    return render(req,'login.html',locals())
def register(req):
    # print(req.path) #就是一个路径名称
    # print(req.get_full_path()) #带着数据的一个路径
    if req.method == 'POST':
        print(req)
        print(req.POST)
        print(req.POST.get('user'))
        user = req.POST.get('user')
        print(req.POST.get('paswd'))
        print(req.POST.get('hoby'))
        if user == 'yuan':
            print('123yuan')
            # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
            return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
        return HttpResponse('success ok l ')
    return render(req,'register.html')
class Animal:
    def __init__(self,name,sex):
        self.name =name
        self.sex = sex
def query(req):
    d = {"name":'jack','age':336}
    return render(req,'query.html',locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello {{ d }}</h1>
{% if d.age > 30 %}
    {% if d.age < 50 %}
        <h1>{{ d.name }}大于30且小于50岁</h1>
    {% else %}
         <h1>hello {{ d.name }}</h1>
        <h1>hello {{ d.name }}大于50了</h1>
    {% endif %}
{#    <h1>{{ d.name }} 年龄大于30岁</h1>#}
    {% elif d.age > 20 %}
    <h1>{{ d.name }} 年龄大于20小于30岁</h1>
    {% else %}
    <h1>{{ d.name }}年龄是未成年</h1>
{% endif %}
</body>
</html>
query.html
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # url(r'^register/', include('blog.urls')),
    url(r'^show_time/', views.show_time),
    url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py

 

------{% for %}的使用

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>


#在标签里添加reversed来反序循环列表:

    {% for obj in list reversed %}
    ...
    {% endfor %}

#{% for %}标签可以嵌套:

    {% for country in countries %}
        <h1>{{ country.name }}</h1>
        <ul>
         {% for city in country.city_list %}
            <li>{{ city }}</li>
         {% endfor %}
        </ul>
    {% endfor %}


#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
#这个变量含有一些属性可以提供给你一些关于循环的信息

1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:

    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter
4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:

    
    {% for object in objects %}   
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
         {{ object }}   
        </li>  
    {% endfor %}  
    
# 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
# Django会在for标签的块中覆盖你定义的forloop变量的值
# 在其他非循环的地方,你的forloop变量仍然可用


#{% empty %}

{{li }}
      {%  for i in li %}
          <li>{{ forloop.counter0 }}----{{ i }}</li>
      {% empty %}
          <li>this is empty!</li>
      {% endfor %}

#         [11, 22, 33, 44, 55]
#            0----11
#            1----22
#            2----33
#            3----44
#            4----55
View Code

案列:

1|、

from django.shortcuts import render,HttpResponse,render_to_response,redirect
import time
import datetime
# Create your views here.
# def show_time(req):
#     times = time.ctime()
#     # return render(req,'show_time.html',{"times":t}
#     return render(req,'show_time.html',locals())
# def articles(req,year,mon):
#     return HttpResponse("years: %s  months:%s" %(year,mon))
# def login(req):
#     user = 'yuan'
#     return render(req,'login.html',locals())
# def register(req):
#     # print(req.path) #就是一个路径名称
#     # print(req.get_full_path()) #带着数据的一个路径
#     if req.method == 'POST':
#         print(req)
#         print(req.POST)
#         print(req.POST.get('user'))
#         user = req.POST.get('user')
#         print(req.POST.get('paswd'))
#         print(req.POST.get('hoby'))
#         if user == 'yuan':
#             print('123yuan')
#             # return render(req,'login.html') #如何这样写,虽然可以跳过去,但是网址(url)不会变,不建议用,url不变,一刷新又重新过去了
#             return redirect('/login/') #跳转到的是一个路径,所以需要再urls里配置,执行login函数
#         return HttpResponse('success ok l ')
#     return render(req,'register.html')
# class Animal:
#     def __init__(self,name,sex):
#         self.name =name
#         self.sex = sex
def query(req):
    d = {"name":'jack','age':336}
    L = ['alex','wusir','张三','李四','王五']
    return render(req,'query.html',locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello {{ L }}</h1>
{% for item in L %}
    {{ item }}
{#    <h1>从1开始{{ forloop.counter }}:{{ item }}</h1>#}
{#    <h1>从零开始{{ forloop.counter0 }}:{{ item }}</h1>#}
{#    <h1>倒序排{{ forloop.revcounter }}:{{ item }}</h1>#}
    <h1>倒序排{{ forloop.revcounter0 }}:{{ item }}</h1>
{% endfor %}
</body>
</html>
query.html
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # # url(r'^register/', include('blog.urls')),
    # url(r'^show_time/', views.show_time),
    # url(r'^register/', views.register,name = 'regi'),
    # url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py

2、forloop.first当第一次循环时值为True,在特别情况下很有用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .first {
            color: red;
        }
    </style>
</head>
<body>
    <h1>hello {{ L }}</h1>
     {% for name in L %}
{#         如果是第一次循环#}
         {% if forloop.first %}
{#             创建一个li标签#}
            <li class="first">
        {% else %}
            <li>
        {% endif %}
         {{ name }}
        </li>
    {% endfor %}
</body>
</html>
query.html

其他和上面的一样

3、#{% empty %}  判断是否为空

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
    </style>
</head>
<body>
    <h1>hello {{ L }}</h1>
{% for item in L %}
    {% empty %}
    <h1>列表是一个w空列表</h1>
{% endfor %}
</body>
</html>
query.html
from django.shortcuts import render,HttpResponse,render_to_response,redirect
def query(req):
    L = []
    return render(req,'query.html',locals())
views.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # # url(r'^register/', include('blog.urls')),
    # url(r'^show_time/', views.show_time),
    # url(r'^register/', views.register,name = 'regi'),
    # url(r'^login/', views.login),
    url(r'^query/', views.query),
]
urls.py

------{%csrf_token%}:csrf_token标签

     用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效

     其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

form表单里加上 {%csrf_token%} ,就不用注释settings配置文件里的  'django.middleware.csrf.CsrfViewMiddleware',否则再提交时会报错,这个是安全验证

案列如下:

<!DOCTYPE html>
<html lang="en">
{% load staticfiles %}
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="{% url 'login' %}" method="post">
    <p>姓名:<input type="text" name="user"></p>
    <p>年龄:<input type="text" name="age"></p>
    <p><input type="submit">提交</p>
{#    #解决安全验证问题#}
    {% csrf_token %}
</form>
</body>
</html>
login.html
from django.shortcuts import render,HttpResponse,render_to_response,redirect
def login(req):
    print(req)
    return render(req,'login.html')
views.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # # url(r'^register/', include('blog.urls')),
    # url(r'^show_time/', views.show_time),
    # url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login,name='login'),
    # url(r'^query/', views.query),
]
urls.py

 

------{% url %}:  引用路由配置的地址

<form action="{% url "bieming"%}" >
          <input type="text">
          <input type="submit"value="提交">
          {%csrf_token%}
</form>
View Code

------{% with %}:用更简单的变量名替代复杂的变量名   只能在with 和end with 之间使用

{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

------{% verbatim %}: 禁止render

{% verbatim %}
         {{ hello }}
{% endverbatim %}

案列:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hello {{ age }}</h1>
{#{% verbatim %}: 禁止render,可渲染出大括号#}
{% verbatim %}
    <h1>hello {{ name8}}</h1>
{% endverbatim %}
</body>
</html>
login.html
from django.shortcuts import render,HttpResponse,render_to_response,redirect
def login(req):
    name2 = 'aleex'
    age6 = 16
    print(req)
    return render(req,'login.html',{'age':age6})
views.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # # url(r'^register/', include('blog.urls')),
    # url(r'^show_time/', views.show_time),
    # url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login,name='login'),
    # url(r'^query/', views.query),
]
urls.py

------{% load %}: 加载标签库 

3   templatetags的使用

建立一个一样的templates或者templateags,django找的时候会先从外面开始找,如果外面找不到 会继续从每一个app里面找,如果都找不到才会报错,如果多个app里面templates有重命名,会按照注册的顺序去找,就会出现覆盖的现象,为了防止覆盖的现象发生,可以在每个app里面再建立一层如:template/rbac/base.html(rbac根据APP的名称变化)

自定义filter和simple_tag   切记需要重启项目 执行 python manage.py runserver 127.0.0.1:8080

------a、在app中创建templatetags模块(必须的) 创建的是一个 pyhton package   

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

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


@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2


@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)
View Code

------c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

------d、使用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 %}
View Code

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

案列:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
#前三行代码是固定的
from django import template
from django.utils.safestring import mark_safe
register = template.Library()   #register的名字是固定的,不可改变

#自定义过滤器 只能传入两个参数
@register.filter
def filter_multi(v1,v2):
    print(v1,v2) #v1是d.age,右边v2是第二个参数
    return  v1 * v2

#自定义标签  判断函数是标签还是过滤器就看继承的装饰器是什么
#自定义标签可以传任意个参数,但是不能用在控制语句里
@register.simple_tag
def simple_tag_multi(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)
my_tags.py
"""django_lesson6 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from blog import  views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    # # url(r'^register/', include('blog.urls')),
    # url(r'^show_time/', views.show_time),
    # url(r'^register/', views.register,name = 'regi'),
    url(r'^login/', views.login,name='login'),
    # url(r'^query/', views.query),
]
urls.py
from django.shortcuts import render,HttpResponse,render_to_response,redirect
def login(req):
    d= {"name":'wusir','age':20}
    L= ['jack',12,'alex']  #传入一个列表  没有意义,知道可以传过去就行,能提取到值就行
    print(req)
    return render(req,'login.html',locals())
views.py
{% load my_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>现在的年龄是(用的是过滤器):{{ d.age }}</h1>
<h1>现在的年龄翻三倍是(用的是过滤器):{{ d.age|filter_multi:3 }}</h1>
<h1>如果传入列表(用的是过滤器):{{ d.age|filter_multi:L }}</h1>
<h1>我是自定义标签:{% simple_tag_multi d.age  3 10 %}</h1>

</body>
</html>
login.html

注意:

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

{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}
View Code

inclusion_tag 的使用

1、步骤和上面类似都需要在app中创建templatetags模块(必须的) 创建的是一个 pyhton package  具体代码如下:

templatetags下的my_tags.py文件内容如下:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from django import template
register = template.Library()   #register的名字是固定的,不可改变
@register.inclusion_tag('rbac/menu.html')
def get_menu(request,):
    # 获取当前用户可以放到菜单栏中的权限
    menu_permission_list=request.session.get('menu_permission_list')
    return {'menu_permission_list':menu_permission_list} #把数据传入到'rbac/menu.html' 进行使用
my_tags.py

base.html文件内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
</head>
<style>
        *{
            margin: 0px;
        }
        .header{
            width: 100%;
            height: 60px;
            background-color: #336699;
        }
        .menu{
            width: 200px;
            background-color: chocolate;
            position: fixed;
            top: 60px;
            left: 0px;
            bottom: 0px;
        }
        .content{
            position: fixed;
            left: 200px;
            top:60px;
            bottom: 0px;
            right: 0px;
            padding: 20px;
            overflow: auto;
        }
    .menu_p{
        padding: 30px 0px;
        font-size: 20px;
        text-align: center;
    }
    </style>
<body>
<div class="header"> 欢迎{{ user_obj.name }}登录
    <div class="container">
{#    导入my_tags文件#}
    {% load my_tags %}
        <div class="menu">
{#            引入my_tags文件里的函数#}
            {% get_menu request %}
        </div>
        <div class="content">
            {% block con %}
            {% endblock %}
        </div>
    </div>
</div>
</body>
</html>
base.html
<div>
      {% for item in menu_permission_list %}
            <p class="menu_p"><a href="{{ item.0 }}">{{ item.1 }}</a></p>
            {% endfor %}
</div>
menu.html

目录结构如下:

extend模板继承

------include 模板标签

在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。

------extend(继承)模板标签

到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?

解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。

本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

让我们通过修改 current_datetime.html 文件,为 current_datetime 创建一个更加完整的模板来体会一下这种做法:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>The current time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>It is now {{ current_date }}.</p>
 
    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>
View Code

这看起来很棒,但如果我们要为 hours_ahead 视图创建另一个模板会发生什么事情呢?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>Future time</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
 
    <hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>
View Code

很明显,我们刚才重复了大量的 HTML 代码。 想象一下,如果有一个更典型的网站,它有导航条、样式表,可能还有一些 JavaScript 代码,事情必将以向每个模板填充各种冗余的 HTML 而告终。

解决这个问题的服务器端 include 方案是找出两个模板中的共同部分,将其保存为不同的模板片段,然后在每个模板中进行 include。 也许你会把模板头部的一些代码保存为 header.html 文件:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
View Code

你可能会把底部保存到文件 footer.html :

<hr>
    <p>Thanks for visiting my site.</p>
</body>
</html>
View Code

对基于 include 的策略,头部和底部的包含很简单。 麻烦的是中间部分。 在此范例中,每个页面都有一个<h1>My helpful timestamp site</h1> 标题,但是这个标题不能放在 header.html 中,因为每个页面的 <title> 是不同的。 如果我们将 <h1> 包含在头部,我们就不得不包含 <title> ,但这样又不允许在每个页面对它进行定制。 何去何从呢?

Django 的模板继承系统解决了这些问题。 你可以将其视为服务器端 include 的逆向思维版本。 你可以对那些不同 的代码段进行定义,而不是 共同 代码段。

第一步是定义 基础模板,该框架之后将由子模板所继承。 以下是我们目前所讲述范例的基础模板:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>
View Code

这个叫做 base.html 的模板定义了一个简单的 HTML 框架文档,我们将在本站点的所有页面中使用。 子模板的作用就是重载、添加或保留那些块的内容。 (如果你一直按顺序学习到这里,保存这个文件到你的template目录下,命名为 base.html .)

我们使用模板标签: {% block %} 。 所有的 {% block %} 标签告诉模板引擎,子模板可以重载这些部分。 每个{% block %}标签所要做的是告诉模板引擎,该模板下的这一块内容将有可能被子模板覆盖。

现在我们已经有了一个基本模板,我们可以修改 current_datetime.html 模板来 使用它:

{% extends "base.html" %}
 
{% block title %}The current time{% endblock %}
 
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
View Code

再为 hours_ahead 视图创建一个模板,看起来是这样的:

{% extends "base.html" %}
 
{% block title %}Future time{% endblock %}
 
{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}
View Code

看起来很漂亮是不是? 每个模板只包含对自己而言 独一无二 的代码。 无需多余的部分。 如果想进行站点级的设计修改,仅需修改 base.html ,所有其它模板会立即反映出所作修改。

      以下是其工作方式:

      在加载 current_datetime.html 模板时,模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。 模板引擎立即装载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的三个 {% block %} 标签,并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 block title %} 中定义的标题,对 {% block content %} 也是如此。 所以,网页标题一块将由{% block title %}替换,同样地,网页的内容一块将由 {% block content %}替换。

     注意由于子模板并没有定义 footer 块,模板系统将使用在父模板中定义的值。 父模板 {% block %} 标签中的内容总是被当作一条退路。继承并不会影响到模板的上下文。 换句话说,任何处在继承树上的模板都可以访问到你传到模板中的每一个模板变量。你可以根据需要使用任意多的继承次数。 使用继承的一种常见方式是下面的三层法:

   <1> 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
   <2> 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,
并包含区域特定的风格与设计。 <3> 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。

      这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。

以下是使用模板继承的一些诀窍:

<1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

 <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
    你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
    多越好。

 <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模
    板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

 <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
    相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。
View Code

模板继承综合案列:

启动项目  python manage.py runserver 127.0.0.1:8080  输入网址:http://127.0.0.1:8080/backend/    ---》点击学生管理 可以查看相关信息

"""django_lesson7 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from app import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^backend/', views.backend),
    url(r'^student/', views.student),
]
urls.py
from django.shortcuts import render

# Create your views here.
def backend(req):
    return render(req,'base.html')
def student(req):
    student_L = ['alex','jack','张三','李四','王五']
    return render(req,'student.html',locals())
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
{% block stytles_1 %}
{% endblock %}
<style>
    .head_title {
        height: 44px;
        width: 100%;
        background-color: #2459a2;
        color: white;
    }
    .head_title h1{
        text-align: center;
    }
    .left_qu {
        background-color: darkgray;
        width: 30%;
        min-height: 600px;
        float: left;
    }
    .bottom_qu {
        text-align: center;
    }
    .manage {
        margin: 30px 80px;
        padding: 30px 50px;
    }
     a{
        text-decoration: none;
    }
</style>
<body>
<div class="outer">
    <div class="head_title">
        <h1>标题</h1>
    </div>
    <div class="left_qu">
        <div class="student manage"><a href="/student">学生管理</a></div>
        <div class="student manage"><a href="">老师管理</a></div>
        <div class="student manage"><a href="">课程管理</a></div>
        <div class="student manage"><a href="">班里管理</a></div>
    </div>
    <div class="right_qu"></div>

    <div class="bottom_qu">
{#     content这个是名称#}
        {% block content %}
        <h1>welcome to login</h1>
        {% endblock  %}
    </div>
</div>
</body>
</html>
base.html
{#继承基础模板信息#}
{% extends 'base.html' %}
{% load staticfiles %}

{% block stytles_1 %}
    <style>
        h3{
            color: blue;
        }
    </style>
{% endblock %}


{% block content %}
{#    #把父类的信息提取过来#}
    {{ block.super }}
    <h2>hello {{ student_L }}</h2>
{#    #循环列表数据#}
    {% for item in student_L %}
        <h3>hello2 {{ item }} </h3>
    {% endfor %}
{#    添加新的网页代码 还需要加 {% load staticfiles %} 加在上面#}
    {% include "test_add.html" %}
{% endblock %}





{#<!DOCTYPE html>#}
{#<html lang="en">#}
{#<head>#}
{#    <meta charset="UTF-8">#}
{#    <title>Title</title>#}
{#</head>#}
{#<body>#}
{#    <h1>娃哈哈</h1>#}
{#</body>#}
{#</html>#}
student.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>

</style>
<body>
    <h1 style="color: red">hello workd我是新增的</h1>
</body>
</html>
test_add.html

 元信息

ORM对应的类里面包含另一个Meta类,而Meta类封装了一些数据库的信息。主要字段如下:

db_table

ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。

index_together

联合索引。

unique_together

联合唯一索引。

ordering

指定默认按什么字段排序。

只有设置了该属性,我们查询到的结果才可以被reverse()。

from django.db import models
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
# Create your models here.
class Author(models.Model):
    name = models.CharField(max_length=12)
    price = models.IntegerField()
    pub_date = models.DateField()
    class Meta:
        db_table='author'  #指定表在数据库里的名字为author 默认为app1_author
meta案列

 

八 Models

  • orm本身就是python写的 ,要学会用ORM来写SQL
  • 有些复杂的SQL 只能用原生SQL
  • ORM写的SQL 在搬迁的时候是很容易的 如 数据库换成Oracle了
  • 这时用orm写的不用修改代码,但是用PYMYSQL 可能就得改SQL了

数据库的配置

1    django默认支持sqlite,mysql, oracle,postgresql数据库。

     <1> sqlite

            django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

     <2> mysql

            引擎名称:django.db.backends.mysql

2    mysql驱动程序

  •    MySQLdb(mysql python)  python2都用这个
  •    mysqlclient
  •    MySQL
  •    PyMySQL(纯python的mysql驱动程序)   python3都用这个

3     在django的项目中会默认使用sqlite数据库,在settings里有如下设置:

           

如果我们想要更改数据库,需要修改如下:

           

DATABASES = {

    'default': {

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

        'NAME': 'books',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': '', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}
View Code

注意:

NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建

USER和PASSWORD分别是数据库的用户名和密码。

设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。

然后,启动项目,会报错:no module named MySQLdb

这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL

所以,我们只需要找到项目名文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

问题解决!
View Code

案列:

一、使用Django自带的splite数据库

1、点击Database 截图如下:

2、选择Splite 第一次使用需要下载,点击download

 3、点击apply  再点击OK

二、+++连接MYSQL数据库+++++++++++++++

 1、创建一张表book,代码如下:

from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=20)
    price = models.IntegerField()
    pub_date = models.DateField()
models.py
"""
Django settings for Djang_lesson_orm project.

Generated by 'django-admin startproject' using Django 1.8.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'wibuc7-1otk)om-e$33&==*-y4ph%v-vfiemmcgnjyuorxjl0!'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app_blog',
)

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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'Djang_lesson_orm.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Djang_lesson_orm.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
#默认连接Django自带的splite数据库的配置方式
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
#连接MYSQL数据库的配置方式
DATABASES = {

    'default': {

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

        'NAME': 'django_test',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': 'liuwenchao', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
settings配置文件

 

2、执行 python manage.py makemigrations    报错 如下 

 因为Django默认用的是MySQLdb连接方式

3、修改成pymysqldb方式

在项目名称下的__init文件里增加下面两行代码:截图如下:

import pymysql
pymysql.install_as_MySQLdb()

4、执行  python manage.py makemigrations       和python manage.py migrate

截图如下:

5、执行完后会创建多张表截图如下: 表的命名方式:第一次创建会创建多张表

如:类的名称是Boo k则表的名称是 app_blog_book  app_blog是Django的项目名称,Book是类名称,两个拼接起来就是表的名称

 

6、在python里操作mysql数据库里的表截图如下:

7、如果第一次连接需要下载截图如下: 下载完后点击 apply  和OK

8、可以在库里操作表截图如下: + 是增条记录    -是删除记录    另外一一个刷新按钮

三、在原来的基础上增加字段和新建一张表

1、在以有的book表上添加字段(新增author字段),同时再创建一张新表(author表)代码如下: ()

from django.db import models

# Create your models here.


#如果要创建一张表,就让BOOK 继承 models.Model 类,必须继承这个类
class Book(models.Model):  #Book 是表名  
    name=models.CharField(max_length=20) #name是字段名称  CharField 表示字符串类型 相当于varchar   max_length是最大长度
    price=models.IntegerField() # floatfiled() float类型  IntegerField整型
    pub_date=models.DateField()  #DateField日期类型
    author=models.CharField(max_length=32,null=False) #null=False 表示不允许为空,默认为TRue 允许为空

    # def __str__(self): 显示出相关信息 ,先不加看效果,就是为了方便显示用的
    #     return self.name

class Author(models.Model):
    name=models.CharField(max_length=32)
models.py

2、在终端运行  python manage.py makemigrations  如下提示: 输入  1

Please select a fix:
1) Provide a one-off default now (will be set on all existing rows) (现在提供一次性默认值(将设置在所有现有行上))
2) Quit, and let me add a default in models.py (退出,让我在MultMy.Py中添加一个默认值)
Select an option:

3、截图如下:第一次输入是 选择 1还是2,输入1  再输入默认值是什么 如下默认值是“alex“”:

4、再执行   python manage.py migrate   ,此时 book表新增了字段author默认值全是alex,也新创建了一张表author表(需点击一下刷新按钮)

 

ORM(对象关系映射)

用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。

优点: 1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

          2 可以避免一些新手程序猿写sql语句带来的性能问题。

            比如 我们查询User表中的所有字段:

            

            新手可能会用select * from  auth_user,这样会因为多了一个匹配动作而影响效率的。

 缺点:1  性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

          2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

          3  通过QuerySet的query属性查询对应操作的sql语句

author_obj=models.Author.objects.filter(id=2)
print(author_obj.query)

     下面要开始学习Django ORM语法了,为了更好的理解,我们来做一个基本的 书籍/作者/出版商 数据库结构。 我们这样做是因为 这是一个众所周知的例子,很多SQL有关的书籍也常用这个举例。

表(模型)的创建:

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

from django.db import models<br>
class Publisher(models.Model):
    name = models.CharField(max_length=30, verbose_name="名称")
    address = models.CharField("地址", max_length=50)
    city = models.CharField('城市',max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
 
    class Meta:
        verbose_name = '出版商'
        verbose_name_plural = verbose_name
 
    def __str__(self):
        return self.name
 
class Author(models.Model):
    name = models.CharField(max_length=30)
    def __str__(self):
        return self.name
 
class AuthorDetail(models.Model):
    sex = models.BooleanField(max_length=1, choices=((0, ''),(1, ''),))
    email = models.EmailField()
    address = models.CharField(max_length=50)
    birthday = models.DateField()
    author = models.OneToOneField(Author)
 
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
    def __str__(self):
        return self.title
View Code

注意1:记得在settings里的INSTALLED_APPS中加入'app01',然后再同步数据库。

注意2: models.ForeignKey("Publish") & models.ForeignKey(Publish)

分析代码:

       <1>  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

       <2>  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

       <3>  模型之间的三种关系:一对一,一对多,多对多。

             一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;

             一对多:就是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

       <4>  模型常用的字段类型参数

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
View Code

       <5>  Field重要参数

<1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)
View Code

表的操作(增删改查):

-------------------------------------增(create  ,  save) -------------------------------

复制代码
from app01.models import *

    #create方式一:   Author.objects.create(name='Alvin')

    #create方式二:   Author.objects.create(**{"name":"alex"})

    #save方式一:     author=Author(name="alvin")
                    author.save()

    #save方式二:     author=Author()
                    author.name="alvin"
                    author.save()
复制代码

重点来了------->那么如何创建存在一对多或多对多关系的一本书的信息呢?(如何处理外键关系的字段如一对多的publisher和多对多的authors)

#一对多(ForeignKey):

    #方式一: 由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
    #       字段设定对应值:
           Book.objects.create(title='php',
                               publisher_id=2,   #这里的2是指为该book对象绑定了Publisher表中id=2的行对象
                               publication_date='2017-7-7',
                               price=99)


    #方式二:
    #       <1> 先获取要绑定的Publisher对象:
        pub_obj=Publisher(name='河大出版社',address='保定',city='保定',
                state_province='河北',country='China',website='http://www.hbu.com')
    OR  pub_obj=Publisher.objects.get(id=1)

    #       <2>将 publisher_id=2 改为  publisher=pub_obj

#多对多(ManyToManyField()):

    author1=Author.objects.get(id=1)
    author2=Author.objects.filter(name='alvin')[0]
    book=Book.objects.get(id=1)
    book.authors.add(author1,author2)
    #等同于:
    book.authors.add(*[author1,author2])
    book.authors.remove(*[author1,author2])
    #-------------------
    book=models.Book.objects.filter(id__gt=1)
    authors=models.Author.objects.filter(id=1)[0]
    authors.book_set.add(*book)
    authors.book_set.remove(*book)
    #-------------------
    book.authors.add(1)
    book.authors.remove(1)
    authors.book_set.add(1)
    authors.book_set.remove(1)

#注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
#     如果第三张表是自己创建的:
     class Book2Author(models.Model):
            author=models.ForeignKey("Author")
            Book=  models.ForeignKey("Book")
#     那么就还有一种方式:
            author_obj=models.Author.objects.filter(id=2)[0]
            book_obj  =models.Book.objects.filter(id=3)[0]

            s=models.Book2Author.objects.create(author_id=1,Book_id=2)
            s.save()
            s=models.Book2Author(author=author_obj,Book_id=1)
            s.save()
View Code

-----------------------------------------删(delete) ---------------------------------------------

>>> Book.objects.filter(id=1).delete()
(3, {'app01.Book_authors': 2, 'app01.Book': 1})

我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除。

如果是多对多的关系: remove()和clear()方法:

#正向
book = models.Book.objects.filter(id=1)

#删除第三张表中和女孩1关联的所有关联信息
book.author.clear()        #清空与book中id=1 关联的所有数据
book.author.remove(2)  #可以为id
book.author.remove(*[1,2,3,4])     #可以为列表,前面加*

#反向
author = models.Author.objects.filter(id=1)
author.book_set.clear() #清空与boy中id=1 关联的所有数据

-----------------------------------------改(update和save) ----------------------------------------

实例:

    

注意:

<1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。

<2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。

#---------------- update方法直接设定对应属性----------------
    models.Book.objects.filter(id=3).update(title="PHP")
    ##sql:
    ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3)


#--------------- save方法会将所有属性重新设定一遍,效率低-----------
    obj=models.Book.objects.filter(id=3)[0]
    obj.title="Python"
    obj.save()
# SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", 
# "app01_book"."color", "app01_book"."page_num", 
# "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; 
# 
# UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556,
# "publisher_id" = 1 WHERE "app01_book"."id" = 3;
View Code

      在这个例子里我们可以看到Django的save()方法更新了不仅仅是title列的值,还有更新了所有的列。 若title以外的列有可能会被其他的进程所改动的情况下,只更改title列显然是更加明智的。更改某一指定的列,我们可以调用结果集(QuerySet)对象的update()方法,与之等同的SQL语句变得更高效,并且不会引起竞态条件。

此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。

注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
LOGGING

注意:如果是多对多的改:

 

    obj=Book.objects.filter(id=1)[0]
    author=Author.objects.filter(id__gt=2)

    obj.author.clear()
    obj.author.add(*author)

---------------------------------------查(filter,value等) -------------------------------------

---------->查询API:

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
                                     
#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。
View Code

补充:

#扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  
extra

---------->惰性机制:

所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       <1>  可迭代的

       <2>  可切片

#objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])
View Code

QuerySet的高效使用:

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。
View Code

---------->对象查询,单表条件查询,多表条件关联查询

#--------------------对象形式的查找--------------------------
    # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到与它绑定的Book对象呢?
    print(ret2.book_set.all()) #ret2.book_set是一个queryset集合

#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的双下划线(__)之多表条件关联查询---------------

# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(条件)之一对多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(条件)之多对多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
      #一对多和多对多在这里用法没区别

# 反向查找(条件)

    #反向查找之一对多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多对多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一对多和多对多在这里用法没区别
View Code

注意:条件查询即与对象查询对应,是指在filter,values等方法中的通过__来明确查询条件。

---------->聚合查询和分组查询

<1> aggregate(*args,**kwargs):

   通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

from django.db.models import Avg,Min,Sum,Max

从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
图书的集合。

>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}

aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
一个名称,可以向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}


如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
View Code

<2> annotate(*args,**kwargs):

   可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。

       查询alex出的书总价格                   

       

        查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name

           

         查询各个出版社最便宜的书价是多少

       

---------->F查询和Q查询

仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

# F 使用查询条件的值,专门取对象中某列值的操作

    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


# Q 构建搜索条件
    from django.db.models import Q

    #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
    q1=models.Book.objects.filter(Q(title__startswith='P')).all()
    print(q1)#[<Book: Python>, <Book: Perl>]

    # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
    Q(title__startswith='P') | Q(title__startswith='J')

    # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
    Q(title__startswith='P') | ~Q(pub_date__year=2005)

    # 4、应用范围:

    # Each lookup function that takes keyword-arguments (e.g. filter(),
    #  exclude(), get()) can also be passed one or more Q objects as
    # positional (not-named) arguments. If you provide multiple Q object
    # arguments to a lookup function, the arguments will be “AND”ed
    # together. For example:

    Book.objects.get(
        Q(title__startswith='P'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )

    #sql:
    # SELECT * from polls WHERE question LIKE 'P%'
    #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

    # import datetime
    # e=datetime.date(2005,5,6)  #2005-05-06

    # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    # 正确:
    Book.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        title__startswith='P')
    # 错误:
    Book.objects.get(
        question__startswith='P',
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
View Code

raw sql

django中models的操作,也是调用了ORM框架来实现的,pymysql 或者mysqldb,所以我们也可以使用原生的SQL语句来操作数据库!

综合案列

1、单表增删改查 综合案列

from django.shortcuts import render,HttpResponse
from app_blog.models import  *
# Create your views here.
def index(req):
    return render(req,'index.html')
def addbook(req):
    # 添加记录的方法一
    # b = Book(name = 'python基础',price=99,author='yuan',pub_date='2017-12-12')
    # b.save()
    # 添加记录的方法二 不用保存,直接就保存了
    Book.objects.create(name = 'C++基础',price=89,author = 'zheng',pub_date='2016-12-12')
    return HttpResponse('添加成功')

def updatebook(req):
    #修改记录方法一以后都用 update方法 save不是 很好,save效率低
    #filter是筛选条件 查找author="yuan" 作者是alex的数据进行update
    Book.objects.filter(author='alex').update(price=300)
    return HttpResponse('记录修改成功')
    #方法一执行的update语句
    #UPDATE `app_blog_book` SET `price` = 300 WHERE `app_blog_book`.`author` = 'alex'; args=(300, 'alex')

    # 修改记录方法二
    # b = Book.objects.get(author='alex')
    # b.price=10
    # b.save()
    # return HttpResponse('记录修改成功')
    #save方法执行的SQL,每个字段都会进行修改一下,不改的也会进行一下赋值。所以效率低
  #  UPDATE `app_blog_book` SET `name` = 'linux', `price` = 10, `pub_date` = '2018-10-18', `author` = 'alex'
 #WHERE `app_blog_book`.`id` = 1; args=('linux', 10, '2018-10-18', 'alex', 1)


def deletebook(req):
    Book.objects.filter(author='zheng').delete()
    return HttpResponse('删除成功')


def selectbook(req):
    book_list = Book.objects.all()  # 查看所有数据
    print('列表数据',book_list) #是一个queryset的集合对象
    print('列表数据第一个元素',book_list[0]) #执行结果是Book object  当放开models.py文件里的__str__方法,执行结果是linux
    # book_list = Book.objects.filter(id=2) #查看id =2的数据 filter拿到的肯定是一个对象
    # book_list = Book.objects.all()[:3] # 显示前三条

    # book_list = Book.objects.all()[::2] #两个两个取,取到底,设置步长为2
    # book_list = Book.objects.all()[::-1]  #倒着提取
    # book_list = Book.objects.first()  #一个对象无法用循环
    # book_list = Book.objects.last()  #一个对象无法用循环
    # 上面拿到的都是一个集合
    # book_list = Book.objects.get(id=2)#只能取出一条记录时才不报错,提取到的是一个bookk对象,用get提取如果是多条记录或者空则报错

    # ret1=Book.objects.filter(author="alex").values("name",'price') #拿到的是字典   #提取出条件等于  where author="oldboy" 的name和price两个字段
    # ret2=Book.objects.filter(author="yuan").values_list("name","price") #拿到的是列表
    # book_list=Book.objects.exclude(author="yuan").values("name","price")  # exclude是filter的反义词,提取相反的数据   exclude不能用value_list
    # print('ret1的结果集',ret1)
    # print('ret2的结果集',ret2)

    # book_list= Book.objects.all().values("name").distinct()  #去重
    # book_count= Book.objects.all().values("name").distinct().count()
    # print(book_count)

    # 万能的  __ (双下划綫)  filter是过滤的意思    price__gt是大于的意思
    # book_list=Book.objects.filter(price__gt=150).values("name","price") #提取出price大于150的name和price两个字段
    # book_list = Book.objects.filter(name__contains="P").values("name", "price")# name__contains表示包含的意思 默认区分大小写类似于like
    # book_list = Book.objects.filter(name__icontains='P').values("name")# name_icontaaions表示不区分大小写 类似于like

    return render(req,'index.html',{"book_list":book_list})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    *{
        margin: 0px;
    }
    .head_title {
        height: 44px;
        width: 100%;
        background-color: #2459a2;
    }
    .left_qu{
        background-color: darkgray;
        min-height: 600px;
        width: 30%;
        float: left;
    }
    h1{
        text-align: center;
        color: red;
    }
    .jilu {
        margin: 30px 10px;
    }
    .query_result{
{#        background-color: yellow;#}
        float: left;
        width: 70%;
        min-height: 600px;
    }
</style>
<body>
    <div class="outer">
        <div class="head_title">
            <h1>标题</h1>
        </div>
        <div class="left_qu">
            <a class="jilu" href="/addbook/">添加3书籍</a>
            <a class="jilu" href="/updatebook/">修改书籍</a>
            <a class="jilu" href="/deletebook/">删除书籍</a>
            <a class="jilu" href="/selectbook/">查询书籍</a>
        </div>
        <div class="queryResult">
            <h2>查询数据如下:</h2>
         {% for book in book_list %}
             <div>
              <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
            </div>
         {% endfor %}
        </div>
    </div>
</body>
</html>
index.html
from django.db import models

# Create your models here.


#如果要创建一张表,就让BOOK 继承 models.Model 类,必须继承这个类
class Book(models.Model):  #Book 是表名
    name=models.CharField(max_length=20) #name是字段名称  CharField 表示字符串类型 相当于varchar   max_length是最大长度
    price=models.IntegerField() # floatfiled() float类型  IntegerField整型
    pub_date=models.DateField()  #DateField日期类型
    author=models.CharField(max_length=32,null=False) #null=False 表示不允许为空,默认为TRue 允许为空

    def __str__(self): #当打印实体对象的时候,显示name
        return self.name


class Author(models.Model):
    name=models.CharField(max_length=32)
models.py
"""
Django settings for Djang_lesson_orm project.

Generated by 'django-admin startproject' using Django 1.8.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'wibuc7-1otk)om-e$33&==*-y4ph%v-vfiemmcgnjyuorxjl0!'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app_blog',
)

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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'Djang_lesson_orm.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Djang_lesson_orm.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
#默认连接Django自带的splite数据库的配置方式
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
#连接MYSQL数据库的配置方式
DATABASES = {

    'default': {

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

        'NAME': 'django_test',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': 'liuwenchao', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
#加上LOGGING配置 ,就可以看到执行的SQL了
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
settings配置文件
"""Djang_lesson_orm URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from app_blog import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^updatebook/', views.updatebook),
    url(r'^deletebook/', views.deletebook),
    url(r'^selectbook/', views.selectbook),
]
urls.py

z注意:settings配置文件:

#加上LOGGING配置下面的内容 ,就可以看到执行的SQL了 

2、多表查询综合案列  通过外键进行查询

方法一 、    第三张表通过   author = models.ManyToManyField('Author')  关联生成

from django.shortcuts import render,HttpResponse
from app9.models import  *
# Create your views here.
def index(request):
    return render(request,'index.html')
def deletebook(request):
    pass
def updatebook(req):
    pass
def addbook(req):
    pass
def selectbook(request):
    #添加记录方法一
    publish_obj = Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish2_id=2)#publish_id这个字段应该是数据库对应的字段,所以是publish2_id
    #添加记录方法二 从外键表里查询出数据,并复制给publish
    publish_obj = Publish.objects.filter(name = '郑州出版社')[0]
    Book.objects.create(name = "GO",price = 32,pub_date='2007-12-8',publish2=publish_obj)
    book_obj = Book.objects.get(name = 'GO') #得到一个对象
    print(book_obj.name) #提取这个记录的相关字段
    print(book_obj.price)
    print(book_obj.pub_date)
    #一对多:book_obj.publish2一定是一个对象  publish2是外键  点外键一定是一个对象
    print(book_obj.publish2.city) #book_obj.publish 是一条记录的对象
    print(book_obj.publish2.name)
    print('类型b',type(book_obj),book_obj)
    print('类型C',type(book_obj.publish2),book_obj.publish2) #是一个实列对象

    # 查询北京出版社出过的所有书籍名字和价格
    # 方式一:
    pub_obj = Publish.objects.filter(name = '北京出版社')[0] #提取出行对象
    ret = Book.objects.filter(publish2=pub_obj).values('name','price')
    print('pub类型',type(pub_obj),pub_obj)
    print(ret,pub_obj.city,pub_obj.name)
    # 方式二
    pub_obj = Publish.objects.filter(name = '北京出版社')[0] #提取的是这条记录的对象
    print(pub_obj.book_set.all().values('name','price'))
    print('方式二类型',type(pub_obj.book_set.all())) #book是表  _set是固定搭配,拿到的是一个集合对象(Queryset)
    print(pub_obj.book_set.all())
    #方式三  publish是外键字段的名称
    ret = Book.objects.filter(publish2__name='北京出版社').values('name','pub_date','price')
    print('类型a',ret,type(ret))


    # python这本书出版社的名字  两种写法
    ret1 = Book.objects.filter(name = 'python').values('publish2__name','publish2__city')
    print(ret1)
    ret2 = Publish.objects.filter(book__name='python').values('name','city')
    print(ret2)
    ret3 = Book.objects.filter(publish2__city='郑州').values('price','pub_date')
    print(ret3)
    ret4 = Book.objects.filter(pub_date__gt='2008-10-01',pub_date__lt='2017-12-31').values('price','name','pub_date')
    print('结果集合',ret4)


    # # 通过对象的方式绑定关系  多对多的关系
    # 正向查找
    book_obj = Book.objects.get(id=3)
    print('类型book',type(book_obj),book_obj)
    print('结果集',book_obj.author.all())
    print(type(book_obj.author.all())) #拿到的是一个集合  在Author类里加上str方法就可以看到名称了

    # 反向查找
    author_obj = Author.objects.get(id=1)
    print(author_obj.book_set.all())

    book_obj = Book.objects.get(id=5) #得到这本书的对象
    author_objs = Author.objects.all() #得到的是一个集合
    author_obj = Author.objects.get(id=2)  #一条记录
    print('类型',type(author_obj),author_obj)
    print('类型2', type(book_obj), book_obj)

    book_obj.author.add(author_obj) #不许要加 * 号,因为author_obj获取到的是一条记录,给这本书增加作者ID
    book_obj.author.add(*author_objs) #放一个集合需要放一个星,因为author_objs获取到的是一个集合,给这本书增加所有的作者ID
    book_obj.author.remove(*author_objs) #解除多条记录
    book_obj.author.remove(4) #解除id=4的关系


    print('类型a',type(publish_obj),publish_obj)
    return  HttpResponse('查询成功')
views.py
from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    pub_date = models.DateField()
    publish2 = models.ForeignKey('Publish') #publish最好加上引号,如果不加引号publish类要放在上面 #通过外键把两张表关联起来
    author = models.ManyToManyField('Author') #创建第三张表 多对多的映射
    def __str__(self):
        return self.name
class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    def __str__(self):
        return self.name
models.py
"""Django_ORM URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from app9 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^deletebook/', views.deletebook),
    url(r'^updatebook/', views.updatebook),
    url(r'^selectbook/', views.selectbook),
]
urls.py
"""
Django settings for Django_ORM project.

Generated by 'django-admin startproject' using Django 1.8.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y22(ev=36@obq1zk9z651(+%4wv_v-4o3v!@x4&3)p*nz+pcc9'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app9',
)

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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'Django_ORM.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Django_ORM.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

#连接 mysql数据库
DATABASES = {

    'default': {

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

        'NAME': 'django_test',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': 'liuwenchao', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
settings.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    *{
        margin:  0px
    }
    .head_title {
        background-color: #2459a2;
        height: 44px;
        width: 100%;
    }
    .left_qu {
        background-color: darkgray;
        width: 30%;
        min-height: 800px;
    }
    .head_title h1{
        text-align: center;
        color: white;
    }
    .left_qu {
        float: left;
    }
    .left_qu a{
        display: inline-block;
        padding: 60px 100px;
    }
    .bottom_qu h1 {
        text-align: center;
    }
</style>
<body>
<div class="outer">
    <div class="head_title">
        <h1>标题</h1></div>
    <div class="left_qu">
        <p><a href="/addbook/">添加书籍</a></p>
        <p><a href="/updatebook/">修改书籍</a></p>
        <p><a href="/deletebook/">删除书籍</a></p>
        <p><a href="/selectbook/">查询书籍</a></p>
    </div>
    <div class="bottom_qu">
        {% block neirong %}
        <h1>welcome to login</h1>
        {% endblock %}
    </div>
</div>

</body>
</html>
index.html

 对表操作,一对多,以后用这种方式

 #查询记录(filter values  双下划线__) 以后用这个
                     
                    #人民出版社出版过的书籍与价格  publish 是外键
                    ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
                    
                    #python这本书出版社的名字
                    ret2=Publish.objects.filter(book__name="python").values("name")
                    
                    #python这本书出版社的名字
                    ret3=Book.objects.filter(name="python").values("publish__name")
                    
                    #北京的出版社出版书的名字
                    ret4=Book.objects.filter(publish__city="北京").values("name")
                    
                    #2017年上半年出版过书的出版社的名字
                    ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
                    

多表操作,多对多 

 多表操作(多对多):  
                     
                    创建多对多的关系 author= models.ManyToManyField("Author")(推荐)
                    
                    
                    书籍对象它的所有关联作者  obj=book_obj.authors.all()
                            绑定多对多的关系  obj.add(*QuerySet)   
                                              obj.remove(author_obj)
                                              
                                              
                    如果想向第三张表插入值的方式绑定关系:  手动创建第三张表  不建议用这种

                            # class Book_Author(models.Model):
                            #     book=models.ForeignKey("Book")
                            #     author=models.ForeignKey("Author")                    
                            Book_Author.objects.create(book_id=2,author_id=3)
                            
                    
                    掌握:通过 filter values (双下换线)进行多对多的关联查询(形式和一对多)

方法二、手工创建第三张表,这种方式不建议使用,记住方法一就行

from django.shortcuts import render,HttpResponse
from app9.models import  *
# Create your views here.
def index(request):
    return render(request,'index.html')
def deletebook(request):
    return HttpResponse('删除成功')
def updatebook(req):
    pass
def addbook(req):
    pass
def selectbook(request):
    #第三张表的数据 Book_author
    Book_author.objects.create(book_id = 2,author_id = 2) #增加绑定关系
    obj = Book.objects.get(id = 2)
    print('数据',obj.book_author_set.all())
    print('数据', obj.book_author_set.all()[0].author)
    # alex出过的书籍名称及价格  查询时还是用这种方式
    ret = Book.objects.filter(book_author__author__name='alex').values('name','price')
    print(ret)
    return HttpResponse('查询成功')
views.py
from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    pub_date = models.DateField()
    publish2 = models.ForeignKey('Publish') #publish最好加上引号,如果不加引号publish类要放在上面 #通过外键把两张表关联起来
    # author = models.ManyToManyField('Author') #创建第三张表 多对多的映射
    def __str__(self):
        return self.name
class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    def __str__(self):
        return self.name
#手工创建第三张表
class Book_author(models.Model):
    book = models.ForeignKey('Book')
    author = models.ForeignKey('Author')

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=30) #在原来基础上再加的时候选择2,就是默认值的意思(2) Quit, and let me add a default in models.py)
    def __str__(self):
        return self.name
models.py

注意:其他配置文件和方法一 一样

 

双下划线可以通过外键一直找下去,

案列如下:

 

class School(models.Model):
    name = models.CharField(max_length=32)
 
class Classes(models.Model):
    """
    班级表,男
    """
    titile = models.CharField(max_length=32)
    fk = models.ForeignKey("School")

class Student(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    gender = models.BooleanField()  
    cs = models.ForeignKey(Classes) #cs是class的一个对象(title,fk是school的对象(n))
    
    Student.object.all().values("username","cs__titile","cs__fk__name") #cs__name  cs__fk__name可以一直夸下去

 

3、分组,聚合查询等

from django.shortcuts import render,HttpResponse
from app9.models import  *
from django.db.models import Avg,Min,Sum,Max,Count
from django.db.models import Q,F
# Create your views here.
def index(request):
    return render(request,'index.html')
def deletebook(request):
    return HttpResponse('删除成功')
def updatebook(req):
    pass
def addbook(req):
    pass
def selectbook(request):
    book_obj = Book.objects.get(id=2)
    author_obj = Author.objects.get(id=3)
    book_obj.authors.add(author_obj)
    # alex出过的书籍名称及价格
    ret2 = book_obj = Book.objects.filter(authors__name='alex').values('name','price')
    print(ret2)
    
    ret = Book.objects.all().aggregate(Avg('price'))  #求平均值
    ret = Book.objects.all().aggregate(Sum('price')) #求和
    ret = Book.objects.filter(authors__name='alex').aggregate(Sum('price'))
    ret = Book.objects.filter(authors__name='alex').aggregate(sum_money = Sum('price'),avg_money = Avg('price'),max_money = MAX('price')) #求多个值
    ret = Book.objects.filter(authors__name='alex').aggregate(alex_money = Sum('price')) #alex_money 给字典的key取值
    ret = Book.objects.filter(authors__name='alex').aggregate(Count("price"))
    #annotate  分组函数  类似于group  by authors__name
    ret = Book.objects.values("authors__name").annotate(Sum('price'))
    ret = Publish.objects.values('name').annotate(Min("book__price"))
    ret = Book.objects.get(name = 'PHP',price=110) #只筛选出一条,get如果找不到就报错,找到而且是一条时不报错
    #F 使用查询条件的值,专门取对象中某列值的操作
    Book.objects.all().update(price = F("price") + 10) #修改,所有记录加10元
    ret = Book.objects.filter(Q(name__contains="Go"))
    ret = Book.objects.filter(Q(name='Go'),price=80) #Q查询一定要放在前面
    ret = Book.objects.filter(price=110) #拿到的是一个集合,并没有执行,只有当print的时候才会执行
    ret = Book.objects.all() #如果修改了必须重新赋值,因为有缓存
    for i in ret:
        print('循环结果:',i.name,i.price,i.pub_date)
    if ret.exists(): #判断是否有数据 exists有数据返回true,无返回false,不会把数据放入缓存
        print('OK')
    
    ret_sult = ret.iterator() #迭代器,用一个就提取一个,
    print('类型',type(ret_sult),ret_sult)
    
    for i in ret_sult:
        print('结果4',i.name)  #迭代器只会显示一次
    
    for i in ret_sult:
        print('结果5',i.name)   #数据量非常大的时候用迭代器


    print('结果是:', ret)
    return HttpResponse('查询成功')

views.py
views.py
from django.db import models

# Create your models here.
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    pub_date = models.DateField()
    publish2 = models.ForeignKey('Publish') #publish最好加上引号,如果不加引号publish类要放在上面 #通过外键把两张表关联起来
    authors = models.ManyToManyField('Author') #创建第三张表 多对多的映射
    def __str__(self):
        return self.name
class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=30) #在原来基础上再加的时候选择2,就是默认值的意思(2) Quit, and let me add a default in models.py)
    def __str__(self):
        return self.name
models.py
"""Django_ORM URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from app9 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^deletebook/', views.deletebook),
    url(r'^updatebook/', views.updatebook),
    url(r'^selectbook/', views.selectbook),
]
urls.py
"""
Django settings for Django_ORM project.

Generated by 'django-admin startproject' using Django 1.8.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y22(ev=36@obq1zk9z651(+%4wv_v-4o3v!@x4&3)p*nz+pcc9'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app9',
)

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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'Django_ORM.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Django_ORM.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

#连接 mysql数据库
DATABASES = {

    'default': {

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

        'NAME': 'django_test',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': 'liuwenchao', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
setting.py

九 admin的配置

admin是django强大功能之一,它能共从数据库中读取数据,呈现在页面中,进行管理。默认情况下,它的功能已经非常强大,如果你不需要复杂的功能,它已经够用,但是有时候,一些特殊的功能还需要定制,比如搜索功能,下面这一系列文章就逐步深入介绍如何定制适合自己的admin应用。

如果你觉得英文界面不好用,可以在setting.py 文件中修改以下选项

LANGUAGE_CODE = 'en-us'  #LANGUAGE_CODE = 'zh-hans'

一  认识ModelAdmin

   管理界面的定制类,如需扩展特定的model界面需从该类继承。

二 注册medel类到admin的两种方式:

     <1>   使用register的方法

admin.site.register(Book,MyAdmin)

     <2>   使用register的装饰器

@admin.register(Book)

三 掌握一些常用的设置技巧

  •     list_display:     指定要显示的字段
  •     search_fields:  指定搜索的字段
  •     list_filter:        指定列表过滤器
  •     ordering:       指定排序字段
from django.contrib import admin
from app01.models import *
# Register your models here.

# @admin.register(Book)#----->单给某个表加一个定制
class MyAdmin(admin.ModelAdmin):
    list_display = ("title","price","publisher")
    search_fields = ("title","publisher")
    list_filter = ("publisher",)
    ordering = ("price",)
    fieldsets =[
        (None,               {'fields': ['title']}),
        ('price information', {'fields': ['price',"publisher"], 'classes': ['collapse']}),
    ]

admin.site.register(Book,MyAdmin)
admin.site.register(Publish)
admin.site.register(Author)

 admin综合案列

auth系统 是认证系统 auth系统是Django自带的认证功能
python   manage.py  createsuperuser    创建登录用户   密码不低于六位   这个是管理用户

在界面上可以创建新的用户 大小写敏感
直接登录时 登录失败
创建用户后还需要授权
active是激活的意思
staff staus 勾上,表明是员工,就可以登录了,此时没有任何权限

修改settings配置文件里的LANGUAG_CODE= 'zh_hans' 这时界面就是中文了

输入网址  127.0.0.1:8080/admin   用户名和密码就是上面创建的用户和密码

from django.contrib import admin

# Register your models here.
from app9 import models

#BookAdmin 名字自己起,自定制类
class BookAdmin(admin.ModelAdmin):
    list_display = ('id','name','price','publish2') #默认显示四个字段,authors字段不能加,因为authors是多对多字段
    list_editable = ('name','price') #增加直接在界面上的修改功能
    # filter_horizontal = ('name',)
    list_per_page = 3 #改成3条分页
    search_fields = ('id','price','publish2__name') #增加按照这三个字段搜索,相当于增加三个字段搜索功能,publish__name这个是因为关联表
    list_filter = ('pub_date','publish2') #增加过滤功能
    # ordering = ('price',) #按照升序排序
    # ordering = ('-price',) #按照降序排序
    ordering = ('id','price') #按照ID和价格排序
    #fieldsets看全端效果
    fieldsets = [
        (None,          {'fields':['title']}),
        ('price information',{'fields':['price','publish'],'classes':['collapse']}),
                 ]
#注册三张表
admin.site.register(models.Author)
admin.site.register(models.Book,BookAdmin) #加入参数就可以对表进行自定制了
admin.site.register(models.Publish)
admin.py
from django.db import models

# Create your models here.
class Book(models.Model):
   # verbose_name = '姓名'  价格  在admin界面字段显示成汉子了
    name = models.CharField(max_length=32,verbose_name='姓名')
    price = models.IntegerField('价格',null=True) #表示这个字段允许为空
    pub_date = models.DateField()
    publish2 = models.ForeignKey('Publish') #publish最好加上引号,如果不加引号publish类要放在上面 #通过外键把两张表关联起来
    authors = models.ManyToManyField('Author') #创建第三张表 多对多的映射
    def __str__(self):
        return self.name
class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=30) #在原来基础上再加的时候选择2,就是默认值的意思(2) Quit, and let me add a default in models.py)
    def __str__(self):
        return self.name
models.py
"""Django_ORM URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
from app9 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^deletebook/', views.deletebook),
    url(r'^updatebook/', views.updatebook),
    url(r'^selectbook/', views.selectbook),
]
urls.py
"""
Django settings for Django_ORM project.

Generated by 'django-admin startproject' using Django 1.8.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y22(ev=36@obq1zk9z651(+%4wv_v-4o3v!@x4&3)p*nz+pcc9'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app9',
)

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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 'Django_ORM.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Django_ORM.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

#连接 mysql数据库
DATABASES = {

    'default': {

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

        'NAME': 'django_test',    #你的数据库名称

        'USER': 'root',   #你的数据库用户名

        'PASSWORD': 'liuwenchao', #你的数据库密码

        'HOST': '', #你的数据库主机,留空默认为localhost

        'PORT': '3306', #你的数据库端口

    }

}


# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh_hans'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
settings.py

 admin 其他

from django.db import models
class Img(models.Model):
    #FileField 文件类  后台会变成上传按钮
    #verbose_name  在admin里进行添加时默认显示的字段名,给字段名起别名
    #upload_to 指定图片上传到 那个路径下
    src = models.FileField(max_length=32,verbose_name='图片路径',upload_to='static/upload')
    title = models.CharField(max_length=32,verbose_name='标题')
    summary = models.CharField(max_length=128,verbose_name='简介')

    ##admin默认显示的是Img(类名),改成显示 图片信息2 信息
    class Meta:
        verbose_name_plural = '图片信息2'

    #预览数据时默认返回的是img object,自定义默认返回的字段名
    def __str__(self):
        return self.title

 

参考文献:http://www.admin10000.com/document/2220.html

 

 
posted @ 2018-10-22 18:48  奋斗的小孩_小小鸟  阅读(543)  评论(0编辑  收藏  举报