关键词

Django Form and ModelForm的区别与使用

Django是一款常用的Web开发框架,它提供了丰富的功能和组件来帮助开发者创建高效的Web应用程序。其中,Form和ModelForm是Django中非常重要的两个组件,用于处理表单数据和数据模型。本文将深入探讨Django Form和ModelForm的区别和使用。

1. Form和ModelForm的区别

在Django中,Form和ModelForm都是用于处理表单数据的组件。Form是一个基本的表单,它通过定义表单字段,验证表单数据并转换成Python对象。而ModelForm则是对Form进行了进一步的封装,它可以自动处理模型对象和表单对象之间的映射关系,从而能够快速地创建和修改模型对象的数据。

具体来说,Form和ModelForm的主要区别如下:

  1. 数据源不同:

Form可以从任何数据源中获取数据,比如request.POST或request.GET,而ModelForm则必须以一个模型对象作为其数据源。这意味着,使用ModelForm时必须要从数据库中读取模型对象,才能够自动生成表单对象。

  1. 保存数据的方式不同:

Form无法直接保存数据到数据库中,而是需要手动将表单数据转换成模型对象并保存到数据库中。而ModelForm则可以自动将表单数据保存到其对应的模型中,省去了手动处理的步骤。

  1. 表单字段不同:

Form中的字段是直接定义的,而ModelForm中的字段则是从模型中自动获取的。这意味着,使用ModelForm时无需手动定义表单字段,也无需手动添加验证规则,这些都会自动继承模型的属性。

2. 使用Form和ModelForm

Django提供了丰富的表单组件以支持用户输入和提交数据。下面我们将介绍如何使用Form和ModelForm创建表单对象,以及如何在模板中使用表单对象。

2.1 使用Form

使用Form时,需要首先定义表单类,例如:

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    email = forms.EmailField()
    message = forms.CharField(widget=forms.Textarea)

以上代码定义了一个名为ContactForm的表单,它包括三个字段:name、email和message。其中,name和email都是基本的CharField和EmailField字段,而message使用了Textarea小部件以提供多行输入。

在视图函数中,可以通过以下步骤实例化表单对象、验证表单数据并进行相应处理:

from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import ContactForm

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # 处理表单数据
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            # 转向成功页面
            return HttpResponseRedirect('/success/')
    else:
        form = ContactForm()
    return render(request, 'contact.html', {'form': form})

以上代码中,首先判断请求的方法是否为POST,如果是则实例化表单对象,并调用is_valid()方法验证表单数据是否合法。如果表单数据验证通过,则从表单对象的cleaned_data属性中获取处理后的数据,并进行相应的处理。如果表单数据验证失败,则返回原表单并给出错误提示。如果请求的方法为GET,则直接返回空的表单对象以供用户填写。

在模板中,可以通过以下代码引用表单对象并渲染表单:

<form method="post" action="">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

以上代码中,使用了form.as_p渲染表单对象,并添加了一个CSRF令牌,以防御跨站点伪造请求攻击(CSRF)。

2.2 使用ModelForm

与使用Form类似,使用ModelForm也需要先定义一个模型表单类,例如:

from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content', 'is_public']
        widgets = {
            'content': forms.Textarea(attrs={'cols': 80, 'rows': 10}),
        }

以上代码定义了一个名为ArticleForm的ModelForm,它继承了Django提供的ModelForm类,并指定了模型类Article作为它的数据源。在Meta类中,可以设置fields属性以指定表单字段,widgets属性以定制表单小部件。

在视图函数中,可以通过以下步骤实例化模型表单对象、验证表单数据并进行相应处理:

from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import ArticleForm

def create_article(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            # 处理表单数据
            article = form.save(commit=False)
            article.author = request.user
            article.save()
            # 转向成功页面
            return HttpResponseRedirect('/success/')
    else:
        form = ArticleForm()
    return render(request, 'article_create.html', {'form': form})

以上代码中,首先判断请求的方法是否为POST,如果是则实例化模型表单对象,并调用is_valid()方法验证表单数据是否合法。如果表单数据验证通过,则从表单对象的cleaned_data属性中获取处理后的数据,并使用form.save()方法将表单数据保存到相应的模型中。在这个例子中,我们还添加了一个作者(即request.user)来创建文章。如果表单数据验证失败,则返回原表单并给出错误提示。

在模板中,可以使用与使用Form类似的方式引用模型表单对象:

<form method="post" action="">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

以上代码中,使用了form.as_p渲染模型表单对象,并添加了一个CSRF令牌。

3. 示例说明

接下来,我们以一个简单的应用程序为例来说明如何使用Form和ModelForm创建和处理表单数据。

假设我们有一个名为blog的Django应用程序,它包含一个文章模型Article,该模型包括标题、正文、日期等属性。我们希望添加两个表单页面:一个用于创建新文章,另一个用于搜索文章。

3.1 创建新文章

为了创建新文章,我们首先需要创建一个ArticleForm模型表单类:

# blog/forms.py
from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'content', 'pub_date']
        labels = {
            'title': '标题',
            'content': '正文',
            'pub_date': '发布日期',
        }
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'content': forms.Textarea(attrs={'class': 'form-control'}),
            'pub_date': forms.DateInput(attrs={'class': 'form-control'}),
        }

以上代码中,我们定义了一个ArticleForm类,并指定了Article类作为数据源。我们同时设置了该表单的字段,标签和小部件,以提高表单的表现力和用户交互性。

然后,我们在视图函数中使用该表单类处理表单数据:

# blog/views.py
from django.shortcuts import render, redirect
from .models import Article
from .forms import ArticleForm

def create_article(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('blog:index')
    else:
        form = ArticleForm()
    return render(request, 'blog/new_article.html', {'form': form})

以上代码中,我们定义了create_article视图函数,其使用ArticleForm类来处理表单数据。如果表单数据验证通过,则使用form.save()方法将文章保存到数据库中,并重定向到博客主页。

最后,我们使用模板渲染该表单:

<!-- blog/templates/blog/new_article.html -->
{% extends "base.html" %}

{% block title %}创建新文章{% endblock %}

{% block content %}
    <h1>创建新文章</h1>
    <form method="post" action="{% url 'blog:create_article' %}">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn-primary">提交</button>
    </form>
{% endblock %}

以上代码中,我们使用了form.as_p渲染表单对象,并添加了一个按钮以提交表单数据。该表单使用了Bootstrap框架样式来提高用户体验。

3.2 搜索文章

为了搜索文章,我们可以使用一个普通的表单和一个查询函数来实现:

# blog/views.py
def search_articles(request):
    query = request.GET.get('q')
    results = Article.objects.filter(title__icontains=query)
    return render(request, 'blog/search_results.html', {'results': results, 'query': query})

# blog/templates/blog/search.html
{% extends "base.html" %}

{% block title %}搜索文章{% endblock %}

{% block content %}
    <h1>搜索文章</h1>
    <form method="get">
        <div class="form-group">
            <label for="q">搜索标题</label>
            <input type="text" name="q" class="form-control" value="{{ query }}">
        </div>
        <button type="submit" class="btn btn-primary">搜索</button>
    </form>
{% endblock %}

{% block results %}
    {% if results %}
        <h2>搜索结果</h2>
        <ul>
            {% for article in results %}
                <li><a href="{{ article.get_absolute_url }}">{{ article.title }}</a></li>
            {% endfor %}
        </ul>
    {% else %}
        <p>没有符合条件的文章。</p>
    {% endif %}
{% endblock %}

以上代码中,我们定义了search_articles视图函数以处理表单数据。该视图函数使用简单的filter查询来查找所有匹配的文章,并将其传递给search_results模板,以便用于渲染相应的搜索结果。

最后,我们使用search.html模板来渲染搜索表单,以及使用search_results.html模板来渲染搜索结果。

本文链接:http://task.lmcjl.com/news/14415.html

展开阅读全文