Django 表单字段不会显示

标签 django forms modelform django-context

我正在关注 Code School 上的 Django 基础教程,到目前为止,我已经很好地理解、跟进并解决了我自己出现的问题。本教程构建了一个井字棋游戏。

我正在尝试添加在轮到用户时进行移动的功能。

我的相关代码如下。我已将其范围缩小到我认为它与使用上下文有关,因为如果我将其取出并尝试以下操作,它将显示该表单。我想确保我的表单没问题,并且如果这样做的话,它似乎可以正确显示。

if request.method == 'POST':
    form = MoveForm(data=request.POST, instance=Move(game=game))
    if form.is_valid():
        form.save()
        return redirect('tictactoe_game_detail', pk=pk)
else:
    form = MoveForm()
return render(request, "tictactoe/game_do_move.html", {'form': form})

看到了吗?它显示表单,但仅显示表单: my attempt at getting the form to work to prove that the form is okay

我希望它显示在提交按钮上方的框中,但由于某种原因它不在那里。

doing the form the way the tutorial does

我非常有信心表格没问题。我也尝试这样做只是为了看看这些字段是否不存在或上下文中是否有某些内容,但它显示了 x, y 作为字段。

enter image description here

我已经盯着这个看了一天了,我不知道我做错了什么。我正在使用 Django 1.8.1。 (本教程适用于 1.6,但到目前为止似乎还不错。迁移而不是syncdb似乎是我注意到的最大变化之一)

感谢您提供的所有帮助!

代码:

模型.py
class Game(models.Model):
    first_player = models.ForeignKey(User, related_name="games_first_player")
    second_player = models.ForeignKey(User, related_name="games_second_player")
    next_to_move = models.ForeignKey(User, related_name="games_to_move")
    start_time = models.DateTimeField(auto_now_add=True)
    last_active = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=1, default='A', choices=GAME_STATUS_CHOICES)

    objects = GamesManager()

    def as_board(self):
        """Return a representation of the game board as a two dimensional list,
         so you can ask for the state of a square in position [y][x].

         It will contain a list of lines, where eveyr line is a list of 'X', 'O', or ''.
         For example, a 3x3 board position:
         [['', 'X', ''],
          ['O', '', ''],
          ['X', '', '']]
         """
        board = [['' for x in range(BOARD_SIZE)] for y in range(BOARD_SIZE)]
        for move in self.move_set.all():
            board[move.y][move.x] = FIRST_PLAYER_MOVE if move.by_first_player else SECOND_PLAYER_MOVE
        return board

    def last_move(self):
        return self.move_set.latest()

    def get_absolute_url(self):
        return reverse('tictactoe_game_detail', args=[self.id])

    def games_for_user(self, user):
        return "none"

    def is_users_move(self, user):
        return self.status == 'A' and self.next_to_move == user

    def __str__(self):
        return "{0} vs {1}".format(self.first_player, self.second_player)


class Move(models.Model):
    x = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(BOARD_SIZE-1)])
    y = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(BOARD_SIZE-1)])
    comment = models.CharField(max_length=300, blank=True)
    game = models.ForeignKey(Game)
    by_first_player = models.BooleanField(default=False)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        get_latest_by = 'timestamp'

    def player(self):
        return self.game.first_player if self.by_first_player else self.game.second_player

views.py
@login_required
def game_detail(request, pk):
    game = get_object_or_404(Game, pk=pk)
    if game.is_users_move(request.user):
        return redirect('tictactoe_game_do_move', pk=pk)
    return render(request, "tictactoe/game_detail.html", {'game': game})


@login_required
def game_do_move(request, pk):
    game = get_object_or_404(Game, pk=pk)
    if not game.is_users_move(request.user):
        raise PermissionDenied
    context = {'game': game}
    if request.method == 'POST':
        form = MoveForm(data=request.POST, instance=Move(game=game))
        context['form'] = form
        if form.is_valid():
            form.save()
            return redirect('tictactoe_game_detail', pk=pk)
    else:
        context['form'] = MoveForm()
    return render(request, "tictactoe/game_do_move.html", {'game': game})

game_do_move.html

{% extends "tictactoe/game_detail.html" %}
{% load staticfiles %}
{% load crispy_forms_tags %}

{% block styling %}
    {{ block.super }}
    <style type="text/css">
        .tictactoe-cell.empty:hover {
            background-color: #48CA3B;
            cursor: pointer;
        }
    </style>
{% endblock styling %}

{% block moveform %}
        {{ block.super }}
    <div class="well col-md-6">
        <form action="" method="post">
            {% csrf_token %}
            {{ form | crispy }}
            <button type="submit">Submit</button>
        </form>
    </div>
{% endblock moveform %}

game_detail.html

{% extends "base.html" %}
{% load staticfiles %}

{% block title %}
    Tic-Tac-Toe game: {{ game.first_player }} vs {{ game.second_player }}
{% endblock title %}

{% block styling %}
    {{ block.super }}
    <link rel="stylesheet"
          href="{% static 'bootstrap/font-awesome-4.3.0/font-awesome-4.3.0/css/font-awesome.min.css' %}">
    <style type="text/css">
        .tictactoe-cell {
            background-color: #debb27;
        }

        #last-move {
            background-color: #DF6E1E;
        }
    </style>
{% endblock styling %}

{% block content %}
    <h3>Game: {{ game }}</h3>
    <div class="col-sm-9">
        <table class="table table-bordered" style="width: 60px; border-width: 2px">
            {% for line in game.as_board %}
                <tr>
                    {% for square in line %}
                        <td class="tictactoe-cell {% if not square %}empty{% endif %}"
                            style="width: 20px; height: 20px">
                            {{ square }}
                        </td>
                    {% endfor %}
                </tr>
            {% endfor %}
        </table>
        {% block moveform %}{% endblock moveform %}
    </div>
{% endblock content %}

forms.py
class MoveForm(ModelForm):
    class Meta:
        model = Move
        exclude = ['game', 'by_first_player', 'comment']

urls.py
urlpatterns = patterns('tictactoe.views',
                       url(r'^invite$', 'new_invitation', name='tictactoe_invite'),
                       url(r'^invitation/(?P<pk>\d+)/$', 'accept_invitation', name='tictactoe_accept_invitation'),
                       url(r'^game/(?P<pk>\d+)/$', 'game_detail', name='tictactoe_game_detail'),
                       url(r'^game/(?P<pk>\d+)/do_move$', 'game_do_move', name='tictactoe_game_do_move'),
                       )

最佳答案

问题出在views.py中。行中:

返回渲染(request, "tictactoe/game_do_move.html", {'game': game})

{'game': game} 部分是上下文。对于任何 GET 请求(例如呈现空白表单),您都不会呈现 form 上下文变量。

将该行更改为:

返回渲染(请求,“tictactoe/game_do_move.html”,上下文)

它应该可以工作。您将空白 form 对象添加到了lines

中的上下文变量中
else:
    context['form'] = MoveForm()

但如果不将其传递给 render 方法,它就不会出现在模板中。

关于Django 表单字段不会显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30670375/

相关文章:

javascript - 修复了 PrettyPhoto 中的窗口大小

django - 扩展django rest框架以允许在嵌套序列化程序中继承上下文

python - Django Rest Framework,使用MultiPartParser时Query Dict为空

python - 如何预填充 Django 更新表单并将其写回数据库

python - 根据当前登录用户在 Django CreateView 中显示不同的默认值?

django - 如何在基于Django类的 View 中获取表单的提交值?

javascript - 当表单位于弹出窗口中时,如何将表单的操作属性定向到自身?

ruby-on-rails - 在Rails中,如何生成不带符号的表单标签,这些标签仍会创建正确的 "for"属性?

javascript - jQuery 表单提交阻止默认操作然后提交

django - 如何更改模型标签并为其指定自定义名称