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

 

posted @ 2018-12-31 18:04  silence_cho  阅读(3184)  评论(0编辑  收藏  举报