django-将多个实例传递到表单中并将其保存在数据库中

时间:2018-09-10 23:01:33

标签: django django-forms

我有一个视图,其中有多个帖子,并且我希望当用户喜欢其中一个帖子时,该表单采用user_id和post_id并将其保存到数据库中。这是Models.py:

class LikePost(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Posts, on_delete=models.CASCADE)

    def __str__(self):
        return '{} - {}'.format(self.user.username, self.post.name)

Forms.py:

class LikePostForm(forms.ModelForm):
    class Meta:
        model = LikedShops
        fields = ['user', 'post']
        widgets = {
            'user': forms.HiddenInput(),
            'post': forms.HiddenInput()
        }

Views.py:

def posts(request):
    if request.method == 'POST':
        form = LikePostForm(request.POST)
        if form.is_valid():
            u = form.save(commit=False)
            u.user = request.user
            u.save()
            return redirect('posts')
    else:
        form = LikePostForm()
    context = {
        'posts': Posts.objects.all(),
        'form': form
    }
    return render(request, "posts.html", context)

,这是posts.html中的表格:

{% for post in posts %}
    <div class="col-md-3">
        <article class="card mb-4">
            <header class="card-header">
                <h4 class="card-title"><b>{{ post.name }}</b></h4>
            </header>
            <img style="width: 100%; height: 150px;" class="card-img" src="{{ post.image.url }}"/>
            <div class="card-body">
                <p class="card-text">{{ post.description }}</p>
            </div>
            {% if user.is_authenticated %}
                <div class="card-footer">
                    <div class="row">
                        <div class="col">
                            <form action="/posts/" method="post">
                                {% csrf_token %}
                                {{ l_form|crispy }}
                                <button type="submit" class="btn btn-outline-success">Like</button>
                            </form>
                        </div>
                    </div>
                </div>
            {% endif %}

        </article><!-- /.card -->
    </div>
{% endfor %}

这是我的编辑,我做了您说的话,对以下内容进行了更改:

forms.py:

class Meta:
    model = Liked
    fields = ['user', 'post']
    widgets = {
        'user': forms.HiddenInput(),
        'post': forms.HiddenInput()
    }

posts.html:

<form action="/posts/" method="post">
      {% csrf_token %}
      <input type="hidden" name="post" value="{{ post.pk }}">
      {{ l_form|crispy }}
      <button type="submit" class="btn btn-outline-success">Like</button>
</form>

views.py:

def posts(request):
    if request.method == 'POST':
        l_form = LikePostForm(request.POST, instance=request.user.profile)
        if l_form.is_valid():
            u = l_form.save(commit=False)
            u.post = Posts.objects.filter(pk=l_form.cleaned_data.get('post')).first()
            u.save()
            messages.success(request, f"Form is valid!")
        else:
            messages.warning(request, f'Form is not valid! {request.POST}')
    else:
        l_form = LikePostForm(instance=request.user.profile)
    context = {
        'post': Posts.objects.all(),
        'l_form': l_form
    }
    return render(request, "posts.html", context)

现在,当我单击“赞”按钮时,我收到此消息**Form is not valid! <QueryDict: {'csrfmiddlewaretoken': ['cNk9ZDS33Nj0l95TBfwtedL1jjAbzDSrH15VjMNZAcxjQuihWNZzOkVnIyRzsjwN'], 'post': ['1', ''], 'user': ['1']}>**

1 个答案:

答案 0 :(得分:0)

您的代码有几个问题。


首先,__str__()方法应返回一个字符串而不是一个元组

class LikePost(models.Model):
    ...
    def __str__(self):
        return '{} - {}'.format(self.user.username, self.post.name)

第二,有一个错字;将Pots更改为Posts

context = {
    'posts': Posts.objects.all(),
    'form': form,
}
return render(request, "posts.html", context)

最后,第三行u.post = request.post抛出您提到的错误,因为request对象没有属性post

因此,更改您的表单代码以在隐藏状态下添加帖子(我使用fields而不是exclude):

class LikePostForm(forms.ModelForm):
    class Meta:
        model = LikePost
        fields = ['post', ]
        widgets = {
            'post': forms.HiddenInput(),
        }

然后更改您的视图:

form = LikePostForm(request.POST)
if form.is_valid():
    u = form.save(commit=False)
    u.user = request.user
    u.save()

编辑问题后:

尝试将post.pk添加为表单中的隐藏输入:

<form action="/posts/" method="post">
    {% csrf_token %}
    <input type="hidden" name="post" value="{{ post.pk }}">
    {{ l_form|crispy }}
    <button type="submit" class="btn btn-outline-success">Like</button>
</form>

或者您也可以在自己的视图中这样做:

u.post = Posts.objects.filter(pk=form.cleaned_data.get('post')).first()