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 field Form 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM