表结构设计

上篇我们实现了出版社的增删改查,出版社数据表有两个字段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. ng 打包给路径添加前缀

    1.ng build --base --href /前缀名/--common - chunk --output-hashing=all --optimization 2.更改ts和html中的路径,将 ...

  2. Python - 批量下载 IIS 共享的文件

    1.说明 用 IIS 以WEB形式发布了本地文件夹,提供文件下载,并设置了访问权限:默认下载需要点击一个一个的下载,web界面如下: 3.脚本 执行脚本批量下载文件,会在当前目录创建文件夹,并压缩该文 ...

  3. 【linux】lvm扩展根分区

    lvm扩展根目录 1.lvm的基本概念 physical volume (PV) 通常是一快硬盘.相当于一个物理设备,磁盘空间物理卷PV. volume group (VG) 相当于LVM的卷组,属于 ...

  4. java线程锁基础

    定义运行方法 package com.company; // 包名import java.util.concurrent.locks.ReentrantLock;import java.util.co ...

  5. redis 实战操作RDB和AOF快照持久化

    前言:redis是我们常用的缓存方式,今天就来介绍下两种持久化的方式吧,先科普概念,再实战操作 一.RDB Redis将某一时刻的快照(备份的数据库数据)保存成一种称为RDB格式的文件中,这种格式是经 ...

  6. asp.net web 项目 针对aspx和ashx的 IHttpHandlerFactory 开发

    ASP.NET Framework处理一个Http Request的流程: HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNE ...

  7. v-on 事件触发

    1.v-on 绑定事件 2.methods: 事件绑定语法. 3.v-on:click 可以简写成@click 但是在mvc中会有问题 <!DOCTYPE html> <html&g ...

  8. SpringApplication到底run了什么(上)

    在上篇文章:SpringBoot源码解析:创建SpringApplication对象实例中,我们详细描述了SpringApplication对象实例的创建过程,本篇文章继续看run方法的执行逻辑吧 p ...

  9. webview学习

    Android中WebView使用6,js调java实现播放视频 https://blog.csdn.net/zhaihaohao1/article/details/77993890 android ...

  10. 【软件工程第二次作业】个人项目:WordCountPy

    一.GitHub 地址 项目 GitHub 地址为:https://github.com/bytemo/WordCountTool 二.PSP表格 PSP2.1 Personal Software P ...