怎样让自己网站的文章被百度收录,建设摩托车型号大全,搜索 引擎优化,韩文网站建设ORM表操作
1.ORM单表操作 首先想操作表的增删改查#xff0c;需要先导入这个表,以之前创建的UserInfo表为例,在app下的views.py中导入
from app import modelsdef query(request):new_obj models.UserInfo(id1,name北北,bday2019-09-27,checked1,)new_obj.save()return Htt…ORM表操作
1.ORM单表操作 首先想操作表的增删改查需要先导入这个表,以之前创建的UserInfo表为例,在app下的views.py中导入
from app import modelsdef query(request):new_obj models.UserInfo(id1,name北北,bday2019-09-27,checked1,)new_obj.save()return HttpResponse(ok)这样就创建了一条记录
增加
方式1:
obj models.UserInfo(id 2,name 京京,bday 2019-9-27,checked 1,)
obj.save()方式2:
ret models.UserInfo.objects.create(name 欢欢,bady 2019-9-27,checked 0,)
print(ret) #UserInfo object#ret 是创建的新的记录的model对象ps:批量插入(bulk_create)
obj_list []
for i in range(20):obj models.Book(titlef西游记{i},price20i,publish_datef2019-09-{i1},publisher人民出版社)obj_list.append(obj)models.Book.objects.bulk_create(obj_list) #批量创建从前端页面获取到的数据即:request.POST得到的是querydict类型data request.POST.dict() --能够将querydict转换成普通的字典
创建数据时可以:models.Book.objects.create(**data)删除
首先要通过简单查询:filter() -- 查询结果是queryset类型的数据,里面是一个个的model对象,此数据类型类似于列表
方式1:
models.UserInfo.objects.filter(id 3).delete()
#通过queryset对象删除方式2:
models.UserInfo.objects.filter(id 3)[0].delete()
#通过model对象删除修改
方式1:
models.UserInfo.objects.filter(id 2).update(name 英英,checked 0,)
#通过queryset对象进行修改,而model对象不能调用update方法
方式2:
ret models.UserInfo.objects.filter(id 2)[0]
ret.name 英英
ret.checked 0
ret.save()查找
查询API
1.all() 查询所有结果,得到的是queryset类型ret models.UserInfo.objects.all()2.filter(**kwargs) 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 ret models.UserInfo.objects.filter(name英英 checked0)
#and多条件查询
#查询条件不能匹配到数据时,不会报错,会返回一个空的query(QuerySet []),如果没有写查询条件会获取所有数据,queryset类型的数据还能继续调用filter方法3.get(**kwargs) ret models.UserInfo.objects.get(name英英)
#得到的是一个model对象(行记录对象),有且只能有一个
#1.查不到数据会报错:UserInfo matching query does noe exist.
#2.超过一个也会报错:returned more than one UserInfo4.exclude(**kwargs) 排除,它包含了与所给筛选条件不匹配的对象,返回的时queryset类型ret models.UserInfo.objects.exclude(name英英)
#1.object能够调用models.UserInfo.objects.exclude(name__startswith贝贝)
#2.queryset类型数据能够调用models.UserInfo.objects.all().exclude(name__startswith贝贝)5.order_by(*filed) queryset类型的数据来调用对查询结果排序,默认是按照id来升序排列的返回值还是queryset类型ret models.UserInfo.objects.all().order_by(-grade,id)
#按成绩降序排列,成绩相同的按id升序排列6.reverse() queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型ret models.UserInfo.objects.all().order_by().reverse()
#数据排序后才能进行反装7.count() queryset类型的数据来调用返回数据库中匹配查询(QuerySet)的对象数量。ret models.UserInfo.objects.all().count()8.first() queryset类型的数据来调用,返回第一条记录ret models.UserInfo.objects.all().first()9.last() queryset类型的数据来调用,返回最后一条记录ret models.UserInfo.objects.all().last()10.exists() queryset类型的数据来调用,如果queryset包含数据,就返回True,否则返回Falseret models.UserInfo.objects.filter(id9).exists()
#判断返回结果集是不是有数据11.values(*filed)
#queryset类型的数据来调用返回一个ValueQuerySet——一个特殊的QuerySet运行后得到的并不是一系列model的实例化对象而是一个可迭代的字典序列,只要是返回的queryset类型就可以继续链式调用queryset类型的其他的查找方法其他方法也是一样的。retmodels.UserInfo.objects.filter(id2).values(name,bday)12.values_list(*filed)
#它与values()非常相似它返回的是一个元组序列values返回的是一个字典序列retmodels.UserInfo.objects.all().values_list(name,bday)#调用values或者values_list的是objects控制器,那么返回所有数据
# ret models.Book.objects.all().values()
# ret models.Book.objects.values() 13.distinct() #values和values_list得到的queryset类型的数据来调用从返回结果中剔除重复记录ret models.UserInfo.objects.all().values(checked).distinct()基于双下划线的模糊查询
ret models.Book.objects.filter(price__gt35) #大于
ret models.Book.objects.filter(price__gte35) # 大于等于
ret models.Book.objects.filter(price__lt35) # 小于等于
ret models.Book.objects.filter(price__lte35) # 小于等于
ret models.Book.objects.filter(price__range[35,38])
# 大于等35,小于等于38 where price between 35 and 38
ret models.Book.objects.filter(price__in[32,35,38])
# price值等于这三个值里面的任意一个的对象 or
ret models.Book.objects.filter(title__contains西游记)
# 字段数据中包含这个字符串的数据都要
ret models.Book.objects.filter(title__icontainspython) # 不区分大小写
ret models.Book.objects.filter(title__startswithpy)
# 以什么开头istartswith 不区分大小写
ret models.Book.objects.filter(publish_date2019-09-15)
#按照日期查询查询某年某月某日:
ret models.Book.objects.filter(publish_date__year2018)
#2018写数字也可以
ret models.Book.objects.filter(publish_date__year__gt2018)
#查询出版日期大于2018年的ret models.Book.objects.filter(publish_date__year2019,publish_date__month8,publish_date__day1)
#查询出版日期为2019-8-1的找字段数据为空的双下滑线
ret models.Book.objects.filter(publish_date__isnullTrue) #这个字段值为空的那些数据插入时间问题
在表的结构里新增列来显示时间
class UserInfo(models.Model):id models.AutoField(primary_keyTrue)name models.CharField(max_length10)bday models.DateField()checked models.BooleanField()# now models.DateTimeField(nullTrue)now models.DateTimeField(auto_now_addTrue,nullTrue)#自动插入时间now2 models.DateTimeField(auto_nowTrue,nullTrue)# 更新记录时,自动添加更新时的时间,创建新纪录时也会帮你自动添加创建时的时间在提交后进行新增记录:
import datetime
current_date datetime.datetime.now()
models.UserInfo.objects.create(name妮妮,bdaycurrent_date,nowcurrent_date, # 自己手动直接插入时间没有时区问题checked0)#但是如果让这个字段自动来插入时间,就会有时区的问题,auto_now_add创建记录时自动添加当前创建记录时的时间,存在时区问题
now models.DateTimeField(auto_now_addTrue,nullTrue)
解决方法:settings配置文件中将USE_TZ的值改为FalseUSE_TZ False # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
使用pycharm的数据库客户端的时候,时区问题要注意更新时的auto_now参数# 更新记录时,自动更新时间,创建新纪录时也会帮你自动添加创建时的时间,但是在更新时只有使用save方法的model对象的形式更新才能自动更新时间,有缺陷,放弃now2 models.DateTimeField(auto_nowTrue,nullTrue)2.ORM多表操作
创建模型
表和表之间的关系 一对一、多对一、多对多 用book表和publish表自己来想想关系想想里面的操作加外键约束和不加外键约束的区别一对一的外键约束是在一对多的约束上加上唯一约束。
实例我们来假定下面这些概念字段和关系 作者模型一个作者有姓名和年龄。 作者详细模型把作者的详情放到详情表包含生日手机号家庭住址等信息。作者详情模型和作者模型之间是一对一的关系one-to-one 出版商模型出版商有名称所在城市以及email。 书籍模型 书籍有书名和出版日期一本书可能会有多个作者一个作者也可以写多本书所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版所以出版商和书籍是一对多关联关系(one-to-many)。 模型建立如下
from django.db import models# Create your models here.class Author(models.Model): 作者表namemodels.CharField(max_length32)agemodels.IntegerField()aumodels.OneToOneField(AuthorDetail,on_deletemodels.CASCADE)#就是foreignkeyunique只不过不需要我们自己来写参数了并且orm会自动帮你给这个字段名字拼上一个_id数据库中字段名称为authorDetail_id# 与AuthorDetail建立一对一的关系一对一的这个关系字段写在两个表的任意一个表里面都可以class AuthorDetail(models.Model):作者详细信息表birthdaymodels.DateField()telephonemodels.BigIntegerField()addrmodels.CharField( max_length64)class Publish(models.Model):出版社表namemodels.CharField( max_length32)citymodels.CharField( max_length32)#class Meta:#db_tableauthordetail --指定表名#ordering[id] --指定排序方式#多对多的表关系手动创建一个第三张表然后写上两个字段每个字段外键关联到另外两张多对多关系的表orm的manytomany自动帮我们创建第三张表两种方式建立关系都可以手动创建的第三张表进行orm操作的时候很多关于多对多关系的表之间的orm语句方法无法使用,如果想删除某张表只需要将这个表注销掉然后执行那两个数据库同步指令就可以了自动就删除了。
class Book(models.Model):书籍表title models.CharField( max_length32)publishDatemodels.DateField()pricemodels.DecimalField(max_digits5,decimal_places2)
publishsmodels.ForeignKey(toPublish,on_deletemodels.CASCADE)authorsmodels.ManyToManyFiled(Author,)# foreignkey里面可以加很多的参数to指向表to_field指向你关联的字段不写默认会自动关联主键字段on_delete级联删除 字段名称不需要写成publish_idorm在翻译foreignkey的时候会自动给你这个字段拼上一个_id,这个字段名称在数据库里面就自动变成了publish_id # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个自动创建第三张表并且查看book表的时候看不到这个字段因为这个字段就是创建第三张表的意思不是创建字段的意思所以只能说这个book类里面有authors这个字段属性# 与Publish建立一对多的关系,外键字段建立在多的一方字段publish如果是外键字段那么它自动是int类型#注意不管是一对多还是多对多写to这个参数的时候最后后面的值是个字符串不然你就需要将你要关联的那个表放到这个表的上面增加
通过两种方式
一对一:
au_obj models.AuthorDetail.objects.get(id 4)
models.Author.objects.create(name 韩寒,age 32,#方式1:将对象作为值给au,也就是自动将au_obj的id赋值给au_idau au_obj,#方式2:直接写id值#au_id 4, )一对多:
pub_obj models.Publish.objects.get(id 3)
models.Book.objects.create(title 红楼梦,price 160.00,publishDate 2011-11-12,#方式1:类属性作为关键字段时,值为model对象publishs pub_obj,#方式2:如果关键字为数据库字段名称,那么值为关联数据的值#publish_id 3)多对多:
new_obj models.Book.objects.create(title 红楼梦,price 180.00,publishDate 2010-08-13,publishs_id 2,)
#方式1:
new_obj.authors.add(3,5)
# new_obj.authors.add(*[3,5]) 利用打散的方式,等同于上面的方式#方式2:
obj1 models.Author.objects.get(id3)
obj2 models.Author.objects.get(id5)
new_obj.authors.add(obj1,obj2)删除
一对一:
models.AuthorDetail.objects.filter(id3).delete()models.Author.objects.filter(id3).delete()
一对多:
models.Publish.objects.filter(id3).delete()models.Book.objects.filter(id4).delete()
多对多:
book_obj models.Book.objects.get(id2)
book_obj.authors.remove(1) #指定删除
book_obj.authors.clear() #清空
book_obj.authors.set([1,2]) #先清除在添加,相当于修改
修改
修改的方法与添加类似
ret models.Publish.objects.get(id2)
models.Book.objects.filter(id5).update(title 活着,#方式1:publishs ret,#方式2:#publishs_id 1,)
查询
基于对象的跨表查询
一对一查询(Author与AuthorDetail) 关系属性写在表1,关联到表2,那么通过表1的数据去找表2的数据,叫做正向查询,返过来就是反向查询# 正向查询 对象.属性# 例:查询一下韩寒的电话号码obj models.Author.objects.filter(name韩寒).first()ph obj.au.telephoneprint(ph)# 反向查询 对象.小写的表名# 例:查一下电话号码为120的作者姓名obj models.AuthorDetail.objects.filter(telephone120).first()ret obj.author.name print(ret)
一对多查询(Publish与Book) #正向查询# 查询一下红楼梦这本书是哪个出版社出版的 obj models.Book.objects.filter(title海狗的怂逼人生).first()ret obj.publishs.nameprint(ret) #反向查询# 查询一下 人民出版社出版过哪些书obj models.Publish.objects.filter(name人民出版社).first()ret obj.book_set.all()for i in ret:print(i.title)
多对多查询(Author与Book) # 正向查询# 查询一下红楼梦是哪些作者写的 obj models.Book.objects.filter(title海狗的怂逼人生).first()ret obj.authors.all()for i in ret:print(i.name)# 反向查询# 查询一下韩寒写了哪些书 obj models.Author.objects.filter(name韩寒).first()ret obj.book_set.all()for i in ret:print(i.title)#print(i.publishs.name) --查询这些书的出版社名称
3.基于双下划线的跨表查询(基于join实现的)
Django还提供了一种直观而且高效的方式在查询(lookups)中表示关联关系,它能自动确认SQL JOIN联系.要做跨关系查询,就使用双下划线来连接模型(model)间关联字段的名称,直到最终连接到需要的model
基于双下划线的查询:正向查询按字段,反向查询按表名小写来告诉orm引擎join哪张表,一对一,一对多,多对多都是一个写法(在写orm查询的时候,哪张表在前哪张表在后都没问题,因为是join连表操作)
一对一查询
查询韩寒的手机号正向查询
ret models.Author.objects.filter(name韩寒).values(au__telephone)反向查询
ret models.AuthorDetail.objects.filter(author__name 韩寒).values(telephone)
一对多查询
红楼梦是哪个出版社出版的正向查询
ret models.Book.objects.filter(title红楼梦).values(publishs__name)反向查询
ret models.Publish.objects.filter(book__title红楼梦).values(name)查询一下人民出版社出版了哪些书正向查询
ret models.Book.objects.filter(publishs__name人民出版社).values(title)反向查询
ret models.Publish.objects.filter(name人民出版社).values(book_title)
多对多查询
查询一下红楼梦是哪些作者写的正向查询
ret models.Book.objects.filter(title红楼梦).values(authors__name)反向查询
ret models.Author.objects.filter(book__title红楼梦).values(name)
related_name
反向查询时,如果定义了related_name,则用related_name替换表名,比如
publish ForeignKey(topublisher,related_name booklist)
查询人民出版社出版过哪些书反向查询 不再按表名:book,而是related_name:booklist
ret models.Publish.objects.filter(name人民出版社).values(booklist__title)
4.聚合查询和分组查询
聚合查询
aggregate(*args,**kwargs)
计算所有图书的平均价格from django.db.models import Avg
ret models.Book.objects.all().aggregate(Avg(price))
#或者给它起名字:aggretate(aAvg(price))
print(ret)
#{price__avg:34.35}
aggregate()是QuerySet的一个终止语句,意思是说,它返回一个包含一些键值对的字典.键的名称是聚合值的标识符,值是计算出来的聚合值,键的名称是按照字段和聚合函数的名称自动生成出来的.如果你想为聚合值指定一个名称,可以向聚合子句提供它.
ret models.Book.objects.aggregate(aAvg(price))
print(ret)
#{a:34.35}
如果希望生成不止一个聚合,可以向aggregate()子句中添加另一个参数,所以,可以这样查询
from django.db.models import Avg,Max,Min,Countret models.Book.objects.aggregate(Avg(price),Max(price),Min(price))
print(ret)
#{price__avg:34.35,price__max:Decimal(81.20),price__min:Decimal(12.99)}
分组查询
annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)
跨表分组查询的本质就是将关联表join成一张表,再按单表的思路进行分组查询
查询每个出版社出版的书的平均价格#用publish表的id字段进行分组
ret models.Book.objects.values(publish__id).annotate(aAvg(price))#用book表的publish_id字段进行分组
ret models.Book.objects.values(publishs_id).annotate(aAvg(price))ret models.Publish.objects.annotate(aAvg(book__price)).values(a)
F查询与Q查询
F查询
假设在book表中加入两个字段:评论数:comment,收藏数:keep
Django提供F()来做这样的比较,F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值
查询评论数大于收藏数的书籍from django.db.models import F
ret models.Book.objects.filter(comment__gtF(keep))
Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作
查询评论数大于收藏数两倍的书籍ret models.Book.objects.filter(comment__gtF(keep)*2)
修改操作也可以使用F函数,比如将每一本书的价格提高30元
models.Book.objects.all().update(priceF(price)30)
Q查询
filter()等方法中的关键字参数查询都是一起进行AND的,如果需要执行更复杂的查询(例如OR语句),可以使用Q对象
Q对象可以使用(与), |(或) , ~(非) 操作符组合起来.当一个操作符在两个Q对象使用时,它产生一个新的Q对象
from django.db.models import Qret models.Book.objects.filter(Q(authors__name韩寒)|Q(authors__name余华))
等同于下面的SQL where子句
where name 韩寒 or name 余华
可以组合使用 和 | 操作符以及使用括号进行分组来编写任意复杂的Q对象.同时,Q对象可以使用 ~ 操作符取反,允许组合正常的查询和取反 (not)查询
ret models.Book.objects.filter(Q(authors__name韩寒)~Q(publishdate__year2017)).values_list(title)ret models.Book.objects.filter(Q(Q(authors__name韩寒)~Q(publishdate__year2017))Q(id__gt6)).values_list(title)
#可以使用Q嵌套,多层Q嵌套等
查询函数可以混合使用Q对象和关键字参数 .所有提供给查询函数的参数(关键字参数或Q对象)都将AND在一起,但是,如果出现Q对象,它必须位于所有关键字参数的前面,例如
ret models.Book.objects.filter(Q(publishdate__year2016) | Q(publishdate__year2017),titlepython #也是and的关系,但是Q必须写在前面)
5.ORM执行原生SQL语句
在模型查询API不够用的情况下我们还可以使用原始的SQL语句进行查询。
Django 提供两种方法使用原始SQL进行查询一种是使用raw()方法进行原始SQL查询并返回模型实例另一种是完全避开模型层直接执行自定义的SQL语句。
执行原生查询
raw()管理器方法用于原始的SQL查询并返回模型的实例 注意raw()语法查询必须包含主键。
这个方法执行原始的SQL查询并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样通过迭代来提供对象实例。
举个例子
class Person(models.Model):first_name models.CharField(...)last_name models.CharField(...)birth_date models.DateField(...)
可以像下面这样执行原生sql语句
for p in Person.objects.raw(SELECT * FROM myapp_person): print(p)
raw()查询可以查询其他表的数据
举例:
ret models.Student.objects.raw(select id, tname as hehe from app02_teacher)for i in ret:print(i.id, i.hehe)
raw()方法自动将查询字段映射到模型字段。还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典
d {tname: haha}ret models.Student.objects.raw(select * from app02_teacher, translationsd)for i in ret:print(i.id, i.sname, i.haha)
原生SQL还可以使用参数注意不要自己使用字符串格式化拼接SQL语句防止SQL注入
d {tname: haha}ret models.Student.objects.raw(select * from app02_teacher where id %s, translationsd, params[1,])for i in ret:print(i.id, i.sname, i.haha)
直接执行自定义SQL
我们可以直接从django提供的接口中获取数据库连接然后像使用pymysql模块一样操作数据库。
from django.db import connection, connections
cursor connection.cursor()
# cursor connections[default].cursor()
cursor.execute(SELECT * from auth_user where id %s, [1])
ret cursor.fetchone()
6.python脚本中调用django环境(django外部脚本使用models)
如果想通过自己创建的python文件在django项目中使用django的models那么就需要调用django的环境
import osif __name__ __main__:os.environ.setdefault(DJANGO_SETTINGS_MODULE, BMS.settings)import djangodjango.setup()from app01 import models #引入也要写在上面三句之后books models.Book.objects.all()print(books)