from django.db import models
# 作者表
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE) # 作者和作者详细信息 一对一关系
# 如果不创建nid,mysql会自动创建id,建立联系时候需要添加to_field
# authorDetail = models.OneToOneField(to="AuthorDetail", to_field="id")
def __str__(self):
return self.name
# 作者详细信息表
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday = models.DateField()
telephone = models.CharField(max_length=32)
address = models.CharField(max_length=64)
def __str__(self):
return self.address
# 出版社
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
# 书籍表
class Books(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.ForeignKey(to="Publish") # 一个出版社可出版多本书籍 多对一关系
authors = models.ManyToManyField(to="Author") # 一个作者有多本书籍,一本书籍可由多个作者完成 多对多关系
# authors = models.ManyToManyField(to="Author", through="BookToAuthor",through_fields=("author_id", "book_id"))
def __str__(self):
return self.title
# 通过创建第三张表的方式,建立多对多关系,里面可以添加额外字段
# class BookToAuthor(models.Model):
# book_id = models.ForeignKey(to="Books")
# author_id = models.ForeignKey(to="Author")
# other = models.CharField(max_length=32)
# 方式一 作者和作者信息
def add(request):
author_detail = models.AuthorDetail.objects.create(
birthday="1990-01-01",
telephone="18000000000",
address="恶魔岛",
)
models.Author.objects.create(
name="罗宾",
age="18",
authorDetail=author_detail
)
return HttpResponse("200")
# 方式二
def add(request):
obj = models.AuthorDetail.objects.get(address="葫芦岛")
# obj = models.AuthorDetail.objects.filter(address="冰火岛").first()
models.Author.objects.create(
name="葫芦娃",
age="18",
authorDetail=obj
)
return HttpResponse("200")
# 方式三
def add(request):
obj = models.AuthorDetail.objects.get(address="蛋糕岛")
# obj = models.AuthorDetail.objects.filter(address="冰火岛").first()
models.Author.objects.create(
name="大妈",
age="88",
authorDetail_id=obj.nid
)
return HttpResponse("200")
# 跟一对一方法基本一样 书籍对出版社
def add_book(request):
obj = models.Publish.objects.get(nid=1)
models.Books.objects.create(
title="睡前故事",
publishDate="2020-07-17",
price=1.11,
publish=obj,
# publish_id=obj.nid
)
return HttpResponse("200")
# 书和出版社多对多
# 方式一
def add(request):
book_obj = models.Books.objects.get(nid=1)
book_obj.authors.add(*[1, 2])
return HttpRespon("200")
# 方式二
def add(request):
author1 = models.Author.objects.get(nid=3)
author2 = models.Author.objects.get(nid=4)
book = models.Books.objects.get(nid=2)
book.authors.add(*[author1, author2])
return HttpRespon("200")
# 一对一删除 作者和作者信息表
models.AuthorDetail.objects.get(nid=2).delete()
models.Author.objects.get(nid=3).delete()
# 一对多删除 书籍和出版社表
models.Publish.objects.get(nid=1).delete()
models.Book.objects.get(nid=1).delete()
# 多对多删除 书籍和作者表
book_obj = models.Book.objects.get(nid=6)
# book_obj.authors.remove(6) # 删除单个
# book_obj.authors.remove(*[5,6]) # 删除多个
book_obj.authors.clear() # 删除书籍nid为6的所有信息
book_obj.authors.set('1') # 删除nid为6的书籍,然后让书籍6和出版社1创建联系
book_obj.authors.set(['5','6']) # 批量操作
book_obj.authors.add(*[2, 3]) # 为书籍6添加出版社2和3的联系
# 一对一
models.Author.objects.filter(pk=5).update(
name='小崔',
age=36,
# authorDetail=models.AuthorDetail.objects.get(pk=5),
authorDetail_id=4,
)
# 一对多
models.Book.objects.filter(pk=4).update(
title='往事不堪回首',
# publishs=models.Publish.objects.get(id=3),
publishs_id=3,
)
# 多对多
book_obj = models.Book.objects.get(nid=6)
book_obj.authors.set('1') # 删除nid为6的书籍,然后让书籍6和出版社1创建联系
book_obj.authors.set(['5','6']) # 批量操作
book_obj.authors.add(*[2, 3]) # 为书籍6添加出版社2和3的联系
查询分为正向查询和反向查询,哪张表创建时候关键属性字段创建在哪张表(ForeignKey,OneToOneField、ManyToManyField),去查询另外一张表为正向查询,反之为反向查询
# 如果model中,关键属性字段添加了related_name='xx',则在反向查询时候不能用表明,只能用这个xx
def index(request):
# 一对一正向查询——查询路飞的生日
author_obj = models.Author.objects.filter(name="路飞").first()
print(author_obj.authorDetail.birthday) # authorDetail为创建关系的字段名
# 一对一反向查询——已知电话查询是谁
address_obj = models.AuthorDetail.objects.get(telephone="15000000000")
print(address_obj.author.name) # author为类名(小写)
return HttpResponse("200")
def index(request):
# 一对多正向查询——查询python这本书是那个出版社出版的
book_obj = models.Books.objects.get(title='python')
print(book_obj.publish.name)
# 一对多反向查询——查询北京出版社都出了哪些书
publish_obj = models.Publish.objects.get(name='北京出版社')
print(publish_obj.books_set.all()) # querySet类型
return HttpResponse("200")
def index(request):
# 多对多正向查询——查询金瓶梅这本书都有哪些作者创作
book_obj = models.Books.objects.get(title="金瓶梅")
print(book_obj.authors.all())
# 多对多反向查询——查询罗宾都创作了哪些书籍
author_obj = models.Author.objects.get(name="罗宾")
print(author_obj.books_set.all())
return HttpResponse("200")
# 如果model中,关键属性字段添加了related_name='xx',则在反向查询时候不能用表明,只能用这个xx
def index(request):
# 一对一正向查询——查询路飞的地址和生日
author_obj = models.Author.objects.filter(name="路飞").values('authorDetail__address', 'authorDetail__birthday')
print(author_obj)
# 一对一反向查询——查询路飞的地址和生日
author_obj = models.AuthorDetail.objects.filter(author__name="路飞").values('address', 'birthday') # author为类名(小写)
print(author_obj)
return HttpResponse("200")
def index(request):
# 一对多正向查询——查询python这本书是那个出版社出版的
book_obj = models.Books.objects.filter(title='python').values('publish__name')
print(book_obj)
# 一对多反向查询——查询python这本书是那个出版社出版的
publish_obj = models.Publish.objects.filter(books__title='python').values('name')
print(publish_obj)
return HttpResponse("200")
def index(request):
# 多对多正向查询——查询金瓶梅这本书都有哪些作者创作
book_obj = models.Books.objects.filter(title="金瓶梅").values('authors__name')
print(book_obj)
# 多对多反向查询——查询金瓶梅这本书都有哪些作者创作
author_obj = models.Author.objects.filter(books__title="金瓶梅").values('name')
print(author_obj)
return HttpResponse("200")
# 多于两张表的查询
def index(request):
# 北京出版社出版的所有书名称和作者名称
obj = models.Publish.objects.filter(name="北京出版社").values("books__title","books__authors__name")
print(obj)
# 手机号以4开头的作者出版过的所有书籍名称以及出版社名称
ret = models.AuthorDetail.objects.filter(telephone__startswith='4').values('author__book__title','author__book__publishs__name')
return HttpResponse("200")
from django.db.models import Min, Max, Avg
def index(request):
# 查询书籍的平均价格,最大价格,最小价格
price_dict = models.Books.objects.all().aggregate(Avg('price'), Max('price'), Min('price'))
# price_dict = models.Books.objects.all().aggregate(a=Avg('price'), m=Max('price'), n=Min('price')) # 将返回字典的key起别名
print(price_dict) # {'price__avg': 76.4, 'price__max': Decimal('188.70'), 'price__min': Decimal('10.00')}
return HttpResponse("200")
def query(request):
# 统计每个出版社出版书籍的平均价格
# 方法一
ret = models.Books.objects.values("publish__nid", "publish__name").annotate(a=Avg("price"))
print(ret) #
# 方法二
ret = models.Publish.objects.annotate(a=Avg("books__price")).values("name", "a")
print(ret)
return HttpResponse("200")
from django.db.models import F,Q
def query(request):
# books表添加评论和点赞字段
# 查询books表中 点赞数大于评论数+1的书籍
ret = models.Books.objects.filter(like__gt=F('comment')+1)
print(ret)
# 让books表中的说有书籍价格加20
models.Books.objects.all().update(price=F('price')+20)
return HttpResponse("200")
def query(request):
# 查询评论数大于70的或点赞数小于等于70的书籍
ret = models.Books.objects.filter(Q(comment__gt=70) | ~Q(like__gt=70))
# Q还可做嵌套
# ret = models.Books.objects.filter(Q(Q(comment__gt=70) | Q(like__gt=70)) & Q(price=38))
print(ret)
return HttpResponse("200")
# 多个Q查询配置
def customers(request):
kw = request.GET.get('kw') # 关键字
search_field = request.GET.get("search_field")
if kw:
q_obj = Q()
q_obj.connector = 'or' # 设置多个Q之间关系,default=and
q_obj.children.append((search_field, kw)) # 将查询条件 k=v 添加到元组中
customer_list = models.Customer.objects.filter(q_obj)
def query(request):
ret = models.Books.objects.raw('select * from app01_books')
print(ret) #
for i in ret:
print(i.publishDate)
return HttpResponse("200")
from django.db import connection
def query(request):
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from app01_author where nid = %s""", [1])
ret = cursor.fetchone()
print(ret) # (1, '路飞', 18, 1)
return HttpResponse("200")
# 查看原生sql语句
from django.db import connection
print(connection.queries)
# 行级锁——必须用在事务里边——select_for_update()
entries = Entry.objects.select_for_update().filter(author=request.user) # 加互斥锁,由于mysql在查询时自动加的是共享锁,所以我们可以手动加上互斥锁。create、update、delete操作时,mysql自动加行级互斥锁
# 全局事务settings
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mxshop',
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': 'root',
'PASSWORD': '123',
'OPTIONS': {
"init_command": "SET default_storage_engine='INNODB'",
#'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", #配置开启严格sql模式
}
"ATOMIC_REQUESTS": True, #全局开启事务,绑定的是http请求响应整个过程
"AUTOCOMMIT":False, #全局取消自动提交,慎用
},
'other':{
'ENGINE': 'django.db.backends.mysql',
......
} #还可以配置其他数据库
}
# views
from django.db import transaction
@transaction.non_atomic_requests # 设置不使用事务处理,针对全局设置
def my_view(request):
do_stuff()
@transaction.non_atomic_requests(using='other')
def my_other_view(request):
do_stuff_on_the_other_database()
# 装饰器添加事务
from django.db import transaction
@transaction.atomic
def viewfunc(request):
# This code executes inside a transaction.
do_stuff()
# 上下文管理
from django.db import IntegrityError, transaction
@transaction.atomic
def viewfunc(request):
create_parent()
try:
with transaction.atomic():
generate_relationships()
except IntegrityError:
handle_exception()
add_children()