Django——图书管理系统
一、前期准备
1、创建好 Django 项目
2、准备好数据库 —— 创建数据库:book_system
3、配置项目中的数据库引擎
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'book_system', 'HOST': '127.0.0.1', 'USER': 'root', 'PASSWORD': 'root' } }
4、配置静态文件的搜索路径 , 以及在项目的根目录中创建一个 static 存放静态文件数据文件夹
STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
5、导入 html 模板文件和静态文件数据。
二、用户注册
1、响应用户注册页面的视图
# 路由 # 用户注册视图路由 path('register/' , views.RegisterView.as_view()), # 响应视图 class RegisterView(View): ''' 用户注册页面视图 ''' def get(self , request): # 响应注册页面 return render(request , 'register.html')
2、定义用户数据模型类 , 保存用户注册的个人数据信息
class User(models.Model): ''' 保存用户注册数据 ''' username = models.CharField(max_length=20) password = models.IntegerField() email = models.EmailField()
3、设置后端对用户注册数据进行验证 , 在对应的应用下创建一个 forms 的模块 , 实现数据验证
class RegisterForm(forms.Form): ''' 验证用户注册数据 ''' username = forms.CharField(min_length=3 , max_length=15, error_messages={ 'min_length':'用户名长度不足', 'max_length':'用户名长度超出', 'required':'用户名不允许为空', }) password = forms.CharField(min_length=6 , max_length=15, error_messages={ 'min_length':'密码长度不足', 'max_length':'密码长度超出', 'required':'密码不允许为空', }) resetpw = forms.CharField(min_length=6 , max_length=15, error_messages={ 'min_length':'密码长度不足', 'max_length':'密码长度超出', 'required':'密码不允许为空', }) email = forms.EmailField(error_messages={'invalid':'邮箱格式不正确', 'required':'邮箱不允许为空'}) def clean(self): pwd1 = self.cleaned_data.get('password') pwd2 = self.cleaned_data.get('resetpw') if pwd1 != pwd2: self.add_error('resetpw' , '两次密码输入不一致') return self.cleaned_data def clean_username(self): name = self.cleaned_data.get('username') if not re.match(r'^[a-zA-Z0-9_]{3,15}$' , name): self.add_error('username' , '用户名格式不正确') return name
4、在注册视图中接收用户注册传递的数据 , 进行数据验证
class RegisterView(View): ''' 用户注册页面视图 ''' def get(self , request): # 响应注册页面 return render(request , 'register.html') def post(self , request): # 接收用户注册输入的数据 # 传递给 forms 组件进行数据验证 register_form = RegisterForm(request.POST) # 判断 forms 组件是否返回异常信息 if register_form.is_valid(): # 说明数据合法 没有异常 , 将用户数据保存到数据库中 # 用户数据要从 forms 组件中取 username = register_form.cleaned_data.get('username') password = register_form.cleaned_data.get('password') email = register_form.cleaned_data.get('email') return HttpResponse('用户数据正常') else: # 用户数据不合法 , 将异常信息返回到前端页面中 return render(request , 'register.html' , locals())
当用户数据异常不合法的情况下 ,后端将异常请求返回到前端 。在 html 页面中获取后端的异常数据信息
<div class="form-group"> <i class="fa fa-user" aria-hidden="true"></i> 用户名:<input class="form-control required" type="text" name="username" id="username" placeholder="请输入用户名" required> <span style="color:red;">{{ register_form.username.errors.0 }}</span> </div>
5、实现图片验证码 , 进行验证用户输入的验证码 ,验证码正确数据保存到数据库中,注册成功;否则用户注册失败。
实现图片验证码的代码,直接使用之前写的。
在当前应用下创建包 —— ImageCode
实现验证码的视图
# 路由 # 图片验证码 path('image_code/' , views.CodeImg), # 视图 def CodeImg(request): # 响应图片验证码视图 # 获取图片验证码以及验证码数据 image , text = create_img() # session 会话 # 将验证码数据保存到 session 会话中 , 以键值对的方式保存 request.session['code'] = text # 将图片响应到出现 return HttpResponse(image , content_type='image/png')
在注册是模板中添加验证码的文本框
<div class="form-group"> <i class="fa fa-envelope" aria-hidden="true"></i> 验证码:<input class="form-control required" type="text" name="img_code" id="img_code" placeholder="请输入验证码"> <img src="/image_code/"> </div>
6、前端数据校验 , 使用 vue 的框架进行数据校验
在标签中绑定数据信息 ,以及对文本框绑定对应的方法
<div class="form-group"> <i class="fa fa-user" aria-hidden="true"></i> 用户名:<input class="form-control required" type="text" name="username" id="username" placeholder="请输入用户名" required v-model="username" @blur="check_name"> <span style="color:red;">{{ register_form.username.errors.0 }}</span> </div>
校验用户名是否重复的视图
# 路由 # 检验用户名是否重复 re_path('count/(?P<username>[a-zA-Z0-9_ ]{3,15})/' , views.username_count), # 视图 def username_count(request , username): # 从数据库获取用户数据 count = User.objects.filter(username=username).count() return JsonResponse({'code':200 , 'errmsg':"OK" , 'count':count})
在静态文件中创建 register.js 文件
let vm = new Vue({ el:'#app', delimiters: ['[[' , ']]'], data:{ username:'', password:'', resetpw:'', image_code_url:'', error_name:false, error_password:false, error_resetpw:false, error_name_message:'', }, // 这个方法在 html 页面执行的时候 , 会被自动调用 mounted(){ this.image_code(); }, methods:{ // 生成图片验证码 image_code(){ // 短时间内路由一致的情况下,会无法响应成功 // 添加时间参数,保证在短时间内请求的路由不一致 this.image_code_url = '/image_code/?'+ new Date().getTime() }, // 验证用户名 check_name(){ // 定义用户名的规则范围 let re = /^[a-zA-Z0-9_]{3,15}$/; // 判断用户名是否满足定义的规则 if(re.test(this.username)){ // 用户名合法 this.error_name = false; } else { // 用户名不合法 this.error_name = true; this.error_name_message = '用户名不合法'; } // 判断用户名是否重复 // 前提保证用户名合法 if(this.error_name == false){ // 发送 ajax 请求 axios.get( '/count/'+this.username+'/', {responseType:'json'} ) // 请求成功 .then(response => { if(response.data.count > 0){ // 用户已存在 this.error_name = true; this.error_name_message = '用户名已存在'; } else { this.error_name = false; } }) // 请求失败 .catch(error => { console.log(error.response) }) } }, // 校验密码 check_password(){ let re = /^[a-zA-Z0-9_]{6,15}$/; if(re.test(this.password)){ // 密码字符合法 this.error_password = false; } else { // 密码字符不合法 this.error_password = true; } }, // 校验两次密码是否一致 check_resetpw(){ if(this.password == this.resetpw){ this.error_resetpw = false; } else { this.error_resetpw = true; } }, // 表单是否允许提交的方法 on_submit(){ // 调用所有绑定的方法 this.check_name(); this.check_password(); this.check_resetpw(); // 判断 error 对应的值是否为 true , 如果其中有一个为 true 则不允许提交 if(this.error_name == true || this.error_password == true || this.error_resetpw == true){ // 数据问题 , 禁止表单提交 window.event.returnValue = false; } } } })
修改 图片验证码的 html 标签
<div class="form-group"> <i class="fa fa-envelope" aria-hidden="true"></i> 验证码:<input class="form-control required" type="img_code" name="img_code" id="img_code" placeholder="请输入验证码"> <img v-bind:src="image_code_url" class="img_code" @click="image_code"> </div>
7、在注册视图中 , 实现图片验证码的校验 , 验证码校验正确,用户数据保存到数据库中,用户注册成功;否则注册失败。
class RegisterView(View): ''' 用户注册页面视图 ''' def get(self , request): # 响应注册页面 return render(request , 'register.html') def post(self , request): # 接收用户注册输入的数据 # 传递给 forms 组件进行数据验证 register_form = RegisterForm(request.POST) # 判断 forms 组件是否返回异常信息 if register_form.is_valid(): # 说明数据合法 没有异常 , 将用户数据保存到数据库中 # 用户数据要从 forms 组件中取 username = register_form.cleaned_data.get('username') password = register_form.cleaned_data.get('password') email = register_form.cleaned_data.get('email') # 校验验证码 , 获取用户数输入的验证码 img_code = request.POST.get('img_code') # 从 session 会话中获取保存的验证码 code = request.session['code'] if img_code == code: # 验证码正确 , 将用户拒数据保存到数据库中,用户注册成功 User.objects.create(username=username , password=password , email=email) # 注册成功重定向首页 return redirect('/index/') else: # 验证码错误 return render(request , 'register.html' , {'code_error':'验证码错误'}) else: # 用户数据不合法 , 将异常信息返回到前端页面中 return render(request , 'register.html' , locals())
8、实现首页
# 网站首页 path('index/' , views.index), def index(request): # 响应首页 return render(request , 'index.html')
三、用户登录
响应登录页面数据 , 接收用户登录的数据。
# 用户登录 path('login/' , views.LoginView.as_view()), class LoginView(View): ''' 用户登录视图 ''' def get(self , request): return render(request , 'login.html') def post(self , request): # 校验用户输入的数据 login_form = LoginForm(request.POST) if login_form.is_valid(): username = login_form.cleaned_data.get('username') password = login_form.cleaned_data.get('password') # 到数据库中进行查询用户数据是否存在 user = User.objects.filter(username=username , password=password) if user: # 用户登录成功 return redirect('/index/') else: return render(request, 'login.html', {'errormsg': '账号或者密码错误'}) else: return render(request , 'login.html' , {'errormsg':'账号或者密码错误'})
四、出版社信息
1、 定义出版社模型类
class PublishingHouse(models.Model): ''' 出版社信息模型类 ''' # 出版社名称 name = models.CharField(max_length=20) # 出版社类型 publisher_type = models.CharField(max_length=15) # 出版社成立时间 create_time = models.DateField() # 出版社位置 address = models.CharField(max_length=30)
2、设置出版社模板页面
{% block main%} <table border="1" class="table table-hover table-bordered"> <thead> <tr> <td>序号</td> <td>出版社名称</td> <td>出版社类型</td> <td>出版社成立时间</td> <td>出版社地址</td> <td>操作</td> </tr> </thead> <tbody> {% for foo in publisher %} <tr> <td>{{ foo.id }}</td> <td>{{ foo.name }}</td> <td>{{ foo.publisher_type }}</td> <td>{{ foo.create_time }}</td> <td>{{ foo.address }}</td> <td> <a href="#">修改</a> <a href="#">删除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
3、 响应视图
# 出版社列表响应 path('publisher_list/' , views.publisher_list), # 视图 def publisher_list(request): # 响应出版社列表 # 从数据库中获取出版社的所有信息 publisher = PublishingHouse.objects.all() return render(request , 'publisher_list.html' , locals())
4、添加出版社信息操作
实现添加数据的模板页面
{% block main%} <form method="post"> {% csrf_token %} <p>出版社名称<input type="text" name="name"></p> <p>出版社类型<input type="text" name="publisher_type"></p> <p>出版社成立时间<input type="date" name="create_time"></p> <p>出版社地址<input type="text" name="address"></p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
# 添加出版社数据 path('add_publisher/' , views.AddPublisher.as_view()), # 视图 class AddPublisher(View): ''' 添加出版社数据视图 ''' def get(self , request): return render(request , 'add_publisher.html') def post(self , request): name = request.POST.get('name') publisher_type = request.POST.get('publisher_type') create_time = request.POST.get('create_time') address = request.POST.get('address') # 将数据保存到数据库中 PublishingHouse.objects.create( name=name, publisher_type=publisher_type, create_time=create_time, address=address ) # 数据保存成功 , 重定向到列表页 return redirect('/publisher_list/')
5、修改出版社信息
获取要修改的出版社信息 , 要知道是哪个出版社信息需要修改
获取要修改的出版社信息 , 响应到页面中。
重新接收用户修改好的出版社数据保存到数据库中。
实现修改数据模板页
{% block main %} <form method="post"> {% csrf_token %} <p>出版社名称<input type="text" name="name" value="{{ edit.name }}"></p> <p>出版社类型<input type="text" name="publisher_type" value="{{ edit.publisher_type }}"></p> <p>出版社成立时间<input type="date" name="create_time" value="{{ edit.create_time }}"></p> <p>出版社地址<input type="text" name="address" value="{{ edit.address }}"></p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
# 路由 # 修改出版社信息 path('edit_publisher/' , views.EditPublisher.as_view()), # 视图 class EditPublisher(View): ''' 修改出版社信息的视图 ''' def get(self , request): # 获取用户要修改的出版社信息 id = request.GET.get('id') edit = PublishingHouse.objects.get(id=id) return render(request , 'edit_publisher.html' , locals()) def post(self , request): id = request.GET.get('id') name = request.POST.get('name') publisher_type = request.POST.get('publisher_type') create_time = request.POST.get('create_time') address = request.POST.get('address') edit_data = PublishingHouse.objects.filter(id=id) edit_data.update( name=name, publisher_type=publisher_type, create_time=create_time, address=address ) return redirect('/publisher_list/')
6、删除出版社信息
# 路由 # 删除出版社信息 path('del_publisher/' , views.del_publisher), # 视图 def del_publisher(request): # 获取要删除的出版社信息:id id = request.GET.get('id') PublishingHouse.objects.filter(id=id).delete() return redirect('/publisher_list/')
五、图书信息
1、图书模型类
class Book(models.Model): ''' 图书信息模型类 ''' name = models.CharField(max_length=20) carrier = models.CharField(max_length=10) number_of_words = models.IntegerField() publisher_time = models.DateField() book_image = models.CharField(max_length=20) book_intro = models.CharField(max_length=300) price = models.DecimalField(max_digits=5 , decimal_places=2) inventory = models.IntegerField() publisher = models.ForeignKey(to='PublishingHouse' , on_delete=models.CASCADE)
2、图书列表页
{% block main %} <table border="1" class="table table-hover table-bordered"> <thead> <tr> <td>序号</td> <td>图书名称</td> <td>图书价格</td> <td>库存</td> <td>查询详情</td> <td>操作</td> </tr> </thead> <tbody> {% for foo in book %} <tr> <td>{{ foo.id }}</td> <td>{{ foo.name }}</td> <td>{{ foo.price }}</td> <td>{{ foo.inventory }}</td> <td><a href="/check_book/?id={{ foo.id }}">查看</a></td> <td> <a href="#">修改</a> <a href="#">删除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock main %}
# 查看图书列表页 path('book_list/' , views.book_list), def book_list(request): book = Book.objects.all() return render(request , 'book_list.html' , locals())
3、添加图书数据
{% block main%} <form method="post" enctype="multipart/form-data"> {% csrf_token %} <p>图书名称<input type="text" name="name"></p> <p>图书载体<input type="text" name="carrier"></p> <p>图书字数<input type="text" name="number"></p> <p>图书发表时间<input type="date" name="time"></p> <p>图书图片<input type="file" name="book_image"></p> <p>图书简介<textarea rows="10" cols="20" name="book_intro"></textarea></p> <p>图书价格<input type="text" name="price"></p> <p>图书库存<input type="text" name="inventory"></p> <p>出版社<select multiple name="publisher_id"> {% for foo in publisher %} <option value="{{ foo.id }}">{{ foo.name }}</option> {% endfor %} </select> </p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
# 添加图书信息 path('add_book/' , views.AddBook.as_view()), class AddBook(View): ''' 添加图书信息 ''' def get(self , request): # 获取出版社数据 publisher = PublishingHouse.objects.all() return render(request , 'add_book.html' , locals()) def post(self , request): name = request.POST.get('name') carrier = request.POST.get('carrier') number = request.POST.get('number') time = request.POST.get('time') book_image = request.FILES.get('book_image') book_intro = request.POST.get('book_intro') price = request.POST.get('price') inventory = request.POST.get('inventory') publisher_id = request.POST.get('publisher_id') # 在项目的静态文件夹中 , 创建一个文件夹保存图书的图片 if book_image: # 获取文件名 book_image_name = book_image.name # 将图片保存到指定位置 image_dir = os.path.join(STATICFILES_DIRS[0] , 'book_image' , book_image_name) with open(image_dir , 'wb') as f: for i in book_image: f.write(i) else: book_image = '暂无.jpg' if not book_intro: book_intro = '暂无作品介绍,正在整理中……' Book.objects.create( name=name, carrier=carrier, number_of_words=number, publisher_time=time, book_image=book_image, book_intro=book_intro, price=price, inventory=inventory, publisher_id=publisher_id ) return redirect('/book_list/')
4、查看图书详情
{% block main %} <h1>图书名称:{{ book.name }}</h1> <h2>图书作者:</h2> <table border="1" class="table table-hover table-bordered"> <tr> <th>图书简介</th> <td>{{ book.book_intro }}</td> <th>图书图片</th> <td><img src="/static/book_image/{{ book.book_image }}"></td> </tr> <tr> <th>文学载体</th> <td>{{ book.carrier }}</td> <th>图书字数</th> <td>{{ book.number_of_words }}</td> </tr> <tr> <th>发表时间</th> <td>{{ book.publisher_time }}</td> <th>图书出版社</th> <td>{{ book.publisher.name }}</td> </tr> </table> {% endblock main %}
# 查看图书详情 path('check_book/' , views.book_particulars), def book_particulars(request): id = request.GET.get('id') book = Book.objects.get(id=id) return render(request , 'book_particulars.html' , locals())
5、删除图书信息
def del_book(request): id = request.GET.get('id') Book.objects.filter(id=id).delete() return redirect('/book_list/')
6、修改图书信息
class EditBook(View): def get(self , request): id = request.GET.get('id') book = Book.objects.get(id=id) publisher = PublishingHouse.objects.all() return render(request , 'edit_book.html' , locals()) def post(self , request): id = request.GET.get('id') name = request.POST.get('name') carrier = request.POST.get('carrier') number = request.POST.get('number') time = request.POST.get('time') book_image = request.FILES.get('book_image') book_intro = request.POST.get('book_intro') price = request.POST.get('price') inventory = request.POST.get('inventory') publisher_id = request.POST.get('publisher_id') # 在项目的静态文件夹中 , 创建一个文件夹保存图书的图片 if book_image: # 获取文件名 book_image_name = book_image.name # 将图片保存到指定位置 image_dir = os.path.join(STATICFILES_DIRS[0], 'book_image', book_image_name) with open(image_dir, 'wb') as f: for i in book_image: f.write(i) else: book_image = '暂无.jpg' if not book_intro: book_intro = '暂无作品介绍,正在整理中……' edit_data = Book.objects.filter(id=id) edit_data.update( name=name, carrier=carrier, number_of_words=number, publisher_time=time, book_image=book_image, book_intro=book_intro, price=price, inventory=inventory, publisher_id=publisher_id ) return redirect('/book_list/')
{% block main%} <form method="post" enctype="multipart/form-data"> {% csrf_token %} <p>图书名称<input type="text" name="name" value="{{ book.name }}"></p> <p>图书载体<input type="text" name="carrier" value="{{ book.carrier }}"></p> <p>图书字数<input type="text" name="number" value="{{ book.number_of_words }}"></p> <p>图书发表时间<input type="date" name="time" value="{{ book.publisher_time }}"></p> <p>图书图片<input type="file" name="book_image"></p> <p>图书简介<textarea rows="10" cols="20" name="book_intro">{{ book.book_intro }}</textarea></p> <p>图书价格<input type="text" name="price" value="{{ book.price }}"></p> <p>图书库存<input type="text" name="inventory" value="{{ book.inventory }}"></p> <p>出版社<select multiple name="publisher_id"> {% for foo in publisher %} <option value="{{ foo.id }}">{{ foo.name }}</option> {% endfor %} </select> </p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
六、作者信息
1、作者模型类
class Author(models.Model): ''' 作者信息 ''' # 作者姓名 name = models.CharField(max_length=15) # 作者照片 author_picture_name = models.CharField(max_length=20) # 作者简介 author_intro = models.CharField(max_length=150) # 作者图书 book = models.ManyToManyField(to='Book')
2、作者列表页响应
{% block main %} <table border="1" class="table table-hover table-bordered"> <thead> <tr> <td>序号</td> <td>作者名称</td> <td>作者详情</td> <td>操作</td> </tr> </thead> <tbody> {% for foo in author %} <tr> <td>{{ foo.id }}</td> <td>{{ foo.name }}</td> <td><a href="/check_author/?id={{ foo.id }}">查看</a></td> <td> <a href="/edit_author/?id={{ foo.id }}">修改</a> <a href="/del_author/?id={{ foo.id }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock main %}
def author_list(request): author = Author.objects.all() return render(request , 'author_list.html' , locals())
3、添加作者信息
{% block main%} <form method="post" enctype="multipart/form-data"> {% csrf_token %} <p>作者名称<input type="text" name="name"></p> <p>作者图片<input type="file" name="author_image"></p> <p>作者简介<textarea rows="10" cols="20" name="author_intro"></textarea></p> <p>作者作品 {% for foo in book %} <input type="checkbox" value="{{ foo.id }}" name="books">{{ foo.name }} {% endfor %} </p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
class AddAuthor(View): def get(self , request): book = Book.objects.all() return render(request , 'add_author.html' , locals()) def post(self , request): name = request.POST.get('name') author_intro = request.POST.get('author_intro') author_image = request.FILES.get('author_image') # 前端中的多选框 , 接受的是一个列表类型的数据 # getlist 的方式接受 books = request.POST.getlist('books') # 在项目的静态文件夹中 , 创建一个文件夹保存图书的图片 if author_image: # 获取文件名 author_image_name = author_image.name # 将图片保存到指定位置 image_dir = os.path.join(STATICFILES_DIRS[0], 'author_image', author_image_name) with open(image_dir, 'wb') as f: for i in author_image: f.write(i) else: author_image = '暂无.jpg' if not author_intro: author_intro = '暂无作者介绍,正在整理中……' author = Author.objects.create( name=name, author_picture_name=author_image, author_intro=author_intro) author.book.set(books) return redirect('/author_list/')
4、查看作者详情数据
def check_author(request): id = request.GET.get('id') author = Author.objects.get(id=id) book = Book.objects.filter(author__id=id) return render(request , 'check_author.html' , locals())
{% block main %} <h1>作者:{{ author.name }}</h1> <table border="1" class="table table-hover table-bordered"> <tr> <th>作者简介</th> <td>{{ author.author_intro }}</td> <th>作者图片</th> <td><img src="/static/author_image/{{ author.author_picture_name }}"></td> </tr> </table> <table border="1" class="table table-hover table-bordered"> <thead> <tr> <td>作品</td> </tr> </thead> <tbody> <tr> {% for foo in book %} <td>{{ foo.name }}</td> {% endfor %} </tr> </tbody> </table> {% endblock main %}
5、修改作者信息
{% block main%} <form method="post" enctype="multipart/form-data"> {% csrf_token %} <p>作者名称<input type="text" name="name" value="{{ author.name }}"></p> <p>作者图片<input type="file" name="author_image"></p> <p>作者简介<textarea rows="10" cols="20" name="author_intro">{{ author.author_intro }}</textarea></p> <p>作者作品 {% for foo in book %} <input type="checkbox" value="{{ foo.id }}" name="books">{{ foo.name }} {% endfor %} </p> <p><button type="submit" class="btn">提交</button></p> </form> {% endblock main %}
class EditAuthor(View): def get(self , request): id = request.GET.get('id') author = Author.objects.get(id=id) book = Book.objects.all() return render(request , 'edit_author.html' , locals()) def post(self , request): id = request.GET.get('id') name = request.POST.get('name') author_intro = request.POST.get('author_intro') author_image = request.FILES.get('author_image') # 前端中的多选框 , 接受的是一个列表类型的数据 # getlist 的方式接受 books = request.POST.getlist('books') # 在项目的静态文件夹中 , 创建一个文件夹保存图书的图片 if author_image: # 获取文件名 author_image_name = author_image.name # 将图片保存到指定位置 image_dir = os.path.join(STATICFILES_DIRS[0], 'author_image', author_image_name) with open(image_dir, 'wb') as f: for i in author_image: f.write(i) else: author_image = '暂无.jpg' if not author_intro: author_intro = '暂无作者介绍,正在整理中……' edit_data = Author.objects.get(id=id) edit_data.name = name edit_data.author_intro = author_intro edit_data.author_picture_name = author_image edit_data.book.set(books) edit_data.save() return redirect('/author_list/')
6、删除作者
def del_author(request): id = request.GET.get('id') Author.objects.filter(id=id).delete() return redirect('/author_list/')