Django之form进阶和ModelForm

一.form进阶

1.字段批量添加样式:

def __init__(self,*args,**kwargs):
    super(BookForm,self).__init__(*args,**kwargs)
    for field in self.fields.values():
        field.widget.attrs.update({'class':'form-control'})
解释:
	1.fields.values:所有的值  字段名是key 
	2.widget.attrs.update :字典中更新一条记录

2.form版本图书管理系统:
校验类BookForm:

from django import forms
class BookForm(forms.Form):
    title = forms.CharField(
        max_length=32,
        min_length=12,
        label='书名',
        )
    publishDate = forms.DateField(
        label='出版日期',
        widget=forms.widgets.TextInput(attrs={'type':'date'})
    )
    price = forms.DecimalField(
        max_digits=5,
        decimal_places=2,
        label='价格',

    )
    publishs = forms.ModelChoiceField(  #如果想用数据库中数据进行展示需要用model
        label='出版社',
        queryset=app02.models.Publish.objects.all(),  #直接把所有数据查出来
        widget=forms.widgets.Select()
    )
    authors = forms.ModelMultipleChoiceField(  
        label='作者',
        queryset=app02.models.Author.objects.all(),
        widget=forms.widgets.SelectMultiple(),
    )

前端页面:
在这里插入图片描述
视图函数中:

添加书籍:

# 添加数据
def add_book(request):
    if request.method == 'GET':
        book_forms = BookForm()
        return render(request, 'many_test/book_add.html', {'book_forms':book_forms})
    else:
        book_forms = BookForm(request.POST)
        if book_forms.is_valid():
            print(book_forms.cleaned_data)  #通过的数据
            authors = book_forms.cleaned_data.pop('authors')  #将多对多的数据取出来
            new_book = app02.models.Book.objects.create(**book_forms.cleaned_data)
            new_book.authors.add(*authors) #保存多对多的关系
            return redirect('app03:show_book')
        else:
            print(book_forms.errors)  #错误信息
            return render(
            request, 'many_test/book_add.html',
             {'book_forms': book_forms}) #如果有错误将页面再返回 此时book_forms是有值的

		#以前的写法:
        # authors = request.POST.getlist('authors')
        # all_data = request.POST.dict()
        # del all_data['csrfmiddlewaretoken']
        # del all_data['authors']
        # book_obj = app02.models.Book.objects.create(**all_data)
        # book_obj.authors.add(*authors)
        # return redirect('app03:show_book')

展示书籍:

# 展示书籍
def show_book(request):
    start = 0
    book_list = app02.models.Book.objects.all() 
    paginator = Paginator(book_list, 2)  # 创建一个panginator对象
    page = request.GET.get('page', 1)
    currentPage = int(page)
    if currentPage != 1:
        start = (currentPage - 1) * 2
    try:
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)  # 这个是对你的分页的数据进行取值  去除你的分页过后的第一页
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)  # 分页数
    return render(
        request, 'manytable/show_book.html',
        {'paginator': paginator, 'book_list': book_list, 'currentPage': currentPage, 'start': start})

编辑书籍:

# 编辑书籍
def edit_book(request, book_id):
    book_obj = app02.models.Book.objects.filter(pk=book_id)
    print(book_obj.values())
    if request.method == 'GET':
        book_forms = BookForm(book_obj.values()[0])
        return render(request, 'many_test/book_edit.html', {'book_forms': book_forms,'book_obj':book_obj})
    else:
        pass

编辑书籍页面效果:
可以看到我们用form去做编辑时没有将出版社和作者信息给选中,如果要选中的话就需要用我们之前的那种判断方式,比较麻烦,所以这块需要用到下面的ModelForm来解决。
在这里插入图片描述

删除书籍:

# 删除书籍
def delete_book(request, book_id):
    app02.models.Book.objects.filter(pk=book_id).delete()
    return redirect('app03:show_book')

二.ModelForm

组件的功能就是把model和form组合起来,会把所有的字段信息转换成forms里面的字段(上面定义的BookForm),校验规则就是我们数据库中定义的,但是我们也可以在ModelForm里面自己定义,这样就会覆盖我们model里面的那个字段。
创建ModelForm类:

from django.forms import ModelForm

class BookModelForm(ModelForm):
	#title = forms.CharField(max_length=16) 如果这里也定义了一个title,那就会把你数据库里面的title给替换掉
    class Meta: #原类Meta(规定写法,并注意首字母是大写的)
        model = app02.models.Book   #指定book表 全部转换成上面BookForm里面的校验数据
        fields = '__all__'          #指定表里面的所有的字段  告诉Book表将表里面所有的字段信息全部给我生成forms里面的字段
        exclude = ['title'],        #排除
        error_messages = {          #错误信息
                'title':{'required':'不能为空!!'},
                'price':{'required':'不能为空!!'},
                'publishs':{'required':'不能为空!!'},
                'publishDate':{'required':'不能为空!!'},
                'authors':{'required':'不能为空!!'},
                         },
        help_texts = {'title':'书名!'}     #帮助信息
        widgets = {}                        #添加样式

    #全局钩子
    def clean(self):
        pass

    # 局部钩子
    def clean_title(self):
        value = self.cleaned_data.get('title')
        if '666' in value:
            raise ValidationError('敏感词汇!!666')
        else:
            return value
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for field in self.fields.values():
            field.widget.attrs.update({'class':'form-control'})

ModelForm版本图书管理系统:
添加书籍:

# 添加数据
def add_book(request):
    if request.method == 'GET':
        book_model_form = BookModelForm()
        return render(request, 'many_test/book_add.html', {'book_model_form':book_model_form})
    else:
        book_model_form = BookModelForm(request.POST)
        if book_model_form.is_valid():
            print(book_model_form.cleaned_data)
            book_model_form.save()  #直接保存 因为上面定义了model = app02.models.Book
            return redirect('app03:show_book')
        else:
            print(book_model_form.errors)
            return render(request, 'many_test/book_add.html', {'book_model_form': book_model_form})

书籍展示:

# 展示书籍
def show_book(request):
    start = 0
    book_list = app02.models.Book.objects.all() 
    paginator = Paginator(book_list, 5)  # 创建一个panginator对象
    page = request.GET.get('page', 1)
    currentPage = int(page)
    if currentPage != 1:
        start = (currentPage - 1) * 5
    try:
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)  # 这个是对你的分页的数据进行取值  去除你的分页过后的第一页
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)  # 分页数
    return render(
        request, 'many_test/book_show.html',
        {'paginator': paginator, 'book_list': book_list, 'currentPage': currentPage, 'start': start})

编辑书籍:

# 编辑书籍
def edit_book(request, book_id):
    book_obj = app02.models.Book.objects.filter(pk=book_id)
    book_obj = book_obj.first()
    if request.method == 'GET':
        book_model_form = BookModelForm(instance=book_obj) #需要指定给那个实例编辑
        return render(request, 'many_test/book_edit.html', {'book_model_form': book_model_form,'book_obj':book_obj})
    else:
        book_model_form = BookModelForm(
        request.POST,instance=book_obj) #这里也需要指定一下,不然下面的save会新增加一条
        if book_model_form.is_valid():
            book_model_form.save()
            return redirect('app03:show_book')
        else:
            return render(request, 'many_test/book_edit.html',
                          {'book_model_form': book_model_form, 'book_obj': book_obj})

删除书籍:

# 删除书籍
def delete_book(request, book_id):
    app02.models.Book.objects.filter(pk=book_id).delete()
    return redirect('app03:show_book')

html文件:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    {% for bookform in book_model_form %}
        <div>
        <label for="{{ bookform.id_for_label }}">{{ bookform.label }}</label>
        {{ bookform }}
        <span style="color: red;font-size: 14px">{{ bookform.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit">
</form>
</body>
</html>

实际上我们的编辑和添加页面是内容是重复的,可以做一个base模板,用incloud调用就行了:
base:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% for bookform in book_model_form %}
        <div>
        <label for="{{ bookform.id_for_label }}">{{ bookform.label }}</label>
        {{ bookform }}
        <span style="color: red;font-size: 14px">{{ bookform.errors.0 }}</span>
        </div>
    {% endfor %}
</body>
</html>

add_book:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<h1>添加书籍</h1>
<form action="" method="post">
    {% csrf_token %}
    {% include 'many_test/base.html' %}

    <input type="submit">
</form>
</body>
</html>

edit_book:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
</head>
<body>
<h1>编辑书籍</h1>
<form action="" method="post">
    {% csrf_token %}
    {% include 'many_test/base.html' %}
    <input type="submit">
</form>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/105652717