Django框架之Modelform
作用--根据模型类生成form类
创建modelform
# 首先导入ModelForm,modelsform需要继承这个类 from django.forms import ModelForm # 假如模型中有个Student类,我们为他创建一个模型类 class Student(ModelForm): class Meat: # 在这个类中再写一个原类Meta(规定) model = models.Student #对应的Model中的类 fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段 exclude = None #排除的字段 labels = None #提示信息 help_texts = None #帮助提示信息 widgets = None #自定义插件 error_messages = None #自定义错误信息 #error_messages用法: error_messages = { 'name':{'required':"用户名不能为空",}, 'age':{'required':"年龄不能为空",}, } #widgets用法,比如把输入用户名的input框给为Textarea #首先得导入模块 from django.forms import widgets as wid #因为重名,所以起个别名 widgets = { "name":wid.Textarea(attrs={"class":"c1"}) #还可以自定义属性 } #labels,自定义在前端显示的名字 labels= { "name":"用户名" }
这个类的使用简直是和form一模一样
渲染
只需要实例化这个类,把对象交给模板,模板就可以渲染出对应的输入框
def student(request): if request.method == 'GET': student_list = StudentList() return render(request,'student.html',{'student_list':student_list})
循环这个对象得到student,放在页面上是一个个input框,student.label是数据库中每个字段的verbose_name ,如果没有设置这个属性,拿到的默认就是字段名,还可以通过student.errors.0 拿到错误信息
提交保存
保存数据的时候,不必再去post请求中去拿那些数据,直接save()就可以写入数据库,而且还可以验证,如果错误可以不刷新页面,简直和form一模一样
def student(request): if request.method == 'GET': student_list = StudentList() return render(request,'student.html',{'student_list':student_list}) else: student_list = StudentList(request.POST) if student_list.is_valid(): # 验证 student_list.save() # 提交 return redirect() return render(request,'student_list.html',{'student_list':student_list})
编辑数据
之前编辑数据时,要取到一条数据的对象,获得他的信息再传递到模板.
而使用modelform你只要拿到这条数据的对象,再把他交给modelform就可以在模板中显示其信息
def student_edit(request,pk): obj = models.Student.objects.filter(pk=pk).first() if not obj: return redirect('test') if request.method == "GET": student_list = StudentList(instance=obj) return render(request,'student_edit.html',{'student_list':student_list})
编辑的提交
编辑的提交不同于上面的提交,如果仍使用上面的方法,那么就会生成一条数据而不是修改一条数据,如果想要修改一条数据,就要告诉他要修改那条数据.就需要把数据对象也传给他
def student_edit(request,pk): obj = models.Student.objects.filter(pk=pk).first() ...同上 else: student_list = StudentList(request.POST,instance=obj) # 传入数据及对象 if student_list.is_valid(): student_list.save() return render(request,'student_edit.html',{'student_list':student_list})
modelform与model的关系
modelform 下的字段对象都是 model转化过去的 每个字段都是BoundField的实例对象,而不是form下的类似于ModelChoiceField的实例对象 打印这个字段对象的到的是对应的标签字符串 BoundFieldObj.name 是form字段名 BoundFieldObj.field 是form字段对应类的对象 ModelChoiceField这种form字段对象接收一个queryset是模型类对应的queryset 可以通过queryset取出模型类 # 这三个类是继承关系 class ChoiceField(Field): class ModelChoiceField(ChoiceField): class ModelMultipleChoiceField(ModelChoiceField):
...
# 模型类 class Book(models.Model): # "book" title=models.CharField(verbose_name="标题",max_length=32) price=models.DecimalField(verbose_name="价格",decimal_places=2,max_digits=5,default=12) # 999.99 1000 state=models.IntegerField(choices=((1,"已出版"),(2,"未出版")) ,default=1) publish=models.ForeignKey(verbose_name="出版社",to="Publish",default=1) authors=models.ManyToManyField(to='author',default=1) def __str__(self): return self.title # modelform类 class BookModelForm(ModelForm): class Meta: model=Book fields="__all__" error_messages={ "title":{"required":"不能为空"}, "price":{"required":"不能为空"}, } a = BookModelForm() # 取最后一个字段 for i in a: b=i print(b) #<select name="authors" required id="id_authors" multiple="multiple"> # <option value="1" selected>alex</option> # <option value="2">egon</option> # <option value="3">yuan</option> # <option value="4">yuan</option> #</select> print(type(b)) # <class 'django.forms.boundfield.BoundField'> print(b.name) # 字段的名字 # authors print(b.field) # form中的一个字段类的实例 # <django.forms.models.ModelMultipleChoiceField object at 0x000001F930BCE278> print(b.field.queryset) # 对应字段的全部对象,对应的,对应的,而不是本类中的对象 #<QuerySet [<author: alex>, <author: egon>, <author: yuan>, <author: yuan>]> print(b.field.queryset.model) # 使用queryset获得类名 # <class 'app01.models.author'>