Skip to content

Commit ce71ec7

Browse files
committed
Add create and update post views.
1 parent 7d148e0 commit ce71ec7

6 files changed

Lines changed: 173 additions & 3 deletions

File tree

project/newsletter/test_views.py

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,72 @@ def test_pagination(self):
206206
)
207207

208208

209+
class TestUpdatePost(DataTestCase):
210+
def test_staff_user_required(self):
211+
user = User.objects.create_user(username="basic")
212+
self.client.force_login(user)
213+
url = reverse(
214+
"newsletter:update_post", kwargs={"slug": self.data.private_post.slug}
215+
)
216+
response = self.client.post(url)
217+
self.assertRedirects(response, f"{settings.LOGIN_URL}?next={url}")
218+
219+
def test_get(self):
220+
self.client.force_login(self.user)
221+
url = reverse(
222+
"newsletter:update_post", kwargs={"slug": self.data.private_post.slug}
223+
)
224+
response = self.client.get(url)
225+
self.assertTemplateUsed(response, "staff/post_form.html")
226+
227+
def test_invalid(self):
228+
self.client.force_login(self.user)
229+
url = reverse(
230+
"newsletter:update_post", kwargs={"slug": self.data.private_post.slug}
231+
)
232+
response = self.client.post(url, data={})
233+
self.assertTemplateUsed(response, "staff/post_form.html")
234+
self.assertInHTML(
235+
"<li>This field is required.</li>",
236+
response.content.decode("utf-8"),
237+
)
238+
239+
def test_update(self):
240+
post = Post.objects.create(
241+
author=self.data.author,
242+
title="Test Update",
243+
slug="test-update",
244+
content="c",
245+
)
246+
self.client.force_login(self.user)
247+
248+
data = {
249+
"title": "Test Update2",
250+
"slug": "test-update2",
251+
"categories": [self.data.career.id],
252+
"content": "content",
253+
"summary": "summary",
254+
"is_public": False,
255+
"is_published": True,
256+
"open_graph_description": "description",
257+
}
258+
response = self.client.post(
259+
reverse("newsletter:update_post", kwargs={"slug": post.slug}), data=data
260+
)
261+
self.assertRedirects(
262+
response, reverse("newsletter:update_post", kwargs={"slug": "test-update2"})
263+
)
264+
post.refresh_from_db()
265+
self.assertEqual(post.slug, "test-update2")
266+
self.assertEqual(post.title, "Test Update2")
267+
self.assertEqual(post.categories.get(), self.data.career)
268+
self.assertEqual(post.content, "content")
269+
self.assertEqual(post.summary, "summary")
270+
self.assertEqual(post.open_graph_description, "description")
271+
self.assertFalse(post.is_public)
272+
self.assertTrue(post.is_published)
273+
274+
209275
class TestTogglePostPrivacy(DataTestCase):
210276
def test_staff_user_required(self):
211277
user = User.objects.create_user(username="basic")
@@ -240,12 +306,68 @@ def test_toggle(self):
240306
self.assertFalse(post.is_public)
241307

242308
# Toggle the property back and verify the redirect to next.
243-
response = self.client.post(url + f"?next={reverse('newsletter:landing')}")
244-
self.assertRedirects(response, reverse("newsletter:landing"))
309+
response = self.client.post(
310+
url
311+
+ f"?next={reverse('newsletter:update_post', kwargs={'slug': post.slug})}"
312+
)
313+
self.assertRedirects(
314+
response, reverse("newsletter:update_post", kwargs={"slug": post.slug})
315+
)
245316
post.refresh_from_db()
246317
self.assertTrue(post.is_public)
247318

248319

320+
class TestCreatePost(DataTestCase):
321+
def test_staff_user_required(self):
322+
user = User.objects.create_user(username="basic")
323+
self.client.force_login(user)
324+
url = reverse("newsletter:create_post")
325+
response = self.client.post(url)
326+
self.assertRedirects(response, f"{settings.LOGIN_URL}?next={url}")
327+
328+
def test_get(self):
329+
self.client.force_login(self.user)
330+
url = reverse("newsletter:create_post")
331+
response = self.client.get(url)
332+
self.assertTemplateUsed(response, "staff/post_form.html")
333+
334+
def test_invalid(self):
335+
self.client.force_login(self.user)
336+
response = self.client.post(reverse("newsletter:create_post"), data={})
337+
self.assertTemplateUsed(response, "staff/post_form.html")
338+
self.assertInHTML(
339+
"<li>This field is required.</li>",
340+
response.content.decode("utf-8"),
341+
)
342+
343+
def test_create(self):
344+
self.client.force_login(self.user)
345+
346+
data = {
347+
"title": "Test Create",
348+
"slug": "test-create",
349+
"categories": [self.data.career.id],
350+
"content": "content",
351+
"summary": "summary",
352+
"is_public": False,
353+
"is_published": True,
354+
"open_graph_description": "description",
355+
}
356+
response = self.client.post(reverse("newsletter:create_post"), data=data)
357+
358+
self.assertRedirects(
359+
response, reverse("newsletter:update_post", kwargs={"slug": "test-create"})
360+
)
361+
post = Post.objects.get(slug="test-create")
362+
self.assertEqual(post.title, "Test Create")
363+
self.assertEqual(post.categories.get(), self.data.career)
364+
self.assertEqual(post.content, "content")
365+
self.assertEqual(post.summary, "summary")
366+
self.assertEqual(post.open_graph_description, "description")
367+
self.assertFalse(post.is_public)
368+
self.assertTrue(post.is_published)
369+
370+
249371
class TestUpdateSubscription(DataTestCase):
250372
def setUp(self) -> None:
251373
super().setUp()

project/newsletter/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
path("account/", views.update_subscription, name="update_subscription"),
1010
path("analytics/", views.analytics, name="analytics"),
1111
path("post/unpublished/", views.unpublished_posts, name="unpublished_posts"),
12+
path("post/create/", views.create_post, name="create_post"),
13+
path("post/<slug>/update/", views.update_post, name="update_post"),
1214
path(
1315
"post/<slug>/toggle_privacy/",
1416
views.toggle_post_privacy,

project/newsletter/views.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from martor.utils import LazyEncoder
2020

2121
from project.newsletter import operations
22-
from project.newsletter.forms import SubscriptionForm
22+
from project.newsletter.forms import PostForm, SubscriptionForm
2323
from project.newsletter.models import Category, Post, Subscription
2424

2525
LIST_POSTS_PAGE_SIZE = 100
@@ -129,6 +129,24 @@ def unpublished_posts(request):
129129
)
130130

131131

132+
@staff_member_required(login_url=settings.LOGIN_URL)
133+
@require_http_methods(["GET", "POST"])
134+
def update_post(request, slug):
135+
"""
136+
Staff update post view
137+
"""
138+
post = get_object_or_404(Post, slug=slug)
139+
form = PostForm(instance=post)
140+
if request.method == "POST":
141+
form = PostForm(request.POST, instance=post)
142+
if form.is_valid():
143+
form.instance.author = request.user
144+
post = form.save()
145+
messages.success(request, f"Post '{post.title}' was updated successfully.")
146+
return redirect("newsletter:update_post", slug=post.slug)
147+
return render(request, "staff/post_form.html", {"form": form, "post": post})
148+
149+
132150
@staff_member_required(login_url=settings.LOGIN_URL)
133151
@require_http_methods(["POST"])
134152
def toggle_post_privacy(request, slug):
@@ -152,6 +170,23 @@ def toggle_post_privacy(request, slug):
152170
return redirect("newsletter:list_posts")
153171

154172

173+
@staff_member_required(login_url=settings.LOGIN_URL)
174+
@require_http_methods(["GET", "POST"])
175+
def create_post(request):
176+
"""
177+
Staff create post view
178+
"""
179+
form = PostForm()
180+
if request.method == "POST":
181+
form = PostForm(request.POST)
182+
if form.is_valid():
183+
form.instance.author = request.user
184+
post = form.save()
185+
messages.success(request, f"Post '{post.title}' was created successfully.")
186+
return redirect("newsletter:update_post", slug=post.slug)
187+
return render(request, "staff/post_form.html", {"form": form, "post": None})
188+
189+
155190
@staff_member_required(login_url=settings.LOGIN_URL)
156191
@require_http_methods(["GET"])
157192
def analytics(request):

project/templates/base.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
<div class="menu transition hidden" tabindex="-1">
2626
<a href="{% url "newsletter:list_posts" %}" class="item">Published</a>
2727
<a href="{% url "newsletter:unpublished_posts" %}" class="item">Unpublished</a>
28+
<div class="divider"></div>
29+
<a href="{% url "newsletter:create_post" %}" class="item">Create</a>
2830
</div>
2931
</div>
3032
{% endif %}

project/templates/posts/detail.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
{{ post.title }}
2929
{% endif %}
3030
</div>
31+
{% if request.user.is_staff %}
32+
<div class="divider"> / </div>
33+
<a href="{% url "newsletter:update_post" slug=post.slug %}" class="section">Edit</a>
34+
{% endif %}
3135
</div>
3236
<p>
3337
Posted {{ post.publish_date|naturaltime }}

project/templates/posts/includes/list_item.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ <h3 class="ui header">{{ post.title }}</h3>
2222
<div class="left floated six wide column">
2323
<a href="{{ post.get_absolute_url }}" class="ui large button">Read More</a>
2424
</div>
25+
{% if request.user.is_staff %}
26+
<div class="right floated six wide column">
27+
<a href="{% url "newsletter:update_post" slug=post.slug %}" class="ui basic compact button">Edit</a>
28+
</div>
29+
{% endif %}
2530
</div>

0 commit comments

Comments
 (0)