diff --git a/apps/article/serializers_admin.py b/apps/article/serializers_admin.py index fb4e028..b754755 100644 --- a/apps/article/serializers_admin.py +++ b/apps/article/serializers_admin.py @@ -39,18 +39,23 @@ class AbsoluteFileField(serializers.FileField): class AdminArticleCategorySerializer(serializers.ModelSerializer): + slug = serializers.CharField(required=False, allow_blank=True) + class Meta: model = ArticleCategory fields = ["id", "title", "slug", "status", "order"] class AdminArticleCollectionSerializer(serializers.ModelSerializer): + slug = serializers.CharField(required=False, allow_blank=True) + class Meta: model = ArticleCollection fields = ["id", "title", "slug", "summary", "display_position", "status", "order"] class AdminArticleListSerializer(serializers.ModelSerializer): + slug = serializers.CharField(required=False, allow_blank=True) thumbnail = AbsoluteImageField(required=False, allow_null=True) article_file = AbsoluteFileField(required=False, allow_null=True) categories = AdminArticleCategorySerializer(many=True, read_only=True) @@ -77,6 +82,7 @@ class AdminArticleListSerializer(serializers.ModelSerializer): class AdminArticleDetailSerializer(serializers.ModelSerializer): + slug = serializers.CharField(required=False, allow_blank=True) thumbnail = AbsoluteImageField(required=False, allow_null=True) article_file = AbsoluteFileField(required=False, allow_null=True) categories = serializers.PrimaryKeyRelatedField( @@ -129,6 +135,8 @@ class AdminArticleDetailSerializer(serializers.ModelSerializer): def create(self, validated_data): validated_data.pop("remove_thumbnail", False) validated_data.pop("remove_article_file", False) + if not validated_data.get("slug"): + validated_data.pop("slug", None) categories = validated_data.pop("categories", []) collections = validated_data.pop("collections", []) article = super().create(validated_data) @@ -141,6 +149,8 @@ class AdminArticleDetailSerializer(serializers.ModelSerializer): def update(self, instance, validated_data): remove_thumbnail = validated_data.pop("remove_thumbnail", False) remove_article_file = validated_data.pop("remove_article_file", False) + if not validated_data.get("slug"): + validated_data.pop("slug", None) categories = validated_data.pop("categories", None) collections = validated_data.pop("collections", None) diff --git a/apps/article/urls.py b/apps/article/urls.py index db5642e..5946b8f 100755 --- a/apps/article/urls.py +++ b/apps/article/urls.py @@ -24,8 +24,9 @@ urlpatterns = [ path('pinned-collections/', PinnedArticleCollectionListView.as_view(), name='pinned-collection-list'), path('collections/', MiddleArticleCollectionListView.as_view(), name='collection-list'), - path('list/', ArticleListAPIView.as_view(), name='podcast-list'), - re_path(r'detail/(?P[\w-]+)/$', ArticleDetailAPIView.as_view(), name='podcast-detail'), + path('list/', ArticleListAPIView.as_view(), name='article-list'), + path('detail//', ArticleDetailAPIView.as_view(), name='article-detail'), + re_path(r'detail/(?P.+)/$', ArticleDetailAPIView.as_view(), name='podcast-detail'), path('admin/', include(admin_router.urls)), # # User playlist endpoints diff --git a/apps/article/views.py b/apps/article/views.py index 4e7090f..1644083 100755 --- a/apps/article/views.py +++ b/apps/article/views.py @@ -251,6 +251,23 @@ class ArticleDetailAPIView(Gone410ViewMixin, CanonicalSlugViewSetMixin, generics def get_queryset(self): return Article.objects.all() + def get_object(self): + queryset = self.filter_queryset(self.get_queryset()) + slug_val = self.kwargs.get(self.lookup_field or 'slug') + if slug_val: + import urllib.parse + unquoted_slug = urllib.parse.unquote(slug_val) + obj = queryset.filter( + Q(slug=slug_val) | + Q(slug=unquoted_slug) | + Q(slug__iexact=slug_val) | + Q(slug__iexact=unquoted_slug) + ).first() + if obj: + self.check_object_permissions(self.request, obj) + return obj + return super().get_object() + def retrieve(self, request, *args, **kwargs): instance = self.get_object() instance.increment_view_count() diff --git a/apps/library/models.py b/apps/library/models.py index de38714..c1898f6 100644 --- a/apps/library/models.py +++ b/apps/library/models.py @@ -77,8 +77,8 @@ class Category(LowercaseSlugMixin, models.Model): @property def books_count(self): - """Return the number of books in this category""" - return self.related_categories.count() + """Return the number of active books in this category""" + return self.related_categories.filter(status=True).count() class Meta: verbose_name = _('Category') diff --git a/apps/library/views.py b/apps/library/views.py index cfdc254..bbc585f 100644 --- a/apps/library/views.py +++ b/apps/library/views.py @@ -47,7 +47,7 @@ class CategoryListView(ListAPIView): return Category.objects.filter( status=True ).annotate( - books_count_annotation=Count('related_categories') + books_count_annotation=Count('related_categories', filter=Q(related_categories__status=True)) ).order_by('title')