orm字段及参数
orm字段
1. null 2. default 3. unique 4. db_index 5. DateField和DateTimeField才有的参数: auto_now_add=True --> 创建数据的时候自动把当前时间赋值 auto_add=True --> 每次更新数据的时候更新当前时间 上述两个不能同时设置!!! 5. class Meta: db_table = "表名"
创建表
索引
联合唯一

class Meta: # 建立联合唯一约束 unique_together = ("author", "book")
一对一

# 作者 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() phone = models.IntegerField() books = models.ManyToManyField(to="Book", related_name="authors") detail = models.OneToOneField(to="AuthorDetail") def __str__(self): return self.name # 作者详情 class AuthorDetail(models.Model): # 爱好 hobby = models.CharField(max_length=32) # 地址 addr = models.CharField(max_length=128)
一对多
使用外键:

class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=64,unique=True) price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99) publisher=models.ForeignKey( to="Publisher", related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。 related_query_name="xxoo",#用于双下方法查询 on_delete=True, ) def __str__(self): return "<Book Object:{}>".format(self.title)
关联表内字段

class Comment(models.Model): """ 评论表 """ nid=models.AutoField(primary_key=True) article=models.ForeignKey(to="Article",to_field="nid") user=models.ForeignKey(to="UserInfo",to_field="nid") content=models.CharField(max_length=255) create_time=models.DateTimeField(auto_now_add=True) parent_comment=models.ForeignKey("self",null=True)
多对多
方式一:自动生成,第三张表

#书 class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=64,unique=True) price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99) publisher=models.ForeignKey( to="Publisher", related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。 related_query_name="xxoo",#用于双下方法查询 on_delete=True, ) def __str__(self): return "<Book Object:{}>".format(self.title) #作者 class Author(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=16,unique=True) book=models.ManyToManyField(to="Book") def __str__(self): return "<Author Object:{}>".format(self.name)
方式二:手动创建第三张表

# 出版社 class Publisher(models.Model): name = models.CharField(max_length=32) city = models.CharField(max_length=32) def __str__(self): return self.name # 书 class Book(models.Model): title = models.CharField(max_length=32) publish_date = models.DateField(auto_now_add=True) price = models.DecimalField(max_digits=5, decimal_places=2) # 创建外键,关联publish publisher = models.ForeignKey(to="Publisher") def __str__(self): return self.title # 作者 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() phone = models.IntegerField() books = models.ManyToManyField(to="Book", related_name="authors") detail = models.OneToOneField(to="AuthorDetail") def __str__(self): return self.name # 作者详情 class AuthorDetail(models.Model): # 爱好 hobby = models.CharField(max_length=32) # 地址 addr = models.CharField(max_length=128)
方式三:指定关联创建

class Book(models.Model): title = models.CharField(max_length=32, verbose_name="书名") # 自己创建第三张表,并通过ManyToManyField指定关联 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) # through_fields接受一个2元组('field1','field2'): # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。 class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book") class Meta: unique_together = ("author", "book")
orm操作
查询
查询示例
model1

from django.db import models # Create your models here. ''' 图书馆里系统 ''' #出版社 class Publisher(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=64,unique=True) addr=models.CharField(max_length=128) def __str__(self): return "<Publisher Object:{}>".format(self.name) #书 class Book(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=64,unique=True) publish_date = models.DateField(verbose_name='出版日期',auto_now_add=True,null=True,blank=True) # 库存数 kucun = models.IntegerField(default=1000) # 卖出数 maichu = models.IntegerField(default=0) price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99) publisher=models.ForeignKey( to="Publisher", related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。 related_query_name="xxoo",#用于双下方法查询 on_delete=True, ) def __str__(self): return "<Book Object:{}>".format(self.title) #作者 class Author(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=16,unique=True) book=models.ManyToManyField(to="Book") detail=models.OneToOneField(verbose_name="用户详情",to="AuthorDetail",on_delete=models.CASCADE,null=True,blank=True) def __str__(self): return "<Author Object:{}>".format(self.name) class Person(models.Model): name = models.CharField(max_length=32) age = models.IntegerField(default=18) birthday = models.DateField(auto_now_add=True) def __str__(self): return "<Person Object:{}>".format(self.name) #作者详情 class AuthorDetail(models.Model): hobby=models.CharField(verbose_name='爱好',max_length=32,null=True) addr=models.CharField(verbose_name='地址',max_length=128,null=True) #手动创建第三张表 # class Author2Book(models.Model): # id = models.AutoField(primary_key=True) # # 作者id # author = models.ForeignKey(to="Author") # # 书id # book = models.ForeignKey(to="Book") # # class Meta: # # 建立联合唯一约束 # unique_together = ("author", "book")
orm1

""" ORM小练习 如何在一个Python脚本或文件中 加载Django项目的配置和变量信息 """ import os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings') import django django.setup() from app01 import models #查询所有 # ret=models.Person.objects.all() # print(ret) #get查询(不存在会报错) # ret2=models.Person.objects.get(name='李世民1') # print(ret2) #filter # ret3=models.Person.objects.filter(id=1) # print(ret3) #查询结果只有一个也返回queryset # ret4=models.Person.objects.filter(id=1)[0] # print(ret4) # print("exclude".center(80, "*")) # #查询除了id=1的 # ret5=models.Person.objects.exclude(id=1) # print(ret5) #只查询指定字段,里面是字典 # ret6=models.Person.objects.values('name','birthday') # print(ret6) # 只查询指定字段,里面是元祖 # ret7=models.Person.objects.values_list('name','birthday') # print(ret7) #字段排序 # ret8 = models.Person.objects.order_by('birthday') # print(ret8) #将有序的Querysset进行反转 # ret9 = models.Person.objects.order_by('id').reverse() # print(ret9) #返回queryset中对象的数量 # ret10=models.Person.objects.count() # print(ret10) #返回QuerySet中第一个对象 # ret11=models.Person.objects.first() # print(ret11) #返回QuerySet中最后一个对象 # ret12=models.Person.objects.last() # print(ret12) #判断表中有没有数据 # ret13=models.Person.objects.exists() # print(ret13) # # 单表查询双下划线 #查询id大于1小于4的内容 # r1=models.Person.objects.filter(id__gt=1,id__lt=4) # print(r1) #查询id在[1,3,5,7]中的结果 # r2=models.Person.objects.filter(id__in=[1,3,5,7]) # print(r2) #查询id不在[1,3,5,7]中的数据 # r3 = models.Person.objects.exclude(id__in=[1, 3, 5, 7]) # print(r3) #查询名字中包含李的字段 # r4=models.Person.objects.filter(name__contains='李') # print(r4) # # icontains 忽略大小写包含指定值 # r5=models.Person.objects.filter(name__icontains='C') # print(r5) # # range # # 判断id值在 哪个区间的 SQL语句中的between and 1<= <=3 # r6=models.Person.objects.filter(id__range=[1,3]) # print(r6) #日期和时间字段查询 # r7=models.Person.objects.filter(birthday__year='2018') # print(r7) # r8 = models.Person.objects.filter(birthday__year=2018, birthday__month=10) # print(r8) #外键查询 #正向查询 #基于对象跨表查询 # book_obj = models.Book.objects.all().first() # f1 = book_obj.publisher # 和我这本书关联的出版社对象 # print(f1, type(f1)) # f2=book_obj.publisher.name # print(f2) #查询id为1的书的出版社 #使用双下方法进行跨表查询 # f3=models.Book.objects.filter(id=2).values_list('price','publisher__name') # print(f3) #反向查询, #1.基于对象查询 #publisher_obj=models.Publisher.objects.get(id=1) # f4= publisher_obj.book_set.all() # print(f4) #配置related_name='books'后book_set将不再可用。 # f5= publisher_obj.books.all() # print(f5) #2.基于双下方法 #添加related_query_name="xxoo",#用于双下方法查询 # f5=models.Publisher.objects.filter(id=1).values_list('xxoo__title') # print(f5) #多对多 # 查询 # author_obj=models.Author.objects.all().first() # print(author_obj) # #查看所有书 # f6=author_obj.book.all() # print(f6,type(f6)) #通过作者添加一本书 # author_obj = models.Author.objects.all().first() # author_obj.book.create(title='明朝那些事',publisher_id=2) #add() #给id为3的作者添加id为10的一本书,必须使用get()查 #get获取的是类,filter,获取的是querySet() # author_obj=models.Author.objects.get(id=3) # book_obj=models.Book.objects.get(id=10) # author_obj.book.add(book_obj) #添加多个 # book_objs=models.Book.objects.filter(id__gt=1) # print(book_objs) # author_obj.book.add(*book_objs) #直接添加id # author_obj.book.add(9) # 删除关联 #把id为3的作者,的id为10的书取消关联 # author_obj=models.Author.objects.get(id=3) # author_obj.book.remove(10) #也可以使用对象 # book_obj=models.Book.objects.get(id=8) # author_obj.book.remove(book_obj) #clear #清除所有关联 # author_obj=models.Author.objects.get(id=3) # author_obj.book.clear() # 使用反向关联 # 找到id是1的出版社 # publisher_obj = models.Publisher.objects.get(id=2) # publisher_obj.books.clear() #聚合 from django.db.models import Avg,Max,Min,Count,Sum #获取所有书的平均价格 # h1= models.Book.objects.all().aggregate(price_avg=Avg("price")) # print(h1) #平均,最大,最小价格 # h2=models.Book.objects.all().aggregate(price_avg=Avg("price"),price_max=Max("price"),price_min=Min("price")) # print(h2) #分组查询 #查询每本书对应作者数量 # h3=models.Book.objects.all().annotate(author_num=Count("author")) # print(h3) # for book in h3: # print('书名{},作者数量:{}'.format(book.title,book.author_num)) #查询作者数量大于1的书 # h4=models.Book.objects.all().annotate(author_num=Count("author")).filter(author_num__gt=1) # for book in h4: # print('书名{},作者数量:{}'.format(book.title, book.author_num)) #查询每个作者出的书的总价格 # h5=models.Author.objects.all().annotate(price_sum=Sum("book__price")).values_list('name','price_sum') # for author in h5: # print(author) # h6=models.Author.objects.all().annotate(price_sum=Sum("book__price")) # for i in h6: # print(i,i.name,i.price_sum) # # print(h6.values_list("name","price_sum")) #F和Q from django.db.models import F #查出库存数大于卖出数的所有书】 # f1=models.Book.objects.filter(kucun__gt=F("maichu")) # print(f1) # for i in f1: # print(i.title,i.kucun,i.maichu) # print('库存{},卖出{}'.format(f1.kucun,f1.maichu)) #把每一本书的卖出数乘3 # book_obj=models.Book.objects.first() # book_obj.maichu=book_obj.maichu*3 # book_obj.save() # # models.Book.objects.update(maichu=(F("maichu")+1)*3) #给每一本书名后面加上第一版 from django.db.models.functions import Concat from django.db.models import Value # models.Book.objects.update(title=Concat(F("title"),Value("第一版"))) from django.db.models import Q #查询卖出数大于1000,价格小于100的所有书 # q1=models.Book.objects.filter(maichu__gt=1000,price__lt=100) # print(q1) #查询卖出数大于1000或价格小于100的所有书 # q2=models.Book.objects.filter(Q(maichu__gt=1000)|Q(price__lt=100)) # print(q2) #Q查询和字段查询同时存在的,字段查询要放在后面 # q3=models.Book.objects.filter(Q(maichu__gt=1000)|Q(price__lt=100),title__contains='go') # print(q3) # Django ORM 事务 # try: # from django.db import transaction # with transaction.atomic(): # # 创建一个出版社 # new_publisher = models.Publisher.objects.create(name="火星出版社", addr="火星路") # # 创建一本书 # models.Book.objects.create( # title='橘子物语', # price=11.11, # kucun=100, # maichu=10, # publisher_id=1000#指定一个不存在的出版社 # ) # except Exception as e: # print(str(e)) #没有指定原子操作 # try: # #创建一个出版社 # new_publisher=models.Publisher.objects.create(title="火星出版社",addr="火星路") # #创建一本书 # models.Book.objects.create( # title='橘子物语', # price=11.11, # kucun=100, # maichu=10, # publisher_id=1000 # ) # except Exception as e: # print(str(e)) #执行原生sql from django.db import connection # cursor=connection.cursor() # cursor.execute("select * from app01_book where id=%s",[2]) # #多条查询 # # ret=cursor.fetchall() # #单条查询 # ret=cursor.fetchone() # print(ret) # 在QuerSet查询的基础上自己指定其他的SQL语句(了解即可)
orm2

import sys,os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings') import django django.setup() from app01 import models #一对一关联 o1=models.Author.objects.first(); print(o1.detail.hobby) #查询id为2作者关联的书 # author_obj=models.Author.objects.get(id=2) # print(author_obj.book.all()) #从作者2关联的书中移除id为2的书 # models.Author.objects.get(id=2).book.remove(2) #在app01中,查询,作者id为1,的所有书的id, from app02 import models # o3=models.Author2Book.objects.filter(author_id=1).values_list('book_id') # ret=[i[0] for i in o3] # print(ret) # o4=models.Book.objects.filter(id__in=ret) # print(o4) #刪除关联 # models.Author2Book.objects.get(book_id=1,author_id=1).delete()
orm3

import sys,os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings') import django django.setup() from app01 import models #查询名字里面包含go的书 # q1=models.Book.objects.filter(title__contains='go') # print(q1) #查询2019年出版的书 # q2=models.Book.objects.filter(publish_date__year=2019) # print(q2) #去重distinct() #查询所有书关联的出版社 # q3=models.Book.objects.all().values_list("publisher__name") # print(q3.distinct()) #把所有的书按照价格倒序排列 # q4=models.Book.objects.all().order_by('price').reverse() # # print(q4) #支持负号 # q5=models.Book.objects.all().order_by('-price') # print(q5) #查询go法典的出版社城市 # q6=models.Book.objects.filter(title='go法典').values_list("publisher__addr") # print(q6) #查询go法典作者的爱好 # q7=models.Book.objects.filter(title='go法典').values_list("author__detail__hobby") # print(q7) #
增加
models.UserInfo.objects.create(name="张三")
修改
删除
del_obj = models.Publisher.objects.get(id=del_id)
# 删除
del_obj.delete()
其他技巧
自定义数据类型

from django.db import models ''' 自定义char字段 ''' class FixedCharField(models.Field): """ 自定义的char类型的字段类 """ def __init__(self, max_length, *args, **kwargs): super().__init__(max_length=max_length, *args, **kwargs) self.length = max_length def db_type(self, connection): """ 限定生成数据库表的字段类型为char,长度为length指定的值 """ return 'char(%s)' % self.length
在python脚本中调用django环境
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() from app01 import models books = models.Book.objects.all() print(books)
在django终端打印sql语句
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }