一、添加表记录
# 方式一:
book=Book(title="GO",price="99",pub_date="2018-12-31",publish="人民出版社")
book.save()
print(book.nid) # 返回值就是 Book 生成的对象
# 方式二:
# 注意:create 方法的返回当前生成的表记录对象
book = Book.objects.create(title="GO",price="99",pub_date="2018-12-31",publish="人民出版社")
注:关于create和save方法2种方式的不同,具体详见原文链接:
https://blog.csdn.net/weixin_42134789/article/details/80203270
深入理解Django创建对象的create和save方法:
Django的模型(Model)的本质是类,并不是一个具体的对象(Object)。当你设计好模型后,你就可以对Model进行实例化从而创建一个一个具体的对象。Django对于创建对象提供了2种不同的save与create方法,我们来仔细分析下这两种方式有什么不同。
用save方法创建对象
用save方法创建一个名叫john的具体对象,我们可以这么做。记住你只有用了save()方法后,Django才会将这个对象的信息存储到数据库中。
用create方法创建对象
正因为用save方法创建对象有2步,而且编程人员容易忘记加上save(),Django提供了一个更便捷的create方法,如下。如果你使用create方法,无需再加上save()。create方法不仅创建了新的对象,而且直接将信息存储到数据库里。
save与create方法比较:
create只能用于创建新的对象,在数据库层总是执行insert的操作。save不仅用于创建新的对象,也能用于更新对象的现有数据,在数据库层总是先执行update,找不到具体对象后再执行insert的操作。对于创建全新的对象,两者都可以。如果更新已有对象信息,只能用save()方法。
User自带的create_user方法
如果你要Auth自带的User模型创建新对象,你需要使用create_user方法,而不是create方法,如下所示。create_user方法很有用,自动会给密码加Hash。
————————————————
版权声明:本文为CSDN博主「大江狗」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42134789/article/details/80203270
二 、查询表记录
1、查询API:
all(): | 查询所有结果 |
filter(**kwargs): | 包含了与所给筛选条件相匹配的对象 |
get(**kwargs): | 返回与所给筛选条件相匹配的对象,返回结果有且只有一个 |
exclude(**kwargs): | 包含了与所给筛选条件不匹配的对象 |
order_by(*field): | 对查询结果排序 |
reverse(): | 对查询结果反向排序 |
order_by(*field): | 对查询结果排序 |
count(): | 返回数据库中匹配查询(QuerySet)的对象数量。 |
first(): | 返回第一条记录 |
last(): | 返回最后一条记录 |
exists(): | 如果QuerySet包含数据,就返回True,否则返回False |
distinct(): | 从返回结果中剔除重复记录 |
"""以下演示单表查询的代码"""
# 1、all(): 查询所有结果 返回值是 queryset
ret = Book.objects.all()
print(ret) # <QuerySet [<Book: Book object (22)>, <Book: Book object (23)>, <Book: Book object (24)>, <Book: Book object (25)>]>
# 2、filter(): 查询包含了与所给筛选条件相匹配的对象
ret = Book.objects.filter(title="JAVA",price="88") # 多条件查询 当一个条件不满足时,显示为空- “且”的关系。<QuerySet []>
print(ret) # <QuerySet [<Book: Book object (23)>]>
# 3、get(): # 查询结果有且只有一个才执行。
ret = Book.objects.get(price="88") # 报错:get() returned more than one Book -- it returned 3! 如果符合筛选条件的对象超过一个或者没有都会抛出错误。
ret = Book.objects.get(title="JAVA") # get() 返回与所给筛选条件相匹配的对象,返回结果有且只有一个
print(ret.title) # JAVA
# 4、first() last() # 返回第一条记录 model对象
ret = Book.objects.all()[0]
ret = Book.objects.all().first()
ret = Book.objects.all().last()
# 5、exclude() # 返回值是 queryset
ret = Book.objects.exclude(price=88)
print(ret) # <QuerySet [<Book: Book object (25)>]>
# 6、order_by # 排序,返回值是 queryset
ret = Book.objects.all().order_by("price") # 按价格升序
ret = Book.objects.all().order_by("-price") # 按价格降序
# 7、count() # 计数,返回数据库中匹配查询(QuerySet)的对象数量。返回值是 int 类型
ret = Book.objects.all().count()
print(ret) # 4
# 8、reverse() # 对查询结果反向排序
Book.objects.all().order_by("price").reverse()
# 9、exists() # 逻辑判断!如果QuerySet包含数据,就返回True,否则返回False
is_exist = Book.objects.all().exists() # b'SELECT (1) AS `a` FROM `app01_book` LIMIT 1'; args=()
if is_exist:
print("OK")
# ------------------------------------------------------------------------------------------------
# 重点!!
# 10、values() # 返回值是 queryset
ret = Book.objects.all().values("title","price") # 返回一个ValueQuerySet——一个特殊的QuerySet 列表套字典 [{...}]
print(ret) # <QuerySet [{'title': 'python', 'price': Decimal('99.00')}, {'title': 'JAVA', 'price': Decimal('88.00')}, {'title': 'JavaScript', 'price': Decimal('88.00')}, {'title': 'GO', 'price': Decimal('66.00')}]>
# 11、values_list() # 返回值是 queryset
# 12、distinct() # 从返回结果中剔除重复记录,返回值是 queryset
ret = Book.objects.all().distinct() # 针对这种 all()再调用 distinct 没有意义,因为对象包含了主键 nid,不可能重复!
ret = Book.objects.all().values("title").distinct() # 总共5本书,去重后结果是4本。配合匹配 values 去重功能才会显现
print(ret) # <QuerySet [{'title': 'python'}, {'title': 'JAVA'}, {'title': 'JavaScript'}, {'title': 'GO'}]>
2、基于双下划线的模糊查询:
"""查询价格"""
ret = Book.objects.filter(price__in=[88,99]).values("price")
# 查询价格区间在 88~99 的书籍
ret = Book.objects.filter(price__lt=100).values("price")
# 查询价格小于等于 100 的书籍
ret = Book.objects.filter(price__gt=100).values("price")
# 查询价格大于等于 100 的书籍
ret = Book.objects.filter(price__gte=80).values("price")
# 查询价格大于等于 88 的书籍
"""查询名称以 “J” 开头的"""
ret = Book.objects.filter(title__startswith="J").values("title")
# 查询结果区分大小写
ret = Book.objects.filter(title__istartswith="j").values("title")
# 查询结果不区分大小写
ret = Book.objects.filter(title__contains="S").values("title")
# 查询结果只要包含S的,区分大小写
ret = Book.objects.filter(title__icontains="S").values("title")
# 查询结果不区分大小写
"""查询时间:2018年发布的"""
ret = Book.objects.filter(pub_date__year=2018).values("title")
# 仅查询发布年份
ret = Book.objects.filter(pub_date__year=2018,pub_date__month=10).values("title")
# 查询2018年10月发布的
print(ret)
# <QuerySet []> 输出为空的原因:遇到时间偏差,因为时间模块出问题,需要到 settings.py 中修改 :USE_TZ = True 改为 False
# <QuerySet [{'title': 'C++'}]> 这是修改以后的输出,问题解决!
注意:
最后查询年月打印输出为空的原因:遇到时间偏差,因为时间模块出问题,需要到 settings.py 中修改 :USE_TZ = True 改为 False
<QuerySet [{‘title’: ‘C++’}]> 这是修改以后的输出,问题解决。
三、删除表记录
删除方法就是 delete()。它运行时立即删除对象而不返回任何值。例如:
也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。
示例:下面的代码将删除 book_price 是 123 的 Book 对象:
# 以下2种写法都可以
Book.objects.filter(price=123).delete()
Book.objects.filter(price=delete_book_price).delete()
四、修改表记录
update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
其实以上只单纯演示语法,它需要在浏览器中输入对应的值才能执行操作。相信没有人愿意这样做。在下面的案例练习中会结合HTML页面按钮,来实现增、删、改、查的操作。
练习:图书管理系统
urls.py:
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.books, name="books"),
path('books/add/', views.addbook),
# re_path('books/delete/(\d+)', views.delbook, name="books"), # 这里仅用于删除!
re_path('books/delete/(\d+)', views.delbook), # name="books"是唯一的,就不能再用了!
re_path('books/edit/(\d+)', views.editbook),
]
app01\views.py:
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book
from django.urls import reverse
def addbook(request):
"""添加功能"""
if request.method == "POST":
# 获取用户提交的数据
print(request.POST)
# ---------------------------------------------------------------------------------------
# 方式 1 :逐个取主键来创建数据,比较麻烦,特别是数据量大的情况下。
title = request.POST.get("title")
price = request.POST.get("price")
pub_date = request.POST.get("pub_date")
publish = request.POST.get("publish")
book = Book.objects.create(title=title,price=price,pub_date=pub_date,publish=publish)
# ---------------------------------------------------------------------------------------
# 方式 2 :先转成字典,再进行添加操作,相对于上面的方式1,方便许多!但是不直观!
# data = request.POST.dict()
# del data["csrfmiddlewaretoken"]
# book = Book.objects.create(**data)
# ---------------------------------------------------------------------------------------
return redirect(reverse("books"))
else:
return render(request,"addbook.html")
def books(request):
"""查询功能"""
book_list = Book.objects.all() # 查所有
# print(book_list) # [obj1, obj2, obj3...]
# print(book_list[0].title)
return render(request,"books.html",{"book_list":book_list})
def delbook(request,delete_book_id):
"""删除功能"""
Book.objects.filter(nid=delete_book_id).delete()
return redirect(reverse("books"))
def editbook(request,edit_book_id):
"""修改功能"""
# 以下2行代码只是演示了2种功能,查询与编辑同时进行
# Book.objects.filter(nid=edit_book_id).update(price=88,title="Django") # 只要输入符合的ID,都会修改为:price=88,title="Django"
# Book.objects.filter(price=88).update(publish="工业出版社") # 只要输入符合的 price,都会修改为:publish="工业出版社"
if request.method == "GET": # GET请求
edit_book = Book.objects.filter(nid=edit_book_id)[0]
return render(request, "editbook.html",{"edit_book":edit_book})
else: # POST请求
title = request.POST.get("title")
price = request.POST.get("price")
pub_date = request.POST.get("pub_date")
publish = request.POST.get("publish")
Book.objects.filter(nid=edit_book_id).update(title=title, price=price, pub_date=pub_date, publish=publish)
return redirect("/books/")
models.py:
from django.db import models
# 存放表结构
class Book(models.Model):
nid = models.AutoField(primary_key=True) #自动递增主键
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2) #999999.99
pub_date = models.DateTimeField() #"2019-10-01"
publish = models.CharField(max_length=32)