正确使用 Django FormPreview
Using Django FormPreview the right way
我的目标
我有一个带有表单的 django 项目,我想在用户提交之前显示一个预览页面。
问题
我可以使用 Django FormPreview 显示预览页面,但并非所有表单数据都能正确显示。具体来说,如果我有一个带有 choices
的字段,则不会显示这些选项的字符串值。我在将模板过滤器应用于日期字段时也遇到了问题。最终结果是预览页面部分数据可见,部分数据空白:
但是,如果我为 post 显示实际提交的相同数据,那么一切都会正确显示:
我的代码
models.py:
class Game(models.Model):
# Game Choices
FOOTBALL = 0
BASKETBALL = 1
TENNIS = 2
OTHER = 3
GAME_CHOICES = (
(FOOTBALL, 'Football'),
(BASKETBALL, 'Basketball'),
(TENNIS, 'Tennis'),
(OTHER, 'Other')
)
game_id = models.AutoField(primary_key=True)
location = models.CharField(max_length=200, verbose_name="Location")
game = models.IntegerField(choices=GAME_CHOICES, default=FOOTBALL)
game_date = models.DateField(verbose_name='Game Date')
forms.py
class GameForm(ModelForm):
class Meta:
model = Game
fields = (
'location',
'game',
'game_date'
)
我很确定问题出在我的 views.py 中:我不确定我是否正在处理 POST
请求以正确的方式将所有数据提供给预览页面.
views.py
def form_upload(request):
if request.method == 'GET':
form = GameForm()
else:
# A POST request: Handle Form Upload
form = GameForm(request.POST) # Bind data from request.POST into a GameForm
# If data is valid, proceeds to create a new game and redirect the user
if form.is_valid():
game = form.save()
return render(request, 'games/success.html', {})
return render(request, 'games/form_upload.html', {
'form': form,
})
preview.py
class GameFormPreview(FormPreview):
form_template = 'games/form_upload.html'
preview_template = 'games/preview.html'
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
return HttpResponseRedirect('/games/success')
form_upload.html
...
<form method="post">
{% csrf_token %}
<ul><li>{{ form.as_p }}</li></ul>
<button type="submit">Preview your post</button>
</form>
...
preview.html
{% load humanize %}
...
<h1>Preview your submission</h1>
<div>
<p>Location: {{ form.data.location }}</p>
<p>Game Date: {{ form.data.game_date|date:"l, F d, Y" }}</p>
<p>Game Type: {{ form.data.get_game_display }}</p>
</div>
<div>
<form action="{% url 'form_upload' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.as_hidden }}
{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2" />
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
<!-- Submit button -->
<button type="submit">Submit your post</button>
<!-- Go back button -->
<button type="submit">
<a href="{% url 'form_upload' %}"
onClick="history.go(-1);return false;" >
Go back and edit your post
</a>
</button>
</div>
</form>
</div>
...
两期
基本上,我遇到了这两个问题:
- 不显示
choices
的字符串值。如果我在 preview.html
模板中使用 get_FOO_display() 方法,它会 returns 空白。但是,如果我在提交 post 后在页面中使用它,它会正确显示。
humanize
日期过滤器不起作用。如果我在 preview.html
中应用 humanize
过滤器 ({{ form.data.game_date|date:"l, F d, Y" }}
),它也会显示空白。同样,这适用于提交的 posts.
我的问题本质上是:在这里使用 FormPreview
的正确方法是什么?
form.data
没有 get_FOO_display
属性。当您在模板中访问 {{ form.data.get_game_display }}
时,它静默失败并且不显示任何内容。
get_FOO_display
是实例的方法,所以试试这个。
{{ form.instance.get_game_display }}
只要有可能,您应该从 form.cleaned_data
(经过验证和 'cleaned')而不是 form.data
访问数据,后者是提交给表单的原始数据。
过滤器不适用于 form.data.game_date
,因为它是原始字符串。他们应该使用已转换为 python 日期对象的 form.cleaned_data.game_date
。
最后,你还没有在你的 done
方法中实现任何东西,你只是从文档中复制了评论。您可以使用 cleaned_data
创建一个新游戏,如下所示:
def done(self, request, cleaned_data):
game = Game.objects.create(**cleaned_data)
return HttpResponseRedirect('/games/success')
我的目标
我有一个带有表单的 django 项目,我想在用户提交之前显示一个预览页面。
问题
我可以使用 Django FormPreview 显示预览页面,但并非所有表单数据都能正确显示。具体来说,如果我有一个带有 choices
的字段,则不会显示这些选项的字符串值。我在将模板过滤器应用于日期字段时也遇到了问题。最终结果是预览页面部分数据可见,部分数据空白:
但是,如果我为 post 显示实际提交的相同数据,那么一切都会正确显示:
我的代码
models.py:
class Game(models.Model):
# Game Choices
FOOTBALL = 0
BASKETBALL = 1
TENNIS = 2
OTHER = 3
GAME_CHOICES = (
(FOOTBALL, 'Football'),
(BASKETBALL, 'Basketball'),
(TENNIS, 'Tennis'),
(OTHER, 'Other')
)
game_id = models.AutoField(primary_key=True)
location = models.CharField(max_length=200, verbose_name="Location")
game = models.IntegerField(choices=GAME_CHOICES, default=FOOTBALL)
game_date = models.DateField(verbose_name='Game Date')
forms.py
class GameForm(ModelForm):
class Meta:
model = Game
fields = (
'location',
'game',
'game_date'
)
我很确定问题出在我的 views.py 中:我不确定我是否正在处理 POST
请求以正确的方式将所有数据提供给预览页面.
views.py
def form_upload(request):
if request.method == 'GET':
form = GameForm()
else:
# A POST request: Handle Form Upload
form = GameForm(request.POST) # Bind data from request.POST into a GameForm
# If data is valid, proceeds to create a new game and redirect the user
if form.is_valid():
game = form.save()
return render(request, 'games/success.html', {})
return render(request, 'games/form_upload.html', {
'form': form,
})
preview.py
class GameFormPreview(FormPreview):
form_template = 'games/form_upload.html'
preview_template = 'games/preview.html'
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
return HttpResponseRedirect('/games/success')
form_upload.html
...
<form method="post">
{% csrf_token %}
<ul><li>{{ form.as_p }}</li></ul>
<button type="submit">Preview your post</button>
</form>
...
preview.html
{% load humanize %}
...
<h1>Preview your submission</h1>
<div>
<p>Location: {{ form.data.location }}</p>
<p>Game Date: {{ form.data.game_date|date:"l, F d, Y" }}</p>
<p>Game Type: {{ form.data.get_game_display }}</p>
</div>
<div>
<form action="{% url 'form_upload' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.as_hidden }}
{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2" />
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
<!-- Submit button -->
<button type="submit">Submit your post</button>
<!-- Go back button -->
<button type="submit">
<a href="{% url 'form_upload' %}"
onClick="history.go(-1);return false;" >
Go back and edit your post
</a>
</button>
</div>
</form>
</div>
...
两期
基本上,我遇到了这两个问题:
- 不显示
choices
的字符串值。如果我在preview.html
模板中使用 get_FOO_display() 方法,它会 returns 空白。但是,如果我在提交 post 后在页面中使用它,它会正确显示。 humanize
日期过滤器不起作用。如果我在preview.html
中应用humanize
过滤器 ({{ form.data.game_date|date:"l, F d, Y" }}
),它也会显示空白。同样,这适用于提交的 posts.
我的问题本质上是:在这里使用 FormPreview
的正确方法是什么?
form.data
没有 get_FOO_display
属性。当您在模板中访问 {{ form.data.get_game_display }}
时,它静默失败并且不显示任何内容。
get_FOO_display
是实例的方法,所以试试这个。
{{ form.instance.get_game_display }}
只要有可能,您应该从 form.cleaned_data
(经过验证和 'cleaned')而不是 form.data
访问数据,后者是提交给表单的原始数据。
过滤器不适用于 form.data.game_date
,因为它是原始字符串。他们应该使用已转换为 python 日期对象的 form.cleaned_data.game_date
。
最后,你还没有在你的 done
方法中实现任何东西,你只是从文档中复制了评论。您可以使用 cleaned_data
创建一个新游戏,如下所示:
def done(self, request, cleaned_data):
game = Game.objects.create(**cleaned_data)
return HttpResponseRedirect('/games/success')