文章目录
- 代码目录结构
- 逻辑代码
- urls.py
- models.py
- forms.py(app01)
- views.py(app01)
- template
- author_add.html
- author_list.html
- book_add.html
- book_edit.html
- book_list.html
代码目录结构
逻辑代码
urls.py
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book_list/', views.book_list),
path('book_add/', views.BookAdd.as_view()),
re_path(r'book_del/(?P<id>\d+)', views.book_del),
re_path('book_edit/(?P<id>\d+)/', views.BookEdit.as_view()),
path('author_list/', views.author_list),
path('author_add/', views.AuthorAdd.as_view()),
re_path(r'author_del/(?P<id>\d+)', views.author_del),
]
models.py
from django.db import models
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=16)
age = models.IntegerField()
phone = models.CharField(max_length=16, unique=True)
class Meta:
verbose_name = "作者"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Publisher(models.Model):
name = models.CharField(max_length=16)
class Meta:
verbose_name = "出版社"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE)
authors = models.ManyToManyField(to="Author", related_name="zuopin")
class Meta:
verbose_name = "书籍"
verbose_name_plural = verbose_name
def __str__(self):
return self.title
forms.py(app01)
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from app01 import models
class BookForm(forms.Form):
title = forms.CharField(
max_length=16,
label="书名",
# 这里加一个插件是为了往字段中加入 class 属性值, 文字框为 TextInput
widget=forms.TextInput(
attrs={
"class": "form-control"
}
)
)
publisher = forms.ModelChoiceField(
queryset=models.Publisher.objects.all(),
# 单选框为 Select
widget=forms.Select(
attrs={
"class": "form-control"
}
)
)
authors = forms.ModelMultipleChoiceField(
queryset=models.Author.objects.all(),
# 多选框为 SelectMultiple
widget=forms.SelectMultiple(
attrs={
"class": "form-control"
}
)
)
# 钩子函数(hook) clean_字段
def clean_title(self):
# 从处理后的数据中拿到 title 的值
v = self.cleaned_data.get("title")
if "alex" in v:
raise ValidationError("包含敏感词 alex")
else:
return v
# 自定义的校验规则函数
def phone_validate(v):
# 用用户填写的手机号去数据库查找
is_exist = models.Author.objects.filter(phone=v)
if is_exist:
# 如果已经存在, 就不能注册
raise ValidationError("该手机号已经注册")
else:
return v
class AuthorForm(forms.Form):
name = forms.CharField(
max_length=16,
label="姓名",
widget=forms.TextInput(
attrs={
"class": "form-control"
}
)
)
age = forms.IntegerField(
required=False,
initial=18,
label="年龄",
widget=forms.TextInput(
attrs={
"class": "form-control"
}
)
)
# 校验手机号唯一且符合手机号格式规则
phone = forms.CharField(
min_length=11,
max_length=11,
label="手机号",
widget=forms.TextInput(
attrs={
"class": "form-control"
}
),
validators=[RegexValidator(r'^1[356789]\d{9}$', "手机号格式有误"), phone_validate]
)
pwd1 = forms.CharField(
label="pwd-1",
widget=forms.PasswordInput(
attrs={
"class": "form-control"
}
)
)
pwd2 = forms.CharField(
label="pwd-2",
widget=forms.PasswordInput(
attrs={
"class": "form-control"
}
)
)
# 全局钩子
def clean(self):
# 可以取到 cleaned_data 中所有的数据进行对比校验
pwd1 = self.cleaned_data.get("pwd1")
pwd2 = self.cleaned_data.get("pwd2")
if pwd1 != pwd2:
# self.add_error("字段", "密码和确认密码不一致"), 这个是定义报错信息的位置
self.add_error("pwd2", "密码不相同")
else:
pass
views.py(app01)
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
from django import views
from app01.forms import BookForm, AuthorForm
from django.forms import model_to_dict # 将模型快速转换为字典
# Create your views here.
def book_list(request):
data = models.Book.objects.all()
return render(request, "book_list.html", {"data": data})
class BookAdd(views.View):
def get(self, request):
book_obj = BookForm()
return render(request, "book_add.html", {"book_obj": book_obj})
def post(self, request):
# 先实例化
book_obj = BookForm(request.POST)
# 检验, 这个是内置的
if book_obj.is_valid():
# 先处理多对多字段
authors = book_obj.cleaned_data.pop("authors")
# 根据处理之后的数据 cleaned_data 实例化
book_obj = models.Book.objects.create(**book_obj.cleaned_data)
# 设置多对多字段的值
book_obj.authors.set(authors)
# 返回
return redirect('/book_list/')
else:
return render(request, "book_add.html", locals())
def book_del(request, id):
models.Book.objects.filter(id=id).first().delete()
return redirect("/book_list/")
class BookEdit(views.View):
def get(self, request, id):
ret = models.Book.objects.filter(id=id).first()
# model_to_dict 方法可以将 orm 对象快速转换为字典
book_obj = BookForm(model_to_dict(ret))
return render(request, "book_edit.html", locals())
def post(self, request, id):
query_ret = models.Book.objects.filter(id=id).first()
book_obj = BookForm(request.POST)
if book_obj.is_valid():
query_ret.title = book_obj.cleaned_data.get("title")
query_ret.publisher_id = book_obj.cleaned_data.get("publisher")
query_ret.save()
query_ret.authors.set(book_obj.cleaned_data.get("authors"))
return redirect("/book_list/")
else:
return render(request, "book_edit.html", locals())
def author_list(request):
data = models.Author.objects.all()
return render(request, "author_list.html", {"data": data})
class AuthorAdd(views.View):
def get(self, request):
author_obj = AuthorForm()
return render(request, "author_add.html", {"author_obj": author_obj})
def post(self, request):
author_obj = AuthorForm(request.POST)
if author_obj.is_valid():
models.Author.objects.create(**author_obj.cleaned_data)
return redirect("/author_list/")
else:
return render(request, "author_add.html", locals())
def author_del(request, id):
models.Author.objects.filter(id=id).first().delete()
return redirect("/author_list/")
class AuthorEdit(views.View):
def get(self, request):
pass
def post(self, request):
pass
template
author_add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加作者</title>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post" autocomplete="off" novalidate>
{% csrf_token %}
{% for foo in author_obj %}
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }}
<p style="color: red">{{ foo.errors.0 }}</p>
{% endfor %}
<input type="submit" class="btn btn-success" value="提交">
</form>
</div>
</div>
</div>
</body>
</html>
author_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍列表</title>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>作者列表</h1>
<a href="/author_add/">添加作者</a>
<table class="table table-striped">
<thead>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>手机号</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{% for foo in data %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ foo.name }}</td>
<td>{{ foo.age }}</td>
<td>{{ foo.phone }}</td>
<td><a href="/author_edit/{{ foo.id }}/">编辑</a> <a href="">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
book_add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加书籍</title>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post" novalidate autocomplete="off"> <!-- 不检验, 关闭补全提示 -->
{% csrf_token %}
{% for foo in book_obj %}
<div class="form-group">
<!-- id_for_label 和 label 都是内置的方法 -->
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }}
<!-- 这里加了一行错误提示, 错误信息由 post 方法返回 -->
<p style="color: red">{{ foo.errors.0 }}</p>
</div>
{% endfor %}
<input type="submit" value="提交" class="btn btn-success">
</form>
</div>
</div>
</div>
</form>
</body>
</html>
book_edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>编辑书籍</title>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form action="" method="post" novalidate autocomplete="off">
{% csrf_token %}
{% for foo in book_obj %}
<label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
{{ foo }}
<p style="color: red">{{ foo.errors.0 }}</p>
{% endfor %}
<input type="submit" class="btn btn-success" value="提交">
</form>
</div>
</div>
</div>
</body>
</html>
book_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍列表</title>
<link href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h1>书籍列表</h1>
<a href="/book_add/">添加书籍</a>
<table class="table table-striped">
<thead>
<tr>
<td>序号</td>
<td>书名</td>
<td>作者</td>
<td>出版社</td>
<td>操作</td>
</tr>
</thead>
<tbody>
{% for foo in data %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ foo.title }}</td>
<td>
{% for datum in foo.authors.all %}
{{ datum }}
{% endfor %}
</td>
<td>{{ foo.publisher.name }}</td>
<td><a href="/book_edit/{{ foo.id }}/">编辑</a> <a href="/book_del/{{ foo.id }}">删除</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>