Django完整入门指南-第3部分--2

mac2024-11-04  59

Creating Forms The Right Way

好吧,我们以前的表格看起来更好,对吗?我们将在稍后修复它。

它现在看起来可能坏了,但是请相信我。现在背后有很多东西。而且功能非常强大。例如,如果我们的表单有50个字段,则只需键入即可渲染所有字段。{ { form.as_p } }

此外,Django将使用Forms API验证数据并将错误消息添加到每个字段。让我们尝试提交一个空表格:

 注意:

如果您看到以下信息:提交表单时,那不是Django。这是您的浏览器进行的预验证。要禁用它,请将novalidate属性添加到表单标签中:<form method="post" novalidate>

你可以留着; 没问题。只是因为我们的表单现在非常简单,并且没有太多数据验证可看。

另一个需要注意的重要事情是:没有“客户端验证”之类的东西。JavaScript验证或浏览器验证仅出于可用性目的。并且还减少了对服务器的请求数量。数据验证应始终在服务器端进行,我们可以完全控制数据。

它还处理可以在Form类或Model类中定义的帮助文本:

board / forms.py

from django import forms from .models import Topic class NewTopicForm(forms.ModelForm): message = forms.CharField( widget=forms.Textarea(), max_length=4000, help_text='The max length of the text is 4000.' ) class Meta: model = Topic fields = ['subject', 'message']

我们还可以为表单字段设置额外的属性:

board / forms.py

from django import forms from .models import Topic class NewTopicForm(forms.ModelForm): message = forms.CharField( widget=forms.Textarea( attrs={'rows': 5, 'placeholder': 'What is on your mind?'} ), max_length=4000, help_text='The max length of the text is 4000.' ) class Meta: model = Topic fields = ['subject', 'message']

渲染自举表格

好吧,让我们再次使事情变得漂亮。

在使用Bootstrap或任何其他前端库时,我喜欢使用一个名为django-widget-tweaks的Django包。它使我们能够更好地控制渲染过程,保持默认设置,并在其之上添加额外的自定义设置。

让我们开始安装它:

pip install django-widget-tweaks

现在将其添加到INSTALLED_APPS:

myproject / settings.py

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'widget_tweaks', 'boards', ] INSTALLED_APPS = [ 'django.contrib.admin' , 'django.contrib.auth' , 'django.contrib.contenttypes' , 'django.contrib.sessions' , 'django.contrib.messages' , 'django.contrib.staticfiles' , 'widget_tweaks' , 'boards' , ]

现在让我们使用它:

templates / new_topic.html

{% extends 'base.html' %} {% load widget_tweaks %} {% block title %}Start a New Topic{% endblock %} {% block breadcrumb %} <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li> <li class="breadcrumb-item"><a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a></li> <li class="breadcrumb-item active">New topic</li> {% endblock %} {% block content %} <form method="post" novalidate> {% csrf_token %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {% render_field field class="form-control" %} {% if field.help_text %} <small class="form-text text-muted"> {{ field.help_text }} </small> {% endif %} </div> {% endfor %} <button type="submit" class="btn btn-success">Post</button> </form> {% endblock %}

在那里!因此,这里我们使用django-widget-tweaks。首先,我们使用template标签将其加载到模板中。然后的用法:{ % load widget_tweaks % }

{% render_field field class = "form-control" %}

该render_field标签是没有的Django的一部分; 它位于我们安装的软件包中。要使用它,我们必须传递一个表单字段实例作为第一个参数,然后我们可以添加任意HTML属性对其进行补充。这将很有用,因为这样我们就可以根据某些条件分配类。

render_field模板标记的一些示例:

{% render_field form.subject class="form-control" %} {% render_field form.message class="form-control" placeholder=form.message.label %} {% render_field field class="form-control" placeholder="Write a message!" %} {% render_field field style="font-size: 20px" %}

现在要实现Bootstrap 4验证标签,我们可以更改new_topic.html模板:

templates / new_topic.html

<form method="post" novalidate> {% csrf_token %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %} <div class="invalid-feedback"> {{ error }} </div> {% endfor %} {% else %} {% render_field field class="form-control is-valid" %} {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %} <small class="form-text text-muted"> {{ field.help_text }} </small> {% endif %} </div> {% endfor %} <button type="submit" class="btn btn-success">Post</button> </form>

结果是这样的:

因此,我们有三种不同的渲染状态:

初始状态:表单没有数据(未绑定)无效:我们添加.is-invalidCSS类,并在带有类的元素中添加错误消息.invalid-feedback。表单字段和消息显示为红色。有效:我们添加了.is-validCSS类,以便将表单字段绘制为绿色,从而向用户反馈该字段适合使用。

可重用表格模板

模板代码看起来有点复杂,对吧?好吧,好消息是我们可以在整个项目中重复使用此代码段。

在模板文件夹中,创建一个名为include的新文件夹:

myproject/ |-- myproject/ | |-- boards/ | |-- myproject/ | |-- templates/ | | |-- includes/ <-- here! | | |-- base.html | | |-- home.html | | |-- new_topic.html | | +-- topics.html | +-- manage.py +-- venv/

现在在includes文件夹中,创建一个名为form.html的文件:

template / includes / form.html

% load widget_tweaks %} {% for field in form %} <div class="form-group"> {{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %} <div class="invalid-feedback"> {{ error }} </div> {% endfor %} {% else %} {% render_field field class="form-control is-valid" %} {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %} <small class="form-text text-muted"> {{ field.help_text }} </small> {% endif %} </div> {% endfor %}

现在,我们更改new_topic.html模板:

templates / new_topic.html

{% extends 'base.html' %} {% block title %}Start a New Topic{% endblock %} {% block breadcrumb %} <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li> <li class="breadcrumb-item"><a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a></li> <li class="breadcrumb-item active">New topic</li> {% endblock %} {% block content %} <form method="post" novalidate> {% csrf_token %} {% include 'includes/form.html' %} <button type="submit" class="btn btn-success">Post</button> </form> {% endblock %}

顾名思义,用来将HTML模板包含在另一个模板中。这是在项目中重用HTML组件的非常有用的方法。{ % include % }

我们实现的下一个表单,我们可以简单地使用它来呈现它。{ % include 'includes/form.html' % }

添加更多测试

现在我们正在使用Django Forms;我们可以添加更多测试以确保其运行顺畅:

boards / tests.py

# ... other imports from .forms import NewTopicForm class NewTopicTests(TestCase): # ... other tests def test_contains_form(self): # <- new test url = reverse('new_topic', kwargs={'pk': 1}) response = self.client.get(url) form = response.context.get('form') self.assertIsInstance(form, NewTopicForm) def test_new_topic_invalid_post_data(self): # <- updated this one ''' Invalid post data should not redirect The expected behavior is to show the form again with validation errors ''' url = reverse('new_topic', kwargs={'pk': 1}) response = self.client.post(url, {}) form = response.context.get('form') self.assertEquals(response.status_code, 200) self.assertTrue(form.errors)

现在,我们是assertIsInstance第一次使用该方法。基本上,我们从上下文数据中获取表单实例,并检查它是否为NewTopicForm。在上一个测试中,我们添加了self.assertTrue(form.errors),以确保当数据无效时表单显示错误。


结论

在本教程中,我们重点介绍URL,可重用模板和表单。与往常一样,我们还实现了几个测试用例。这就是我们充满信心地发展的方式。

我们的测试文件开始变得越来越大,因此在下一个教程中,我们将对其进行重构以提高可维护性,从而维持我们代码库的增长。

我们还达到了需要与登录用户进行交互的地步。在下一个教程中,我们将学习有关身份验证以及如何保护我们的视图和资源的所有知识。

希望您喜欢本教程系列的第三部分!第四部分将于下周,即2017年9月25日发布。如果您希望在第四部分结束时收到通知,则可以订阅我们的邮件列表。

该项目的源代码可在GitHub上获得。项目的当前状态可以在发行标签v0.3-lw下找到。下面的链接将带您到正确的地方:

https://github.com/sibtc/django-beginners-guide/tree/v0.3-lw


←第2部分-基本原理

第4部分-身份验证→

最新回复(0)