Django-model基础

时间:2022-08-16 16:28:36

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表内容

Django-model基础

常用查询相关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")

输出:

回龙观