A
A
Artur Zenkov2015-08-09 20:05:58
Django
Artur Zenkov, 2015-08-09 20:05:58

How to override the result of a POST request in Django CBV?

I'm trying to add a like system to blog posts using this form:

<form action="/article/like/{{ article.id }}/" method="post">
    {% csrf_token %}
    <input hidden name="like" value="+">
    <input type="submit" value="-">
</form>

How to use CBV to catch the result of a POST request and redefine and supplement it?
That is, create a condition: if like=+ is passed in the form, then ...
The only way I found is to override form_valid something like this:
def form_valid(self, form):
        instance = form.save(commit=False)
        instance.user = request.user
        instance.save() 
        return redirect(self.get_success_url())

Only I do not quite understand where my like value is contained.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman Kitaev, 2015-08-09
@Hrom

The answer to your question looks like this:

def post(self, request, *args, **kwargs):
    ...

But. Why would you override POST in CreateView? Edit form_valid to look like this:
def form_valid(self, form):
    instance = form.save(commit=False)
    if instance.like == '+':
        instance.user = request.user
        instance.save()
    else:
        bad_mojo()
    return redirect(self.get_success_url())

At the same time, it is not clear why the like field in the model should be equal to "+". Maybe you don't have it and you're just confused?
A trivial system of likes for an article would look like this:
in models.py:
class Like(Model):  # Модель лайков
    user = ForeignKey(User)


class Article(Model):  # Твоя модель статьи
    # Чтобы уменьшить количество записей в таблице Like, просто будем присваивать статьям
    # один и тот же лайк через М2М связь.
    likes = ManyToManyField(Like)

    def like(self, user):
        try:
            like = Like.objects.get(user=user)
            self.likes.add(like)
        except Like.DoesNotExist:
            self.likes.create(user=user)

We make the view as dumb as possible (since our model is fat):
class LikeArticle(SingleObjectMixin, View):
    model = Article

    def post(self, request, *args, **kwargs):
        obj = self.get_object()
        obj.like(request.user)
        return redirect(obj)  # Чтобы использовать такую форму, нужно определить метод get_absolute_url для Article

We write the name of the view in the urls, not the (shit) hardcode in the templates:
...
url(r'article/(?P<pk>\d+)/like$', LikeArticle.as_view(), name='like-article'),
# Заметь, article/<id>/like, а не article/like/<id>. Архитектурно так более верно.
...

Well, it remains to insert into the template:
<form action="{% url 'like-article' object.pk %}" method="POST">{% csrf_token %}
    {# Где object - экземпляр статьи #}
    <input type="submit"/>
</form>

A
Alexander Pinkevich, 2015-08-09
@pinkevich

in the view, the like value can be obtained through instance.cleaned_data.get('like')
And when you begin to understand what is happening, then the raw value can be taken from
self.request.POST.get('like')

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question