Python学习之路—2018/6/29
1.跨表查询
跨表查询:
- 基于对象查询
- 基于双下划线查询
- 聚合和分组查询
- F与Q查询
F查询
过滤器只能讲字段值与常量进行比较,如果需要用到与字段值进行比较则需要用到F查询,F查询还支持与常量之间的加减乘除的运算。数据:
# 查询评论数大于阅读数的书籍
>>> Book.objects.filter(comment_count__gt=F("read_count"))
<QuerySet [<Book: 斗破苍穹>, <Book: 吞噬星空>]>
# 将所有书的价格提高10元
>>> Book.objects.all().update(price=F("price")+10)
Q查询
过滤器中可以用逗号起到“和”的作用,如果想要用“或”的操作就需要用到Q查询
# 查询书籍名为斗破苍穹或者价格为130的
>>> Book.objects.filter(Q(title="斗破苍穹") | Q(price=130))
<QuerySet [<Book: 坏蛋是怎样炼成的>, <Book: 斗破苍穹>, <Book: 武动乾坤>]>
2.基于多表的图书管理系统
主要有图书的增删改查四个功能,对应设置四个视图函数分别为add()、query()、edit()、delete()
2.1 创建模型
分别有作者表(author),作者详细信息表(authordetail),图书表(book),出版社表(publish)以及作者图书关联表(book_authors)。
其中因为一个作者只有一个详细信息,所以作者表(author)与作者详细信息表(authordetail)是一对一关系;一个出版社可以出版多本书,所以图书表(book)与出版社表(publish)是一对多关系;一个出版社可以出版多个作者的书籍,而一位作者可以签约多个出版社,所以图书表(book)与作者表(author)是多对多关系。
models.py
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建立一对一关系
author_detail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)
def __str__(self):
return self.name
class AuthorDetail(models.Model):
aid = models.AutoField(primary_key=True)
birthday = models.DateField()
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64)
class Publish(models.Model):
pid = 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 Book(models.Model):
bid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
# 与Publish建立一对多关系,外键字段建立在多的一方
publish = models.ForeignKey(to="Publish", to_field="pid", on_delete=models.CASCADE)
"""
publish_id INT,
FOREIGN KEY(publish_id) REFERENCES publish(pid)
"""
# 与Author建立多对多关系
authors = models.ManyToManyField(to="Author")
"""
CREATE TABLE book_author(
id INT PRIMARY KEY AUTO_INCREMENT,
book_id INT,
author_id INT,
FOREIGN KEY(book_id) REFERENCES Book(bid),
FOREIGN KEY(author_id) REFERENCES Author(nid),
)
"""
def __str__(self):
return self.title
2.2 配置static
为了使static文件夹下面的css、js文件生效,需要将static路径加入到STATICFILES_DIRS中
settings.py
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
2.3 建立视图函数
views.py
from django.shortcuts import render, HttpResponse, redirect
from .models import *
def add(request):
pub_list = Publish.objects.all()
author_list = Author.objects.all()
if request.method == "GET":
return render(request, "add.html", locals())
elif request.method == "POST":
# 获取输入的值
title = request.POST.get("title")
price = request.POST.get("price")
pub_date = request.POST.get("pub_date")
publish = request.POST.get("publish")
authors_list = request.POST.getlist("author") # getlist适用于多选的
# orm添加数据
Book.objects.create(title=title, publishDate=pub_date, price=price, publish_id=publish)
book = Book.objects.get(title=title)
book.authors.add(*authors_list)
# 添加提交后回到图书界面
return redirect("/book")
def book(request):
book_list = Book.objects.all()
return render(request, "book.html", locals())
def delete(request, bid):
Book.objects.get(bid=bid).delete()
return redirect("/book")
def edit(request, bid):
book_obj = Book.objects.filter(bid=bid)
books = Book.objects.get(bid=bid)
pub_list = Publish.objects.all()
author_list = Author.objects.all()
if request.method == "GET":
return render(request, "edit.html", locals())
elif request.method == "POST":
title = request.POST.get("title")
price = request.POST.get("price")
pub_date = request.POST.get("pub_date")
authors_list = request.POST.getlist("author")
book_obj.update(title=title, price=price, publishDate=pub_date)
books.authors.set(authors_list)
return redirect("/book")
2.4 模板层
book.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>book</title>
<link rel="stylesheet" href="/static/bootstrap.min.css">
<style type="text/css">
.table-bordered>thead>tr>th, .table-bordered>tbody>tr>td{
text-align: center;
line-height: 33px;
}
</style>
</head>
<body>
<h3>查看书籍</h3>
<div class="container">
<div class="row">
<div class="col-md-8 col-lg-offset-2">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>名称</th>
<th>价格</th>
<th>出版日期</th>
<th>出版社</th>
<th>作者</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{# 根据传入的book_list,循环添加表数据 #}
{% for book in book_list %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.publishDate|date:"Y-m-d" }}</td>
<td>{{ book.publish }}</td>
<td>{% for i in book.authors.all %}
{% if forloop.last %}
<span>{{ i.name }}</span>
{% else %}
<span>{{ i.name }}</span>,
{% endif %}
{% endfor %}
</td>
<td>
<a class="btn btn-primary" href="/edit/{{ book.bid }}">编辑</a> {# 传入book ID参数,便于在数据库中的表寻找数据后进行编辑和删除功能 #}
<a class="btn btn-danger" href="/delete/{{ book.bid }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<a class="btn btn-default" href="/add">添加书籍</a>
</div>
</div>
</div>
</body>
</html>
add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<link rel="stylesheet" href="/static/bootstrap.min.css">
</head>
<body>
{% block h3 %}
<h3>添加书籍</h3>
{% endblock %}
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
<label>名称</label>
{% block title %}
<input class="form-control" type="text" name="title">
{% endblock title %}
</div>
<div class="form-group">
<label>价格</label>
{% block price %}
<input class="form-control" type="text" name="price">
{% endblock price %}
</div>
<div class="form-group">
<label>出版日期</label>
{% block pub_late%}
<input class="form-control" type="date" name="pub_date">
{% endblock pub_late %}
</div>
<div class="form-group">
<label>出版社</label>
<select class="form-control" name="publish">
{% for i in pub_list %}
{% block publish %}
<option value="{{ i.pk }}">{{ i.name }}</option>
{% endblock %}
{% endfor %}
</select>
</div>
<div class="form-group">
<label>作者</label>
<select class="form-control" name="author" multiple>
{% for author in author_list %}
{% block author %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endblock %}
{% endfor %}
</select>
</div>
<input type="submit" class="btn btn-default">
</form>
</div>
</div>
</div>
</body>
</html>
edit.html
继承add.html,重写block里的内容
{% extends "add.html" %}
{% block h3 %}
<h3>编辑书籍</h3>
{% endblock %}
{% block title %}
{{ book_obj.title }}
<input class="form-control" type="text" name="title" value="{{ books.title }}">
{% endblock %}
{% block price %}
<input class="form-control" type="text" name="price" value="{{ books.price }}">
{% endblock %}
{% block pub_late%}
<input class="form-control" type="date" name="pub_date" value="{{ books.publishDate|date:'Y-m-d'}}">
{% endblock %}
{% block publish %}
{# 通过传入的book出版社与所有出版社名字进行比较,相同的添加selected属性,起到编辑时的默认选中功能 #}
{% if books.publish.name == i.name %}
<option value="{{ i.pk }}" selected>{{ i.name }}</option>
{% else %}
<option value="{{ i.pk }}">{{ i.name }}</option>
{% endif %}
{% endblock %}
{% block author %}
{% if author in books.authors.all %}
<option value="{{ author.pk }}" selected>{{ author.name }}</option>
{% else %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endif %}
{% endblock %}
2.5 路由层
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('add/', views.add),
path('book/', views.book),
re_path(r'^delete/(d+)', views.delete),
re_path(r'^edit/(d+)', views.edit)
]
首先在浏览器中输入127.0.0.1:8080/book,到展示图书界面,接下来便可以操作添加、编辑、删除功能了。