案例效果如下:
- 打开 /booktest/显示书籍列表
- 点击新增,增加一条数据
- 点击删除,删除一条数据
- 点击查看,跳转英雄信息界面
1.定义模型类
打开booktest/models.py文件,定义模型类如下
from django.db import models
# Create your models here.
# 定义书籍模型类
class BookInfo(models.Model):
btitle = models.CharField(max_length=20) # 书籍名称
bpub_date = models.DateField() # 发布日期
bread = models.IntegerField(default=0) # 阅读量
bcomment = models.IntegerField(default=0) # 评论量
isDelete = models.BooleanField(default=False) # 逻辑删除
# 定义英雄模型类
class HeroInfo(models.Model):
hname = models.CharField(max_length=20) # 英雄姓名
hgender = models.BooleanField(default=True) # 英雄性别,True为男
hcomment = models.CharField(max_length=200) # 英雄描述信息
hbook = models.ForeignKey(BookInfo, on_delete=models.DO_NOTHING) # 英雄与书籍关系为一对多
2.迁移
python manage.py makemigrations
python manage.py migrate
表bookinfo结构如下:
注意:默认值并不在数据库层面生效,而是在django创建对象时生效。
表booktest_heroinfo结构如下:
注意:Django框架会根据关系属性生成一个关系字段,并创建外键约束。
3.导入测试数据
在数据库命令行中,复制如下语句执行,向booktest_bookinfo和booktest_heroinfo表中插入测试数据:
insert into booktest_bookinfo(id,btitle,bpub_date,bread,bcomment,isDelete) values
(1,'射雕英雄传','1980-5-1',12,34,0),
(2,'天龙八部','1986-7-24',36,40,0),
(3,'笑傲江湖','1995-12-24',20,80,0),
(4,'雪山飞狐','1987-11-11',58,24,0);
insert into booktest_heroinfo(hname,hgender,hbook_id,hcomment) values
('郭靖',1,1,'左右互搏'),
('黄蓉',0,1,'打狗棍法'),
('黄药师',1,1,'弹指神通'),
('欧阳锋',1,1,'蛤蟆功'),
('梅超风',0,1,'九阴白骨爪'),
('乔峰',1,2,'降龙十八掌'),
('段誉',1,2,'六脉神剑'),
('虚竹',1,2,'天山六阳掌'),
('王语嫣',0,2,'神仙姐姐'),
('令狐冲',1,3,'独孤九剑'),
('任盈盈',0,3,'弹琴'),
('岳不群',1,3,'华山剑法'),
('东方不败',0,3,'葵花宝典'),
('胡斐',1,4,'胡家刀法'),
('苗若兰',0,4,'黄衣'),
('程灵素',0,4,'医术'),
('袁紫衣',0,4,'六合拳');
4.定义视图
打开booktest/views.py文件,定义视图代码如下:
import datetime from django.shortcuts import render, redirect, get_object_or_404 from booktest.models import BookInfo, HeroInfo from django.urls import reverse from django.http import HttpResponse, Http404 # 查看所有书籍 def index(request): books = BookInfo.objects.all() context = {'title': '书籍列表', 'books': books} return render(request, 'booktest/index.html', context) # 新增书籍 def create(request): book = BookInfo(btitle="流星蝴蝶剑1", bpub_date=datetime.date(1995, 12, 30), bread=2, bcomment=1) # django的类属性值可以在实例化时修改 book.save() book = BookInfo.objects.create(btitle="流星蝴蝶剑2", bpub_date=datetime.date(1995, 12, 30), bread=2, bcomment=1) book.save() book = BookInfo() book.btitle = "流星蝴蝶剑3" book.bpub_date = datetime.date(1995, 12, 30) book.bread = 2 book.bcomment=1 book.save() # return redirect("/booktest/") return redirect(reverse("booktest:index")) # 重定向的界面若需要传个book.id参数时reverse('booktest:index', args=(book.id,)) # 删除书籍 def delete(request, bid): # try: # book = BookInfo.objects.get(id=int(bid)) # book.delete() # return redirect("/booktest/index") # except: # raise Http404("书籍不存在") # book = get_object_or_404(BookInfo, id=int(bid), ) # pk就是primary key的缩写,model中都是有的主键,model的主键名称默认为id,所以大部分时候我们可以认为pk和id是完全一样的。 # get_object_or_404() 为快捷函数,不能自定义404显示信息 book = get_object_or_404(BookInfo, pk=int(bid), ) book.delete() return redirect("/booktest/") # 查看英雄信息 def hero_info(request, bid): heros = HeroInfo.objects.filter(hbook_id=int(bid)) for hero in heros: if hero.hgender: hero.hgender = "男" else: hero.hgender = "女" context = {'title': '英雄信息', 'heros': heros} return render(request, "booktest/heroInfo.html", context)
redirect方法是在执行完代码后,将界面重定向到index界面,使用时需要import导入
5.配置url
打开test1/urls.py文件,配置url如下:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('booktest/', include('booktest.urls')), # booktest/ 可以为空白
]
在booktest应用下创建urls.py文件,代码如下:
from django.urls import path from django.urls import re_path from booktest import views urlpatterns = [ # ex: /booktest/ # 调用index视图函数 path('', views.index, name='index'), # ex: /booktest/create # 调用create视图函数 path('create', views.create), # ex: /booktest/delete/1 # re_path('delete/(d+)', views.delete), # 在path中使用正则时需要导入re_path方法 path('delete/<int:bid>', views.delete, name='delete'), # bid为视图函数的的形参名 path('search/<int:bid>', views.hero_info, name='search') ]
注意:
1、正则分组匹配的值可以当做视图函数的参数被引用。
2、<int:bid>中的bid为视图函数 def hero_info(request, bid) 中的bid
6.创建模板
打开test1/settings.py文件,配置模板查找目录TEMPLATES的DIRS。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
在templates/booktest/ 目录下创建index.html和heroInfo.html文件。
index.html模板代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书列表</title>
<style>
body {background-color: #efefef;}
td {text-align: center;}
</style>
</head>
<body>
<h1>{{title}}</h1>
<a href="/booktest/create">新增</a>
<table width="500px">
<tr>
<th>书籍名称</th>
<th>发布日期</th>
<th>阅读量</th>
<th>评论量</th>
<th>操作</th>
</tr>
{%for book in books%}
<tr>
<td>{{book.btitle}}</td>
<td>{{book.bpub_date}}</td>
<td>{{book.bread}}</td>
<td>{{book.bcomment}}</td>
<td>
<a href="/booktest/delete/{{book.id}}">删除</a>
<a href="/booktest/search/{{book.id}}">查看英雄</a>
</td>
</tr>
{%endfor%}
</table>
</body>
</html>
heroInfo.html模板代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>英雄信息</title>
</head>
<body>
<h1>{{title}}</h1>
{% for hero in heros %}
<li> {{ hero.hname }},{{ hero.hgender }},{{ hero.hcomment }}</li>
{% endfor %}
</body>
</html>
7.运行
运行服务器。
python manage.py runserver 9000