使用Django FormPreview正确的方法 [英] Using Django FormPreview the right way

查看:130
本文介绍了使用Django FormPreview正确的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标



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



问题



我可以使用Django 方法在我的 preview.html 模板中,它返回空白。但是,如果我在发布信息后在一个页面中使用它,它会正常显示。

  • humanize date filter doesn'工作如果我申请人性化过滤器( {{form.data.game_date | date:l,F d,Y}} )在 preview.html 中,它也显示为空白。再次,这适用于提交的帖子。

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

    解决方案

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



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

      {{form.instance.get_game_display}} 

    只要有可能,您应该从< a href =https://docs.djangoproject.com/en/1.8/ref/forms/api/#django.forms.Form.cleaned_data =nofollow noreferrer> form.cleaned_data (已验证和清除),而不是 form.data ,这是提交到表单的原始数据。 p>

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



    最后,您没有在完成方法中执行任何操作,您刚刚从文档中复制了该注释。您可以使用 clean_data 创建一个新游戏,如下所示:

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

    My Goal

    I have a django project with a form, and I want to display a preview page before the user submits.

    The problem

    I can display a preview page using a Django FormPreview, but not all form data is displayed properly. Specifically, if I have a field with choices, the string values of these choices aren't displayed. I'm also having problems applying template filters to date fields. The end result is that some data on the preview page is visible but other data is blank:

    However, if I display the same data for posts that have actually been submitted, then everything displays properly:

    My Code

    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'
        )
    

    I'm pretty sure that the problem is in my views.py: I'm not sure that I'm processing the POST request the right way to feed all data to the preview page.

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

    Two issues

    Essentially, I'm having these two issues:

    1. String values for choices are not displayed. If I use the get_FOO_display() method in my preview.html template, it returns blank. However, if I use this in a page after the post has been submitted, it displays properly.
    2. The humanize date filter doesn't work. If I apply a humanize filter ({{ form.data.game_date|date:"l, F d, Y" }}) in preview.html, it also displays blank. Again, this works for submitted posts.

    My question essentially is: what's the right way to use the FormPreview here?

    解决方案

    form.data does not have get_FOO_display attributes. When you access {{ form.data.get_game_display }} in the template, it fails silently and doesn't display anything.

    The get_FOO_display are methods of the instance, so try this instead.

    {{ form.instance.get_game_display }}
    

    Wherever possible you should access data from form.cleaned_data (which is validated and 'cleaned') instead of form.data, which is the raw data submitted to the form.

    The filters don't work with form.data.game_date because it's a raw string. They should work with form.cleaned_data.game_date, which has been converted to a python date object.

    Finally, you haven't implemented anything in your done method, you've just copied the comment from the docs. You could create a new game using cleaned_data as follows:

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

    这篇关于使用Django FormPreview正确的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆