python - Django ModelForm 不保存到数据库
问题描述
我是 Django 新手,很难弄清楚如何获取模型表单以保存到我的数据库中。我一直在关注一些教程/书籍,并在 SO 上花费了大量时间,但我无法弄清楚这部分内容。我正在关注的书籍示例是创建一个 IMDB 类型的网站,用户可以在其中投票电影质量(在我的示例中更改为游戏)。
python v. 3.6.7,django v. 2.1.3,postgres v. 2.2.2
这是我要存储的模型和相关的管理器
class VoteManager(models.Manager):
def get_vote_or_unsaved_blank_vote(self, game, user):
try:
vote = Vote.objects.get(game=game, user=user)
return vote
except self.model.DoesNotExist:
vote = Vote(game=game, user=user)
return vote
class Vote(models.Model):
objects = VoteManager()
value = models.FloatField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
game = models.ForeignKey(Game, on_delete=models.CASCADE,)
voted_on = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ('user', 'game')
现在我尝试使用的模型表单来尝试存储它
class VoteForm(forms.ModelForm):
user = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=get_user_model().objects.all(), disabled=True)
game = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=Game.objects.all(), disabled=True)
value = forms.FloatField()
class Meta:
model = Vote
fields = ('user', 'game', 'value')
我用来显示此信息的模板。
{% block main %}
<h1>{{ object }}</h1>
<p class="lead">
{{ object.summary }}
</p>
{% endblock %}
{% block sidebar %}
{# rating div omitted #}
<div>
{% if vote_form %}
<form
method="post"
action="{{ vote_form_url }}" >
{% csrf_token %}
{{ vote_form.as_p }}
<button
class="btn btn-primary" >
Vote
</button >
</form >
<h3>Score: {{ object.score|default_if_none:"No score yet!" }}</h3>
{% else %}
<p >Log in to vote for this game</p >
{% endif %}
</div >
{% endblock %}
最后是组合所有这些部分的视图
class GameDetail(DetailView):
queryset = Game.objects.all_with_related_persons_and_score()
def post(self, request, *args, **kwargs):
return redirect('core:CreateVote', game_id=kwargs['pk'])
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
if self.request.user.is_authenticated:
vote = Vote.objects.get_vote_or_unsaved_blank_vote(game=self.object, user=self.request.user)
if vote.id:
vote_form_url = reverse('core:UpdateVote', kwargs={'game_id': vote.game.id, 'pk': vote.id})
else:
vote_form_url = reverse('core:CreateVote', kwargs={'game_id': self.object.id})
ctx['vote_form'] = VoteForm(instance=vote)
ctx['vote_from_url'] = vote_form_url
return ctx
class CreateVote(LoginRequiredMixin, CreateView):
form_class = VoteForm
def get_initial(self):
initial = super().get_initial()
initial['user'] = self.request.user.id
initial['game'] = self.kwargs['game_id']
return initial
def get_success_url(self):
print('never called?')
game_id = self.kwargs['game_id']
return reverse('core:GameDetail', kwargs={'pk': game_id})
def render_to_response(self, context, **response_kwargs):
game_id = self.kwargs['game_id']
game_detail_url = reverse('core:GameDetail', kwargs={'pk': game_id})
return redirect(to=game_detail_url)
我目前的猜测是我只是不知道如何从模板中获取表单,这里的许多示例在请求时创建表单,我一直遵循的教程在 get_context_data 中创建表单,然后将其传递给模板。所以我一直在努力弄清楚如何保存或验证表格是否正确。
对不起所有的文字,但这些片段是如此相互关联,我想确保我包含了所有有用的东西。从数据库显示和读取似乎可以工作,如果我手动进入并通过管理面板添加投票,我可以成功读取它们,当尝试通过投票按钮写入新分数时没有任何反应,下面是终端窗口输出的内容。
[12/Dec/2018 20:24:34] "GET /game/85 HTTP/1.1" 200 2081
[12/Dec/2018 20:46:49] "POST /game/85 HTTP/1.1" 302 0
[12/Dec/2018 20:46:49] "GET /game/vote/85/create HTTP/1.1" 302 0
[12/Dec/2018 20:46:49] "GET /game/85 HTTP/1.1" 200 2081
哦,也许 url 模式可能有用。
app_name = 'core'
urlpatterns = [
path('', views.MainPage.as_view(), name='MainPage'),
path('games', views.GameList.as_view(), name='GameList'),
path('game/<int:pk>', views.GameDetail.as_view(), name='GameDetail'),
path('game/vote/<int:game_id>/create', views.CreateVote.as_view(), name='CreateVote'),
path('game/vote/<int:game_id>/update/<int:pk>', views.UpdateVote.as_view(), name='UpdateVote'),
]
在此先感谢,我已经在这个问题上撞墙了一段时间。
解决方案
尝试将 type="submit" 添加到您的按钮:
<button class="btn btn-primary" type="submit">Vote</button >
然后在您的 CreateView 添加一个 form_valid 方法:
class CreateVote(LoginRequiredMixin, CreateView):
model = Vote
template_name = 'folder/create_vote.html'
form_class = VoteForm
...
def form_valid(self, form):
vote = form.save(commit=False)
game = Game.objects.get(id=game_id)
vote.game = game
vote.save() # You have to save the vote for it to be added to the db.
return HttpResponseRedirect(reverse('redirect_view'))
推荐阅读
- java - 如何在 .war 部署后阻止 Tomcat 9 被杀死?
- regex - Linux 短符号
- mysql - 无法使用传单打开geojson
- string - 如何找到不一定相等长度的字符串的汉明距离?
- main - iOS和Android是否支持html5标签
? - node.js - 如何取消busboy / express文件上传流(中流)
- c - 如何从节点中找到所有简单路径?
- django - 为什么 django-rest-framework 将令牌存储在数据库中?
- android - MPAndroidChart - 如何在 x 轴上仅显示一次日期,数据点以毫秒为单位?
- python-3.x - 如何在 keras 中打印标记化的数据?