一.F与Q查询
model.py文件:
from django.db import models class Product(models.Model): name = models.CharField(max_length=32) # 都是类实例化出来的对象 price = models.DecimalField(max_digits=8,decimal_places=2) maichu = models.IntegerField() kucun = models.IntegerField() info = MyCharField(max_length=32,null=True) # 改字段可以为空def __str__(self): return '商品对象的名字:%s'%self.name
在数据库中添加记录后:
在test.py中的普通查询:
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day59.settings") import django django.setup() from app01 import models # 查询卖出数大于50的商品 res = models.Product.objects.filter(maichu__gt=50) print(res)
查询卖出数大于库存数的商品要使用F查询:
from django.db.models import F,Q # F查询 res = models.Product.objects.filter(maichu__gt=F('kucun')) print(res) # <QuerySet [<Product: 商品对象的名字:高跟鞋>]>
其他F查询示例:
# 将所有的商品的价格提高100块 models.Product.objects.update(price=F('price')+100) # 将所有商品的名字后面都加一个爆款 from django.db.models.functions import Concat from django.db.models import Value models.Product.objects.update(name=Concat(F('name'),Value('爆款')))
Q查询:
res = models.Product.objects.filter(price=188.88,name='连衣裙爆款') print(res) from django.db.models import F, Q res = models.Product.objects.filter(Q(price=188.88),Q(name='连衣裙爆款')) # and res = models.Product.objects.filter(Q(price=188.88)|Q(name='连衣裙爆款')) # or res = models.Product.objects.filter(Q(price=188.88)|~Q(name='连衣裙爆款')) # not # 混合使用 需要注意的是Q对象必须放在普通的过滤条件前面 res = models.Product.objects.filter(~Q(name='连衣裙爆款'),price=188.88) # Q取反再和price交集 print(res)
Q查询补充 (如果过滤的条件是字符串的查询方式):
# from django.db.models import F, Q q = Q() q.connector = 'or' # 通过这个参数可以将Q对象默认的and关系变成or q.children.append(('price',300.00)) q.children.append(('name','高跟鞋爆款')) res = models.Product.objects.filter(q) # Q对象查询默认也是and print(res)
二.事务
# 事务的ACID """ 原子性 一致性 隔离性 持久性 """ from django.db import transaction from django.db.models import F with transaction.atomic(): # 在with代码块儿写你的事务操作 models.Product.objects.filter(id=1).update(kucun=F('kucun')-1) models.Product.objects.filter(id=1).update(maichu=F('maichu')+1) # 写其他代码逻辑
三.自定义orm字段
from django.db import models # Create your models here. class MyCharField(models.Field): def __init__(self,max_length,*args,**kwargs): self.max_length = max_length super().__init__(max_length=max_length,*args,**kwargs) def db_type(self, connection): return 'char(%s)'%self.max_length
class Product(models.Model): name = models.CharField(max_length=32) # 都是类实例化出来的对象 price = models.DecimalField(max_digits=8,decimal_places=2) maichu = models.IntegerField() kucun = models.IntegerField() info = MyCharField(max_length=32,null=True) # 改字段可以为空
四.only与defer (拿到的是一个对象 两者是相反的):
首先给product对象添加一个name属性,如果查询的恰好就是name,只需走一次数据库,如果查的是其他属性,比如price, product对象无此属性,需要走多次数据库 # res = models.Product.objects.values('name') # print(res) # < QuerySet[{'name': '丝袜爆款'}, {'name': '连衣裙爆款'}, {'name': '高跟鞋爆款'}] > 查询name字段: 走1次数据库 res = models.Product.objects.only('name') for i in res: print(i.name) 查询price字段: 走4次数据库 res = models.Product.objects.only('name') for i in res: print(i.price)
defer与only访问数据库的方式正好相反: 查询name字段: 走4次数据库 res = models.Product.objects.defer('name') for i in res: print(i.name) 查询price字段: 走1次数据库 res = models.Product.objects.defer('name') for i in res: print(i.price)
五.choices字段
models.py:
class Product(models.Model): name = models.CharField(max_length=32) # 都是类实例化出来的对象 price = models.DecimalField(max_digits=8,decimal_places=2) maichu = models.IntegerField() kucun = models.IntegerField() # info = MyCharField(max_length=32,null=True) # 改字段可以为空 choices = ((1,'男'),(2,'女'),(3,'其他')) gender = models.IntegerField(choices=choices,default=2)
test.py:
res = models.Product.objects.filter(id=1).first() print(res.gender) # 1 print(res.get_gender_display()) # 获取编号对应的中文注释 男 创建时传数字: models.Product.objects.create(...gender=1)
六.图书管理系统
models.py:
class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_time = models.DateField(auto_now_add=True) publish = models.ForeignKey(to='Publish') authors = models.ManyToManyField(to='Author') def __str__(self): return '书籍对象的名字:%s'%self.title
class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return '出版社对象的名字:%s'%self.name class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() authordetail = models.OneToOneField(to='AuthorDetail') def __str__(self): return '作者对象的名字:%s'%self.name class AuthorDetail(models.Model): phone = models.BigIntegerField() addr = models.CharField(max_length=32) def __str__(self): return '作者详情对象的名字:%s'%self.phone
1.创建主页:
urls.py:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.home), ]
views.py:
from django.shortcuts import render,redirect,HttpResponse,reverse from app01 import models # Create your views here. def home(request): return render(request,'home.html')
home.html:
主页效果:
2.查询所有书籍:
urls.py:
url(r'^admin/', admin.site.urls), url(r'^$', views.home), url(r'^book_list/', views.show_book,name='book_list'),
views.py:
def show_book(request): # 先查询所有的书籍 book_list = models.Book.objects.all() return render(request,'book_list.html',locals())
book_list.html (继承主页页面,并在block区域添加表格):
{% extends 'home.html' %} {% block content %} <a href="{% url 'book_add' %}" class="btn btn-success">添加</a> <table class="table table-striped table-bordered table-hover"> <thead> <tr> <th>id</th> <th>title</th> <th>price</th> <th>publish_time</th> <th>publish</th> <th>authors</th> <th>actions</th> </tr> </thead> <tbody> {% for book in book_list %} <tr> <td>{{ book.pk }}</td> <td>{{ book.title }}</td> <td>{{ book.price }}</td> <td>{{ book.publish_time|date:'Y-m-d' }}</td> <td>{{ book.publish.name }}</td> <td> {% for author_obj in book.authors.all %} {% if forloop.last %} {{ author_obj.name }} {% else %} {{ author_obj.name }}, {% endif %} {% endfor %} </td> <td> <a href=" " class="btn btn-primary btn-sm">编辑</a> <a href=" " class="btn btn-danger btn-sm">删除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
点击图书列表会打开book_list页面 (因为在home.html里面通过a链接到了book_list路由):
<a href="{% url 'book_list' %}" class="list-group-item">图书列表</a>
效果:
3.添加书籍:
点击添加按钮,则跳转到add_book页面,所以需要在book_list.html 的a链接连到add_book路由:
<a href="{% url 'book_add' %}" class="btn btn-success">添加</a>
urls.py:
url(r'^admin/', admin.site.urls), url(r'^$', views.home), url(r'^book_list/', views.show_book,name='book_list'), url(r'^add_book/', views.add_book,name='book_add'),
views.py:
from django.shortcuts import render,HttpResponse,redirect,reverse from app01 import models def add_book(request): if request.method == 'POST': # print(request.POST) title = request.POST.get("title") price = request.POST.get("price") publish_date = request.POST.get("date") publish_id = request.POST.get("publish") authors = request.POST.getlist("authors") # 数据库新增数据 book_obj = models.Book.objects.create(title=title,price=price,publish_time=publish_date,publish_id=publish_id) # 你可以尝试用**request.POST来新增数据(字典拆开的value是列表,不可行) # 去书籍与作者的第三表手动创建关系 book_obj.authors.add(*authors) # 跳转到图书的展示页面 return redirect(reverse('book_list')) # 将出版社和作者数据全部传递给添加页面 publish_list = models.Publish.objects.all() author_list = models.Author.objects.all() # get请求返回一个添加页面 return render(request,'add_book.html',locals())
add_book.html:
{% extends 'home.html' %} {% block content %} <h1 class="text-center">添加书籍</h1> <form action="" method="post"> <p>title:<input type="text" class="form-control" name="title"></p> <p>price:<input type="text" class="form-control" name="price"></p> <p>publish_date:<input type="date" class="form-control" name="date"></p> <p>publish: <select name="publish" id="" class="form-control"> {% for publish in publish_list %} <option value="{{ publish.pk }}">{{ publish.name }}</option> {% endfor %} </select> </p> <p>authors: <select name="authors" id="" class="form-control" multiple> {% for author in author_list %} <option value="{{ author.pk }}">{{ author.name }}</option> {% endfor %} </select> </p> <input type="submit" class="btn btn-warning pull-right"> </form> {% endblock %} </body> </html>
4.删除书籍:
点击删除按钮,则跳转到delete_book页面,所以需要在book_list.html 的a链接连到delete_book路由:
<a href="{% url 'book_delete' book.pk %}" class="btn btn-danger btn-sm">删除</a>
urls.py:
url(r'^admin/', admin.site.urls), url(r'^$', views.home), url(r'^book_list/', views.show_book,name='book_list'), url(r'^add_book/', views.add_book,name='book_add'), url(r'^delete_book/(d+)/', views.delete_book,name='book_delete'),
views.py:
def delete_book(request,delete_id): # 获取用户想要删除的数据的id??? # print(delete_id) models.Book.objects.filter(pk=delete_id).delete() return redirect(reverse('book_list'))
5.编辑书籍:
点击编辑按钮,则跳转到edit_book页面,所以需要在book_list.html 的a链接连到edit_book路由:
<a href=" {% url 'book_edit' book.pk %}" class="btn btn-primary btn-sm">编辑</a>
urls.py:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.home), url(r'^book_list/', views.show_book,name='book_list'), url(r'^add_book/', views.add_book,name='book_add'), url(r'^delete_book/(d+)/', views.delete_book,name='book_delete'), url(r'^edit_book/(d+)/', views.edit_book,name='book_edit'), ]
views.py:
def edit_book(request,edit_id): # 返回一个编辑页面,但是你这个编辑页面需要将原来数据的信息展示出来 edit_obj = models.Book.objects.filter(pk=edit_id).first() if request.method == 'POST': # print(request.POST) title = request.POST.get("title") price = request.POST.get("price") publish_date = request.POST.get("date") publish_id = request.POST.get("publish") authors = request.POST.getlist("authors") models.Book.objects.filter(pk=edit_id).update(title=title,price=price,publish_time=publish_date,publish_id=publish_id) edit_obj.authors.set(authors) return redirect(reverse('book_list')) publish_list = models.Publish.objects.all() author_list = models.Author.objects.all() return render(request,'edit.html',locals())
edit.html:
{% extends 'home.html' %} {% block content %} <h1 class="text-center">编辑书籍</h1> <form action="" method="post"> <p>title:<input type="text" class="form-control" name="title" value="{{ edit_obj.title }}"></p> <p>price:<input type="text" class="form-control" name="price" value="{{ edit_obj.price }}"></p> <p>publish_date:<input type="date" class="form-control" name="date" value="{{ edit_obj.publish_time|date:'Y-m-d' }}"></p> <p>publish: <select name="publish" id="" class="form-control"> {% for publish in publish_list %} {% if edit_obj.publish == publish %} <option value="{{ publish.pk }}" selected>{{ publish.name }}</option> {% else %} <option value="{{ publish.pk }}">{{ publish.name }}</option> {% endif %} {% endfor %} </select> </p> <p>authors: <select name="authors" id="" class="form-control" multiple> {% for author in author_list %} {% if author in edit_obj.authors.all %} <option value="{{ author.pk }}" selected>{{ author.name }}</option> {% else %} <option value="{{ author.pk }}">{{ author.name }}</option> {% endif %} {% endfor %} </select> </p> <input type="submit" class="btn btn-warning pull-right"> </form> {% endblock %}