【问题标题】:Using Django FormPreview the right way正确使用 Django FormPreview
【发布时间】:2015-08-26 13:01:00
【问题描述】:

我的目标

我有一个带有表单的 django 项目,我想在用户提交之前显示一个预览页面。

问题

我可以使用 Django FormPreview 显示预览页面,但并非所有表单数据都能正确显示。具体来说,如果我有一个带有choices 的字段,则不会显示这些选项的字符串值。我在将模板过滤器应用于日期字段时也遇到了问题。最终结果是预览页面上的一些数据是可见的,而其他数据是空白的:

但是,如果我为实际提交的帖子显示相同的数据,那么一切都会正确显示:

我的代码

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>
...

两个问题

基本上,我有这两个问题:

  1. choices 的字符串值不显示。如果我在preview.html 模板中使用get_FOO_display() 方法,它会返回空白。但是,如果我在提交帖子后在页面中使用它,它会正确显示。
  2. humanize 日期过滤器不起作用。如果我在preview.html 中应用humanize 过滤器({{ form.data.game_date|date:"l, F d, Y" }}),它也会显示为空白。同样,这适用于提交的帖子。

我的问题本质上是:在这里使用FormPreview 的正确方法是什么?

【问题讨论】:

    标签: python django django-forms django-templates


    【解决方案1】:

    form.data 没有get_FOO_display 属性。当您在模板中访问{{ form.data.get_game_display }} 时,它会静默失败并且不显示任何内容。

    get_FOO_display 是实例的方法,所以试试这个。

    {{ form.instance.get_game_display }}
    

    您应该尽可能从form.cleaned_data(经过验证和“清理”)访问数据,而不是form.data,这是提交给表单的原始数据。

    过滤器不适用于form.data.game_date,因为它是一个原始字符串。他们应该使用form.cleaned_data.game_date,它已被转换为python日期对象。

    最后,您还没有在 done 方法中实现任何东西,您只是从文档中复制了评论。您可以使用cleaned_data 创建一个新游戏,如下所示:

    def done(self, request, cleaned_data):
        game = Game.objects.create(**cleaned_data)
        return HttpResponseRedirect('/games/success')
    

    【讨论】:

    • 这太棒了!谢谢!我发现的关于使用FormPreview 的文档都没有这个信息——真的很高兴知道!你知道是否有一个很好的资源来阅读我刚刚错过的这个?
    • 不,我不知道特别是关于 FormPreview 的任何资源。 form.dataform.cleaned_data 之间的区别通常涉及形式,而不仅仅是 FormPreview。同样,能够访问form.instance 是常规模型表单的一个特性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 2012-09-04
    • 2018-11-13
    • 2011-12-17
    • 2013-09-27
    • 1970-01-01
    相关资源
    最近更新 更多