我正在关注Code School的Django Fundamentals教程,并且我已经完成了很好的理解,跟随并找出了我自己的问题,直到这一点。该教程构建了一个井字游戏。
我正在尝试添加在用户转向时进行移动的功能。
我的相关代码如下。我已经将它缩小到我认为它与使用上下文有关的地步,因为如果我把它拿出并尝试以下,它将显示表单。我想确保我的表单没问题,如果这样做的话,它似乎显示正确。
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})
见?它显示表单,但只显示表单:
我希望它显示在提交按钮上方的框中,但由于某种原因它不存在。
我非常有信心表格没问题。我试过这只是为了看看上下文中是否有字段或者某些字段,但是它将x,y显示为字段。
我一直盯着这一天,我无法弄清楚我做错了什么。我正在使用Django 1.8.1。 (该教程适用于1.6,但到目前为止似乎没问题。迁移而不是syncdb似乎是我注意到的最大变化之一)
感谢您的帮助!
代码:
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
@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})
{% 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 %}
{% 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 %}
class MoveForm(ModelForm):
class Meta:
model = Move
exclude = ['game', 'by_first_player', 'comment']
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'),
)
答案 0 :(得分:2)
问题出在views.py中。在该行:
return render(request, "tictactoe/game_do_move.html", {'game': game})
部分{'game': game}
是context
。对于任何GET
请求(如呈现空白表单),您都不会呈现form
上下文变量。
将该行更改为:
return render(request, "tictactoe/game_do_move.html", context)
它应该有效。您将空白form
对象添加到行
else:
context['form'] = MoveForm()
但未将其传递给render
方法,它就不会出现在模板中。