django
1、安装
pip install django
2、基本配置
创建django程序
终端命令:django-admin startproject 项目名
IDE创建django项目时,本质上都是执行上述命令
python manage.py runserver 0.0.0.0
python manage.py startapp appname #新建app
python manage.py makemigrations #迁移数据
python manage.py migrate #同步到数据库
python manage.py createsuperuser #创建超级用户
程序目录
django-admin startproject mysite
python manage.py startapp appname #新建app
-mysite
-mysite
settings.py 配置文件
urls.py 路由系统
wsgi.py web服务网关
-app01
admin.py django自带后台管理
models.py 写类,根据类创建数据库数据
tests.py 单元测试
view.py 业务处理
-templates 存放页面,图片等
index.html
-static 存放静态文件CSS、JS等 需要在settings中设置
-css
-js
manage.py 管理和启动文件
db.sqlte3 数据库
配置文件 setting.py
数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 如下设置放置的与project同名的配置的 __init__.py文件中
import pymysql
pymysql.install_as_MySQLdb()
模版路径
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
静态文件
3、静态文件
在文件最后加入
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'指定文件夹'),
)
路由系统
单一路由对应
url(r'^index$', views.index),
ps:
127.0.0.1:8000/index
基于正则的路由
url(r'^index/(d*)', views.index),
ps:
127.0.0.1:8000/index/0-无穷个数字
index要有足够的位置参数 index(request,id)
url(r'^manage/(?P<name>w*)/(?P<id>d*)', views.manage),
ps:
127.0.0.1:8000/manage/adsa/123
manage中需要对应参数接收 manage(request,name,id)
添加额外的参数
url(r'^manage/(?P<name>w*)', views.manage,{'id':333}),
ps:
manage(request,name,id)
为路由设置别称
url(r'^home', views.home, name='h1'),
url(r'^index/(d*)', views.index, name='h2'),
设置名称之后,可以在不同的地方调用,如:
模板中使用生成URL {% url 'h2' 2012 %}
函数中使用生成URL reverse('h2', args=(2012,)) 路径:django.urls.reverse
Model中使用获取URL 自定义get_absolute_url() 方法
根据app对路由规则进行分类
from django.conf.urls import url,include
url(r'^web/',include('web.urls')),
在web的urls.py 中再设置web后面的URL参数
模版
模版的执行
from django.shortcuts import HttpResponse
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
#HttpResponse() 返回的是字符串
from django import template
t = template.Template('My name is {{ name }}.') #template后面跟的是模版的字符串
c = template.Context({'name': 'Adrian'}) #context用来实现替换模版中的占位符
print t.render(c)
#render()返回的是完整的模版字符串
import datetime
from django import template
import DjangoDemo.settings
now = datetime.datetime.now()
fp = open(settings.BASE_DIR+'/templates/Home/Index.html') #打开模版HTML,获得文件句柄
t = template.Template(fp.read()) #读取模版内容
fp.close()
html = t.render(template.Context({'current_date': now})) #替换占位符
return HttpResponse(html)
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = get_template('current_datetime.html')
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
模版语言
{{ item }}
{% for item in item_list %}
<a>{{ item.0 }}</a>
<a>{{ item.id }}</a>
{% endfor %}
{% if ordered_warranty %}
{% else %}
{% endif %}
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %}
组件:include
{% include "组件.html" %}
pub.html
<div>
<h3>特别漂亮的组件</h3>
<div class="title">标题:{{ name }}</div>
<div class="content">内容:{{ name }}</div>
</div>
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
{% include 'pub.html' %}
{% include 'pub.html' %}
{% include 'pub.html' %}
</body>
</html>
帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
PS:
ajax先服务器提交信息并等待接受
$.ajax({
url: "/submit/", #向哪个url提交数据
type: "POST", #以某种方式发送POST或者GET
data: da, #数据,如果数据中有列表或其他非字符串类型,jquery会对键值做一些处理,可以在后面添加一个属性,traditional:true
{"list":[1,2,3]} 发送到后台就会变成{"list[]":[1,2,3]}
{"list":[1,2,3]},traditional:true 发送到后台:{"list":[1,2,3]}
success: function (data) { #data是从服务器返回的数据
if (data == "false") {
$("#msg").text("不能为空!!!");
}
else {
location.href = data;
}
}
})
服务端发送回来的只能是字符串,render返回的也是字符串,不会实现跳转。这里值得一提的是可以用json来传送字典。
服务器端:
import json
dict={"title":1,"id":2}
return HttpResponse(json.dumps(dict))
浏览器ajax success接收:
Json.parse(data) 将json字符串data转化成dict
Json.stringify(dict) 将dict转化成字符串
request属性
我们定义一个个函数,都至少有一个request。这个参数包含着从浏览器发过来的所有数据。
1、method
request.method:显示的是请求方式是GET还是POST。
2、传入的值
request.GET :显示的是由GET方式传入的参数。也就是通过url的方式或者ajax指定。
request.POST : 显示的是由POST方式传入的参数,有表单form还有ajax等方式。
request.GET.get("键值") 可以获取指定的参数。如果值是列表,那么就用getlist
今日小知识
form的submit和a标签如果有href的话,都有默认跳转,如果我们给他们加了一个click事件,那么等click事件完成,他们还是会执行默认的跳转事件,如何阻止呢,我们可以在click函数中加一句 return false 这样就可以阻止了。
如何获取select下的所有的option标签value:
$("#Newclist option").map(function(){return $(this).val();}).get().join(",");
#Newclist是select标签的ID 。
$().map(function()
{
return $(this).val();
}).get() 这样获取到的是一个列表,可以通过join的方式拼接成一个字符串。
在js中如何判断一个值在不在一个数组里:
可以用indexof:[11,22,33].indexof(22) 存在会返回索引值 不存在会返回-1
XSS攻击
- 慎用 safe和mark_safe
-from django.utils.safestring import mark_safe
- 非要用,一定要过滤关键字
评论等。客户输入的评论不是正常评论。比如<scrip> alert(123) </scrip>
如果直接显示到网页中,则是以代码显示的,每次打开这个页面都会执行一个弹出框。
django自带的对这些进行了处理。如果是非正常字符串,则在网页中他们是以字符串形式显示的。
如果要让他们以原有的形式显示,{{ aaa | safe }} 加上safe
或者传入的时候用mark_safe修改下。
from django.utils.safestring import mark_safe
x="<a href='http://www.baidu.com'>sss</a>"
return render(request,"test.html",{"a":mark_safe(x)})
django自带分页
from django.core.paginator import Paginator,Page
def index(request):
current_page = request.GET.get('page') #获取页码
user_list = models.UserInfo.objects.all() #从数据库中查询数据
paginator = Paginator(user_list,10) #10条数据一组分组
# per_page: 每页显示条目数量
# count: 数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page: page对象
try:
posts = paginator.page(current_page)
except PageNotAnInteger as e:
posts = paginator.page(1)
except EmptyPage as e:
posts = paginator.page(1)
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
return render(request,'index.html',{'posts':posts})
html:
{% for i in posts.object_list %}
{{ i }}
{% endfor %}
自定义分页
def newpage(request):
page=request.GET.get("page")
1 0 -10
2 10-20
start_page=(page-1)*10
end_page=page*10
user_list=models.Userinfo.objects.all()[start_page,end_page]
return render(request,"user.html",{"userlist":user_list})
CSRF
1. CSRF
a. 基本应用
form表单中添加
{% csrf_token %}
b. 全站禁用
# 'django.middleware.csrf.CsrfViewMiddleware',
c. 局部禁用
'django.middleware.csrf.CsrfViewMiddleware',
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def csrf1(request):
if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
d. 局部使用
# 'django.middleware.csrf.CsrfViewMiddleware',
from django.views.decorators.csrf import csrf_exempt,csrf_protect
@csrf_protect
def csrf1(request):
if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
c. 特殊CBV
from django.views import View
from django.utils.decorators import method_decorator
@method_decorator(csrf_protect,name='dispatch')
class Foo(View):
def get(self,request):
pass
def post(self,request):
pass
PS:CBV中添加装饰器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定方法上添加装饰器
# class Foo(View):
#
# @method_decorator(wrapper)
# def get(self,request):
# pass
#
# def post(self,request):
# pass
# 2. 在类上添加
# @method_decorator(wrapper,name='dispatch')
# class Foo(View):
#
# def get(self,request):
# pass
#
# def post(self,request):
# pass
Ajax提交数据时候,携带CSRF:
a. 放置在data中携带
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
data: { "user":user,'csrfmiddlewaretoken': csrf},
success:function(arg){
console.log(arg);
}
})
}
</script>
b. 放在请求头中 cookie和csrf_token 的值是不一样的
<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
function submitForm(){
var token = $.cookie('csrftoken');
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
headers:{'X-CSRFToken': token}, ###
data: { "user":user},
success:function(arg){
console.log(arg);
}
})
}
</script>
COOKIE和SESSION
COOKIE 向服务器发送存在请求头里。服务器发送到浏览器存在响应头里。
a、保存在浏览器端的"键值对",服务端可以向浏览器端写cookie
b、浏览器每次发送请求时,会携带cookie
应用:
a、投票
b、用户登录
登录时,如果用户名和密码正确,可以写
obj=render(request,"index.html")
obj.set_cookie("键","值",max_age=10,path="/") #max_age超时时间,浏览器保存的cookie有效时间。 10秒
#或者expires 他跟的参数是2017年6月21日 11:50:58
#path 指定某个url可以使用当前的cookie path="/index/" /表示所有url都可以用
return obj
obj=set_signed_cookie("键","值",salt="加盐操作")
接收端接收cookie
cook=request.COOKIES.get("上面中的键")
cook=request.get_signed_cookie("键",salt="加盐")
SESSION
a、保存在服务器端的数据(本质是键值对)
b、依赖cookie
c、保持会话(web网站)
好处:敏感信息不会直接给客户端
存放位置
1、数据库中 django默认存放在数据库中
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
2、缓存中
a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
其他同上
3、文件中
a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
其他同上
4、加密的cookie中
a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
5、缓存+数据库
a. 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
查询、设置、删除、修改
# 获取、设置、删除Session中数据
request.session['k1'] #不存在会报错
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']
request.session.delete(request.session.session_key) #删除session
request.session.clear() #删除cookie
# 所有 键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 用户session的随机字符串
request.session.session_key
# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查 用户session的随机字符串 在数据库中是否
request.session.exists("session_key")
# 删除当前用户的所有Session数据
request.session.delete("session_key")
# 设置失效期
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
CBV 和 FBV
CBV url--->类
url(r'^index.html$', views.Login.as_view()),
app01.views
from django.views import View
class Login(View):
'''
get 查
post 创建
put 更新
delete 删除
'''
def dispath(self,request,*args,**kwargs):
obj= super(Login,self).dispatj(request,*args,**kwargs) 继承父类方法
return obj
def get(self,request): 如果是以get方式访问的执行这个函数
return HttpResponse("get")
def post(self,request):如果是以post方式访问的执行这个函数
return HttpResponse("post")
FBV
url(r'^index.html$', views.index),
app01.views
def indes(request):
return Httpresponse("index")
正向操作:
all():返回的是对象
a=models.Userinfo.objects.all() #返回的是一个queryset类型的列表,里面是一个个userinfo.object对象
b=models.Userinfo.objects.all().first() #返回的是all查询结果的第一条userinfo.object对象
for i in a:
print(i.id,i.user)
print(b.id,b.user)
values:返回的是字典
a=models.Userinfo.objects.values("id","user","pawd")
<QuerySet [{'id': 1, 'user': 'egon', 'pawd': '123'},
{'id': 2, 'user': 'alex', 'pawd': '123'},
{'id': 3, 'user': 'alvin', 'pawd': '123'},
{'id': 4, 'user': 'wusir', 'pawd': '123'},
{'id': 5, 'user': 'gao', 'pawd': '123123'},
{'id': 6, 'user': 'sunqi', 'pawd': '123'}]>
b=models.Userinfo_group.objects.values("id","uid__user","gid__gname")
<QuerySet [{'id': 1, 'uid__user': 'egon', 'gid__gname': '主机1'},
{'id': 2, 'uid__user': 'alex', 'gid__gname': '主机1'},
{'id': 3, 'uid__user': 'alvin', 'gid__gname': '主机1'},
{'id': 4, 'uid__user': 'alex', 'gid__gname': '主机2'},
{'id': 5, 'uid__user': 'alvin', 'gid__gname': '主机2'},
{'id': 6, 'uid__user': 'wusir', 'gid__gname': '主机2'},
{'id': 7, 'uid__user': 'egon', 'gid__gname': '主机3'},
{'id': 8, 'uid__user': 'alex', 'gid__gname': '主机3'},
{'id': 9, 'uid__user': 'alvin', 'gid__gname': '主机4'},
{'id': 10, 'uid__user': 'wusir', 'gid__gname': '主机4'}]>
for i in a:
print(i["id"],i["user"],i["pawd"])
for i in b:
print(i["id"],i["uid__user"],i["gid__gname"])
values_list: 返回的是元祖
a=models.Userinfo.objects.values_list("id","user","pawd")
(1, 'egon', '123')
(2, 'alex', '123')
(3, 'alvin', '123')
(4, 'wusir', '123')
(5, 'gao', '123123')
(6, 'sunqi', '123')
b=models.Userinfo_group.objects.values_list("id","uid__user","gid__gname")
(1, 'egon', '主机1')
(2, 'alex', '主机1')
(3, 'alvin', '主机1')
(4, 'alex', '主机2')
(5, 'alvin', '主机2')
(6, 'wusir', '主机2')
(7, 'egon', '主机3')
(8, 'alex', '主机3')
(9, 'alvin', '主机4')
(10, 'wusir', '主机4')
for i in a:
print(i[0],i[1],i[2])
for i in b:
print(i[0],i[1],i[2])
反向操作 userinfo中引用了usergroup的ID外键
小写的表名_set
obj = models.UserGroup.objects.all().first()
result = obj.userinfo_set.all() [userinfo对象,userinfo对象,]
小写的表名 values
v = models.UserGroup.objects.values('id','title')
v = models.UserGroup.objects.values('id','title','小写的表名称')
v = models.UserGroup.objects.values('id','title','小写的表名称__age')
小写的表名 values_list
v = models.UserGroup.objects.values_list('id','title')
v = models.UserGroup.objects.values_list('id','title','小写的表名称')
v = models.UserGroup.objects.values_list('id','title','小写的表名称__age')
PS: 前面的所有数据都会显示
跨表:Userinfo和Usergroup是两张独立的表,userinfo_group是有两个列分别调用的userinfo和usergroup两个表的id
正向:
a=models.Userinfo_group.objects.filter(uid__user="egon").values("id","uid__user","gid__gname")
{'id': 1, 'uid__user': 'egon', 'gid__gname': '主机1'}
{'id': 7, 'uid__user': 'egon', 'gid__gname': '主机3'}
for i in a:
print(i["id"], i["uid__user"], i["gid__gname"])
反向:
a=models.Userinfo.objects.filter(userinfo_group=1).values("id","user","userinfo_group__gid__gname")
{'id': 1, 'user': 'egon', 'userinfo_group__gid__gname': '主机1'}
for i in a:
print(i["id"],i["user"],i["userinfo_group__gid__gname"])
-
其他:
models.UserInfo.objects.all()models.UserInfo.objects.filter(age__isnull=True) #查找age列值为空的数据 models.UserInfo.objects.all().only("id") #只取ID列 models.UserInfo.objects.all().defer("id") #不取ID列 models.UserGroup.objects.values('id','title').distinct() #表示按照id和title去重 models.UserInfo.objects.filter(id=1,id=2) # id=1 and id=2 models.UserInfo.objects.filter(id=1,id=2).exsit() #是否存在,True False models.UserInfo.objects.all().first() #第一条数据 models.UserInfo.objects.all().last() #最后一条数据 models.UserInfo.objects.all().count() #数据总共有多少行 models.UserInfo.objects.all().update() #更新 models.UserInfo.objects.all().delete() #删除 #无论是增删改查,参数都可以加字典操作。 models.xx.objects.filter(id=1,name="alex") models.xx.objects.filter(**{'id':1,'name':'alex'}) models.UserInfo.objects.all()[1:19] #切片 # models.UserInfo.objects.filter(id__gt=1) #id>1 # models.UserInfo.objects.filter(id__lt=1) #id<1 # models.UserInfo.objects.filter(id__lte=1) #id<=1 # models.UserInfo.objects.filter(id__gte=1) #id>=1 # models.UserInfo.objects.filter(id__in=[1,2,3]) #id in [1,2,3] # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # models.UserInfo.objects.filter(id__range=[1,2]) # between 1 and 2 # models.UserInfo.objects.filter(name__startswith='xxxx') #以xxxx开头 # models.UserInfo.objects.filter(name__contains='xxxx') #模糊匹配包含xxxx的name # models.UserInfo.objects.exclude(id=1) #id != 1
分组、排序、其他
分组
from django.db.models import Count,Max,Min,Sum,Avg
obj=models.Userinfo.objects.values("ut_id").annotate(别名=Count("id"))
“select userinfo.ut_id,Count("id") as 别名 from userinfo group by userinfo.id”
obj.query #显示对应的sql原生语句
#以主机ID分组,计算每组中有多少个用户
a=models.Userinfo_group.objects.values("gid").annotate(zhu=Count("id"))
SELECT `userinfo_group`.`gid_id`, COUNT(`userinfo_group`.`id`) AS `zhu` FROM `userinfo_group` GROUP BY `userinfo_group`.`gid_id` ORDER BY NULL
<QuerySet [{'gid': 1, 'zhu': 3}, {'gid': 2, 'zhu': 3}, {'gid': 3, 'zhu': 2}, {'gid': 4, 'zhu': 2}]>
#聚合
models.UserInfo.objects.all().aggregate(Count("age"))
排序
models.Userinfo.objects.all().order_by("id") #按照ID从小到大排列
models.Userinfo.objects.all().order_by("-id") #按照ID从大到小排列
#reverse 反转
models.Userinfo.objects.all().order_by("-id").reverse() #按照ID从小到大排列
其他 from django.db.models import F,Q
F 更新时用于获取原来的值
a=models.UserInfo.objects.all().update(age=F("age")+1) #给所有的age都加1
a的值是受影响的行数
Q 用于构造复杂查询条件
# 应用一:
# models.UserInfo.objects.filter(Q(id__gt=1)) #id>1
# models.UserInfo.objects.filter(Q(id=8) | Q(id=2)) #id=8 or id=2
# models.UserInfo.objects.filter(Q(id=8) & Q(id=2)) #id=8 and id=2 ---->id=8,id=2
# 应用二:
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id__gt', 1))
# q1.children.append(('id', 10))
# q1.children.append(('id', 9))
id>1 or id=10 or id=9
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('c1', 1))
# q2.children.append(('c1', 10))
# q2.children.append(('c1', 9))
c1=1 or c1=10 or c1=9
# q3 = Q()
# q3.connector = 'AND'
# q3.children.append(('id', 1))
# q3.children.append(('id', 2))
# q2.add(q3,'OR')
q3(id=1 and id=2) or q2(c1=1 or c1=10 or c1=9)
# con = Q()
# con.add(q1, 'AND')
# con.add(q2, 'AND')
q1 and q2
# models.UserInfo.objects.filter(con)
extra 额外查询条件以及相关表,排序
models.UserInfo.objects.extra(
self,
select=None,
where=None,
params=None,
tables=None,
order_by=None,
select_params=None
)
# a. 映射
# select
# select_params=None
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
#(select count(1) from app01_usertype where id>1) as newid
# select 此处 from 表
# b. 条件
# where=None
# params=None,
where = ['age>%s'],
params=[18,],
#where age>18
# select * from 表 where 此处
# c. 表
# tables
tables=['app01_usertype']
select * from 表,app01_usertype
# select * from 表,此处
# c. 排序
# order_by=None
order_by=['-age'], #-desc ,正常asc
# order by age desc
# select * from 表 order by 此处
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)
"""
select
app01_userinfo.id,
(select count(1) from app01_usertype where id>1) as newid
from app01_userinfo,app01_usertype
where
app01_userinfo.age > 18
order by
app01_userinfo.age desc
"""
result = models.UserInfo.objects.filter(id__gt=1).extra(
where=['app01_userinfo.id < %s'],
params=[100,],
tables=['app01_usertype'],
order_by=['-app01_userinfo.id'],
select={'uid':1,'sw':"select count(1) from app01_userinfo"}
)
print(result.query)
# SELECT
(1) AS "uid",
(select count(1) from app01_userinfo) AS "sw",
"app01_userinfo"."id",
"app01_userinfo"."name",
"app01_userinfo"."age",
"app01_userinfo"."ut_id"
FROM "app01_userinfo" , "app01_usertype"
WHERE
("app01_userinfo"."id" > 1
AND
(app01_userinfo.id < 100)) ORDER BY ("app01_userinfo".id) DESC
8. 原生SQL语句
from django.db import connection, connections
cursor = connection.cursor() # connection=default数据 默认数据库
cursor = connections['db2'].cursor() #指定数据库 db2
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
row = cursor.fetchall()
- extra
- 原生SQL语句
- raw
result = models.UserInfo.objects.raw('select * from userinfo')
[obj(UserInfo),obj,]
result = models.UserInfo.objects.raw('select id,1 as name,2 as age,4 as ut_id from usertype')
[obj(UserInfo),obj,]
v1 = models.UserInfo.objects.raw('SELECT id,title FROM app01_usertype',translations=name_map)
9. 简单的操作
http://www.cnblogs.com/wupeiqi/articles/6216618.html
性能
select_related:主动连表
models.UserInfo.objects.all().select_related("ut") 在查询userinfo时直接将外键ut关联的表进行inner join连接,这样在for循环的时候就不会再次查询ut那个表
models.UserInfo.objects.all().select_related("ut","gt") inner join 2个表
prefetch_related :不做连表,做多次查询
models.UserInfo.objects.all().prefetch_related("ut")
···
select * from userinfo
Django内部:将外键的ID 全部拿到 去重 比如说是[1,2]
select * from usertype where id in [1,2]
django会把2个select结果集整合。
···