前戏

前面我们已经实现了出版社的增删改查,书的增删改查,书和出版社的对应关系。现在来写一下作者的增删改查和书的对应关系,那书和作者有什么关系呢?一个作者可以写多本书,一本书可以有多个作者,所以书和作者是多对多的关系,这样的话,我们就需要一张表来记录书和作者的关系,想一下sql语句是怎么创建表的

-- 创建作者表
create table author(
id int primary key auto_increment,
name varchar(32) not null
);
-- 创建作者和书的关系表
create table author2book(
id int primary key auto_increment,
author_id int not null,
book_id int not null,
constraint fk_author foreign key (author_id) references author(id) on delete cascade on update cascade,
constraint fk_book foreign key (book_id) references book(id) on delete cascade on update cascade
);

ORM创建表

使用上面的SQL语句创建表是不是很麻烦,那我们使用ORM创建表怎么创建呢?这里有两种方法

第一种:自己创建作者表和第三张关系表

# 作者表
class Author(models.Model):
id = models.AutoField(primary_key=True) # 自增id主键
name= models.CharField(max_length=32) # 作者名字 # 创建作者和书籍的关系
class Author2Book(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(to='Author', on_delete=models.CASCADE)
book = models.ForeignKey(to='Book', on_delete=models.CASCADE)

第二种:让ORM帮我们创建第三张关系表

# 作者表
class Author(models.Model):
id = models.AutoField(primary_key=True) # 自增id主键
name= models.CharField(max_length=32) # 作者名字
books = models.ManyToManyField('Book') # ManyToManyField自动帮我们创建第三张表,只是ORM层面建立的一个多对多的关系,不存在于Author表中   
  def __str__(self):
  return self.name
 

books这个字段不会出现在Author表和Book表里,会另外创建一张表来存两者之间的关系,所以写在Author表或Book表里都可以,如果写在Book表里,里面就要写Author了

我们使用第二种方法来创建数据表,因为如果我们要查作者和书的关系时,第二种方法对象.books就可以查到

执行完生成数据表的命令后,查看数据库,发现ORM自动给我们生成了第三张表,我们在两张数据表里添加一些数

用ORM查询

先来看一下数据表里的数据

作者表

作者和书的对应关系表

书表

添加路由

url(r'^author_list/', views.author_list),  # 作者列表

添加对应函数

def author_list(request):
# 查询到所有的作者
author_data = Author.objects.all() return render(request, 'author_list.html', {'author_list': author_data})

这里需要说明的是author_data是所有作者的对象,

print(author_data)  # <QuerySet [<Author: 邹邹>, <Author: 马云>, <Author: 范冰冰>, <Author: 刘亦菲>, <Author: 景甜>]>

我们去循环author_data

def author_list(request):
# 查询到所有的作者
author_data = Author.objects.all()
print(author_data) # <QuerySet [<Author: 邹邹>, <Author: 马云>, <Author: 范冰冰>, <Author: 刘亦菲>, <Author: 景甜>]>
for author in author_data:
print(author) # 取到每个出版社的作者
print(author.books) # 是一个ORM提供的桥梁,帮我找对应关系
print(author.books.all()) # 取到每个作者出版的书籍 取出来的是一个对象 print('*'*50)

结果

<QuerySet [<Author: 邹邹>, <Author: 马云>, <Author: 范冰冰>, <Author: 刘亦菲>, <Author: 景甜>]>
邹邹
appTest01.Book.None
<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]> 取出来的是一个对象
**************************************************
马云
appTest01.Book.None
<QuerySet [<Book: Book object>]>
**************************************************
范冰冰
appTest01.Book.None
<QuerySet [<Book: Book object>]>
**************************************************
刘亦菲
appTest01.Book.None
<QuerySet [<Book: Book object>]>
**************************************************
景甜
appTest01.Book.None
<QuerySet []>
**************************************************

在取添加author_list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作者列表</title>
</head>
<body>
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>作者id</th>
<th>作者姓名</th>
<th>作者作品</th>
</tr> </thead>
<tbody>
{% for author in author_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ author.id }}</td>
<td>{{ author.name }}</td>
<td style="text-align: center">
{% for book in author.books.all %}
{% if forloop.last %}
《{{ book.title }}》
{% else %}
《{{ book.title }}》,
{% endif %} {% empty %}
暂无作品
{% endfor %}
</td> </tr> {% endfor %} </tbody>
</table>
</body>
</html>

代码解释:

{% for book in author.books.all %}  在前面我们知道 author.books.all()取出来的是一个对象,因为一个作者可能有多个书,所以我们循环这个对象
{% empty %}也是for循环里的,当循环出的book是一个空对象时,执行下面的代码”暂无作品“
{% if forloop.last %}表示循环到最后一个执行下面的代码

添加作者

获取作者的功能已经实现了,那我们在写个添加作者的功能,添加作者,还要选择书,所以这里涉及了两张表,第一张是author表,第二张是author和book对应关系的那张表,先去添加路由

url(r'^add_author/', views.add_author),  # 添加作者

在去添加对应的函数

# 添加作者
def add_author(request):
book_data = Book.objects.all()
return render(request, 'add_author.html', {"book_list": book_data})

添加add_author.html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>添加作者</h1>
<form action="" method="post">
<input type="text" name="author_name">
<select name="books" multiple>
{% for book in book_list %}
<option value="{{book.id }}">{{ book.title }}</option>
{% endfor %} </select>
<input type="submit" value="提交">
</form>
</body>
</html>

因为一个作者可以有多本书,所以书籍是多选的,在去修改对应的函数

# 添加作者
def add_author(request):
if request.method == 'POST':
new_author_name = request.POST.get('author_name') # 这个只能取到一个值
book_ids = request.POST.getlist('books') # 这个取多个值,取到的是一个列表
author_obj = Author.objects.create(name=new_author_name) #创建新的作者
# author_obj.books.add(*book_ids) # 参数是一个一个单独的书籍id值,打散传进去
author_obj.books.set(book_ids) # 参数是书籍id值的列表
return redirect('/author_list/') book_data = Book.objects.all()
return render(request, 'add_author.html', {"book_list": book_data})

因为书籍是多选的,所以可能有多个书的id,所以要用到request.POST.getlist('books')

 author_obj = Author.objects.create(name=new_author_name) 返回的值是作者的名字
author_obj.books.add(*book_ids)因为只能一个一个接收参数,所以这里需要打散,记得前面要加上表名
a = [1, 2, 3]
print(*a) 结果:
1 2 3

打散

author_obj.books.set(book_ids)接收的是一个列表,和上面的效果是一样的

删除作者

添加路由

url(r'^delete_author/', views.delete_author),  # 删除作者

添加对应的函数

# 删除作者
def delete_author(request):
delete_author_id = request.GET.get('id')
Author.objects.get(id=delete_author_id).delete()
return redirect('/author_list/')

html文件只需要更改下author_list.html里的代码即可

<td>
<a href="/delete_author/?id={{ author.id }}">删除</a>
<a href="/edit_author/?id={{ author.id }}">编辑</a>
</td>

编辑作者

添加路由

url(r'^edit_author/', views.edit_author),  # 编辑作者

添加对应的函数

# 编辑作者
def edit_author(request):
edit_author_id = request.GET.get('id') # 取到要编辑的作者id
# edit_author_obj = Author.objects.get(id=edit_author_id) # 取到要编辑的作者对象
edit_author_obj = Author.objects.filter(id=edit_author_id)[0] # 取到要编辑的作者对象 if request.method == 'POST':
new_book_ids = request.POST.getlist('book_ids')
new_author_name = request.POST.get('author_name')
edit_author_obj.name = new_author_name
edit_author_obj.save()
edit_author_obj.books.set(new_book_ids) # 修改作者和书的关系表
return redirect('/author_list/')
book_data = Book.objects.all()
return render(request, 'edit_author.html', {'author': edit_author_obj, 'book_list': book_data})

说明:

edit_author_obj.books.set(new_book_ids)意思是将这个作者和书的对应关系去掉,然后重新设置对应关系

添加edit_author.html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑作者</title>
</head>
<body>
<form action="" method="post">
<input type="text" name="author_name" value="{{ author.name }}">
<select name="book_ids" multiple>
{% for book in book_list %}
{% if book in author.books.all %}
<option selected value="{{ book.id }}">{{ book.title }}</option>
{% else %}
<option value="{{ book.id }}">{{ book.title }}</option>
{% endif %}
{% endfor %} </select>
<input type="submit" value="提交">
</form> </body>
</html>

代码解释

{% if book in author.books.all %} 这里的book是book这个表里的一项,在判断这一项在没在书和作者对应关系的那张表里,如果在,则设置成默认选中的

上传文件

上传文件需要在html文件里的form表单里指定  enctype="multipart/form-data"。这样Django才能正常接收文件

添加路由

url(r'^upload/', views.upload),  # 上传文件

添加对应函数

# 上传文件
def upload(request):
if request.method == 'POST':
file_obj = request.FILES.get('file_name') # 获取文件
file_name = file_obj.name # 取到文件名+后缀
# 从上传文件对象里一点一点读取数据,写到本地
with open(file_name, 'wb') as f:
for line in file_obj:
f.write(line)
return render(request, 'upload.html') 

说明:之前获取提交的数据用的是request.POST.get或者request.GET.get,但是获取文件信息要用request.FILES.get,返回的也是一个字典,key是input输入框里的name属性

添加对应的html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="file_name">
<input type="submit">
</form>
</body>
</html> 

改版:

导入settings.py文件

from django.conf import settings

如果文件存在,重命名

# 上传文件
def upload(request):
if request.method == 'POST':
file_obj = request.FILES.get('file_name') # 获取文件
file_name = file_obj.name # 取到文件名+后缀
# 判断文件是否存在
if os.path.exists(os.path.join(settings.BASE_DIR, file_name)):
# 如果存在同名的文件
name,suffix = file_name.split('.')
name += ''
file_name = name + '.'+ suffix
# 从上传文件对象里一点一点读取数据,写到本地
with open(file_name, 'wb') as f:
for line in file_obj:
f.write(line)
return render(request, 'upload.html')

django -- ORM实现作者增删改查的更多相关文章

  1. django -- ORM实现出版社增删改查

    前戏 我们来完成一个图书管理系统的增删改查 表结构设计 1. 出版社 id   name 2. 作者 id  name 3. 书 id  title  出版社_id 4. 作者_书_关系表 id  书 ...

  2. django -- ORM实现图书增删改查

    表结构设计 上篇我们实现了出版社的增删改查,出版社数据表有两个字段id和name,那图书的表结构怎么设计呢?图书也要有一个主键id,还要有一个名称title,是哪个出版社的,要有个字段press和Pr ...

  3. Django ORM记录的增删改查结合web端

    模版语法分配变量 在views.py文件中定义一个视图函数show_data: def show_data(request): # 定义一个字典 并将它展示在前端HTML文件 user_dic = { ...

  4. [Django框架 - 静态文件配置、request对象方法初识、 pycharm链接数据库、ORM实操增删改查、django请求生命周期]

    [Django框架 - 静态文件配置.request对象方法初识. pycharm链接数据库.ORM实操增删改查.django请求生命周期] 我们将html文件默认都放在templates文件夹下 将 ...

  5. Django项目的创建与介绍.应用的创建与介绍.启动项目.pycharm创建启动项目.生命周期.三件套.静态文件.请求及数据.配置Mysql完成数据迁移.单表ORM记录的增删改查

    一.Django项目的创建与介绍 ''' 安装Django #在cmd中输入pip3 #出现这个错误Fatal error in launcher: Unable to create process ...

  6. Django之数据表增删改查

    Django数据增删改查: 上课代码 from django.shortcuts import render,HttpResponse # Create your views here. from a ...

  7. ORM多表增删改查

    一 创建多表 在models.py里创建4张表:Author(作者).AuthorDetail(作者详细信息).Publish(出版社).Book(书) 四张表关系为: (1)首先创建一对一关系.On ...

  8. 使用轻量级ORM Dapper进行增删改查

      项目背景 前一段时间,开始做一个项目,在考虑数据访问层是考虑技术选型,考虑过原始的ADO.NET.微软的EF.NH等.再跟经理讨论后,经理强调不要用Ef,NH做ORM,后期的sql优化不好做,公司 ...

  9. Django基于类的增删改查,简单逻辑都不用写

    Django是Python中一个非常牛逼的web框架,他帮我们做了很多事,里边也提前封装了很多牛逼的功能,用起来简直不要太爽,在写网站的过程中,增删改查这几个基本的功能我们是经常会用到,Django把 ...

随机推荐

  1. 【C++】Debug模式和Release模式的区别

    VS中的程序有两种编译模式:Debug模式和Release模式. Debug通常称为调试版本,通过一系列编译选项的配合,编译结果通常包含调试信息,而且不做任何优化,以为开发人员提供强大的应用程序调试能 ...

  2. 遇到 npm WARN npm npm does not support Node.js vx.x.x的解决办法

    遇到如下警告 PS C:\Users\Administrator> npm npm WARN npm npm does not support Node.js v9.11.2 npm WARN ...

  3. Spring Boot 如何干掉 if else?

    需求 这里虚拟一个业务需求,让大家容易理解.假设有一个订单系统,里面的一个功能是根据订单的不同类型作出不同的处理. 订单实体: service接口: 传统实现 根据订单类型写一堆的if else: 策 ...

  4. 机器学习之Artificial Neural Networks

    人类通过模仿自然界中的生物,已经发明了很多东西,比如飞机,就是模仿鸟翼,但最终,这些东西会和原来的东西有些许差异,artificial neural networks (ANNs)就是模仿动物大脑的神 ...

  5. Spring Boot 中 10 行代码构建 RESTful 风格应用

    RESTful ,到现在相信已经没人不知道这个东西了吧!关于 RESTful 的概念,我这里就不做过多介绍了,传统的 Struts 对 RESTful 支持不够友好 ,但是 SpringMVC 对于 ...

  6. 从 SOA 到微服务,企业分布式应用架构在云原生时代如何重塑?

    作者 | 易立 阿里云资深技术专家 导读:从十余年前的各种分布式系统研发到现在的容器云,从支撑原有业务到孵化各个新业务,企业的发展离不开统一的.与时俱进的技术架构.本篇文章从企业分布式应用架构层面介绍 ...

  7. C#安全类型转换基于convert

    using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; n ...

  8. linux命令之——grep详解

    grep命令用于查找文件里符合条件的字符串:也可以用于查找内容包含指定的范本样式的文件.它能使用正则表达式搜索,用于在文件中搜索指定的字符串模式,列出含有匹配模式子符串的文件名,并输出含有该字符串的文 ...

  9. React学习笔记③

    生命周期的理解 class App extends Component{ constructor(){ console.log("constructor") //初始化属于组件的属 ...

  10. [转]C++ 堆栈溢出的原因以及可行的解决方法

    栈溢出(stackoverflow)的原因及解决办法 大家都知道,Windows程序的内存机制大概是这样的:全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较大,一般不会溢出: 函数地 ...