实例项目
项目需求分析
通过form表单的方式,来实现以下几个功能
1、html标签的自动生成
2、上次输入数据的保留
3、输入数据的验证
代码实施
数据库代码
from django.db import models
class Classes(models.Model):
title = models.CharField(max_length=32)
class Student(models.Model):
sname = models.CharField(max_length=32)
email = models.CharField(max_length=32)
age = models.IntegerField()
cls = models.ForeignKey('Classes',on_delete=models.CASCADE)
class Teacher(models.Model):
tname = models.CharField(max_length=32)
c2t = models.ManyToManyField('Classes')
数据库报错'on_delete'
Djiango的时候发现执行mange.py makemigrations 和 migrate是会报错,少位置参数on_delete,查了一下是因为指定外键的方式不对,改一下就OK了。
一对多设计 多方持有一方的外键
所以解决方法是:
cls = models.ForeignKey('Classes')
添加字段变成
cls = models.ForeignKey('Classes',on_delete=models.CASCADE)
班级管理
由于不小心把django升级到了2.0版本,在做路由的时候发现出现了问题,下面有记录。2.0是咱们为python3.x出的,先用用看
班级管理功能:
1、班级的列表
2、班级的增加
3、班级的编辑
班级的路由url
from django.contrib import admin
from django.urls import path,re_path
from clsmanagent import views
from django.conf.urls import url
urlpatterns = [
path('class_list/', views.class_list),
path('add_class/', views.add_class),
path('edit_class/<int:nid>/', views.edit_class),
班级管理列表
视图文件py
from django.shortcuts import render,redirect,HttpResponse
from django.forms import Form, fields,widgets
from clsmanagent import models
# 班级form验证
class ClassForm(Form):
title = fields.RegexField('全栈\d+',label='班级名称')
# 班级信息
def class_list(request):
# if request.method == "GET":
obj = models.Classes.objects.all()
return render(request, 'classlist.html', {'obj': obj})
班级的列表的html文件
<h2>班级列表</h2>
<hr>
<span><a href="/add_class/">添加班级</a></span>
{#<form action="/class_list/" method="post">#}
{# {% csrf_token %}#}
<ul>
{% for cls_list in obj %}
<li>{{ cls_list.title }}<a href="/edit_class/{{ cls_list.id }}/">编辑</a></li>
{% endfor %}
</ul>
{#</form>#}
班级增加功能
增加功能视图文件
#添加班级
def add_class(request):
if request.method == "GET":
obj = ClassForm()
return render(request,'addclass.html',{'obj':obj})
else:
obj = ClassForm(request.POST)
if obj.is_valid():
models.Classes.objects.create(**obj.cleaned_data)
return redirect('/class_list/')
return render(request, 'addclass.html', {'obj': obj})
增加班级的html代码
<form action="/add_class/" method="post">
{% csrf_token %}
<p>
{# {{ obj.as_p }}#}
{{ obj.title }} {{ obj.errors.title.0 }}
</p>
<p>
<input type="submit" value="提交">
</p>
</form>
编辑班级
编辑班级视图文件
def edit_class(request,nid):
if request.method == "GET":
cls_info = models.Classes.objects.filter(id=nid).first()
print(cls_info)
obj = ClassForm(initial={'title':cls_info.title})
return render(request,'editclass.html',{'obj':obj,'nid':nid})
else:
obj = ClassForm(request.POST)
if obj.is_valid():
models.Classes.objects.filter(id=nid).update(**obj.cleaned_data)
return redirect('/class_list/')
return render(request,'editclass.html',{'obj':obj,'nid':nid})
编辑班级的html代码
<body>
<h2>编辑班级</h2>
<hr>
<form action="/edit_class/{{ nid }}/" method="post">
{% csrf_token %}
<p>
{{ obj.title }}{{ obj.errors.title.0 }}
</p>
<input type="submit" value="提交">
</form>
学生表功能
功能和班级功能一样,这里就把视图函数全部放到一起
#学生列表
def student_list(request):
stu_list = models.Student.objects.all()
return render(request,'studentlist.html',{'stu_list':stu_list})
#添加学生
##创建学生的Form条件验证
class StuForm(Form):
sname = fields.CharField(min_length=2,max_length=6,label='学生姓名')
email = fields.EmailField()
age = fields.IntegerField()
cls_id = fields.IntegerField(
widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'))#把班级变成下拉框,这里django会自动给我们记录select的value,不需要我们自己来操心
)
def add_stu(request):
if request.method == "GET":
obj = StuForm()
return render(request,'addstudent.html',{'obj':obj})
else:
obj = StuForm(request.POST)
if obj.is_valid():
models.Student.objects.create(**obj.cleaned_data)
return redirect('/student_list/')
return render(request,'addstudent.html',{'obj':obj})
#编辑学生
def edit_stu(request,nid):
if request.method == "GET":
row = models.Student.objects.filter(id=nid).values('sname','email','age','cls_id').first()#让他变成字典的类型可以传参到下面的form里面,因为我们知道表达里面的data和initial后面都是一个字典类型
obj = StuForm(row)
return render(request,'editstudent.html',{'obj':obj,'nid':nid})
else:
obj = StuForm(request.POST)
if obj.is_valid():
models.Student.objects.filter(id=nid).update(**obj.cleaned_data)#参数我一个字典
return redirect('/student_list/')
return render(request,'editstudent.html',{'obj':obj,'nid':nid})
学生列表html代码
<h2>学生列表</h2>
<hr>
<a href="/add_stu/">添加学生</a>
<ul>
{% for stu in stu_list %}
<li>{{ stu.sname }}-{{ stu.age }}-{{ stu.email }}-{{ stu.cls_id }}<a href="/edit_stu/{{ stu.id }}/">编辑</a></li>
{% endfor %}
</ul>
增加学生html代码
<form action="/add_stu/" method="post" novalidate>
{% csrf_token %}
<h2>添加学生</h2>
<hr>
<p>{{ obj.sname }}{{ obj.errors.sname.0 }}</p>
<p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
<p>{{ obj.age }}{{ obj.errors.age.0 }}</p>
<p>{{ obj.cls_id }}{{ obj.errors.cls_id.0 }}</p>
<input type="submit" value="提交">
</form>
编辑学生html代码
<h2>编辑学生信息</h2>
<hr>
<form action="/edit_stu/{{ nid }}" method="post">
{% csrf_token %}
<p>{{ obj.sname }}</p>
<p>{{ obj.email }}</p>
<p>{{ obj.age }}</p>
<p>{{ obj.cls_id }}</p>
<input type="submit" value="提交">
</form>
下面是多对多的操作
添加老师
老师列表html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>老师列表</title>
</head>
<body>
<hr>
<a href="/add_teacher/">添加老师</a>
<hr>
<table>
<thead>
<tr>
<th>ID</th>
<th>老师姓名</th>
<th>任教班级</th>
</tr>
</thead>
<tbody>
<tr>
{% for foo in teach_list %}
<td>{{ foo.id }}</td>
<td>{{ foo.tname }}</td>
<td>{{ foo.c2t.all }}</td>
{% endfor %}
</tr>
</tbody>
</table>
</body>
</html>
添加老师html代码
<form action="/add_teacher/" method="post">
{% csrf_token %}
<p>姓名:{{ obj.tname }}</p>
<p>任教班级:{{ obj.xx }}</p>
<input type="submit" value="提交">
</form>
添加老师和老师列表逻辑代码
def teacher_list(request):
if request.method == "GET":
teach_list = models.Teacher.objects.all()
return render(request,'teacher.html',{'teach_list':teach_list})
class TeachForm(Form):
tname = fields.CharField(min_length=2)
xx = fields.CharField(
widget=widgets.SelectMultiple(choices=models.Classes.objects.values_list('id','title'))
)
#上面这个显示的结果是可以多选,但是clean_data的数据都是字符串格式,对于取值是很麻烦的
要想使用正确的多选框要使用下面的方式
xx = fields.MultipleChoiceField(
choices=models.Classes.objects.values_list('id', 'title'),
widget=widgets.SelectMultiple()
)
# xx = fields.CharField(
# widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'))
# )#这样显示出来的是一个单选的下拉框格式
def add_teacher(request):
if request.method == "GET":
obj = TeachForm()
return render(request,'addteacher.html',{'obj':obj})
else:
obj = TeachForm(request.POST)
if obj.is_valid():
# models.Teacher.objects.create(tname=obj.cleaned_data['tname'])第一种方法,但是对于字段多来说不好用
niubi = obj.cleaned_data.pop('xx')
row = models.Teacher.objects.create(**obj.cleaned_data)
row.c2t.add(*niubi)
return redirect('/teacher/')
return render(request,'addteacher.html',{'obj':obj})
urls故障
django2.0版本主要更新了urls,url变成了path,在使用r'^edit_class/(\d+)/', views.edit_class),
路由的时候,发现报错404不能找到路径。经过查看文档发现2.0v版本以后url变成了path,而path的规则变成了如下:
<ul>
{% for cls_list in obj %}
<li>{{ cls_list.title }}<a href="/edit_class/{{ cls_list.id }}/">编辑</a></li>
{% endfor %}
</ul>
from django.urls import path
from . import views
urlpatterns = [
path('edit_class/<int:nid>/', views.edit_class),
]
这里把传入的参数会变成指定的,不需要(\d+/)了,
转换格式类型
说明
Str
匹配除分隔符(/)外的非空字符,默认类型<year>等价于<str:year>
Int
匹配0和正整数
Slug
匹配字母、数字、横杠、下划线组成的字符串,str的子集
Uuid
匹配格式化的UUID,如075194d3-6885-417e-a8a8-6c931e272f00
path
匹配任何非空字符串,包括路径分隔符,是全集
单选框的方法
转载于:https://blog.51cto.com/sgk2011/2083831