Skip to content

Commit d6d0323

Browse files
committed
Add view for viewing a newsletter post.
[Lab1.1]
1 parent 4c11b7d commit d6d0323

4 files changed

Lines changed: 64 additions & 6 deletions

File tree

project/newsletter/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.db import models
66
from django.db.models import Exists, F, OuterRef
77
from django.db.models.functions import Coalesce
8+
from django.urls import reverse
89
from django.utils import timezone
910
from django.utils.translation import gettext_lazy as _
1011
from martor.models import MartorField
@@ -159,7 +160,7 @@ def publish_date(self):
159160
return self.publish_at or self.created
160161

161162
def get_absolute_url(self):
162-
return f"/p/{self.slug}/"
163+
return reverse("newsletter:view_post", kwargs={"lookup": self.slug})
163164

164165

165166
class SubscriptionQuerySet(models.QuerySet):

project/newsletter/test_views.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,42 @@ def test_pagination(self):
9494
)
9595

9696

97+
class TestViewPost(DataTestCase):
98+
def test_unauthenticated(self):
99+
response = self.client.get(
100+
reverse(
101+
"newsletter:view_post", kwargs={"lookup": self.data.career_post.title}
102+
)
103+
)
104+
self.assertTemplateUsed(response, "posts/detail.html")
105+
self.assertEqual(response.context["post"], self.data.career_post)
106+
107+
def test_authenticated_private_post(self):
108+
self.client.force_login(self.data.subscription.user)
109+
response = self.client.get(
110+
reverse(
111+
"newsletter:view_post", kwargs={"lookup": self.data.private_post.title}
112+
)
113+
)
114+
self.assertTemplateUsed(response, "posts/detail.html")
115+
self.assertEqual(response.context["post"], self.data.private_post)
116+
117+
def test_mark_as_read(self):
118+
notification = SubscriptionNotification.objects.create(
119+
subscription=self.data.subscription,
120+
post=self.data.all_post,
121+
sent=timezone.now(),
122+
)
123+
self.client.force_login(self.data.subscription.user)
124+
response = self.client.get(
125+
reverse("newsletter:view_post", kwargs={"lookup": self.data.all_post.title})
126+
)
127+
self.assertTemplateUsed(response, "posts/detail.html")
128+
self.assertEqual(response.context["post"], self.data.all_post)
129+
notification.refresh_from_db()
130+
self.assertIsNotNone(notification.read)
131+
132+
97133
class TestUnpublishedPosts(DataTestCase):
98134
url = reverse("newsletter:unpublished_posts")
99135

project/newsletter/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
include(
2222
[
2323
path("", views.list_posts, name="list_posts"),
24+
path("<lookup>/", views.view_post, name="view_post"),
2425
]
2526
),
2627
),

project/newsletter/views.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@
99
from django.core.files.base import ContentFile
1010
from django.core.files.storage import default_storage
1111
from django.core.paginator import Paginator
12-
from django.db.models import Case, F, Value, When
13-
from django.http import Http404
14-
from django.db.models import Count, Q
15-
from django.http import HttpResponse, JsonResponse
16-
from django.shortcuts import redirect, render, get_object_or_404
12+
from django.db.models import Case, Count, F, Q, Value, When
13+
from django.http import Http404, HttpResponse, JsonResponse
14+
from django.shortcuts import get_object_or_404, redirect, render
1715
from django.utils import timezone
1816
from django.utils.translation import gettext_lazy as _
1917
from django.views.decorators.http import require_http_methods
2018
from martor.utils import LazyEncoder
2119

20+
from project.newsletter import operations
2221
from project.newsletter.forms import PostForm, SubscriptionForm
2322
from project.newsletter.models import Category, Post, Subscription
2423

@@ -70,6 +69,27 @@ def list_posts(request):
7069
)
7170

7271

72+
@require_http_methods(["GET"])
73+
def view_post(request, lookup):
74+
"""
75+
The post detail view.
76+
"""
77+
posts = Post.objects.published().annotate_is_unread(request.user)
78+
if not request.user.is_authenticated:
79+
posts = posts.public()
80+
post = posts.get(title=lookup)
81+
if post.is_unread:
82+
operations.mark_as_read(post, request.user)
83+
return render(
84+
request,
85+
"posts/detail.html",
86+
{
87+
"post": post,
88+
"open_graph_url": request.build_absolute_uri(post.get_absolute_url()),
89+
},
90+
)
91+
92+
7393
@require_http_methods(["GET", "POST"])
7494
@login_required()
7595
def update_subscription(request):

0 commit comments

Comments
 (0)