Django ModelForm不保存到数据库

时间:2018-12-12 20:56:10

标签: python django python-3.x django-forms

我是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'),
]

在此先感谢我,我已经将头撞在墙上了一段时间了。

2 个答案:

答案 0 :(得分:0)

尝试将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'))

答案 1 :(得分:0)

这有一个痛苦的解决方案,一个简单的错字。在我的GameDetail的get_context_data中,我设置了要使用的模板的数据,其中一个字段是要发布到的网址

[required]="ItemCode !== 'This' || ItemCode !== 'That'”

在模板中,当我尝试引用它时,我将其拼写错误

ctx['vote_from_url'] = vote_form_url

对我来说,令人沮丧的是,如果我在模板中放置任何默认值,它将不会出现错误,默认为父视图的url。我应该已经注意到POST将使用错误的URL,但是我想知道是否有设置或日志会告诉我我正在引用模板中不存在的内容。希望本文能帮助陷入类似情况的人。