Django-model基础
Django-model基础
在Django-ORM中表和类存在映射关系
表名<------------>类名
字段<------------>属性
表记录<------------>类实例对象
常用的字段选项
每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。还有一些适用于所有字段的通用参数:
(1)null
如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
(2)blank
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
(3)default
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
(4)primary_key
如果为True,那么这个字段就是主键。如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。
(5)unique
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
创建表单表操作
创建表
1.创建一张Book表用于存放指定的字段,在models.py模块中创建一个class用于创建表;
class Book(models.Model):
id=models.AutoField(primary_key=True)
title=models.CharField(max_length=32)
pubDate=models.DateField()
price=models.DecimalField(max_digits=6,decimal_places=2)
publish=models.CharField(max_length=32)
注释:
AutoField # 自增约束,自增前提这个键为数字类型
CharField # 表示字符串类型
DateField # 日期类型
DecimalField # 小数类型
字段选项:
primary_key=True # 表示该字段为主键
max_length=32 # 表示字符串的长度
max_digits=6,decimal_places=2 # 表示最大位数为 6位,小数点为2
数据化迁移:
写完表字段后,需要将创建的class类写入到数据库中,所以需要数据化迁移;
# 在项目所在路径 依次执行
C:\pyDjango\cms\cms>python manage.py makemigrations
C:\pyDjango\cms\cms>python manage.py migrate
注:如果执行完以上两步,发现没有完成表的创建,检查settings.py中是否注册该APP
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]
表记录查询
将数据引入到views.py模块中;
from app01 import models
通过objects表管理器操作单表中内容;
1.查询出数据库中所有的数据--objects.all()
from app01 import models
def index(request):
bookList=models.Book.objects.all()
return render(request,"index.html",{"bookList":bookList})
2.插入数据--create()
from app01 import models
def add(request):
if request.method=="POST":
# 如果前端为POST提交数据,先或去所有提交的数据内容
title=request.POST.get("title")
pubdate=request.POST.get("pubdate")
price=request.POST.get("price")
publish=request.POST.get("publish")
# 插入数据 需要将,数据库字段:获取前端值, 一一对应
models.Book.objects.create(title=title,pubDate=pubdate,price=price,publish=publish)
# 添加完成数据后,将页面跳转到 首页
return redirect("/index/")
3.查询数据 和 删除数据,需要从前端接收指定的数据--filter(id=id)和delete()
from app01 import models
def delBook(request,id):
# 根据id值查询出该条语句,然后进行删除
models.Book.objects.filter(id=id).delete()
return redirect("/index/")
4.修改数据 -- update()
def editBook(request,id):
if request.method=="POST":
title=request.POST.get("title")
pubdate=request.POST.get("pubdate")
price=request.POST.get("price")
publish=request.POST.get("publish")
# 根据id值查询出需要修改的那条语句,然后进行update()
models.Book.objects.filter(id=id).update(title=title,pubDate=pubdate,price=price,publish=publish)
return redirect("/index/")
# 获取Book 对象,模板可以调用 所有的方法 edit_book.title 获取书名
edit_book=models.Book.objects.filter(id=id)[0] # 返回值QuerySet [obj1,]
# 当时get 获取时,给用户 返回 edit.html页面,并带着 edit_book 对象数据
return render(request,"edit.html",{"edit_book":edit_book})
表记录的添加
普通字段添加
方法一:通过save存入数据库
publish_obj = models.Book(title=titles, pubDate=pubdate, price=price, publish=publish)
publish_obj.save() # 将数据保存到数据库
方法二:通过publish_obj存入数据库create
models.Book.objects.create(title=titles,pubDate=pubdate,price=price,publish=publish)
方法三:通过request.POST直接获取提交的内容,适用于单表操作 且 获取前端name值和表字段名需要匹配
if request.method=="POST":
models.Book.objects.create(**request.POST.dict())
return redirect("/index/")
一对多表外键字段
方法一:根据obj对象赋值
if request.method=="POST":
titles = request.POST.get("title")
pubdate = request.POST.get("pubdate")
price = request.POST.get("price")
publish_id = request.POST.get("pub")
# 如果拿到的是一个出版社的名称,根据名称找出出版社的obj对象来赋值
publish_obj=models.Publish.objects.filter(name="renmin")[0]
# publisher:与这本书关联的出版社对象 ORM中publisher=Obj中publish_obj
models.Book.objects.create(title=titles, pubDate=pubdate, price=price, publisher=publish_obj)
方法二:
if request.method=="POST":
titles = request.POST.get("title")
pubdate = request.POST.get("pubdate")
price = request.POST.get("price")
publish_id = request.POST.get("pub")
# 如果拿到的是一个关联id值,使用publisher_id直接赋值;
book_obj=models.Book.objects.create(title=titles,price=price,pubDate=pubdate,publisher_id=publish_id)
print(book_obj.title)
一对多的关联表创建
在 一对多的关联表,进行创建关联关系时,需要把关联字段创建在内容多的那张表中;
foreign key dep_id reference dep(id)
ORM创建一对多表
创建一对多的表,publisher为多表中的关联字段,指向Publish表中的主键
from django.db import models
# Create your models here.
class Book(models.Model):
nid=models.AutoField(primary_key=True)
title=models.CharField(max_length=32)
pubDate=models.DateField()
price=models.DecimalField(max_digits=6,decimal_places=2)
# 创建一个publisher 字段用作关联字段,Django会默认加上_id;关联到少的那张表 ForeignKey(to=表名) 无需指定主键
publisher=models.ForeignKey(to="Publish")
class Publish(models.Model):
# Django会默认创建 一个主键id字段
name=models.CharField(max_length=32)
addr=models.CharField(max_length=32)
tel=models.BigIntegerField()
数据化迁移:
# 在项目所在路径 依次执行
C:\pyDjango\cms\cms>python manage.py makemigrations
C:\pyDjango\cms\cms>python manage.py migrate
通过objects表管理器操作一对多表中内容;
1. 添加数据:
def add(request):
if request.method=="POST":
titles=request.POST.get("title")
pubdate=request.POST.get("pubdate")
price=request.POST.get("price")
# publish_id 获取前端传来的select 标签 name="pub"
publish_id = request.POST.get("pub")
# 将数据写入到数据库中,publisher_id=publish_id publisher_id为关联字段,publish_id为获取的前端name值
# models.Book.objects.create(title=titles,pubDate=pubdate,price=price,publisher_id=publish_id)
publish_obj = models.Book(title=titles, pubDate=pubdate, price=price,publisher_id=publish_id)
publish_obj.save()
return redirect(reverse('INDEX'))
# 将所有 出版社的 信息传给前端模板
Price_obj=models.Publish.objects.all()
return render(request,"add.html",{"Price_obj":Price_obj})
2. 前端页面操作:
<form action="{% url 'ADD' %}" method="post">
{% csrf_token %}
<p>书名:<input type="text" name="title"></p>
<p>出版日期:<input type="date" name="pubdate"></p>
<p>价格:<input type="text" name="price"></p>
<p>出版社:
{# 在模板中使用select 标签,下拉框展示出版社名称供选择 #}
<select name="pub" id="">
{# 循环所有的出版社信息表 #}
{% for foo in Price_obj %}
{# value值为出版社的id, 展示内容为 出版社名称 #}
<option value="{{ foo.id }}">{{ foo.name }}</option>
{% endfor %}
</select>
</p>
<input type="submit">
</form>
查询表记录
Book表内容
常用查询相关API
1. 查询所有结果---all():
def query(request):
# 1 all()
book_list=models.Book.objects.all() # QuerySet [obj1,obj2,]
# 循环列出所有的 书名
for book_obj in book_list:
print(book_obj.title)
输出:
数学
英语书
物理书
小黄书
2. 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。---get():
def query(request):
# book_obj=models.Book.objects.get(price=134)
book_obj=models.Book.objects.get(id=11)
print(book_obj.title)
输出:(如果符合筛选条件的对象超过一个或者没有都会抛出错误)
英语书
3. 它包含了与所给筛选条件相匹配的对象---filter():
def query(request):
# 获取所有价格 为 134 的书名
book_list=models.Book.objects.filter(price=134)
for book_obj in book_list:
print(book_obj.title)
################################################
def query(request):
# 获取所有价格 为 134 的书名 且 书名为数学
book_list=models.Book.objects.filter(price=134,title="数学")
for book_obj in book_list:
print(book_obj.title)
################################################
from django.db.models import Q
def query(request):
# 查询出 价格为 134 且名字为 语文书
book_list=models.Book.objects.filter(Q(price=134)|Q(title='语文书'))
for book_obj in book_list:
print(book_obj.title)
输出:
数学
物理书
###############################################
数学
###############################################
数学
物理书
语文书
4. 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列---values():
def query(request):
# 依照字典形式查询 出 指定的列
ret=models.Book.objects.all().values("title",'price')
print(ret)
#################################################
def query(request):
# 依照字典形式查询 所有的 结果
ret=models.Book.objects.all().values()
print(ret)
输出:
<QuerySet
[{'title': '数学', 'price': Decimal('134.00')},
{'title': '英语书', 'price': Decimal('34.00')},
{'title': '物理书', 'price': Decimal('134.00')},
{'title': '小黄书', 'price': Decimal('11.00')}]>
#################################################
<QuerySet [
{'id': 10, 'title': '数学', 'pubDate': datetime.date(2017, 11, 7), 'price': Decimal('134.00'), 'publish': '北京'},
{'id': 11, 'title': '英语书', 'pubDate': datetime.date(2017, 11, 7), 'price': Decimal('34.00'), 'publish': '机械'},
{'id': 12, 'title': '物理书', 'pubDate': datetime.date(2017, 11, 9), 'price': Decimal('134.00'), 'publish': '人民出版社'},
{'id': 13, 'title': '小黄书', 'pubDate': datetime.date(2017, 11, 17), 'price': Decimal('11.00'), 'publish': '小黄人出版社'}]>
5. 它包含了与所给筛选条件不匹配的对象(取反not)价格不是134的---exclude():
def query(request):
book_list=models.Book.objects.exclude(price=134) # QuerySet [obj1,obj2,]
for book in book_list:
print(book.title)
输出:
英语书
小黄书
6. 对查询结果排序(正序:小到大)---order_by():
def query(request):
book_list = models.Book.objects.all().order_by("price").reverse()
for i in book_list:
print(i.title, i.price)
输出:
小黄书 11.00
英语书 34.00
数学 134.00
物理书 134.00
7. 对查询结果反向排序---reverse():
def query(request):
book_list = models.Book.objects.all().order_by("price").reverse()
for i in book_list:
print(i.title, i.price)
输出:
数学 134.00
物理书 134.00
英语书 34.00
小黄书 11.00
8. 从返回结果中剔除重复纪录---distinct():
def query(request):
# 将价格重复的项剔除
ret=models.Book.objects.all().values("price").distinct()
print(ret)
输出:
<QuerySet [{'price': Decimal('134.00')}, {'price': Decimal('34.00')}, {'price': Decimal('11.00')}]>
9. values_list--它返回的是一个元组序列,values返回的是一个字典序列---values_list(*field):
def query(request):
# 依照元组形式查询 出 指定的列
ret = models.Book.objects.all().values_list("title")
print(ret)
###########################################
def query(request):
# 依照元组形式查询 出 所有列
ret = models.Book.objects.all().values_list()
print(ret)
输出:
<QuerySet [('数学',), ('英语书',), ('物理书',), ('小黄书',)]>
###########################################
<QuerySet
[(10, '数学', datetime.date(2017, 11, 7), Decimal('134.00'), '北京'),
(11, '英语书', datetime.date(2017, 11, 7), Decimal('34.00'), '机械'),
(12, '物理书', datetime.date(2017, 11, 9), Decimal('134.00'), '人民出版社'),
(13, '小黄书', datetime.date(2017, 11, 17), Decimal('11.00'), '小黄人出版社')]>
10. 返回数据库中匹配查询数量(count求匹配的条数)匹配价格为134的个数。---count():
def query(request):
count = models.Book.objects.filter(price=134).count()
print(count)
输出:
2
11. 返回第一条记录。---first():
def query(request):
book_obj=models.Book.objects.all().first()
print(book_obj.title)
输出:
数学
12. 返回最后一条记录。---last():
def query(request):
book_obj=models.Book.objects.all().last()
print(book_obj.title)
输出:
小黄书
13. 检查此次查询是否有结果,有结果就返回True,否则返回False。---exists():
def query(request):
ret=models.Book.objects.all().exists()
if ret:
print("Ok")
else:
print("NO")
输出:
Ok
完美的__双下划线
1.查询价格大于12的有几本书--"__gt=12":
def query(request):
book_list=models.Book.objects.filter(price__gt=10)
print(book_list.count())
输出:
3
2.查询依照 语文开头的书--'__startswith="语文"':
def query(request):
book_list=models.Book.objects.filter(title__startswith="语文")
print(book_list[0].title)
输出:
语文书
3.查询依照 书 结尾的书--'__endswith="书"':
book_list=models.Book.objects.filter(title__endswith="书")
for i in book_list:
print(i.title)
输出:
语文书
4.查询包含 书 字的书--'__contains="书"':
def query(request):
book_list=models.Book.objects.filter(title__contains="书")
for i in book_list:
print(i.title)
输出:
语文书
数学书
英语书
物理书
5.查询包含 不区分大小写 --'__icontains="书"':
def query(request):
book_list=models.Book.objects.filter(title__icontains="书")
for i in book_list:
print(i.title)
输出:
语文书
数学书
英语书
物理书
6.查询 价格大于12 小于120 的书 --'price__gt=12,price__lt=120':
def query(request):
book_list=models.Book.objects.filter(price__gt=12,price__lt=120)
for i in book_list:
print(i.title)
输出:
数学书
物理书
7.查询 价格 in [10,88,15]书 --'price__in=[10,88,15]':
def query(request):
book_list=models.Book.objects.filter(price__in=[10,88,15])
for i in book_list:
print(i.title)
输出:
数学书
英语书
物理书
8.查询 价格 not in [10,88,15]书 --'exclude(price__in=[10,88,15])':
def query(request):
book_list=models.Book.objects.exclude(price__in=[10,88,15])
for i in book_list:
print(i.title)
输出:
语文书
9.查询 价格 在[12,50]区间的书 --'filter(price__range=[12,50])':
def query(request):
book_list=models.Book.objects.filter(price__range=[12,50])
for i in book_list:
print(i.title)
输出:
语文书
数学书
一对多的查询
正向查询
1.根据外键所在的表,进行查询设定为正向查找
def temp(request):
# 查询出书名为小黄书的,出版社名称
book_obj=models.Book.objects.filter(title="小黄书")[0].publisher.name
print(book_obj)
输出:
小黄人出版社
反向查找book_set
1.根据出版社,查询出《小黄人出版社》出版的所有书籍
def temp(request):
# 查询出 名称为小黄人出版社的 对象,根据book_set 查出结果
pub_obj=models.Publish.objects.filter(name="小黄人出版社")[0].book_set.values_list("title","price")
print(pub_obj)
输出:
<QuerySet [('小黄书', Decimal('11.00')), ('小兵张嘎', Decimal('17.00'))]>
反向查找之双下划线__形式
正向查询按字段,反向查询按表名
1.根据出版社,查询出《小黄人出版社》出版的所有书籍
def temp(request):
# publisher__name 是Book表 外键字段的名称__name
book_ret = models.Book.objects.filter(publisher__name="小黄人出版社").values_list("title","price")
print(book_ret)
输出:
<QuerySet [('小黄书', Decimal('11.00')), ('小兵张嘎', Decimal('17.00'))]>
###多对多表关系 多对多关联表的创建,依照第三张表的创建关联关系; ####创建多对多关系表 ManyToManyField("表名") 1.创建多对多的表关系 ManyToManyField ```python from django.db import models
书籍表
class Book(models.Model):
title=models.CharField(max_length=32)
pubDate=models.DateField()
price=models.DecimalField(max_digits=6,decimal_places=2)
read_num=models.IntegerField(default=0)
comment_num=models.IntegerField(default=0)
# 创建一个publisher 字段用作关联字段,Django会默认加上_id;关联到少的那张表 ForeignKey(to=表名) 无需指定主键
publisher=models.ForeignKey(to="Publish")
# ManyToMany 指定于哪张表进行多对多的关系,默认会创建一个第三张表,用于绑定多对多的关系记录
# 于 to="Author" 指定多对多的关系
authors = models.ManyToManyField(to="Author")
出版社表
class Publish(models.Model):
# Django会默认创建 一个主键id字段
name=models.CharField(max_length=32)
addr=models.CharField(max_length=32)
tel=models.BigIntegerField()
作者表
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
<b>数据化迁移:</b>
```python
# 在项目所在路径 依次执行
C:\pyDjango\cms\cms>python manage.py makemigrations
C:\pyDjango\cms\cms>python manage.py migrate
多对多关系添加(绑定)
1.添加新书籍,将所有作者绑定到该书上;
def add(request):
if request.method == "POST":
title = request.POST.get("title")
price = request.POST.get("price")
pubdate = request.POST.get("pubdate")
pub = request.POST.get("pub")
# 获取添加这么书的对象
book_obj=models.Book.objects.create(title=title, price=price, pubDate=pubdate, publisher_id=pub)
# 获取 作者 的QuerySet集合
auth_list=models.Author.objects.all()
# 多对多的关系绑定,将这个列表集合,通过*args 的方式add 给book_obj 对象的 authors关联表
book_obj.authors.add(*auth_list)
return HttpResponse("OK")
多对多关系删除(解除绑定)
1.将指定的作者与书籍绑定关系取消--remove;
def add(request):
if request.method == "POST":
# 接触绑定关系
# 找出要解除绑定关系的那本书对象
book_obj=models.Book.objects.get(id=318)
# 找出要解除绑定关系的用户对象
wangwu=models.Author.objects.get(name="王五")
# 通过book_obj对象的authors关联关系,remove出 wangwu对象
book_obj.authors.remove(wangwu)
return HttpResponse("OK")
2.清空指定书籍对象的作者--clear;
def add(request):
if request.method == "POST":
# 接触绑定关系
# 找出要解除绑定关系的那本书对象
book_obj=models.Book.objects.get(id=317)
book_obj.authors.clear()
return HttpResponse("OK")
多对多关系查询
1.查询出id为318这本书的所有作者名称和年龄;
def add(request):
if request.method == "POST":
# 查出318这边书的对象
book_obj=models.Book.objects.filter(id=318)[0]
# 根据这本书对象.authors.values_list取出作者QuerySet集合
age=book_obj.authors.values_list("name","age")
print(age)
return HttpResponse("OK")
一对一表关系
一对一关联表创建,关联关系在任意一张表中,对应关系只能是一对一,关联字段添加一个(unique)属性
在foreign key 的基础上,关联字段必须唯一约束
创建一对一关系表 OneToOneField("表名")
1.创建一对一的表关系 OneToOneField
from django.db import models
# 作者表
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
# 作者详情表
class AuthorDetail(models.Model):
addr=models.CharField(max_length=64)
# 创建关联关系表,一对一的关系,可以任意创建在一张表中
author=models.OneToOneField("Author")
数据化迁移:
# 在项目所在路径 依次执行
C:\pyDjango\cms\cms>python manage.py makemigrations
C:\pyDjango\cms\cms>python manage.py migrate
一对一关系表正向查询
1.查询家在甘家口的作者名称
def temp(request):
authordetail=models.AuthorDetail.objects.filter(addr="甘家口")[0]
print(authordetail.author.name)
return HttpResponse("OK")
输出:
王五
一对一关系表反向查询
1.查询出李四住在哪里;
def temp(request):
# 因为是一对一的关系,所以查询出来的结果一定是唯一的对象,所以不需要 _set的参数;
att=models.Author.objects.filter(name="李四")[0].authordetail.addr
print(att)
return HttpResponse("OK")
输出:
回龙观