• Django中三种方式写form表单


           除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式来实现form表单,实现向数据库中添加书籍的页面,效果如下:

      首先在models类中定义了Book,Author和Publish类,并定义了关联关系,publish,author和book分别为一对多和多对多关系,代码如下:

    class Book(models.Model):
        title = models.CharField(max_length=64)
        price = models.DecimalField(max_digits=5,decimal_places=2,default=0)
        author = models.ManyToManyField(to='Author')
        publish = models.ForeignKey(to='Publish')
        def __str__(self):
            return self.title
        
    class Author(models.Model):
        name = models.CharField(max_length=128)
        age = models.IntegerField()
        def __str__(self):
            return self.name
        
    class Publish(models.Model):
        name = models.CharField(max_length=255)
        address = models.CharField(max_length=255)
        def __str__(self):
            return self.name

    1 原生form表单

           在html页面中手写表单,很简单,直接上代码,对应的Html和视图函数如下:

    addbook.html

    <form action="" method="post">
        {% csrf_token %}
        <p >
            <label>书籍标题:</label>
            <input type="text" name="title" class="form-control"/>
        </p>
        <p>
            <label>价格:</label>
            <input type="number" name="price" class="form-control"/>
        </p>
        <p>
            <label>出版社:</label>
            <select name="publish" class="form-control">
                {% for publish in publishs %}
                <option value="{{ publish.pk }}">{{ publish.name }}</option>
                {% endfor %}
            </select>
        </p>
        <p>
            <label>作者:</label>
            <select multiple="multiple" name="author" class="form-control">
                {% for author in authors %}
                <option value="{{ author.pk }}">{{ author.name }}</option>
                {% endfor %}
            </select>
        </p>
        <input type="submit" value="保存"/>
    </form>

    views.py

    def addbook(request):
        authors = models.Author.objects.all()
        publishs = models.Publish.objects.all()
        if request.method=='POST':
            title = request.POST.get('title')
            price = request.POST.get('price')
            author = request.POST.getlist('author')
            publish = request.POST.get('publish')
            # print author, publish
            book_obj = models.Book.objects.create(title=title,price=price,publish_id=publish)
            book_obj.author.add(*author)  #此时添加的为author的id值 [u'1', u'3]
            # for i in author:
            #     book_obj.author.add(int(i))
            # book_obj.save()
            return redirect('/listbook/')
        return render(request,'addbook.html',locals())
    
    

    2 继承django.forms.Form类

    model 字段和form字段的对应关系

    Model fieldForm field
    AutoField Not represented in the form
    BigAutoField Not represented in the form
    BigIntegerField IntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.
    BinaryField CharField, if editable is set to True on the model field, otherwise not represented in the form.
    BooleanField BooleanField, or NullBooleanField if null=True.
    CharField CharField with max_length set to the model field’s max_length and empty_value set to None if null=True.
    DateField DateField
    DateTimeField DateTimeField
    DecimalField DecimalField
    EmailField EmailField
    FileField FileField
    FilePathField FilePathField
    FloatField FloatField
    ForeignKey ModelChoiceField (see below)
    ImageField ImageField
    IntegerField IntegerField
    IPAddressField IPAddressField
    GenericIPAddressField GenericIPAddressField
    ManyToManyField ModelMultipleChoiceField (see below)
    NullBooleanField NullBooleanField
    PositiveIntegerField IntegerField
    PositiveSmallIntegerField IntegerField
    SlugField SlugField
    SmallIntegerField IntegerField
    TextField CharField with widget=forms.Textarea
    TimeField TimeField
    URLField URLField

          首先定义一个BookForm类,继承forms.Form,根据models中定义的Book类,逐个定义相应的字段,字段中可以定义相应的参数,如required=True,表示默认为True,字段不能为空;label定义标签;initial设置初始值;以及error_messages和widget等,参数详细使用见https://docs.djangoproject.com/zh-hans/2.0/ref/forms/fields/。

    BookForm类如下:

    
    
    class BookForm(forms.Form):
        title=forms.CharField(
            label='书籍标题',
            max_length=32,
            widget=forms.widgets.TextInput(attrs={'class':'form-control'})
        )
        price = forms.DecimalField(
            label='价格',
            widget=forms.widgets.TextInput(attrs={'type':'number','class':'form-control'})
        )  # 设置type来改变类型,显示数字输入框
    
        publish = forms.ModelChoiceField(
            label='出版社',
            queryset=models.Publish.objects.all(),
            widget=forms.widgets.Select(attrs={'class': 'form-control'})
        )
        # gender=forms.ChoiceField(choices=((1,"男"),(2,"女"),(3,"其他")))
        # publish=forms.ChoiceField(choices=Publish.objects.all().values_list("pk","title"))
        #ModelChoiceField继承了ChoiceField
        author = forms.ModelMultipleChoiceField(
            label='作者',
            queryset=models.Author.objects.all(),
            widget=forms.widgets.SelectMultiple(attrs={'class': 'form-control'})
        )

      定义好BookForm类后只需在视图函数中进行实例化,并将实例传给前端html,就能自动生成表单,视图函数和html代码如下。BookForm类除了能自动生成前端表单外,还能对数据进行校验,若校验通过,is_valid()方法返回True,并将校验后的数据以字典形式封装到cleaned_data中

    views.py

    def addbook(request):
        if request.method=='POST':
            form = BookForm(request.POST)
            if form.is_valid():
                author = form.cleaned_data.pop('author')
                # print form.cleaned_data, author
                book_obj = models.Book.objects.create(**form.cleaned_data)
                for i in author:
                    book_obj.author.add(i)  #此时添加的为author queryset对象
                book_obj.save()
                return redirect('/listbook/')
        form = BookForm()
        return render(request,'addbook.html',locals())

    addbook.html

    <form  action="" method="post">
        {% csrf_token %}
        {% for field in form %}
        <div >
            {{ field.label }}
            {{ field }}
        </div>
        {% endfor %}
        <input type="submit" value="保存"/>
    </form>

    3 继承django.forms.ModelForm类

         定义一个BookModelForm类,继承forms.ModelForm,相比forms.Form其更加简单,不用逐个定义字段,只需将Book类和需要显示的字段传入,也可以自定义label,widget等参数,详细使用见 https://docs.djangoproject.com/en/2.1/topics/forms/modelforms/

    BookModelForm类如下:

        class Meta:
            model = models.Book
            fields = '__all__'  # 类似于fields = ['title','price','publish','author'],可以自定义需要显示的字段,__all__为所有字段
            labels = {
                'title': '书籍名称',
                'price': '价格',
                'author':'作者',
                'publish': '出版社'
            }
            widgets = {
                'title':forms.widgets.TextInput(attrs={'class':'form-control'}),
                'price':forms.widgets.TextInput(attrs={'class':'form-control','type':'number'}),
                'author': forms.widgets.SelectMultiple(attrs={'class': 'form-control'}),
                'publish': forms.widgets.Select(attrs={'class':'form-control'})
            }  #必须按定义的字段顺序排列
    
    

      和forms.Form一样,在视图函数中向前端传入BookModelForm实例对象,就能自动生成form表单,但其对表单数据处理更加简单,可以直接调用save方法,而且若未对表单数据校验时,save方法会对数据进行校验,另外可以通过BookModelForm(request.POST,instance=a)形式来传入单个实例,储存一条数据记录,如下:

    >>> a = Article.objects.get(pk=1)
    >>> f = ArticleForm(request.POST, instance=a)
    >>> f.save()

      具体的视图函数和前端代码如下:

    views.py

    def addbook(request):
        form = BookModelForm()
        if request.method=='POST':
            form = BookModelForm(request.POST)  # 参数中还可以传单个实例,来储存一条数据  
            form.save()                      # 若未进行数据校验时,save()方法会对数据进行校验
            return redirect('/listbook/')
        return render(request,'addbook.html',locals())

    addbook.html

    <form  action="" method="post">
        {% csrf_token %}
        {% for field in form %}
        <div >
            {{ field.label }}
            {{ field }}
        </div>
        {% endfor %}
        <input type="submit" value="保存"/>
    </form>

    相关参考博客:http://www.cnblogs.com/yuanchenqi/articles/8034442.html

                            http://www.cnblogs.com/yuanchenqi/articles/7614921.html

  • 相关阅读:
    死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程
    死磕 java集合之TreeMap源码分析(一)- 内含红黑树分析全过程
    死磕 java集合之WeakHashMap源码分析
    死磕 java集合之LinkedHashMap源码分析
    Redis的持久化——RDB
    Redis常见配置redis.conf
    Redis的数据类型及相关操作命令
    django-Ajax发送POST请求-csrf跨站请求的三种方式
    Python基础
    RvmTranslator6.0
  • 原文地址:https://www.cnblogs.com/silence-cho/p/10202634.html
Copyright © 2020-2023  润新知