Skip to content

Commit bc1a50b

Browse files
committed
Add view for viewing a newsletter post.
1 parent 4b0e99a commit bc1a50b

4 files changed

Lines changed: 62 additions & 2 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
@@ -155,7 +156,7 @@ def __repr__(self):
155156
return f"<Post title={self.title} slug={self.slug} is_published={self.is_published} created={self.created} updated={self.updated}>"
156157

157158
def get_absolute_url(self):
158-
return f"/p/{self.slug}/"
159+
return reverse("newsletter:view_post", kwargs={"lookup": self.slug})
159160

160161
@property
161162
def publish_date(self):

project/newsletter/test_views.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from django.utils import timezone
99
from PIL import Image
1010

11-
from project.newsletter.models import Post, Subscription
11+
from project.newsletter.models import Post, Subscription, SubscriptionNotification
1212
from project.newsletter.test import DataTestCase
1313

1414

@@ -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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from django.views.decorators.http import require_http_methods
1818
from martor.utils import LazyEncoder
1919

20+
from project.newsletter import operations
2021
from project.newsletter.forms import PostForm, SubscriptionForm
2122
from project.newsletter.models import Category, Post, Subscription
2223

@@ -68,6 +69,27 @@ def list_posts(request):
6869
)
6970

7071

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+
7193
@require_http_methods(["GET", "POST"])
7294
@login_required()
7395
def update_subscription(request):

0 commit comments

Comments
 (0)