django

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\w)/(?P\d)', views.manage),

ps:
127.0.0.1:8000/manage/adsa/123

manage中需要对应参数接收 manage(request,name,id)

添加额外的参数

url(r'^manage/(?P\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 = "It is now %s." % 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 %}

{{ item.0 }}

{{ item.id }}

{% endfor %}

{% if ordered_warranty %}

{% else %}

{% endif %}

母板:{% block title %}{% endblock %}

子板:{% extends "base.html" %}
   {% block title %}{% endblock %}

组件:include

{% include "组件.html" %}

pub.html


特别漂亮的组件


标题:{{ name }}

内容:{{ name }}


test.html







{% include 'pub.html' %}
{% include 'pub.html' %}
{% include 'pub.html' %}

帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}

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
- 非要用,一定要过滤关键字

评论等。客户输入的评论不是正常评论。比如 alert(123)
如果直接显示到网页中,则是以代码显示的,每次打开这个页面都会执行一个弹出框。

django自带的对这些进行了处理。如果是非正常字符串,则在网页中他们是以字符串形式显示的。

如果要让他们以原有的形式显示,{{ aaa | safe }} 加上safe

或者传入的时候用mark_safe修改下。

from django.utils.safestring import mark_safe
x="sss"
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 }}

自定义分页

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表单中添加

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中携带


{% csrf_token %}


Ajax提交


b. 放在请求头中 cookie和csrf_token 的值是不一样的


{% csrf_token %}


Ajax提交


COOKIE和SESSION

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

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个表

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结果集整合。

···

posted @ 2017-07-02 15:25  高跃  阅读(387)  评论(0)    收藏  举报