Django中三种方式写form表单

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

a4956e0279dfc5340dfd6fa7cf971f6713f.jpg

首先在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)  #此时添加的为authorid [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
AutoFieldNot represented in the form
BigAutoFieldNot represented in the form
BigIntegerFieldIntegerField with min_value set to -9223372036854775808 and max_value set to 9223372036854775807.
BinaryFieldCharField, if editable is set to True on the model field, otherwise not represented in the form.
BooleanFieldBooleanField, or NullBooleanField if null=True.
CharFieldCharField with max_length set to the model field’s max_length and empty_value set to None if null=True.
DateFieldDateField
DateTimeFieldDateTimeField
DecimalFieldDecimalField
EmailFieldEmailField
FileFieldFileField
FilePathFieldFilePathField
FloatFieldFloatField
ForeignKeyModelChoiceField (see below)
ImageFieldImageField
IntegerFieldIntegerField
IPAddressFieldIPAddressField
GenericIPAddressFieldGenericIPAddressField
ManyToManyFieldModelMultipleChoiceField (see below)
NullBooleanFieldNullBooleanField
PositiveIntegerFieldIntegerField
PositiveSmallIntegerFieldIntegerField
SlugFieldSlugField
SmallIntegerFieldIntegerField
TextFieldCharField with widget=forms.Textarea
TimeFieldTimeField
URLFieldURLField

      首先定义一个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 BookModelForm(forms.ModelForm):
    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

 

转载于:https://my.oschina.net/u/2241788/blog/2183946

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值