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:
parent
42e9de6942
commit
0378bf6c7c
4 changed files with 97 additions and 12 deletions
|
@ -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>
|
||||||
|
|
24
quackscape/users/templates/users/generic_delete.html
Normal file
24
quackscape/users/templates/users/generic_delete.html
Normal 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 %}
|
|
@ -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"),
|
||||||
]
|
]
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue