Skip to content
This repository has been archived by the owner on Dec 26, 2023. It is now read-only.

Commit

Permalink
Fix #8: allow users to favorite articles
Browse files Browse the repository at this point in the history
  • Loading branch information
blopker committed Jan 14, 2021
1 parent 052a76f commit cd5dd66
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 22 deletions.
46 changes: 43 additions & 3 deletions articles/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.shortcuts import get_object_or_404
from django.http.response import Http404
from django.shortcuts import get_object_or_404, redirect
from django.conf import settings
from django.urls import reverse_lazy
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.http import HttpResponseRedirect, JsonResponse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView, UpdateView
Expand All @@ -12,7 +14,8 @@


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


class ListArticle(ListView):
Expand Down Expand Up @@ -178,3 +181,40 @@ def form_valid(self, form):
"""
self.object = form.save(self.request.user)
return HttpResponseRedirect(self.get_success_url(), status=303)


def favorite_article(request, slug):
template = "articles/favorite.html"
if request.GET.get("mini", None):
template = "articles/favorite_mini.html"

query = Article.objects.annotate(favorited_by__count=Count("favorited_by"))
article = get_object_or_404(query, slug=slug)

favorited = False
if request.user.is_authenticated:
favorited = request.user.profile.has_favorited(article)

if request.method == "POST" and request.user.is_authenticated:
if favorited:
request.user.profile.unfavorite(article)
else:
request.user.profile.favorite(article)
favorited = not favorited

active_class = "btn-outline-primary"
if favorited:
active_class = "btn-primary"

# refresh counts
article = get_object_or_404(query, slug=slug)

return render(
request,
template,
context={
"article": article,
"active_class": active_class,
"favorited": favorited,
},
)
3 changes: 1 addition & 2 deletions realworld/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = "/static/"
STATICFILES_DIRS = []
STATICFILES_DIRS = ["assets"]

STATIC_ROOT = BASE_DIR / "assets"

Expand Down
5 changes: 5 additions & 0 deletions realworld/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
path("", home_views.index, name="index"),
path("article/<slug:slug>/", articles_views.view, name="article_view"),
path("article/", articles_views.ListArticle.as_view(), name="article_list"),
path(
"article/<slug:slug>/favorite/",
articles_views.favorite_article,
name="article_favorite",
),
path(
"editor/<slug:slug>/", articles_views.EditArticle.as_view(), name="article_edit"
),
Expand Down
14 changes: 6 additions & 8 deletions templates/articles/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ <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-{{ article.slug }}"
src="{% url 'article_favorite' slug=article.slug %}">
</div>
</div>
</div>
Expand Down Expand Up @@ -50,10 +49,9 @@ <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-{{ article.slug }}"
src="{% url 'article_favorite' slug=article.slug %}">
</div>
</div>

Expand Down
33 changes: 33 additions & 0 deletions templates/articles/favorite.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<turbo-frame id="favorite-{{ article.slug }}">
{% if request.user.is_authenticated %}
<form
method="POST"
action="{% url 'article_favorite' article.slug %}"
class="list-inline-item"
>
{% csrf_token %}
<button class="btn btn-sm {{ active_class }}">
<i class="ion-heart"></i>
{% if favorited %} &nbsp; Unfavorite Post {% else %} &nbsp; Favorite Post
{% endif %}
<span class="counter">({{ article.favorited_by__count }})</span>
</button>
</form>
{% else %}
<a
href="{% url 'login' %}?next={{request.path}}"
class="btn btn-sm btn-outline-primary"
target="_top"
>
<i class="ion-heart"></i>
&nbsp; Favorite Post
<span class="counter">({{ article.favorited_by__count }})</span>
</a>
{% endif %} {% if request.method == 'POST' %}
<script>
document
.querySelectorAll("#favorite-{{article.slug}}")
.forEach((e) => e.attributeChangedCallback("src"));
</script>
{% endif %}
</turbo-frame>
22 changes: 22 additions & 0 deletions templates/articles/favorite_mini.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<turbo-frame id="favorite-{{ article.slug }}">
{% if request.user.is_authenticated %}
<form
method="POST"
action="{% url 'article_favorite' article.slug %}?mini=true"
class="list-inline-item pull-xs-right"
>
{% csrf_token %}
<button class="btn {{ active_class }} btn-sm pull-xs-right">
<i class="ion-heart"></i> {{ article.favorited_by__count }}
</button>
</form>
{% else %}
<a
href="{% url 'login' %}?next={{request.path}}"
class="btn btn-sm btn-outline-primary pull-xs-right"
target="_top"
>
<i class="ion-heart"></i> {{ article.favorited_by__count }}
</a>
{% endif %}
</turbo-frame>
13 changes: 5 additions & 8 deletions templates/articles/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
</a>
<span class="date">{{ article.created_at }}</span>
</div>
<button class="btn btn-outline-primary btn-sm pull-xs-right">
<i class="ion-heart"></i> {{ article.favorited_by__count }}
</button>
<turbo-frame
id="favorite-{{ article.slug }}"
src="{% url 'article_favorite' slug=article.slug %}?mini=true"
>
</turbo-frame>
</div>
<a
href="{% url 'article_view' article.slug %}"
Expand Down Expand Up @@ -81,10 +83,5 @@ <h1>{{ article.title }}</h1>
>
{% endif %}
</span>
<script>
function toTop() {
window.scrollTo(0, 0);
}
</script>
</div>
</turbo-frame>
7 changes: 6 additions & 1 deletion templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
<!-- Import the custom Bootstrap 4 theme from our hosted CDN -->
<link rel="stylesheet" href="https://demo.productionready.io/main.css" />
<script
src="https://unpkg.com/@hotwired/[email protected].2/dist/turbo.es2017-umd.js"
src="https://unpkg.com/@hotwired/[email protected].3/dist/turbo.es2017-umd.js"
defer
data-turbo-track="reload"
></script>
<script>
function toTop() {
window.scrollTo(0, 0);
}
</script>
</head>
<body>
<nav class="navbar navbar-light">
Expand Down

0 comments on commit cd5dd66

Please sign in to comment.