一、MVC和MTV模式

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

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

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

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

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

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

二 Django的流程和命令行工具

 django
#安装: pip3 install django 添加环境变量 #1 创建project
django-admin startproject mysite ---mysite ---settings.py
---url.py
---wsgi.py ---- manage.py(启动文件) #2 创建APP
python mannage.py startapp app01 #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

命令行创建

文件介绍:

• manage.py  --- Django项目里面的工具,通过它可以调用django shell和数据库等

• settings.py  --- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。

• urls.py --- 负责把url模式映射到应用程序

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

    同步数据库:python manage.py migrate

注:开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个粗暴方法是将migrations目录下的脚本(除了__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。

-- 访问http://127.0.0.1:8000/admin/login/?next=/admin/时,需要为进入这个项目后台创建超级管理员:python manage.py createsuperuser,设置好账户密码就可以登陆

-- 清空数据库:python manage.py flush

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

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

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

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

提交数据并展示

 <!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")

提交数据并展示(数据库)

三 Django URL(路由系统)

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

 urlpatterns = [
url(正则表达式,views视图函数,参数,别名),
]
 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), ]

示例

四 Django Views(视图函数)

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

  http请求:HttpRequest对象

  http响应:HttpResponse对象

 # 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

HttpResponse对象的属性和方法

注:常用request.POST.getlist('')

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

  HttpResponse类在django.http.HttpResponse

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

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

五 Template基础

模板语法

  • 模板的组成

 HTML代码+逻辑控制代码

  • 逻辑控制代码的组成

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

 格式:    {{ var_name }}

---------Template和Context对象

  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' # 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的
# 方法。

---------变量的过滤器(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'

  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 <%}
<p>num小于100</p> {% else %}
<p>num等于100</p> {% endif %} {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的: {% if obj1 and obj2 or obj3 %}

---------{% 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

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

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

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

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

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

---------{% with %}:用更简单的变量名替代复杂的变量名

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

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

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

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

  3、自定义filter和simple_tag

    a.在app中创建templatetags模块(必须的)

    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)

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

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

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

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

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

  4、extend模板继承

---------include 模板标签

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

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

  在实际应用中,将用Django模板系统来创建整个HTML页面。这就带来一个常见Web开发问题:在整个网站中,如何减少共用页面区域(如站点导航)所引起的重复和冗余代码?

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

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

  第一步:定义基础模板,该框架将由子模板所继承

 <!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>

  以上定义了一个简单的HTML框架文档,将在本站点的所有页面中使用。子模板的作用就是重载、添加或保留那些块的内容。

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

 {% extends "base.html" %}

 {% block title %}The current time{% endblock %}

 {% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
 {% extends "base.html" %}

 {% block title %}Future time{% endblock %}

 {% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock %}

  这样一来,每个模板只包含对自己而言独一无二的代码。无需多余的部分。如果想进行站点级的设计修改,仅需修改基础模板即可,所有其他模板都会被修改。

六 Models

数据库配置

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

  a.sqlite

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

  b.mysql

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

2、mysql驱动程序

  a.MySQLdb(mysql python)

  b.mysqlclient

  c.MySQL

  d.PyMySQL(纯python的mysql驱动程序)

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

 DATABASES = {

     'default': {

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

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

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

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

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

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

     }

 }
 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() 问题解决!

注意!!!

ORM(对象关系映射)

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

优点:

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

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

缺点:

  1、性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载等来减轻这个问题。

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

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

 author_obj=models.Author.objects.filter(id=2)
print(author_obj.query)
 <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参数.

模型常用的字段类型参数

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

Field重要参数

 from django.shortcuts import render,HttpResponse
from app01.models import *
# Create your views here. def index(req):
return render(req,"index.html") def addbook(req):
# 方式一
# b = Book(name="python基础", price=99, author="alex", pub_date="2019-03-30")
# b.save()
# 方式二
Book.objects.create(name="linux", price=99, author="alex", pub_date="2019-03-30")
return HttpResponse("添加成功!")

表单的添加--> views.py

 from django.shortcuts import render,HttpResponse
from app01.models import *
# Create your views here. def index(req):
return render(req, "index.html") def update(req):
# 方式一
# Book.objects.filter(name="linux").update(price=199)
# 方式二
b = Book.objects.get(name="linux")
b.price = 299
b.save()
# 注:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合) # 若想查看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',
# },
# }
# }
return HttpResponse("修改成功!")

表单的修改-->views.py

 from django.shortcuts import render,HttpResponse
from app01.models import *
# Create your views here. def index(req):
return render(req, "index.html") def delete(req):
Book.objects.filter(name="linux").delete()
return HttpResponse("删除成功!")

表单的删除-->views.py

 # 查询相关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。

表单的查询-->查询API

 #扩展查询,有时候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'])

表单的查询-->补充

 from django.shortcuts import render,HttpResponse
from app01.models import *
# Create your views here. def index(req):
return render(req, "index.html") def addbook(req):
# 方式一
# b = Book(name="python基础", price=99, author="alex", pub_date="2019-03-30")
# b.save()
# 方式二
Book.objects.create(name="linux", price=99, author="alex", pub_date="2019-03-30")
return HttpResponse("添加成功!") def update(req):
# 方式一
# Book.objects.filter(name="linux").update(price=199)
# 方式二
b = Book.objects.get(name="linux")
b.price = 299
b.save()
# 注:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合) # 若想查看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',
# },
# }
# }
return HttpResponse("修改成功!") def delete(req):
Book.objects.filter(name="linux").delete()
return HttpResponse("删除成功!") def select(req):
# book_list = Book.objects.all()
# print(book_list[0]) book_list = Book.objects.filter(id=2) # book_list = Book.objects.all()[:3] # book_list = Book.objects.all().first() # book_list = Book.objects.all().last() # book_list = Book.objects.get(id=2) # 只能取一条记录时才不会报错 # book_list = Book.objects.filter(author="alex").values("name") # book_list = Book.objects.filter(author="alex").values_list("name") # book_list = Book.objects.exclude(author="alex").values("name") # book_list = Book.objects.filter(author="alex").values("name").distinct() # book_list = Book.objects.filter(author="alex").values("name").distinct().count()
return render(req, "index.html", {"book_list": book_list})
 <>Django的queryset是惰性的

      Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。 <>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
为了验证这些,需要在settings里加入 LOGGING(验证方式)
obj=models.Book.objects.filter(id=3)
# for i in obj:
# print(i) # if obj:
# print("ok") <>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只会打印一次 <>
简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
数据!为了避免这个,可以用exists()方法来检查是否有数据: obj = Book.objects.filter(id=4)
# exists()的检查可以避免数据放入queryset的cache。
if obj.exists():
print("hello world!") <>当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,可能
会造成额外的数据库查询。

QuerySet的特性

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

聚合查询和分组查询aggregate(*args,**kwargs)

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

F查询和Q查询

 python manage.py makemigrations
python manage.py migrate

创建表

 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加上日志记录 

注:若创建表失败,请看:https://www.cnblogs.com/chenyanbin/p/10628646.html

七 admin的配置

  admin是Django强大功能之一,它能从数据库中读取数据,呈现在页面中,进行管理。默认情况下,它的功能已经非常强大,如果你不需要复杂的功能,它已经够用了,但是有时候,一些特殊的功能还需要定制,比如搜索功能。

 在setting.py中修改以下选项

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

修改页面字

 1、register
admin.site.register(Book,MyAdmin) 2、register的装饰器
@admin.register(Book)

注册medel类到admin的两种方式

创建Django账号

登陆admin

操作admin

一些常用的设置技巧

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

参考文献:http://www.admin10000.com/document/2220.html

Django练习百度云盘:

链接:https://pan.baidu.com/s/1MYWFUt1W_o7gC7mz_2veuQ
提取码:yz6a

Python 小试牛刀,Django详细解读,让你更快的掌握它!!!的更多相关文章

  1. Python 3.12 目标:还可以更快!

    按照发布计划,Python 3.11.0 将于 2022 年 10 月 24 日发布. 据测试,3.11 相比于 3.10,将会有 10-60% 的性能提升,这个成果主要归功于"Faster ...

  2. 让Python代码更快运行的 5 种方法

    不论什么语言,我们都需要注意性能优化问题,提高执行效率.选择了脚本语言就要忍受其速度,这句话在某种程度上说明了Python作为脚本语言的不足之处,那就是执行效率和性能不够亮.尽管Python从未如C和 ...

  3. 【Python】【Web.py】详细解读Python的web.py框架下的application.py模块

    详细解读Python的web.py框架下的application.py模块   这篇文章主要介绍了Python的web.py框架下的application.py模块,作者深入分析了web.py的源码, ...

  4. Windows server iis部署Django详细操作

    教程基于Windows server2012+Python3.6+IIS之上部署django的,同样适用于server2012之上的版本服务器和windows7以上的windows操作系统. 文章来自 ...

  5. MemCache超详细解读

    MemCache是什么 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高 ...

  6. [Python] 利用Django进行Web开发系列(一)

    1 写在前面 在没有接触互联网这个行业的时候,我就一直很好奇网站是怎么构建的.现在虽然从事互联网相关的工作,但是也一直没有接触过Web开发之类的东西,但是兴趣终归还是要有的,而且是需要自己动手去实践的 ...

  7. [Python] 利用Django进行Web开发系列(二)

    1 编写第一个静态页面——Hello world页面 在上一篇博客<[Python] 利用Django进行Web开发系列(一)>中,我们创建了自己的目录mysite. Step1:创建视图 ...

  8. MemCache超详细解读 图

    http://www.cnblogs.com/xrq730/p/4948707.html   MemCache是什么 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于 ...

  9. rpm软件包管理的详细解读

    CentOS系统上使用rpm命令管理程序包:安装.卸载.升级.查询.校验.数据库维护 1.基本安装 rpm -ivh PackageFile 2.rpm选项 rpm -ivh --test Packa ...

随机推荐

  1. idea配github

    下面步骤的三个前提条件:安装git 安装idea 注册github账号 步骤一.绑定我的github账号与我的计算机 绑定我的github账号与我的计算机之后,便能很方便地上传或者更新我的代码,这需要 ...

  2. MYSQL 主从复制,读写分离(8)

    Mysql 数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据文件,而是通过binlog日志复制到需要同步的服务器上. 一 主从复制的原理实现 原理图解说: 数据库更改 生成数据 ...

  3. vue 对列表数组删除和增加

    很重要,一定要好好研究 https://cn.vuejs.org/v2/guide/list.html#%E6%9B%BF%E6%8D%A2%E6%95%B0%E7%BB%84

  4. 任务型对话(一)—— NLU(意识识别和槽值填充)

    1,概述 任务型对话系统越来越多的被应用到实际的场景中,例如siri,阿里小密这类的产品.通常任务型对话系统都是基于pipline的方式实现的,具体的流程图如下: 整个pipline由五个模块组成:语 ...

  5. 一道编程题: 在1~n之间选择若干个数,使其和为m

    这是一道很明显的动态规划的题目. 递推公式为 用sum(n, m)表示所有可能的1~n之间存在的和为m的组合 那么 sum(n,m) = sum(n-1, m) | sum(n-1, m-n) 直接上 ...

  6. .NET Core 必备安全措施

    .NET Core大大简化了.NET应用程序的开发.它的自动配置和启动依赖大大减少了开始一个应用所需的代码和配置量,本文目的是介绍如何创建更安全的.NET Core应用程序. 1.在生产中使用HTTP ...

  7. MySQL学习(三)主备分库分表和恢复数据 --- 2019年2月

    1.MySQL主备切换 readonly 设置对超级(super)权限是无效的,而用于同步更新的线程,就拥有超级权限. 建议在做主备数据库的时候,将备用数据库设置为只读.(反向用readonly来判断 ...

  8. 5. VIM 系列 - 文件管理

    目录 目录树 文件检索 ctrlp.vim fzf.vim 目录树 安装 nerdtree.vim 插件 Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeTo ...

  9. 【TCP协议】(1)---TCP协议详解

    TCP协议 本文内容如下:      1)TCP协议概念      2)TCP头部结构和字段介绍      3)TCP流量控制            滑动窗口      4)TCP拥塞控制      ...

  10. 利用Bootstrap Paginator插件和KnockoutJS完成分页功能

    在最近一个项目中,需要结合一堆条件查询并对查询的结果数据完成一个简单分页功能,可是做着做着,自己的思路越来越模糊,做到心态崩溃!!! 哈哈,特此花点时间重新总结,并从最简单的分页,然后向多条件查询分页 ...