Skip to content

Commit

Permalink
hotwire-django#8 - Allow users to favorite articles
Browse files Browse the repository at this point in the history
  • Loading branch information
luanfonceca committed Jan 9, 2021
1 parent 852411b commit 7a953b9
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 12 deletions.
45 changes: 41 additions & 4 deletions articles/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
from django.shortcuts import get_object_or_404

from django.urls import reverse_lazy
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic.edit import CreateView, UpdateView
from django.db.models import Count

from .models import Article
from .forms import ArticleForm


class IsAuthenticatedOrReadOnly(UserPassesTestMixin):
def test_func(self):
return self.request.method == 'GET' or self.request.user.is_authenticated


def view(req, slug):
return render(req, "articles/detail.html")
return render(req, "articles/detail.html", {
"article": Article.objects.get(slug=slug)
})


class EditArticle(LoginRequiredMixin, UpdateView):
Expand Down Expand Up @@ -55,3 +63,32 @@ def form_valid(self, form):
"""
self.object = form.save(self.request.user)
return HttpResponseRedirect(self.get_success_url(), status=303)


class FavoriteArticle(IsAuthenticatedOrReadOnly, UpdateView):
fields = []
template_name = 'articles/_favorite.html'
queryset = Article.objects.select_related('author__user').annotate(
favorited_by__count=Count('favorited_by')
)

def get_success_url(self):
return reverse_lazy('article_favorite', kwargs={'slug': self.object.slug})

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

if self.request.user.is_authenticated:
context['has_favorited'] = self.request.user.profile.has_favorited(self.object)

return context

def form_valid(self, form):
profile = self.request.user.profile

if profile.has_favorited(self.object):
profile.unfavorite(self.object)
else:
profile.favorite(self.object)

return HttpResponseRedirect(self.get_success_url(), status=303)
1 change: 1 addition & 0 deletions realworld/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
path("admin/", admin.site.urls),
path("", home_views.index, name="index"),
path("article/<slug:slug>/", articles_views.view, name="article_view"),
path("article/<slug:slug>/favorite/", articles_views.FavoriteArticle.as_view(), name="article_favorite"),
path("editor/<slug:slug>/", articles_views.EditArticle.as_view(), name="article_edit"),
path("editor/", articles_views.CreateArticle.as_view(), name="article_create"),
path("@<slug:profile>/", profile_views.view, name="profile_view"),
Expand Down
24 changes: 24 additions & 0 deletions templates/articles/_favorite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<turbo-frame id="favorite-button-{{ article.slug }}">
{% if request.user.is_authenticated %}
<form method="POST" action="{% url 'article_favorite' article.slug %}" class="list-inline-item">
{% csrf_token %}

{% if has_favorited %}
<button class="btn btn-sm btn-primary">
<i class="ion-heart"></i>
&nbsp; Unfavorite Post <span class="counter">({{ article.favorited_by__count }})</span>
</button>
{% else %}
<button class="btn btn-sm btn-outline-primary">
<i class="ion-heart"></i>
&nbsp; Favorite Post <span class="counter">({{ article.favorited_by__count }})</span>
</button>
{% endif %}
</form>
{% else %}
<a data-turbo="false" href="{% url 'login' %}" class="btn btn-sm btn-outline-primary">
<i class="ion-heart"></i>
&nbsp; Login to Favorite <span class="counter">({{ article.favorited_by__count }})</span>
</a>
{% endif %}
</turbo-frame>
17 changes: 9 additions & 8 deletions templates/articles/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ <h1>How to build webapps that scale</h1>
&nbsp; Follow Eric Simons <span class="counter">(10)</span>
</button>
&nbsp;&nbsp;
<button class="btn btn-sm btn-outline-primary">
<i class="ion-heart"></i>
&nbsp; Favorite Post <span class="counter">(29)</span>
</button>

<turbo-frame
id="favorite-button-{{ article.slug }}"
src="{% url 'article_favorite' article.slug %}"
/>
</div>
</div>
</div>
Expand Down Expand Up @@ -50,10 +51,10 @@ <h2 id="introducing-ionic">Introducing RealWorld.</h2>
&nbsp; Follow Eric Simons <span class="counter">(10)</span>
</button>
&nbsp;
<button class="btn btn-sm btn-outline-primary">
<i class="ion-heart"></i>
&nbsp; Favorite Post <span class="counter">(29)</span>
</button>
<turbo-frame
id="favorite-button-{{ article.slug }}"
src="{% url 'article_favorite' article.slug %}"
/>
</div>
</div>

Expand Down

0 comments on commit 7a953b9

Please sign in to comment.