书接上回: Django 框架添加管理员,完成对普通用户信息管理
添加了一些简易的字段,主要是为了熟悉Django ORM框架。需要增添其他复杂字段,可以修改Model模型,使用迁移命令,修改数据库。
1.1.1创建图书模型
在项目目录下的models.py文件添加新的类
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
details = models.TextField()
image_link = models.CharField(max_length=200)
def __str__(self):
return self.title
属性定义了Book模型的字段。以下是每个字段表示的含义:
创建数据库迁移文件:
python manage.py makemigrations
应用数据库迁移:
python manage.py migrate
确保在每次对模型进行更改后都运行这两个命令,以保持数据库结构与模型定义同步。如果在模型中添加、修改或删除字段,Django会生成相应的迁移文件,并通过迁移命令应用这些更改。
上一篇博客已经讲述了 Django的form表单,这里不过赘述。创建一个Django 图书信息表单,在目录下的forms.py 添加一个BookForm类 (如果没有forms.py 手动创建即可 )
class BookForm(forms.ModelForm):
title = forms.CharField(
label="图书名字",
)
author = forms.CharField(
label="作者",
)
image_link = forms.CharField(
label="图片链接",
)
class Meta:
model = Book
fields = ['title', 'author', 'details', 'image_link']
添加好表单之后,创建book 增删改查的视图,笔者这里命名为book_controller.py
def upload_book(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save()
return redirect('/book_list') # 重定向到图书列表页面或其他适当的页面
else:
form = BookForm()
return render(request, 'book/upload_book.html', {'form': form})
创建上传图书信息模板HTML
DOCTYPE html>
<html>
<head>
<title>注册title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<style>
/* 自定义额外样式 */
.form-signup {
max-width: 400px;
margin: 0 auto;
padding: 15px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}
.form-signup h2 {
margin-bottom: 20px;
}
.form-signup label {
font-weight: bold;
display: block;
margin-bottom: 5px; /* 调整标签和输入框之间的间距 */
}
.form-signup input[type="text"],
.form-signup input[type="password"],
.form-signup input[type="email"] {
width: 100%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
.form-signup .btn-primary {
margin-top: 20px;
}
style>
head>
<body>
<div class="container mt-5">
<h2 class="text-center mb-4">添加图书信息h2>
<form method="post" class="form-signup">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary btn-block">上传button>
form>
div>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js">script>
body>
html>
绑定URL
在urls.py增添path
path('upload_book/', book_controller.upload_book, name='upload_book'),
有了数据之后,就可以做查询功能了,直接使用Django为我们创建好的API。
首先,新建一个查询所有图书的函数。
def get_all_books(request):
# 查询所有图书
books = Book.objects.all()
return render(request, 'book/book_list.html', {'books': books})
列出所有图书信息的话,直接用all就可以了,不用加filter,返回给模板HTML。
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>管理菜单title>
<style>
/* 菜单样式 */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.sidebar {
width: 250px;
background-color: #333;
height: 100%;
position: fixed;
left: 0;
top: 0;
overflow-x: hidden;
{#padding-top: 20px;#}
}
.sidebar a {
padding: 10px 16px;
margin: 20px;
text-decoration: none;
font-size: 22px;
color: #85f112;
display: block;
transition: 0.3s;
}
.sidebar a:hover {
background-color: #0edcac;
color: black;
}
.content {
margin-left: 250px;
padding: 20px;
}
.header {
background-color: #f1f1f1;
padding: 10px;
text-align: center;
}
{# 美化表格#}
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
.button {
display: inline-block;
padding: 10px 20px;
margin-bottom: 10px;
text-decoration: none;
color: #fff;
background-color: #007bff;
border: 1px solid #007bff;
border-radius: 4px;
transition: background-color 0.3s;
}
.button:hover {
background-color: #0056b3;
border-color: #0056b3;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 20px;
}
.header-content {
margin-left: auto;
}
style>
head>
<body>
<div class="sidebar">
<div class="header">
<h2>管理菜单h2>
div>
<a href="../user_list/">用户管理a>
<a href="../book_list/">图书管理a>
<a href="../borrow_list/">借阅管理a>
<a href="../migrations_list/">迁移记录a>
div>
<div class="content">
<h2>图书列表h2>
<div class="header-content">
div>
<table>
<tr>
<th>编号th>
<th>书名th>
<th>作者th>
<th>详情th>
<th>图片链接th>
<th>操作th>
tr>
{% for book in books %}
<tr>
<td>{{ book.id }}td>
<td>{{ book.title }}td>
<td>{{ book.author }}td>
<td>{{ book.details }}td>
<td>{{ book.image_link }}td>
<td>
{# 注意这里路径写法#}
<a href="../books/{{ book.id }}/edit/">修改a> <a
href="../delete_book/{{ book.id }}/">删除a>
td>
tr>
{% endfor %}
table>
<a href="../upload_book/" class="button" style="margin-top: 20px">添加图书信息a>
div>
body>
html>
最后绑定urls.py
path('book_list/', book_controller.get_all_books, name='get_all_books'),
一般来讲只要获取到id,首先根据id查询图书信息之后,将图书信息返回给编辑页面。编辑页面与上传信息页面基本上一样,可以进行优化,根据ID的值来判断是上传信息还是编辑信息,ID为零或者没有ID代表是上传信息,ID有值代表是编辑。这里只是简单学习框架,并未进行优化。
分为两步,先根据ID查询图书信息,回显,编辑新的数据,上传。
def get_book_by_id(request, id):
# 根据ID查询book
book = Book.objects.filter(id=id).first()
return render(request, 'book/edit_book.html', {'book': book})
将book信息返回给编辑页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改图书信息</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f7f7f7;
}
form {
max-width: 420px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
textarea{
width: 95%;
padding: 8px;
height:200px ;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 3px;
}
input[type="text"],
input[type="password"],
input[type="email"] {
width: 95%;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 3px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 3px;
background-color: #4caf50;
color: white;
cursor: pointer;
width: 100%;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<form method="post" action="/edit_book/">
{% csrf_token %}
<h2 style="text-align: center">修改图书信息</h2>
<input type="hidden" name="id" value="{{ book.id }}">
<label for="title">图书名称:</label>
<input type="text" id="title" name="title" value="{{ book.title }}" ><br><br>
<label for="author">作者:</label>
<input type="text" id="author" name="author" value="{{ book.author }}" ><br><br>
<label for="detail">详情:</label>
<textarea id="details" name="details" >
{{ book.details }}
</textarea><br><br>
<label for="image_link">图片链接:</label>
<input type="text" id="image_link" name="image_link" value="{{ book.image_link }}" ><br><br>
<button type="submit">修改</button>
</form>
</body>
</html>
def edit_book(request):
if request.method == 'POST':
book_id = request.POST.get('id')
book = get_object_or_404(Book, id=book_id) # 根据ID查询已经存在的book对象
form = BookForm(request.POST, instance=book)
if form.is_valid():
# 更新这个对象的数据
form.save()
return redirect('/book_list') # 重定向到图书列表页面或其他适当的页面
else:
form = BookForm()
return render(request, 'book/upload_book.html', {'form': form})
与上传信息有所不同,首先根据ID对象查询出已经有的对象。创建一个BookForm表单实例,使用POST请求的数据和之前获取的书籍对象作为参数。这样,表单将尝试绑定到该书籍对象,允许我们编辑它的属性。如果表单有效,将会更新这个对象,并存放到数据库,这样就完成了更新数据功能。
最后绑定urls.py
path('books//edit/' , book_controller.get_book_by_id),
path('edit_book/', book_controller.edit_book, name='edit_book'),
查询到图书信息,封装成对象,调用delete 即可
def delete_book(request, id):
try:
book = Book.objects.filter(id=id).first()
book.delete()
return redirect('/book_list')
except Book.DoesNotExist:
return HttpResponse('图书不存在')
最后绑定urls.py
path('delete_book//' , book_controller.delete_book),