zoukankan      html  css  js  c++  java
  • forms表单与modelfrom使用

    详细参考链接:点击

    数据结构models.py

    from django.db import models
    
    # Create your models here.
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        date = models.DateField(null=True)
        publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
        authors = models.ManyToManyField('Author')
    
        def __str__(self):
            return self.title
    
        class Meta:
            verbose_name = '书籍表'
    
    
    class Publish(models.Model):
        title = models.CharField(max_length=24)
        site = models.CharField(max_length=80)
        # author = models.
    
        def __str__(self):
            return self.title
    
        class Meta:
            verbose_name = '出版社'
    
    
    class Author(models.Model):
        name = models.CharField(max_length=10)
    
        def __str__(self):
            return self.name
    
        class Meta:
            verbose_name = '作者'
    model.py

    在页面上对数据进行操作时,如果不用forms组件,在设计HTML页面时,会有冗长的代码,特别是修改数据页面,视图中处理数据也同样不方便:

          <form action="" method="post" novalidate>
                    <div>书名:
                        <input type="text" value="{{ old_book.title }}">
                    </div>
                    <div>价格:
                        <input type="text" value="{{ old_book.price }}">
                    </div>
                    <div>时间:
                        <input type="date" value="{{ old_book.date }}">
                    </div>
                    <div>出版社:
                        <select name="publish" id="">
                            {% for punlish in all_publishs %}
                                {% if old_book.publish == punlish %}
                                    <option value="{{ punlish.id }}" selected>{{ punlish.title }}</option>
                                {% else %}
                                    <option value="{{ punlish.id }}">{{ punlish.title }}</option>
                                {% endif %}
                            {% endfor %}
                        </select>
                    </div>
                    <div>作者:
                        <select name="author" id="" multiple>
                            {% for author in all_authors %}
                                    {% if author in old_book.authors.all %}
                                        <option value="{{ author.id }}" selected>{{ author.name }}</option>
                                    {% else %}
                                        <option value="{{ author.id }}">{{ author.name }}</option>
                                    {% endif %}
                                {% endfor %}
    
                        </select>
                        <input type="submit">
        </form>
    </div>
    HTML页面冗长的代码
    def edit_book(request):
        book_forms = forms.AddBook()
        id = request.GET.get('id')
        old_book = models.Book.objects.filter(id=id).first()
        all_publishs = models.Publish.objects.all()
        all_authors = models.Author.objects.all()
        if request.method == 'POST':
            submit = forms.AddBook(request.POST)
            if submit.is_valid():
                return HttpResponse('ok')
    
        return render(request, 'editbook.html',
                      {'book_forms': book_forms, 'old_book': old_book, 'all_publishs': all_publishs,
                       'all_authors': all_authors})
    视图函数中冗长的代码

    用上modelform组件后:

            {% for fields in book_forms %}
                <div>
                    {{ fields.label }}
                    {{ fields }} <span style="color: red">{{ fields.errors.0 }}</span>
                </div>
            {% endfor %}
    def edit_book(request):
        id = request.GET.get('id')
        old_book = models.Book.objects.filter(id=id).first()
        book_forms = forms.ModelFromBook(instance=old_book)  # modelform接收一个参数instance,为model对象,它自动将这个model对象的值填充到form表单
        if request.method == "POST":
            book_forms = forms.ModelFromBook(request.POST, instance=old_book)
            if book_forms.is_valid():
                book_forms.save()  # 将修改后的值,直接更新
                return redirect('/index/')
            else:
                return render(request, 'editbook.html', {'book_forms': book_forms,})
    
        return render(request, 'editbook.html', locals())

    使用forms组件时需要注意的地方:

    from django import forms
    from django.forms import widgets
    from app01 import models
    
    
    class AddBook(forms.Form):
        title = forms.CharField(max_length=20, min_length=5,
                                error_messages={'required': '标题不能为空',
                                                'min_length': '标题最少为5个字符',
                                                'max_length': '标题最多为20个字符'},
                                )
        price = forms.DecimalField(max_digits=8, decimal_places=2)
        date = forms.DateField(
            widget=widgets.TextInput(attrs={'type': 'date'})
        )
        publish = forms.ModelChoiceField(queryset=models.Publish.objects.all())  # 单选select框  queryset可以从models表中取queryset对象
        authors = forms.ModelMultipleChoiceField(queryset=models.Author.objects.all())  # 多选select框
    forms
    def add_book(request):
        book_forms = forms.AddBook()
        if request.method == 'POST':
            book_forms = forms.AddBook(request.POST)
            if book_forms.is_valid():
                title = request.POST.get('title')
                price = request.POST.get('price')
                date = request.POST.get('date')
                publish = request.POST.get('publish')
                authors = request.POST.getlist('authors')
                book_obj = models.Book.objects.create(title=title, price=price, date=date, publish_id=publish)
                book_obj.authors.add(*authors)
                return redirect('/index/')
            else:
                print(book_forms.errors)
                return render(request,'addbook.html',{"book_forms": book_forms})
    
        return render(request, 'addbook.html', {'book_forms': book_forms})
    views
    <div>
        <form action="" method="post" novalidate>
            {% csrf_token %}
            {% for book_form in book_forms %}
                <p>
                    {{ book_form.label }}
                {{ book_form }} <span>{{ book_form.errors.0 }}</span>
                </p>
    
            {% endfor %}
            <input type="submit">
        </form>
    </div>
    HTML

      1、使用单选与多选框时,queryset参数接收一个queryset对象,可以从models取到。error_messages参数自定义错误提示信息,widgets可以指定input框,并设置样式

      2、提交数据后,视图接收数据,把数据传给forms对象,is_valid方法对数据进行校验,没有错误返回True,之后可以进行数据表操作。有错误返回Flase,errors方法返回所有对应的错误信息的html标签,在模板语言中可以直接通过字段调用错误信息进行渲染,注意需要使用下标获取第一个错误信息

      3、forms的校验方式简洁,但是在校验成功后的数据添加或者更新操作依然麻烦,需要手动的获取每一条数据后,再添加到数据库。modelform很好的解决了这个问题。

    modelform使用:

    from django import forms
    from django.forms import widgets
    from app01 import models
    
    class ModelFromBook(forms.ModelForm):
        class Meta:
            model = models.Book
            fields = '__all__'  # ['title','price']
            widgets = {'date': forms.widgets.TextInput(attrs={'type': 'date',}),
                       # 'title': forms.widgets.TextInput(attrs={'class': 'form-control'}),
                       # 'price': forms.widgets.TextInput(attrs={'class': 'form-control'}),
                       # 'publish': forms.widgets.TextInput(attrs={'class': 'form-control'}),
                       # 'authors': forms.widgets.TextInput(attrs={'class': 'form-control'}),
                       }
            labels = {'title': '书名','date': '时间','price': '价格','publish': '出版社','authors':'作者'}
            error_messages = {'title':{'required': '书名不能为空'},
                              }
    modelform
    # 通过modelform添加数据
    def add_book(request):
        book_forms = forms.ModelFromBook()
        if request.method == 'POST':
            book_forms = forms.ModelFromBook(request.POST)
            if book_forms.is_valid():
                book_forms.save()  # save即可自己添加所有数据
                return redirect('/index/')
            else:
                return render(request,'addbook.html',{'book_forms':book_forms})
    
        return render(request, 'addbook.html', {'book_forms': book_forms})
    views
    <div>
        <form action="" method="post" novalidate>
            {% csrf_token %}
            {% for book_form in book_forms %}
                <p>
                    {{ book_form.label }}
                {{ book_form }} <span>{{ book_form.errors.0 }}</span>
                </p>
    
            {% endfor %}
            <input type="submit">
        </form>
    </div>
    HTML

      1、modelform接收一个参数instance,为model对象,它自动将这个model对象的每个字段值填充到form表单,前端页面的输入框自动将原来的数据填充

      2、更新数据时,同样只需要传入instance参数,校验通过后,只需调用save方法即可将原来的数据更新。

      3、其余方法与forms基本一致,只是在创建forms类不同

    modelform字段对象方法:

                class ModelForms(forms.ModelForm):
                    class Meta:
                        model = self.model
                        fields = '__all__'
                        widgets = {'publishDate': forms.widgets.TextInput(attrs={'type': 'date', }),}
    
    forms_obj = ModelForms()
    for forms_field_obj in forms_obj:
       print('-------', forms_field_obj, type(forms_field_obj))  # django.forms.boundfield.BoundField
       print('+++++++', forms_field_obj.field, type(forms_field_obj.field))  # <class 'django.forms.models.ModelMultipleChoiceField'>  # modelform字段对象
       print('*******', forms_field_obj.name, type(forms_field_obj.name))  # authors <class 'str'>  字段名字(字符串)
      print(forms_field_obj.field.queryset, type(forms_field_obj.field.queryset))  # 返回这个关系字段下所有的对象
       print(forms_field_obj.field.queryset.model, type(forms_field_obj.field.queryset.model))  # 返回这个关系字段的关联模型表
    
      app_label = forms_field_obj.field.queryset.model._meta.app_label  # 获取关联字段的关系模型表所在的app
       model_name = forms_field_obj.field.queryset.model._meta.model_name  # 获取关联字段的关系模型表的表名
  • 相关阅读:
    .net通用签名方法 webapi签名方法
    实体类的[Serializable]标签造成WebAPI Post接收不到值
    html5获取位置信息,h5获取位置信息
    C#采集:图灵机器人信息
    virtualbox压缩虚拟机硬盘文件vhd
    WinFrom控件双向绑定
    ILMerge合并多个DLL
    在Windows Server 2012 R2的Hyper-V中设置虚拟机启用增强会话模式
    (转)✈工欲善其事,必先利其器✔™
    .NET使用ZXing.NET生成中间带图片的二维码
  • 原文地址:https://www.cnblogs.com/aizhinong/p/12405586.html
Copyright © 2011-2022 走看看