Django基础总结全
Django 基础知识 |
Django入门知识 |
Conquering English is not different from conquering a great mountain,both of them requier determination stick and perseverance. ---------小尚不浪 |
目录
第一章 认识django
1.1
第二章 URL视图函数详解
1.ur2详解:
URL是Uniform Resource Locator的简写,统一资源定位符,
一个URL由以下几部分组成:
***
python
scheme://host:port/path/?query_string=xxx #anchor
***
* scheme:代表的是访问的协议,一般为http或者https以及ftp等。
* host:主机名,域名,比如www.baidu.com。
* port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。
* path:查找路径。比如:www.baidu.com/trending/now,后面的trending/now就是path。
* query-string:查询字符串,比如:www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。
* anchor:锚点,后台一般不用管,前端用来做页面定位的。
2 #运行项目:
1.通过pycharm的方式:文件->新建项目->选择django。然后指定项目所在的路径,
以及Python解释器,再点击Create就可以创建项目了。
2. pycharm:直接点击右上角的綠色三角箭头按钮就可以了。
注意:用pycharm运行项目,要避免一个项目运行多次。
在项目配置中,把“只用单一实例”那个选项勾选上,避免同时运行多个项目。
3 #让同局域网中的其他电脑访向本机的项目:
1.在pycharm,右上角->项目配置->host。改成"0.0.0.0"。
2.在"settings.py"文件中,配置"ALLOWED_HOSTS",填入ip地址,或'*'(所有IP均可访问)
***
ALLOWED_HOSTS =["161.171.0.121"]
ALLOWED_HOSTS =["*"]
***
注意:要关闭自己电脑的防火墙才行。|
4 #项目结构分析:
1."manage. py":以后和项目交互基本上都是基于这个文件。一般都是在终端输入python manage.py [子命令]。
2."settings.py":保存项目所有的配置信息。
3."urls.py":用来做url与视图函数映射的,以后来了请求就会从这个文件中找到匹配的视图函数。
4."wsgi.py":专门用来做部署的。不需要修改。
5#django的项目app:
按照功能或者模块进行分层,分成一个个app。所有和某个模块相关的视图都写在对应的app的views.py中,并且模型和其他的也是类似。
然后django已经提供了一个比较方便创建app的命令叫做"python manage.py startapp + [app的名称]"。
6# DEBUG模式:
1.如果开启了DEBUG模式,那么以后我们修改了Django项目的代码,然后按下ctrl+s,那么Django就会自动的给我们重启项目,不需要手动重启。
2.如果开启了DEBUG模式,那么以后Django项目中的代码出现bug了,那么在浏览pi器中和控制台会打印出错信息。
3.在生产环境中,禁止开启DEBUG模式,不然有很大的安全隐患。
4.如果将DEBUG设置为False,那么必须要设置ALLOWED_HOSTS.
#t ALLOWED_HOSTS:
这个变量是用来设置以后别人只能通过这个变量中的Ip地址或者城名来进往访问。|
7# 视图函数:
1.视图函数的第一个参数必须是request。
2.视图函数的返回值必须是' django.http.response.HttpResponseBase '的子类的对象。
8# url映射补充:
1.去urls.py文件中寻找映射,是因为在"settings.py"文件中配置了"ROOT_URLCONF"为"urls.py",所有django会去"urls.py"中寻找。
2.在"urls.py"中我们所有的映射,都应该放在"urlpatterns"这个变量中。
3.所有的映射不是随便写的,而是使用"path"函数或者是"re_path"函数进行包装的。
9# ur1传参数给视图函数:
1.采用在url中使用变量的方式:在path的第一个参数中,使用“<参数名>”的方式可以传递参数。然后在视图函数中也要写一个参数,
视图函数中的参数必须和url中的参数名称保持一致,不然就找不到这个参数。另外,url中可以传递多个参数。
2.采用查询字符串的方式:在url中,不需要单独的匹配查询字符串的部分。只需要在视
图函数中使用'request.GET.get("参数名称")'的方式来获取。示例代码如下:
***
python
def author_detail(request):
author_id =request.GET['id^]
text='作者的id是:%s' % author_id
return HttpResponse(text)
***
因为查询字符串使用的是“GET”请求,所以我们通过"request.GET.get('')"来获取参数。并且因为"GET"是一个类似于字典的据类型,
所有获取值的方式都是一样的。
10# 内置url参数的转换器:
from django.urls import converters(在urls中光标移至converters按下Ctrl+b即可查看显示所有的转换器及其类型)
1. str:除了斜杠'/'以外所有的字符都是可以的。
2. int:只有是一个或者多个的阿拉伯数字。
3. path:所有的字符都是满足的。
4. uuid:只有满足"uuid.uuid4()"这个函数返回的字符串的格式。
5. slug:英文中的模杆或者英文字符或者阿拉伯数字或者下划线才满足。
11# urls分层模块化:
如果项目变得越来越大。那么url会变得越来越多。如果都放在主"urls.py"文件中,那么将不太好管理。
在app中新建一个urls.py文件用来存储所有和这个app相关的子url。
注意:
1.应该使用"include"函数包含子"urls.py",并且这个"urls.py"的路径是相对于项目的路径。
示例代码如下:
***
python
urlpatterns=[
path('admin/', admin.site.urls),
path('book', include('book.urls')),
]
***
2.在"app"的"urls.py"中,所有的ur1匹配要放在一个叫做"urlpatterns:"的变量中,否则找不到。
3."ur1"是会根据主"urls.py"和app中的"urls.py"进行拼接的,因此注意不要多加斜杠。
12# url命名:
1.为什么需要ur1命名?
因为url是经常变化的。如果在代码中写死可能会经常改代码。给url取个名字,以后使用url的时候就使用他的名字进行反转就可以了,
就不需要写死url了。
2.如何给一个ur1指定名称?
在"path"函数中,传递一个"name"参数就可以指定。示例代码如下:
**python
urlpatterns =[
path("",views.index,name="index"),
path("login/',views.login,name='login')
]
#应用命名空间:
在多个app之间,有可能产生同名的url。这时候为了避免反转url的时候产生混淆,可以使用应用命名空间,来做区分。
只要在“app"的"urls.py"中定义一个叫做"app_name"的变量,来指定这个应用的命名空间即可。
***python
app_name='front'
urlpatterns=[
path('',views.index,name='index'),
path('login/',views.login,name='login')
]
13#应用(app)命名空间和实例命名空间:
一个app,可以创建多个实例。可以使用多个url映射同一个app。所以这就会产生一个问题。以后在做反转的时候,
如果使用应用命名空间,就混淆了。我们可以使用实例命名空间。
只要在"include"函数中传递一个"namespace"变量即可。示例代码如下:
***python
urlpatterns = [
path('',include('front.urls')),
#同一app下有两个实例
path('cms1/',include('cms.urls',namespace='cms1')),
path('cms2/',include('cms.urls',namespace='cms2')),
]
在做反转的时候,可根据实例命名空间来指定具体的url。
***python
def index(request):
username=request.GET.get("username")
if username:
return HttpResponse('cms首页')
else:
current_namespace=request.resolver_match.namespace
return redirect(reverse("%s:login"%current_namespace))
14# include函数的用法:
1. include(module,namespace=None):
* module:子url的摸块字符串。
*namespace:实例命名空间。如果指定实例命名空间,那么
前提必须要先指定应用命名空间。在子"urls.py"中添加"app_name"变量。
2. include((pattern_list, app_namespace), namespace=None):"include"函数的第一
个参数既可以为一个字符串,也可以为一个元组,如果是元组,那么元组的第一个参数是
子"urls.py"模块的字符串,元组的第二个参数是应用命名空间。应用命名空间既可以在子
"urls.py"中通过"app_name"指定,也可以在"include"函数中指定。
3. include(pattern_list):'pattern_list'是一个列表。这个列表中装的是"path"或者"
re path"函数。实例代码如下:
***python
path('movie/',include([
path('',views.movie),
path('list/',views.movie_list),
]))
15# re_path函数
1.re_path和path的作用都是一样的。只不过"re_path"是在写url的时候可以用正则表达式,功能更加强大。
2.写正则表达式都推荐使用原生字符串。也就是以'r'开头的字符串。
3.在正则表达式中定义变量,需要使用圈括号括起来。这个参数是有名字的,那么需要使用"?P<参数的名字>"。然后在后面添加正则表达式的规则。
***python
from django.urls import re_path
from.import views
urlpatterns =[
#r"":代表的是原声字符串
re_path(r'^$',views.book),
#book/list/<year>/
re_path(r"^list/(?P<year>\d{4})/$",views.book_list),
re_path(r"^list/(?P<month>\d{2})/$",views.book_list_month)
]
16# reverse函数
1.在反转url的时候,需添加参数,可以传递'kwargs'参数到'reverse'函数中。示例代码如下:
***python
detail_url=reverse('detail',kwargs={"article_id":1,'page':2})
***
2.如果想添加查询字符串的参数,则必须手动进行拼接,示例:
***python
login_url=reverse('login')+"?next=/"
***
17# 自定义url转换器按照以下五个步骤来走就可以了:
1.定义一个类,直接继承自object就可以了。
2.在类中定义一个属性regex,这个属性是用来限制ur1转换器规则的正则表达式。
3.实现to_python(self,value)方法,这个方法是将url中的值转换一下,然后传给视图函数的。
4.实现to_url(self,value)方法,这个方法是在做ur1反转的时候,将传进来的参数转换后拼接成一个正确的url。
5.将定义好的转换器,使用"django.url3.converters.register_converter"方法注册到django中。
示例代码如下:
***python
from django.urls import register_converter
class categoryConverter(object):
regex = r'\w+|(\w+\+\w+)+'
def to_python(self, value):
# python+django+flask
result = value.split("+")
# {'python','django','flast'}
return result
def to_url(self, value):
# value:{'python','django','flask'}
# python+django+flask
if isinstance(value, list):
result = "+".join(value)
return result
else:
raise RuntimeError("转换参数的时候.必须为分类列表!")
register_converter(categoryConverter,'cate')
18# URL映射的时候指定默认参数:
可以指定默认参数,当访问网页时,因没传递参数,默认匹配到第一个,在page函数中,可以指定传递第几个参数。
示例代码如下:
***python views函数
book_list=['三国演义','水浒传','西游记','红楼梦']
def books(request,page=0):
return HttpResponse(book_list[page])
#url函数中
urlpatterns=[
path('',views.books),
path('page/<int:page>/',views.books)
]
第三章模板
1# DTL与普通的HTML文件的区别:
DTL模板是一种带有特殊语法的HTML文件,这个HTMHL文件可以被Django编译,可以传进参数进去,实现数据动态化。
在编译完成后,生成一个普通的HTML文件,然后发送给客户端。
#渲染模板:
渲染模板有多种方式。以下两种常用的方式。
1)render_to_string:找到模板,然后将模板编译后渲染成Python的字符串格式。最后再通过HttpResponse类
包装成一个HttpResponse对象返回回去。示例代码如下:
***python
from django.shortcuts import render
from django.template.loader import render_to_string
from django.http import HttpResponse
def index(request):
html=render_to_string("index.html")
return HttpResponse(html)
***
2) 直接将模板渲染成字符串和包装成HttpResponse对象一步到位。
from django.shortcuts import render
def index(request):
return render(request,'index.html')
2 #模板变量
1.在模版中使用变量,需要将变量放到'{{变量}}'中。
2.如果想要访问对象的属性,那么可以通过'对象.属性名'来进行访问。
***python
class Person(object):
def __init__(self,username):
self.username=username
context={
'person':p
}
***
以后想要访问'person'的'username',那么就是通过'person.username'来访问。
3.如果想要访问一个字典的key对应的value,那么只能通过'字典.key'的方式进行访问。
***python
context={
'person':{
'username':'zhiliao',
}
}
以后在模板中访问'username'。就是以下代码'person.username'。
4.因为在访问字典的'key'时候也是使用'点'来访问,因此不能在字典中定义字典本身就有的属性名当作'key',
否则字典的那个属性将编程字典中的key了。
***python
context={
'person':{
'username':'zhiliao',
'keys':'abc'
}
}
***
以上因为将'keys'作为'person'这个字典的'key'了。因此以后在模版中访问'person.keys'的时候,
返回的不是这个字典的所有key,而是对应的值。
5.如果想要访问列表或者元组,通过'点.'的方式进行访问,不能通过'中括号[]'的形式进行访问。这一点和python中是不一样的。
***python
{{ persons.0}}
3 #常用模板标签
1.1 for...in...笔记:
'for...in...'标签:'for...in...'类似于Python中的'for...in...'.可以遍历列表、元组、字符串、字典等一切可以遍历的对象。
***python
{% for person in persons %}
<li>{{ person.name }}</li>
{% endfor %}
1.2如果想要反向遍历,那么在遍历的时候就在'persons'后面加上一个'reversed'。
1.3遍历字典的时候,需要使用'items'、'keys'和'values'等方法。在DTL中,执行一个方法不能使用圆括号的形式。
***python
{% for key,value in person.items %}
<li>{{ key }}/{{ value }}}</li>
{% endfor %}
2.在‘for’循环中,DTL提供了一些变量可供使用。这些变量如下:
2.1'forloop.counter':当前循环的下标,以1作为起始值。
2.2'forloop.counter0':当前循环的下标,以0作为起始值。
2.3'forloop.revcounter':反向下标元素。'forloop.revcountero':最后一个元素下标是0开始。
2.4'forloop.first':是否是第一次遍历。
2.5'forloop.last':是否是最后一次遍历。
2.6模板中的for...in...没有continue和break语句,这一点和Python中有很大不同。
3.'for...in...empty'标签:
这个标签使用跟'for...in...'是一样的,只不过是在遍历的对象如果没有元素的情况下,会执行'empty'中的内容。
***python
{% for comment in comments %}
<li>{{comment}}</li>
{% empty %}
<li>没有任何评论</li>
{% endfor %}
4.with标签
4.1在模板中,想要定义变量,可通过'with'语句来实现。
4.2'with'语句有两种使用方式,第一种是'with xx=xxx'的形式,第二种是'with xx as xxx'的形式。
5. url标签
5.1'url'标签:在模版中,用'a'标签中定义'href'属性。
***python
<li><a href="/">首页</a></li>
5.2如果'url'反转的时候需要传递参数,那么可以在后面传递。但是参数分位置参数和关键字参数不能同时使用。
***python
# path部分
path('detail/<book_id>/',views.book_detail,name='detail')
# url反转,使用位置参数
<a href="{% url 'book:detail' 1 %}">图书详情页面</a>
# url反转,使用关键字参数
<a href="{% url 'book:detail' book_id=1 %}">图书详情页面</a>
5.3如果想要在使用'url'标签反转的时候要传递查询字符串的参数,那么必须要手动在在后面添加。
***python
<a href="{% url 'login' %}?next=/">登录</a>
5.4如果需要传递多个参数,那么通过空格的方式进行分隔。
***python
<a href="{% url 'detail' book_id='1' category='1' %}">最火的一篇文章</a>
6. spaceless 标签:只移除html中的空白字符,不会移除标签与文本之间的空白字符。包括空格、Tab键、换行等。
7. autoescape自动转义
7.1 DTL中默认开启自动转义,会将特殊字符进行转义。如将'<'转义成'<'等。
7.2 如果变量确实是可信任的,可用'autoescape'标签来关掉自动转义。
***python
{% autoescape off %}
{{ info }}
{% endautoescape %}
8. verbatim 标签:默认在'DTL'模板中是会去解析那些特殊字符的。'{% 和 %}'以及'{{'等。
***python
{% verbatim %}
{{if}}Still alive.{{/if}}
{% endverbatim %}
4 #常用过滤器(指函数)
为什么需要过滤器?
在DTL中,不支持函数的调用形式"()",不能传递参数。而过滤器就是一个函数,可以对需要处理的参数进行处理并
可额外接收一个参数(最多只能有两个参数)。
1.add过滤器:将传进来的参数添加到原来值上面,将'值'和'参数'转换成整形相加。如果转换失败,进行拼接。
***python
def add_view(request):
context={
'value1':['1','2','3'],
'value2':['4','5','6']
}#输出值为['1', '2', '3', '4', '5', '6']
return render(request,'add.html',context=context)
{{ value1|add:value2 }}
2.cut过滤器:移除值中所有指定字符串。
***python
{{ "hello world"|cut:" " }}#输出值为helloworld
3.date过滤器:
***python
数据 context={
'today': datetime.now
}
模板 {{ today|date:"Y/m/d H:i:s" }}#将会输出:'2021/12/09 22:54:06'
还有更多时间格式化的方式。见下表。
|Y|四位数字的年份|2018 |
|m|两位数字的月份| 01-12 | |n|月份,1-9前面没有0前缀| 1-12 |
|d|两位数字的天| 01-31 | |j|天,但1-9前面没有0前缀| 1-31 |
|g|小时,12小时格式的,1-9前面没有0前缀| 1-12 |
|h|小时,12小时格式的,1-9前面有e前缀| 01-12 |
|G|小时,24小时格式的,1-9前面没有0前缀| 1-23 |
|H|小时,24小时格式的,1-9前面有e前缀| 01-23 |
|i|分钟,1-9前面有0前缀| 00-59 |
|s|秒,1-9前面有0前缀| 00-59 |
4.default:如果被评估为False。比如{}、""、None、[]等在这些if判断中为False的值,都会使用default过滤器提供默认值。
***python
{{ value|default:"我是默认值" }}
default_if_none:只有在值为'None'时才会输出提供的默认值。
5.first和last
first:返回列表/元组字符串/中的第一个元素。 {{ value|first }}
last:返回列表/元组字符串/中的最后第一个元素。 {{ value|last }}
6.floatformat
使用四舍五入的方式格式化一个浮点型。如果在过滤器没有传递任何参数,那么只保留一位小数,可以传递一个参数,标识具体保留几个小数。
***python
{{ value|floatformat:2 }} #保留两位小数
7.striptags:删除字符串所有的html标签。
{{ value|striptags }} #如果value是'<script>alert("hello world")</script>'则输出'alert("hello world")'
8.truncatechars如果给定字符超出过滤器指定长度。那么会进行切割,拼接为三个点来作为省略号。
{{ value|truncatechars:"5" }} #如果value值'为北京欢迎您~'呢么输出结果是'北京欢迎...'三点为第五个字符。
truncatechars_html:不会省略标签。
5 #自定义过滤器
1.首先在某个app中,创建一个python包,叫做'templatetags',这个包的名字必须为'templatetags',不然就找不到。
2.在这个'templatetags'包下面,创建一个python文件用来存储过滤器。
3.在新建的python文件中,定义过滤器(也就是函数),这个函数的第一个参数永远是被过滤的那个值,并且如果在使用过滤器的时候传递参数,
那么还可以定义另外一个参数。但是过滤器最多只能有2个参数。
4.在写完过滤器(函数)后,要使用'django.template.Library.filter'进行注册。
.5把这个过滤器所在的这个app添加到'settings.INSTALLED_APS'中,不然Django也找不到这个过滤器。
6.在模板中使用'load'标签加载过滤器所在的python包。#{% load my_filter %}
7.'django.template.Library.filter'还可以当作装饰器来使用。如果'filter'函数没有传递任何参数,那么将会使用这个函数的名字来作为过滤器的
名字。当然如果你不想使用函数的名字来作为过滤器的名字,也可以传递一个'name'参数。
***python
@register.filter('my_greet')
def greet(value,word):
return value + word
6 #模板结构优化:
1.include:有些代码是重复使用的,可单独抽取出来,哪里需要直接使用'include'出来。
2.如果想要在'include'子模板传递参数,可使用'with xxx=xxx'的形式。
***python
{% include 'header.html' with username='小尚不浪' %}
3.模板继承:在父模板中定义好一些变量和方法,然后在子类中实现,因为子模板肯定有自己不同的代码,因此可以在父模板中定义一个'block'接口。
4.base模板:定义好一个'base.html',然后定义好两个'block'接口,让子模板根据具体来实现,子模板通过'extends'标签来实现。
***html
{% extends 'base.html' %}
{% block content %}
<p>这是首页的代码</p>
{{ block.super }}
{% endblock %}
5.需要注意的是:extends标签必须放在模版的第一行。
子模板中的代码必须放在block中,否则将不会被渲染。
如果在某个'block'中需要使用父模版的内容,那么可以使用'{{block.super}}'来继承。
7 #加载静态文件
在DTL中,使用'static'标签来加载静态文件。要使用'static'标签,首先需要'{% load static %}'。
1.首先确保'django.contrib.staticfiles'已经添加到'settings.INSTALLED_APPS'中。
2.确保在"settings.py"中设置了"STATIC_URL"。
3.在已经安装了的'app'下创建一个文件夹叫做'static',然后再在这个'static'文件夹下创建一个当前'app'的名字的文件夹,
再把静态文件放到这个文件夹下。例如你的'app'叫做'book',有一个静态文件叫做'zhiliao.jpg',那么路径为'book/static/book/
zhiliao.jpg'。直接把静态文件放在'static'文件夹下,那么在模版加载静态文件的时候就是使用'zhiliao.jpg',如果在多个'app'
之间有同名的静态文件,这时候可能就会产生混淆。而在'static'文件夹下加了一个同名'app'文件夹,在模版中加载的时候就是使用'app/zhiliao.jpg',
这样就可以避免产生混淆。)
4.如果有一些静态文件是不和任何'app'挂钩的。那么可以在"settings.py"中添加"STATICFILES_DIRS",以后'DTL'就会在这个列表的路径中查找静态文件。
例如可设置为:
***python
STATICFILES_DIRS =[
os.path.join(BASE_DIR,"static")
]
5.在模版中使用'load'标签加载'static'标签。比如要加载在项目的'static'文件夹下的'style.css'的文件。那么示例代码如下:
***html
{% load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">
6.如果不想每次在模版中加z载静态文件都使用'load'加载'static'标签,那么可以在"settings.py"中的"TEMPLATES/OPTIONS"添加
'builtins':['django.templatetags.static'],这样以后在模版中就可以直接使用'static'标签,而不用手动的'load'了。
第四章 数据库
1 #Python DB API下规范下cursor对象常用接口:
1.description :如果 cursor 执行了查询的 sql 代码,那么读取 cursor.description 属性的时候,将返回一个列表,这个列表
中装的是元组,元组中装的分别是(name,type_code,display_size,internal_size,precision,scale,mull_ok),其中 name
代表的是查找出来的数据的字段名称。
2.rowcount :代表的是在执行了 sql 语句后受影响的行数。
3.close:关闭游标。关闭游标以后就再也不能使用了,否则会抛出异常。
4. execute(sql[,parameters]):执行某个 sql 语句。如果在执行 sql 语句的时候还需要传递参数,那么可以传给 parameters 参
数。示例代码如下:
cursor.execute("select * from article where id=%s",(1,))
5.fetchone :在执行了查询操作以后,获取第一条数据。
6.fetchmany(size):在执行查询操作以后,获取多条数据。具体是多少条要看传的 size 参数。如果不传 size 参数,那么默认是获取第一条数据。
7.fetchall :获取所有满足 sq1 语句的数据。
*{
margin: 0; #设置浏览器默认外边距
padding: 0; #内边距
}
.nav{
background: #3a3a3a;#背景颜色
height: 65px; #字体高度
overflow: hidden; #清除浮动,把字体设置在同一行
}
.nav li{
float: left; #左浮动
list-style: none; #列表风格
margin: 0 20px; 标签间距
line-height: 65px;# 使li标签处于居中
}
.nav li a{
color: #fff; #字体颜色
text-decoration: none; #下划线
}
.nav li a:hover{
color: lightblue; #将鼠标放置标签上的颜色
}
2 #ORM模型介绍:
随着项目越来越大,采用写原生SQL的方式在代码中会出现大量的SQL语句:
1.SQL语句重复利用率不高,越复杂的SQL语句条件越多,代码越长。会出现很多相近的SQL语句。
2.很多SQL语句是在业务逻辑中拼出来的,如果有数据库需要更改,就要去修改这些逻辑,这会很容易漏掉对某些SQL语句的修改。
3.写SQL时容易忽略web安全问题,给未来造成隐患。SQL注入。
4.ORM,全称Object Relational Mapping,中文叫做对象关系映射,通过ORM我们可以通过类的方式去操作数据库,而不用再写原生的SOL语句。
通过把表映射成类,把行作实例,把字设作为尾性,ORM在执行对象操作的时候最终还是会把对应的操作转换为数据库原生语句。使用ORM有许多优点:
4.1易用性:使用ORM做数据库的开发可以有效的减少重复SQL语句的概率,写出来的模型也更加直观、清晰。
4.2性能损耗小:ORM转换成底层数据库操作指令确实会有一些开销。但从实际的情况来看,这种性能损耗很少(不足5%),只要
不是对性能有严苛的要求,综合考虑开发效率、代码的阅读性,带来的好处要远远大于性能损耗,而且项目越大作用越明显。
4.3设计灵活:可以轻松的写出复杂的查询。
5.可移植性:Django封装了底尾的数据库实现,支持多个关系龄据库引整,包括流行的MySOL、PostgresOL 和 SQLite 。
OOP(模型) ORM(库) RDB(数据库)
3 #映射模型到数据库中:
将 ORM 模型映射到数据库中。
1.在 settings.py 中,配置好 DATABASES ,做好数据库相关的配置。
2.在 app 中的 models.py 中定义好模型,这个模型必须继承自 django.db.models 。
3.将这个 app 添加到 settings.py 的 INSTALLED_APP 中。
4.在命令行终端,进入到项目所在的路径,然后执行命令 python manage.py makemigrations 来生成迁移脚本文件。
5.同样在命令行中,执行命令 python manage.py migrate 来将迁移脚本文件映射到数据库中。
4 #ORM对数据库的基本操作:
1.添加数据:
先用ORM创建一个对象,再用save保存就可以了。
**python
book = Book(name=‘西游记',author='吴承恩',price=100)
book.save()
2.查找数据:
所有的查找工作都是使用模型上的'objects'属性来完成的。当然也可以自定义查询对象。
2.1根据主键进行查找:使用主键进行查找。可以使用'objects.get(pk=xx)'方法。
**python
book = Book.objects.get(pk=1)
2.2根据字段进行查找:可以使用'objects.filter(name=xx)'方法进行查找。
**python
books = Book.objects.filter(name='三国演义').first()
使用'filter'方法返回来的是一个'QuerySet'对象。使用这个对象的'first'方法来获取第一个值。
3.删除数据:
首先查找到对应的数据模型。然后再执行这个模型的'delete'方法即可删除。
**python
book = Book.objects.get(pk=1)
book.delete()
4.修改数据:
首先查找到对应的数据模型。然后修改这个模型上的属性的值。再执行'save'方法即可修改完成。
**python
book=Book.objects.get(pk=1)
book.price=200
book.save()
5 #ORM常用Field详解:
1.1 django.utils.timezone.now方法:
会根据'settings.py'中是否设置了'USE_TZ=True':获取当前的时间。设置了可获取一个'aware'类型的'UTC'时间。
如果没有设置,那么就会获取一个'navie'类型的时间。
1.2 django.utils.timezone.localtime方法:
会根据'setting.py'中的'TIME_ZONE'来将一个'aware'类型的时间转换为'TIME_Z0NE'指定时区的时间。
2.DateField 日期类型:
在Python中是'datetime.date'类型,可以记录年月日。在映射到数据库中也是'date'类型。使用这个'Field'可以传递以下几个参数:
2.1'auto_now':在每次这个数据保存的时候,都使用当前的时间。
2.2'auto_now_add':在每次数据第一次被添加进去的时候,都使用当前的时间。
3.DateTimeField 日期时间类型:
不仅可以存储日期,还可以存储时间。映射到数据库中是'datetime'类型。这个'Field'也可以使用'auto_now'和'auto_now_add'两个属性。
4.TimeField 时间类型:
在数据库中是'time'类型。在Python中是'datetime.time'类型。
5.EmailField:
类似于'CharField'。在数据库底层也是一个“varchar'类型。最大长度是254个字符。
6.FileField:用来存储文件的。
7.ImageField:用来存储图片文件的。
8.FloatField:浮点类型。映射到数据库中是'float'类型。
9.IntegerField:整形。值的区间是'-2147483648—2147483647'。
10.BigIntegerField:大整形。值的区间是'-9223372036854775898—-9223372036854775807'。
11.PositiveSame11IntegerField:正整形。值的区间是'θ—2147483647'。
12.TextField:大量的文本类型。映射到数据库中是longtext类型。
13.UUIDField:只能存储'uuid'格式的字符串。'uuid'是一个32位的全球唯一的字符串,一般用来作为主键。
14.URLField:类似于'CharField',只不过只能用来存储'ur1'格式的字符串。并且默认的'max_length'是200。
6. #Field的常用参数:
1.null:如果将表设置为True,django将会在映射表指定为空。
2.blank:标识这个字段在表单验证时是否为空。默认值是False。null是一个纯数据库级别的。blank是表单验证级别的。
3.db.column:可设置这个字段数据库的名字
如:db.column='author_age'
4.default:更改该字段的默认值。
5.primary_key:是否为主键。
6.unique:在表中这个字段的值是否唯一。一般是手机号或者邮箱。
7. #Meta类中常见配置:
1.db_table:这个模型映射到数据库中的表名。如果没指定,映射时会使用默认表名。
2.ordering:设置在提取数据的排序方式。
8. #外键和表关系:
1.class Foreignkey:这个参数是引用模型的。
2.to,on_delete,**options:这个参数是使用外键引用的模型数据被删除了,如CASCADE、SET_NULL。
**
class User(models.Model):
username=models.CharField(max_length=20)
password=models.CharField(max_length=200)
class Article(models.Model):
title=models.CharField(max_length=100)
content=models.TextField()
author=models.ForeignKey("User",on_delete=models.CASCADE)
3.引用另一个的app的模型,在传递to参数时使用app.model_name进行指定。
如果模型的外键引用的是本身自己的模型,可将to改为self,或者这个模型的名字。
9. #外键删除操作:
如果一个模型使用了外键。可以通过 on_delete 来指定。可以指定的类型:
1.CASCADE :级联操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除。
2.PROTECT :受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。
3.SET_NULL :设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。如果设置这个选项,前提是要
指定这个字段可以为空,null=True。
4.SET_DEFAULT :设置默认值。如果外键的那条数据被删除了,那么本条数据上就将这个字段设置为默认值。如果设置这个选项,前
提是要指定这个字段一个默认值。
5.SET():如果外键的那条数据被删除了。那么将会获取 SET 函政中的值来作为这个外键的值。 SET函数可以接收一个可以调用的
对象,如果是可以调用的对象,那么会将这个对象调用后的结果作为值返回回去。
6.DO_NOTHING :不采取任何行为。一切全看数据库级别的约束。
10. #表关系 :表关系都是通过外键进行关联的。三种表关系:一对一、一对多(多对一)、多对多。
一对多:
1.应用场景:比如文章和作者的关系。一个文章只能由一个作者编写,但一个作者可以编写多篇文章。
2.实现方式:一对多或多对一都是通过FroeignKey来实现的。示例如下:
class User(models.Model):
username=models.CharField(max_length=20)
password=models.CharField(max_length=200)
class Article(models.Model):
title=models.ChaeField(max_length=100)
context=models.TextField()
author=models.ForeignKey("frontuser.FrontUSer",on_delete=models.CASCADE)
调用函数,直接输入 default_category可得到函数的内容
例:def default_category():
return Category.objects.get(pk=1)
那么以后给Article对象指定author,示例代码如下:
article=Article(title='shang',content='111')
author=User(username='xiaoshang',password='111')
#通过python manage.py makemigrations和python manage.py migrate保存到数据库中创建模型
author.save()
article.author=authorarticle.save()
如果想要获取某个用户下的所有文章,可通过article_set来实现。示例如下:
category=Category.object.first()
#获取第一个用户写的所有文章
articles=category.article_set.all()
#first():获取第一条文章 filter():获取过滤文章 all():获取所有文章
for article in articles:
print(article)
一对一:
1.在Django中一对一是通过OneToOneField来实现的。'OneToOneField'相当于一个外键,有一个“唯一的约束(unique key)”来实现一对一。
2.若想进行反向引用,可通过引用对象改名字小写形式进行访问。示例代码如下:
***python
class FrontUser(models.Model):
username=models.CharField(max_length200)
class UserExtenbsion(models.Model):
school=models.CharField(max_length=100)
user=models.OneToOneField("FrontUser",on_delete.CASADE)
#通过userextension来访问Userextension对象。
若不想使用默认的属性名字,则可在user后面添加'related_name=extension'参数,则'FrontUser'可通过extension来直接访问'Userextension'对象。
多对多:
1.应用场景:例如标签和文章的关系,一篇文章可以有多个标签,一个标签有多篇文章。
2.实现方式:通过ManyToManyField来实现。示例代码如下:
***python
class Tag(models.Model):
tag.models.CharField(max_length=100)
#可以通过related_name修改访问属性。
class Article(models.Model):
title.models.CharField(max_length=100)
context.models.TextField()
article.models.ManyToMany("Article",related_name='tags')
将文章添加到某个分类时的两种方法:
1.使用'bulk=False' 例如:category.article_set.add(article,bulk=False) #注意add中对于‘多对多’没有bulk属性,不能使用bulk=False来添加文章。
2.在添加'category.article_set.add(article)'之前,先通过article.save()将article保存到数据库中。
实际上是为多对多关系建立了一个中间表article_tag_articles,这个中间表分别定义了两个外键,引用到'article'和'tag'两张表的主键。
11 #查询操作:
1.查询条件:查询操作是数据库中一个非常重要的操作,一般使用filter、exclude、get三种方法。在ORM模型上使用field+_+condition的格式。
(1)操作数据库可以不通过Navicat Premium,直接使用pychar来连接并使用。
点击最右边database(数据库),打开数据源中的MySQL,进入配置MySQL页面,输入对应的数据库名称、用户名和密码(注:要跟你之前创建数据库的配置来填),
最后再进test验证是否成功。这样就可以继承Navicat Premium里面对应数据库的内容。
(2)打开之前创建的表格,添加内容,按下Crtl+Enter后可将内容保存到数据库中。
exact:
def inde(request):
#在windows操作系统上,mysql的排序规则是(collation),对于所有来说大小写都是不敏感的
#在Linux操作系统上,mysql的排序规则是(collation),对于utf8_bin 来说,大小写敏感。
article=Article.object.filter(id_exact=1) #_exact可以忽略不写
print(article.query)
print(article)
#like和=:大部分情况下是一样的,只有少数部分是代表不同的,
#exact和iexact:本质就是like和=的区别,exact会被翻译为=,iexact会被翻译为like。
article=Article。object.filter(id_iexact=1)
print(article.query)
print(article)
return HttpResponse("success")