表结构设计

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

创建表

# 图书表
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=32) # 书名
press = models.ForeignKey(to='Press',on_delete=models.CASCADE) # 和出版社表关联的字段

因为书和出版社是多对一的关系,一个出版社可以出版多个书,所以外键要写在多的这张表里面,也就是Book表里面

然后执行

python manage.py makemigrations
python manage.py migrate

说明:to='Press' 默认关联的是Press下的主键,on_delete=models.CASCADE级联删除,也就是如果你删除了出版社,Django会把你这个出版社关联的书都删掉。当然你也可以设置成null或者其他的默认值,不需要删除书。Django1.11中,默认就是级联删除,Django2.0之后必须指定on_delete

to=关联的表名,默认关联表里的主键,还有就是我们的字段是press,但是ORM在操作的时候,会在后面加上_id,在数据库里查看字段显示如下

获取表里的数据

我们往数据表里手动加些数据

url(r'^book_list/', views.book_list),  # 展示图书列表

在去添加对应的函数

#获取图书列表返回给页面
def book_list(request):
#查询所有的书籍
data = Book.objects.all()
return render(request, 'book_list.html', {"data":data})

添加book_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 i in data %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ i.id }}</td>
<td>{{ i.title}}</td>
<td>{{ i.press.name }}</td>
</tr>
{% endfor %} </tbody>
</table> </body>
</html>

book_list.html

说明:

#查询所有的书籍
data = Book.objects.all()
#获取第一本书
first_book = data[0]
print(first_book) #Book表的对象 #取到对象的title属性
print(first_book.title) #取到对象的press属性
print(first_book.press) # press表的对象 #取到这本书关联的出版社的名称
print(first_book.press.name) #取到和我这本书关联的出版社id,也就是book表里的press_id
print(first_book.press_id) #连表查询到出版社id
print(first_book.press.id)

结果:

Book object
python从入门到放弃
Press object
北大出版社
15
15

增加图书

添加路由

url(r'^add_book/', views.add_book),  # 添加图书

添加函数

#添加图书
def add_book(request):
if request.method == "POST":
#获取用户填写的书名
book_title = request.POST.get('book_title')
#获取用户选择的出版社id
pre_id = request.POST.get('press_id')
'''
基于外键对象的创建
press_obj=Press.objects.get(id=press_id)
Book.objects.create(title=book_title, press=press_obj)
'''
#基于外键id值的创建
Book.objects.create(title=book_title, press_id=pre_id)
return redirect('/book_list/') data = Press.objects.all()
return render(request, 'add_book.html', {"press_id": data})

添加add_book.html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加书籍</title>
</head>
<body>
<h1>添加数据</h1>
<form action="/add_book/" method="post">
<input type="text" name="book_title">
<select name="press_id">
{% for press in press_id %}
<option value="{{ press.id }}">{{ press.name }}</option> {% endfor %} </select>
<input type="submit" value="添加">
</form> </body>
</html>

add_book.html

删除图书

在book_list.html里增加如下代码

{% for i in data %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ i.id }}</td>
<td>{{ i.title}}</td>
<td>{{ i.press.name }}</td>
<td>
<a href="/delete_book/?id={{ i.id }}">删除</a> 这句
</td>
</tr>
{% endfor %}

添加路由

url(r'^delete_book/', views.delete_book),  # 删除图书

添加对应的函数

#删除图书
def delete_book(request):
delete_book_id = request.GET.get('id')
Book.objects.filter(id=delete_book_id).delete()
return redirect('/book_list/')

编辑图书

添加路由

url(r'^edit_book/', views.edit_book),  # 编辑图书

添加对应的函数

# 编辑图书
def edit_book(request):
# 从url中取到要编辑的书籍的id值
edit_book_id = request.GET.get('id') # 根据id值找到要编辑的书籍对象
edit_book_obj = Book.objects.get(id=edit_book_id) if request.method == 'POST':
# 取到用户修改后的书籍名称和出版社信息
new_title = request.POST.get('book_title')
new_press_id = request.POST.get('press_id') # 修改书籍相应信息
edit_book_obj.title = new_title
edit_book_obj.press_id = new_press_id # 保存到数据库
edit_book_obj.save() return redirect('/book_list/') # 把所有的出版社查询出来
press_data = Press.objects.all()
return render(request,'edit_book.html', {'book_obj':edit_book_obj, 'press_list': press_data})

添加html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑书籍</title>
</head>
<body>
<h1>编辑书籍</h1>
<form action="" method="post">
<input type="text" name="book_title" value="{{book_obj.title }}"> <select name="press_id" >
{% for press in press_list %}
{% if book_obj.press == press %}
<option selected value="{{press.id }}">{{ press.name }}</option>
{% else %}
<option value="{{press.id }}">{{ press.name }}</option>
{% endif %} {% endfor %} </select>
<input type="submit" value="提交">
</form> </body>
</html>

总结

ORM外键
  press = models.ForignKey(to='Press', on_delete=models.CASCADE)

查询
  1. book_obj.press --> ORM层面封装的,返回的是和我这本书关联的出版社对象
  2. book_obj.press_id --> 数据库中真正存在的字段,保存的是和我关联的出版社id值

编辑

Django模板语言中的if判断
  {% if 条件 %}
    满足时执行的语句
  {% else %}
    不满足时执行的语句
  {% endif %}

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

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

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

  2. django -- ORM实现作者增删改查

    前戏 前面我们已经实现了出版社的增删改查,书的增删改查,书和出版社的对应关系.现在来写一下作者的增删改查和书的对应关系,那书和作者有什么关系呢?一个作者可以写多本书,一本书可以有多个作者,所以书和作者 ...

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

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

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

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

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

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

  6. 基于DRF的图书增删改查练习

    功能演示 信息展示 添加功能 编辑功能 删除功能 DRF构建后台数据 本例的Model如下 from django.db import models class Publish(models.Mode ...

  7. 基于DRF的图书增删改查

    功能演示 信息展示 添加功能 编辑功能 删除功能 DRF构建后台数据 本例的Model如下 from django.db import models class Publish(models.Mode ...

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

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

  9. Django之数据表增删改查

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

随机推荐

  1. What IS MPI

    一.MPI message passing interface A specification for the developers and users of message passing libr ...

  2. 使用velero进行kubernetes灾备

    使用velero可以对集群进行备份和恢复,降低集群DR造成的影响.velero的基本原理就是将集群的数据备份到对象存储中,在恢复的时候将数据从对象存储中拉取下来.可以从官方文档查看可接收的对象存储,本 ...

  3. python3.7环境安装

    wget http://mirror.centos.org/centos/6/os/x86_64/Packages/libffi-devel-3.0.5-3.2.el6.x86_64.rpm rpm ...

  4. 目标检测算法之Fast R-CNN和Faster R-CNN原理

    一.Fast R-CNN原理 在SPPNet中,实际上特征提取和区域分类两个步骤还是分离的.只是使用ROI池化层提取了每个区域的特征,在对这些区域分类时,还是使用传统的SVM作为分类器.Fast R- ...

  5. Maven中的依赖相关总结

    一.Maven的依赖作用域scope compile:编译.测试.运行都会依赖,会打进包中. rumtime:不存于编译,后期运行和测试都会参与,会打进包中. test:只在test classpat ...

  6. 阿里云Centos7用putty ssh链接掉线

    解决方法:修改云服务器 ssh 配置文件(修改前一定要先备份) (1)打开配置文件: vim /etc/ssh/sshd_config 1 (2)找到下面两行: ClientAliveInterval ...

  7. python排序 基数排序

    算法思想 基数排序通过按位比较(一般从最低位开始)将元素按照最低位的数放到10个桶中,当所有的元素都这样被处理一次后,在按从0到9的顺序将每个桶的元素再取出来(不关注其他位的,只关注当前位的)这样就完 ...

  8. SpringBoot 整合MyBatis 统一配置bean的别名

    所谓别名, 就是在mappper.xml配置文件中像什么resultType="xxx" 不需要写全限定类名, 只需要写类名即可. 配置方式有两种: 1. 在 applicatio ...

  9. Springboot 项目源码 vue.js html 跨域 前后分离 shiro权限

    官网:www.fhadmin.org 特别注意: Springboot 工作流  前后分离 + 跨域 版本 (权限控制到菜单和按钮) 后台框架:springboot2.1.2+ activiti6.0 ...

  10. Spring Boot2(八):性感banner,在线发牌

    本文在个人技术博客[鸟不拉屎]同步发布,详情可猛戳 亦可扫描文章末尾二维码关注个人公众号[鸟不拉屎] emmm,没有啥前言 玩过SpringBoot的都知道,SpringBoot启动的时候,默认会在控 ...