feat: allow deleting of posts

This commit is contained in:
m5ka 2024-03-27 16:19:10 +00:00
parent 2fed369027
commit ad27fdf1c2
7 changed files with 63 additions and 9 deletions

View file

@ -5,7 +5,7 @@ from django.urls import include, path
from moku.views.auth import LoginView, LogoutView from moku.views.auth import LoginView, LogoutView
from moku.views.blog import IndexBlogView from moku.views.blog import IndexBlogView
from moku.views.post import EditPostview, FeedView from moku.views.post import DeletePostView, EditPostview, FeedView
from moku.views.recipe import ( from moku.views.recipe import (
DeleteRecipeView, DeleteRecipeView,
DeleteStepView, DeleteStepView,
@ -34,7 +34,8 @@ urlpatterns = [
path("blog", IndexBlogView.as_view(), name="blog.index"), path("blog", IndexBlogView.as_view(), name="blog.index"),
path("privacy", PrivacyView.as_view(), name="privacy"), path("privacy", PrivacyView.as_view(), name="privacy"),
path("terms", TermsView.as_view(), name="terms"), path("terms", TermsView.as_view(), name="terms"),
path("edit/<str:uuid>", EditPostview.as_view(), name="post.edit"), path("post/<str:uuid>", EditPostview.as_view(), name="post.edit"),
path("post/<str:uuid>/delete", DeletePostView.as_view(), name="post.delete"),
path("user/<str:username>", ProfileView.as_view(), name="profile"), path("user/<str:username>", ProfileView.as_view(), name="profile"),
path("user/<str:username>/json", UserJSONView.as_view(), name="json"), path("user/<str:username>/json", UserJSONView.as_view(), name="json"),
path("recipes", IndexRecipeView.as_view(), name="recipe.index"), path("recipes", IndexRecipeView.as_view(), name="recipe.index"),

View file

@ -1,9 +1,13 @@
from django.forms import ModelForm from django.forms import Form, ModelForm
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from moku.models import Post from moku.models import Post
class DeletePostForm(Form):
pass
class PostForm(ModelForm): class PostForm(ModelForm):
"""Form for creating and updating posts.""" """Form for creating and updating posts."""

View file

@ -86,10 +86,10 @@ class Post(models.Model):
objects = PostManager() objects = PostManager()
def __str__(self): def __str__(self):
return f"{self.text} on {self.created_at}" return f"{self.plain_text} on {self.created_at}"
@property @property
def text(self): def html(self):
""" """
The text of the post, with the post's chosen verb hydrated with food and user The text of the post, with the post's chosen verb hydrated with food and user
information. information.
@ -101,3 +101,11 @@ class Post(models.Model):
), ),
"food": escape(self.food), "food": escape(self.food),
} }
@property
def plain_text(self):
"""The text of the post as plain text."""
return self.get_verb_display() % {
"user": f"@{self.created_by.username}",
"food": escape(self.food),
}

View file

@ -2,7 +2,16 @@
{% block content %} {% block content %}
<div class="content block"> <div class="content block">
<h2>{% trans time_ago=post.created_at|naturaltime %}editing post from {{ time_ago }}{% endtrans %}</h2> <p class="mb">
👈 <a href="{{ url('feed') }}">back to feed</a>
<span class="mx">•</span>
❌ <a href="{{ url('post.delete', uuid=post.uuid) }}">delete post</a>
</p>
<h2>
{% trans post_text=post.plain_text, time_ago=post.created_at|naturaltime %}
editing {{ post_text }} from {{ time_ago }}
{% endtrans %}
</h2>
{% include "moku/snippets/post_form.jinja" %} {% include "moku/snippets/post_form.jinja" %}
</div> </div>
{% endblock content %} {% endblock content %}

View file

@ -8,7 +8,7 @@
{% endif %} {% endif %}
<div class="emoji">{{ post.emoji }}</div> <div class="emoji">{{ post.emoji }}</div>
<div class="body"> <div class="body">
<p class="food user-content">{{ post.text|safe }}</p> <p class="food user-content">{{ post.html|safe }}</p>
<p class="metadata"> <p class="metadata">
{{ post.created_at|naturaltime }} {{ post.created_at|naturaltime }}
{% if request.user.is_authenticated and request.user.id == post.created_by.id %} {% if request.user.is_authenticated and request.user.id == post.created_by.id %}

View file

@ -12,4 +12,5 @@ def test_post(post: Post, re_uuid: re.Pattern):
assert post.pk > 0 assert post.pk > 0
assert post.pk == post.id assert post.pk == post.id
assert re_uuid.match(post.uuid) is not None assert re_uuid.match(post.uuid) is not None
assert post.text == '<a href="/user/jean">@jean</a> cooked sausage surprise' assert post.html == '<a href="/user/jean">@jean</a> cooked sausage surprise'
assert post.plain_text == "@jean cooked sausage surprise"

View file

@ -1,12 +1,14 @@
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from moku.constants import EMOJI_CATEGORIES, Verbs from moku.constants import EMOJI_CATEGORIES, Verbs
from moku.forms.post import PostForm from moku.forms.post import DeletePostForm, PostForm
from moku.images import process_post_image from moku.images import process_post_image
from moku.models.post import Post from moku.models.post import Post
from moku.models.recipe import Recipe from moku.models.recipe import Recipe
@ -20,6 +22,35 @@ def _get_verbs(username):
) )
class DeletePostView(LoginRequiredMixin, UserPassesTestMixin, FormView):
"""Allows users to delete their previous posts."""
template_name = "moku/delete.jinja"
form_class = DeletePostForm
def form_valid(self, form):
self.post_object.delete()
messages.success(self.request, _("post deleted successfully!"))
return redirect("feed")
def get_context_data(self, **kwargs):
return {
**super().get_context_data(**kwargs),
"item": _("%(post_text)s from %(time_ago)s") % {
"post_text": self.post_object.plain_text,
"time_ago": naturaltime(self.post_object.created_at),
},
"back_url": reverse("post.edit", kwargs={"uuid": self.post_object.uuid}),
}
@cached_property
def post_object(self):
return get_object_or_404(Post, uuid=self.kwargs.get("uuid"))
def test_func(self):
return self.request.user.id == self.post_object.created_by.id
class EditPostview(LoginRequiredMixin, UserPassesTestMixin, FormView): class EditPostview(LoginRequiredMixin, UserPassesTestMixin, FormView):
"""Allows users to edit their previous posts.""" """Allows users to edit their previous posts."""