1.ORM操作:建数据库,连数据库....
配置文件:
ORM操作 Http请求: url -> 视图(模板+数据) 步骤: 1. 创建数据库 2. DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'s4day70db', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': 3306, } } 3. 在 __init__.py 下,导入 import pymysql pymysql.install_as_MySQLdb() 4.配置静态文件 STATICFILES_DIRS=( os.path.join(BASE_DIR,'static'), ) ORM操作表: 创建表 修改表 -------(SqlAchemy 不能修改表) 删除表 操作数据行: 增删改查 ORM利用pymysql第三方工具连接数据库 默认: SQLlite MySQL: mysql -> MySQLDB(修改django默认连接mySQL方式) 创建数据表: 指令: python manage.py makemigrations python manage.py migrate
创建sqlite数据库:
python manage.py makemigrations
python manage.py migrate
创建超级用户
python manage.py createsuperuser
ORM之删(delete)
>>> Book.objects.filter(id=1).delete() (3, {'app01.Book_authors': 2, 'app01.Book': 1})
我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除。
ORM之查(filter,value)
查询API:
# 查询相关API: # <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 # <2>all(): 查询所有结果 # <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()-------- # <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 # <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 # <6>order_by(*field): 对查询结果排序 # <7>reverse(): 对查询结果反向排序 # <8>distinct(): 从返回结果中剔除重复纪录 # <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 # <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。 # <11>first(): 返回第一条记录 # <12>last(): 返回最后一条记录 # <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False
---------------了不起的双下划线(__)之单表条件查询---------------- # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # # startswith,istartswith, endswith, iendswith,
ORM之改(update和save)
实例:
注意:
<1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。
<2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。
#---------------- update方法直接设定对应属性---------------- models.Book.objects.filter(id=3).update(title="PHP") ##sql: ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3) #--------------- save方法会将所有属性重新设定一遍,效率低----------- obj=models.Book.objects.filter(id=3)[0] obj.title="Python" obj.save() # SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", # "app01_book"."color", "app01_book"."page_num", # "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; # # UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556, # "publisher_id" = 1 WHERE "app01_book"."id" = 3;
此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
聚合查询和分组查询 与 F查询和Q查询
<1> aggregate(*args,**kwargs):
通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。
<2> annotate(*args,**kwargs):
可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
代码:
models.py
from django.db import models class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) def __str__(self): return self.name+" "+self.addr # Book 与 Publish是一对多的关系 :models.ForeignKey(Publish) class Book(models.Model): title=models.CharField(max_length=32) price=models.DecimalField(max_digits=6,decimal_places=2) #创建外键一对多的关系 publish=models.ForeignKey(Publish) # 创建外键多对多的关系 authors=models.ManyToManyField("Author") def __str__(self): return self.title class Author(models.Model): name=models.CharField(max_length=32) def __str__(self): return self.name
urls.py
url(r'^test/',views.test), url(r'^FQ/',views.FQ)
views.py
from django.db.models import Avg,Min,Max,Sum def test(request): #求所有书籍的平均价格 # ret = models.Book.objects.all().aggregate(AvgPrice=Avg('price')) # print(ret) #{'AvgPrice': 55.0} #求所有书籍的的最高价格 # ret1 = models.Book.objects.all().aggregate(MaxPrice=Max('price')) # print(ret1) #{'MaxPrice': Decimal('100.00')} # 钢蛋出版过的书中的最低价 # ret2 = models.Book.objects.filter(authors__name='钢蛋').aggregate(MinPrice=Min('price')) # print(ret2) #{'MinPrice': Decimal('30.00')} #----------------------------annotate------------------------ # 每一个作者出版过的书中的最高价 : 按作者名字分组 # ret3 = models.Book.objects.values('authors__name').annotate(Max('price')) # print(ret3) # ret3 <QuerySet [{'authors__name': '赛貂蝉', 'price__max': Decimal('100.00')}, # {'authors__name': '钢蛋', 'price__max': Decimal('50.00')}]> # for item in ret3: # print(item['authors__name'],item['price__max']) # 每一个出版社出版过的书中最低价格 # ret4 = models.Book.objects.values('publish__name').annotate(Min('price')) # print(ret4) #< QuerySet[{'publish__name': '天空出版社', 'price__min': Decimal('50.00')}, # {'publish__name': '宝贝出版社','price__min': Decimal('30.00')}] > return HttpResponse('****OK*****') from django.db.models import F,Q def FQ(request): #-------F #models.Book.objects.all().update(price=F('price')+0.33) # 查询-----以‘西’开头,且价格大于20的书 # ret = models.Book.objects.filter(title__startswith="西", price__gt=20) # print(ret) #<QuerySet [<Book: 西游>]> # Q查询__支持的逻辑运算: & | ~ # ret2 = models.Book.objects.filter(Q(title__startswith='水') | Q(price__gt=30)) # print(ret2) #<QuerySet [<Book: python>, <Book: 西游>, <Book: 水浒>]> ret3 = models.Book.objects.filter(Q(price__gt=30) | Q(id__gt=1),title__startswith='西') print(ret3) return HttpResponse('****OK*****')
数据库图:
II.ORM连表(用户 与 用户类型)
2.1 建数据表
models.py
from django.db import models class UserType(models.Model): #用户类型 title = models.CharField(max_length=32) class UserInfo(models.Model): #用户 信息 name = models.CharField(max_length=16) age = models.IntegerField() ut = models.ForeignKey('UserType')
2.2 urls.py
from app01 import views urlpatterns = [ #url(r'^admin/', admin.site.urls), # url(r'^login.html$',views.Login.as_view()), url(r'^test.html$', views.test), #此行 ]
2.3 views.py
from django.shortcuts import render,HttpResponse from app01 import models def test(request): ##创建数据 #----用户类型 # models.UserType.objects.create(title='普通用户') # models.UserType.objects.create(title='白金用户') # models.UserType.objects.create(title='黑金用户') #----用户信息 #models.UserInfo.objects.create(name='大宝',age=18,ut_id=1) # models.UserInfo.objects.create(name='二宝',age=18,ut_id=2) # models.UserInfo.objects.create(name='三宝',age=18,ut_id=3) # models.UserInfo.objects.create(name='小钢炮',age=19,ut_id=1) # models.UserInfo.objects.create(name='钢蛋',age=19,ut_id=2) ##************* 获取 ##QuerySet[obj,obj,obj] 对象格式 # result = models.UserInfo.objects.all() # print(result) # for obj in result: # print(obj.name,obj.age,obj.ut_id,obj.ut.title) ## UserInfo表:ut是 Fk字段-- 正向操作 PS:一个用户只有有一个类型 # obj = models.UserInfo.objects.all().first() # print(obj.name,obj.age,obj.ut.title) ##UserType表: 表名小写_set.all()-- 反向操作 PS:一个用户类型下可以有很多用户 # obj = models.UserType.objects.all().first() # print('用户类型:',obj.id,obj.title) # for row in obj.userinfo_set.all(): # print(row.name,row.age) ## QuerySet[{'id':'xx','name':'xx'} ] 类似 字典格式 # result = models.UserInfo.objects.all().values('id','name') # for row in result: # print(row) ## QuerySet[(1,'f'), ] 类似 元组格式 # result = models.UserInfo.objects.all().values_list('id','name') # for row in result: # print(row) ##**************** 获取多个数据 --> UserInfo(正向) ************ ##---------1.[obj,obj.obj] ## models.UserInfo.objects.all # result = models.UserInfo.objects.all() # for item in result: #在循环的时候,跨表 # print(item.name,item.ut.title) ##--------2.[{id:1,name:fd},{id:2,name:fd},{id:3,name:fd},] ## models.UserInfo.objects.all().values('id','name') ##____无法跨表 # result= models.UserInfo.objects.all().values('id','name') # for item in result: # print(item['id'],item['name']) #____进行跨表 # result = models.UserInfo.objects.all().values('id','name','ut__title') #在取值时,跨表 # for item in result: # print(item['id'],item['name'],item['ut__title']) ##--------3.[(1,df),(2.df),(3,df)] ## models.UserInfo.objects.all().values_list('id','name') ##___无法跨表 # result = models.UserInfo.objects.all().values_list('id','name') # for item in result: # print(item[0],item[1]) ##___进行跨表 # result = models.UserInfo.objects.all().values_list('id','name','ut__title') #在取值时,跨表 # for item in result: # print(item[0],item[1],item[2]) ##************** 获取多个数据 --> UserType(反向) ************ ##------ 1.小写表名_set # obj = models.UserType.objects.all().first() # result = obj.userinfo_set.all() # ##print(result) #<QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]> # # for row in result: # print(row.name,row.age,row.ut.title) ##------- 2.小写表名 ## v = models.UserType.objects.values('id','title') ## v = models.UserType.objects.values('id', 'title', '小写的表名称') ## v = models.UserType.objects.values('id', 'title', '小写的表名称__age') # v = models.UserType.objects.values('id','title','userinfo__name','userinfo__age') # # for item in v: # print(item['id'],item['title'],item['userinfo__name'],item['userinfo__age']) ##------3.小写的表名 ## v = models.UserType.objects.values_list('id', 'title') ## v = models.UserType.objects.values_list('id', 'title', '小写的表名称') ## v = models.UserType.objects.values_list('id', 'title', '小写的表名称__age') # v = models.UserType.objects.values_list('id','title','userinfo__name','userinfo__age') # # for item in v: # print(item[0],item[1],item[2],item[3]) return HttpResponse('******&&&&&&*******')
#从性能考虑
示例代码:
#-------------------- - select_related user_list = models.UserInfo.objects.all().select_related('ut') #Fk for row in user_list: print(row.name,row.pwd,row.ut.caption) print(user_list.query) SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."pwd", "app01_userinfo"."ut_id", "app01_usertype"."id", "app01_usertype"."caption" FROM "app01_userinfo" LEFT OUTER JOIN "app01_usertype" ON ("app01_userinfo"."ut_id" = "app01_usertype"."id") #----------------- ---- prefetch_related user_list = models.UserInfo.objects.all().prefetch_related('ut') #Fk for row in user_list: print(row.name,row.pwd,row.ut.caption) print(user_list.query) SELECT "app01_userinfo"."id", "app01_userinfo"."name", "app01_userinfo"."pwd", "app01_userinfo"."ut_id" FROM "app01_userinfo" 结果相同: 钢蛋 123 普通用户 赛貂蝉 345 白金用户 小钢炮 567 钻石用户 如花 789 普通用户
## 未连mysql,直接使用默认的 db.sqlite3
III.多对多
a.自定义关系表
1.urls.py
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test.html$', views.test), ]
2.view.py
from app01 import models def test(request): ##创建数据 # data = [ # models.Boy(name='钢蛋'), # models.Boy(name='大毛'), # models.Boy(name='小钢炮'), # models.Boy(name='阿黄'), # ] # # models.Boy.objects.bulk_create(data,4) # data = [ # models.Girl(nick='赛貂蝉'), # models.Girl(nick='胭脂'), # models.Girl(nick='如花'), # models.Girl(nick='小桃红'), # ] # # models.Girl.objects.bulk_create(data, 4) # models.Love.objects.create(b_id=1,g_id=1) # models.Love.objects.create(b_id=1,g_id=4) # models.Love.objects.create(b_id=2,g_id=4) # models.Love.objects.create(b_id=2,g_id=3) ##----1. 和钢蛋有关系的姑娘 # obj = models.Boy.objects.filter(name='钢蛋').first() # love_list = obj.love_set.all() # for row in love_list: # print(row.g.nick) # love_list = models.Love.objects.filter(b__name='钢蛋') # for row in love_list: # print(row.g.nick) ##-------------- 选择以下查询方法 ---------------- # love_list = models.Love.objects.filter(b__name='钢蛋').values('g__nick') # for item in love_list: # print(item['g__nick']) # love_list = models.Love.objects.filter(b__name='钢蛋').values_list('g__nick') # ## print(love_list) # for item in love_list: # print(item[0]) # love_list = models.Love.objects.filter(b__name='钢蛋').select_related('g') # for obj in love_list: # print(obj.g.nick) return HttpResponse('****** 多对多 *******')
b. ManyToManyField (自动生成关系表)
1. models.py
from django.db import models class Boy(models.Model): name = models.CharField(max_length=32) m = models.ManyToManyField('Girl') class Girl(models.Model): nick = models.CharField(max_length=32) ##m = models.ManyToManyField('Boy')
2. views.py
from django.shortcuts import render,HttpResponse from app01 import models def test(request): ##************** 数据的创建 (针对第三张表) *********** #obj = models.Boy.objects.filter(name='钢蛋').first() #建立obj,备下面的操作 # print(obj.id,obj.name) #1 钢蛋 ##-----增加,移除,清空,重置 # obj.m.add(1) # obj.m.add(2,3) # obj.m.add(*[4,]) # obj.m.remove(2) # obj.m.remove(*[3,4]) # obj.m.clear() # obj.m.set([1,]) #必须是 可迭代的 ##************ 获取数据 ************ # obj = models.Boy.objects.filter(name='钢蛋').first() # 建立obj,备下面的操作 # q = obj.m.all() #得到是 Girl对象 # girl_list = obj.m.all() # girl_list = obj.m.filter(nick='赛貂蝉') # print(girl_list) ##---- 和赛貂蝉有关系的男生 obj = models.Girl.objects.filter(nick='赛貂蝉').first() ##print(obj.id,obj.nick) v = obj.boy_set.all() for i in v: print(i.name) return HttpResponse('***** ManyToManyField ****** ')
注意:
#对于自动生成的关系表,不可以直接对第三张表操作,但可以间接操作
#在此,自动生成的关系表,不会再有额外的列,只能有三列(以后若要增加新的列,使用 自定义关系表)
c.杂交
##这里的 ManyToManyField,仅提供 ------> 查询和清空
IV.多对多(登录、互相展示 有关系对方用户)
A.男生表,女生表,第三张关系表
1.urls.py
2.models.py
from django.db import models class Boy(models.Model): nickname = models.CharField(max_length=32) username= models.CharField(max_length=32) password = models.CharField(max_length=64) class Girl(models.Model): nickname = models.CharField(max_length=32) username = models.CharField(max_length=32) password = models.CharField(max_length=64) class B2G(models.Model): b = models.ForeignKey(to='Boy',to_field='id') g = models.ForeignKey(to='Girl',to_field='id')
3.views
插入数据
def test(request): # models.Boy.objects.create(nickname='tc',username='铁锤',password='123') # models.Boy.objects.create(nickname='xgp', username='小钢炮', password='123') # models.Boy.objects.create(nickname='gd', username='钢蛋', password='123') models.Girl.objects.create(nickname='sdc', username='赛貂蝉', password='123') models.Girl.objects.create(nickname='sdc', username='如花', password='123') models.Girl.objects.create(nickname='xth', username='小桃红', password='123') models.B2G.objects.create(b_id=1,g_id=1) models.B2G.objects.create(b_id=1, g_id=2) return HttpResponse('*******&&&&&&&**********')
love.py
from django.shortcuts import render,redirect,HttpResponse from app01 import models def test(request): # models.Boy.objects.create(nickname='tc',username='铁锤',password='123') # models.Boy.objects.create(nickname='xgp', username='小钢炮', password='123') # models.Boy.objects.create(nickname='gd', username='钢蛋', password='123') models.Girl.objects.create(nickname='sdc', username='赛貂蝉', password='123') models.Girl.objects.create(nickname='sdc', username='如花', password='123') models.Girl.objects.create(nickname='xth', username='小桃红', password='123') models.B2G.objects.create(b_id=1,g_id=1) models.B2G.objects.create(b_id=1, g_id=2) return HttpResponse('*******&&&&&&&**********') def index(request): if not request.session.get('user_info'): return redirect('/login.html') else: #男生:女生列表 #女生:男生列表 gender = request.session.get('user_info').get('gender') if gender == '1': user_list = models.Girl.objects.all() else: user_list = models.Boy.objects.all() return render(request,'index.html',{'user_list':user_list}) def others(request): """ 获取与当前用户有关系的异性 :param request: :return: """ current_user_id = request.session.get('user_info').get('user_id') gender = request.session.get('user_info').get('gender') if gender == '1': user_list = models.B2G.objects.filter(b_id=current_user_id).values('g__username') else: user_list = models.B2G.objects.filter(g_id=current_user_id).values('b__username') for row in user_list: print(row) return render(request,'others.html',{'user_list':user_list})
account.oy
from django.shortcuts import render,HttpResponse,redirect from app01 import models def login(request): if request.method == 'GET': return render(request,'login.html') else: user = request.POST.get('username') pwd = request.POST.get('password') gender = request.POST.get('gender') rmb = request.POST.get('rmb') #性别判断 if gender == '1': obj = models.Boy.objects.filter(username=user,password=pwd).first() else: obj = models.Girl.objects.filter(username=user,password=pwd).first() if not obj: #未登录 return render(request,'login.html',{'msg':'用户名或密码错误'}) else: # request.session['user_id'] = obj.id # request.session['gender'] = gender # request.session['username'] = user request.session['user_info'] = {'user_id':obj.id, 'gender':gender, 'username':user, 'nickname':obj.nickname } return redirect('/index.html') def logout(request): #注销 if request.session.get('user_info'): request.session.clear() return redirect('/login.html')
4.html
user_header.html (注销:小插件)
<h1>当前用户:{{ request.session.user_info.nickname }}</h1> <a href="/logout.html">注销</a>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'user_header.html' %} <h3>异性列表</h3> <a href="/others.html">查看和我有关系的异性[点击]</a> <ul> {% for row in user_list %} <li>{{ row.username}}</li> {% endfor %} </ul> </body> </html>
others.html(只显示 有关系的异性)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'user_header.html' %} <h1>有关系的异性</h1> <ul> {% for row in user_list %} {% if row.g__username %} <li>{{ row.g__username }}</li> {% else %} <li>{{ row.b__username }}</li> {% endif %} {% endfor %} </ul> </body> </html>
login.html(登录验证)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form method="POST" action="/login.html"> {% csrf_token %} <p>用户:<input type="text" name="username"/></p> <p>密码:<input type="password" name="password"/></p> <p>性别: <input type="radio" name="gender" value="1"/>男 <input type="radio" name="gender" value="2"/>女 </p> <p> <input type="checkbox" name="rmb" value="11">一个月免登陆 </p> <input type="submit" value="提交"/>{{ msg }} </form> </body> </html>
ORM 2.0
modeld.py
class Publish(models.Model): name = models.CharField(max_length=32) addr=models.CharField(max_length=32) def __str__(self): return self.name+' '+self.addr class Author(models.Model): name = models.CharField(max_length=32) # 创建外键多对多的关系 books = models.ManyToManyField('Book') def __str__(self): return self.name #Book 与 Publish 是一对多的关系:models.Foreiqnkey(Publish) class Book(models.Model): title=models.CharField(max_length=32) price=models.DecimalField(max_digits=6,decimal_places=2) publish=models.ForeignKey(Publish) def __str__(self): return self.title
views.py(添加方式...)
def add(request): #----添加记录方式一: create方式 #models.Publish.objects.create(name='老衲出版版社',addr='西湖') # ----添加记录方式二: save方式 # p = models.Publish(name='宝贝出版社',addr='幼儿园') # p.save() #++++++++++++++++++++++++++++++++++++++++++++++++ # 一对多:添加一个book记录 方法1: #models.Book.objects.create(title='python',price=99.99,publish_id=1) #查看添加内容 # book_obj=models.Book.objects.get(id=1) # print(book_obj.title) # print(book_obj.price) # print(book_obj.publish) #一对多:create方法:添加一个book记录 方法2: # publish_obj = models.Publish.objects.get(id=2) #一个宝贝出版社对象 #再创建一个Book对象 #models.Book.objects.create(title='西游',price=100.11,publish=publish_obj) #------一对多:save方法 # p_obj=models.Publish.objects.get(id=1) # 一个老衲出版社对象 # b = models.Book(title='xx',price=111,publish=p_obj) # b.save() # b1 = models.Book(title='YY',price=222,publish_id=1) # b1.save() #+++++++++++++++++++++ 添加多对多关系 +++++++++++++++++++ #-------- 通过对象绑定关系 book_obj = models.Book.objects.get(id=6) # author_obj1 = models.Author.objects.get(id=6) # author_obj2 = models.Author.objects.get(id=7) #绑定关系(两种方法) # book_obj.author_set.add(author_obj1,author_obj2) #1 # author_list=models.Author.objects.all() #2 # book_obj.author_set.add(*author_list) #_____注意点____ #print('***',book_obj.author_set.all()) #id=3的这本所有关联的作者对象集合 # 解除绑定 # book_obj.author_set.clear() #1 # author_name = models.Author.objects.get(name='钢蛋') #2 删除一个 # book_obj.author_set.remove(author_name) # book_obj.delete() #3 且清空 book表的书籍表记录 return HttpResponse('**********')