feat: add category update and delete functionality

Introduced CategoryUpdateView and CategoryDeleteView to enable category
editing and deletion. Updated category template links to use Django's
URL template tags for safer URL resolution. Added a new template for
generic deletes, enhancing user feedback during deletion operations.
This improvement allows for more dynamic and secure category management,
aligning with the app's need for scalable user permissions and actions.

These changes not only make the URL handling more robust and
Django-native but also improve the user experience by providing clear
pathways for category management tasks, ensuring that only authorized
users can perform sensitive actions.
This commit is contained in:
Kumi 2024-03-27 09:34:53 +01:00
parent 42e9de6942
commit 0378bf6c7c
Signed by: kumi
GPG key ID: ECBCC9082395383F
4 changed files with 97 additions and 12 deletions

View file

@ -6,10 +6,10 @@
{% endif %} {% endif %}
{% if request.user.is_superuser or request.user == category.owner %} {% if request.user.is_superuser or request.user == category.owner %}
<div> <div>
<a href="/tours/category/{{ category.id }}/edit/" class="btn btn-primary" <a href="{% url "quackscape.users:category-update" category.id %}" class="btn btn-primary"
>Edit category</a >Edit category</a
> >
<a href="/tours/category/{{ category.id }}/delete/" class="btn btn-danger" <a href="{% url "quackscape.users:category-delete" category.id %}" class="btn btn-danger"
>Delete category</a >Delete category</a
> >
</div> </div>

View file

@ -0,0 +1,24 @@
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h4 class="mb-0">{{ title }}</h4>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete {{ object }}?</p>
<a href="{% url 'quackscape.users:categories' %}" class="btn btn-secondary">Cancel</a>
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -1,15 +1,39 @@
from .views import UserAreaMainView, CategoriesView, CategoryView, FileUploadView, Login, Logout, CategoryCreateView from .views import (
UserAreaMainView,
CategoriesView,
CategoryView,
FileUploadView,
Login,
Logout,
CategoryCreateView,
CategoryDeleteView,
CategoryUpdateView,
)
from django.urls import path from django.urls import path
app_name = 'quackscape.users' app_name = "quackscape.users"
urlpatterns = [ urlpatterns = [
path('', UserAreaMainView.as_view(), name='user-area-main'), path("", UserAreaMainView.as_view(), name="user-area-main"),
path('categories/', CategoriesView.as_view(), name='categories'), path("categories/", CategoriesView.as_view(), name="categories"),
path('category/create/', CategoryCreateView.as_view(), name='category-create'), path("category/create/", CategoryCreateView.as_view(), name="category-create"),
path('category/<uuid:category>/', CategoryView.as_view(), name='category'), path("category/<uuid:category>/", CategoryView.as_view(), name="category"),
path('category/<uuid:category>/upload/', FileUploadView.as_view(), name='media-upload'), path(
path('login/', Login.as_view(), name='login'), "category/<uuid:category>/update/",
path('logout/', Logout.as_view(), name='logout'), CategoryUpdateView.as_view(),
name="category-update",
),
path(
"category/<uuid:category>/delete/",
CategoryDeleteView.as_view(),
name="category-delete",
),
path(
"category/<uuid:category>/upload/",
FileUploadView.as_view(),
name="media-upload",
),
path("login/", Login.as_view(), name="login"),
path("logout/", Logout.as_view(), name="logout"),
] ]

View file

@ -88,6 +88,43 @@ class CategoryCreateView(LoginRequiredMixin, TitleMixin, CreateView):
) )
class CategoryUpdateView(LoginRequiredMixin, TitleMixin, UpdateView):
template_name = "users/generic_form.html"
title = "Update Category"
form_class = CategoryForm
model = Category
def get_object(self):
try:
category = Category.objects.get(id=self.kwargs["category"])
assert category.user_has_permission(self.request.user)
return category
except (Category.DoesNotExist, AssertionError):
raise Http404()
def get_success_url(self):
return reverse_lazy(
"quackscape.users:category", kwargs={"category": self.object.id}
)
class CategoryDeleteView(LoginRequiredMixin, TitleMixin, DeleteView):
template_name = "users/generic_delete.html"
title = "Delete Category"
model = Category
def get_object(self):
try:
category = Category.objects.get(id=self.kwargs["category"])
assert category.user_has_permission(self.request.user)
return category
except (Category.DoesNotExist, AssertionError):
raise Http404()
def get_success_url(self):
return reverse_lazy("quackscape.users:categories")
class FileUploadView(LoginRequiredMixin, GenericAPIView): class FileUploadView(LoginRequiredMixin, GenericAPIView):
parser_classes = (MultiPartParser, FormParser) parser_classes = (MultiPartParser, FormParser)