Skip to content

Commit

Permalink
Merge pull request #165 from 2077-Collective/staging
Browse files Browse the repository at this point in the history
Staging to Main merge
  • Loading branch information
losndu authored Sep 3, 2024
2 parents 06080ca + 24e1348 commit 385e087
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 19 deletions.
1 change: 1 addition & 0 deletions server/apps/research/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .category_admin import CategoryAdmin
from .author_admin import AuthorAdmin
from .article_admin import ArticleAdmin
from .log_entry import LogEntryAdmin
10 changes: 10 additions & 0 deletions server/apps/research/admin/log_entry.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.contrib import admin
from django.contrib.admin.models import LogEntry
from django.utils.translation import gettext_lazy as _

class LogEntryAdmin(admin.ModelAdmin):
list_display = ('action_time', 'user', 'content_type', 'object_id', 'action_flag', 'change_message')
list_filter = ('action_flag', 'user', 'content_type')
search_fields = ('object_id', 'change_message')

admin.site.register(LogEntry, LogEntryAdmin)
18 changes: 18 additions & 0 deletions server/apps/research/migrations/0019_alter_article_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-09-02 23:20

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('research', '0018_alter_article_acknowledgement'),
]

operations = [
migrations.AlterField(
model_name='article',
name='status',
field=models.CharField(choices=[('draft', 'Draft'), ('ready', 'Ready')], db_index=True, default='draft', max_length=10),
),
]
4 changes: 2 additions & 2 deletions server/apps/research/models/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class Article(BaseModel):
summary = models.TextField(blank=True)
acknowledgement = HTMLField(blank=True, null=True)
authors = models.ManyToManyField(Author, blank=True, related_name='articles')
slug = models.SlugField(blank=True)
slug = models.SlugField(blank=True, db_index=True)
categories = models.ManyToManyField(Category, blank=True, related_name='articles')
thumb = models.ImageField(upload_to='images/', default=get_default_thumb, blank=True)
views = models.PositiveBigIntegerField(default=0)
status = models.CharField(max_length=10, choices=options, default='draft')
status = models.CharField(max_length=10, choices=options, default='draft', db_index=True)
scheduled_publish_time = models.DateTimeField(null=True, blank=True, db_index=True)

objects = models.Manager()
Expand Down
13 changes: 6 additions & 7 deletions server/apps/research/urls.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
from django.urls import path, include, re_path
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet, index
from django.urls import path, re_path, include
from django.conf import settings
from django.conf.urls.static import static
from django.http import HttpResponse
import requests
from django.views.generic.base import RedirectView
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='article')

urlpatterns = [
path('', index, name='index'),
path('', RedirectView.as_view(url='/admin/', permanent=False)), # Redirect root to admin
path('api/', include(router.urls)),

# Custom URL for retrieving articles by slug or UUID
re_path(r'^api/articles/(?P<identifier>[-\w0-9a-fA-F]+)/$', ArticleViewSet.as_view({'get': 'retrieve_by_identifier'}), name='article-detail-by-identifier'),

# Custom URL for retrieving articles by category
re_path(r'^api/articles/category/(?P<category>[-\w]+)/$', ArticleViewSet.as_view({'get': 'retrieve_by_category'}), name='article-list-by-category'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
26 changes: 16 additions & 10 deletions server/apps/research/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
from rest_framework import viewsets, status
from rest_framework.response import Response
import uuid
import logging

from .models import Article
from .permissions import ArticleUserWritePermission
from .serializers import ArticleSerializer, ArticleCreateUpdateSerializer, ArticleListSerializer

def index(request):
return render(request, 'index.html')
# Set up logging
logger = logging.getLogger(__name__)

class ArticleViewSet(viewsets.ModelViewSet):
"""API endpoint for articles."""
permission_classes = [ArticleUserWritePermission]


def get_serializer_class(self):
"""Return appropriate serializer class based on request method."""
if self.action == 'list':
Expand All @@ -43,22 +43,28 @@ def retrieve_by_identifier(self, request, identifier=None):
else:
instance = Article.objects.get(slug=identifier)
except Article.DoesNotExist:
return Response({'Error': 'Article does not exist'}, status=status.HTTP_404_NOT_FOUND)
return Response({'error': 'Article does not exist'}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
logger.error(f"Error retrieving article by identifier: {e}")
return Response({'error': 'An unexpected error occurred'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

instance.views = F('views') + 1
instance.save(update_fields=['views'])
instance.refresh_from_db(fields=['views'])
serializer = self.get_serializer(instance)
return Response({'success': True, 'data': serializer.data})

#Custom action to retrieve articles by category
# Custom action to retrieve articles by category
@action(detail=False, methods=['get'], url_path=r'category/(?P<category>[-\w]+)')
def retrieve_by_category(self, request, category=None):
"""Retrieve article list by category"""
instances = Article.objects.filter(categories__name=category)
serializer = self.get_serializer(instances, many=True)
return Response({'success': True, 'data': serializer.data})

"""Retrieve article list by category."""
try:
instances = Article.objects.filter(categories__name=category)
serializer = self.get_serializer(instances, many=True)
return Response({'success': True, 'data': serializer.data})
except Exception as e:
logger.error(f"Error retrieving articles by category: {e}")
return Response({'error': 'An unexpected error occurred'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

def is_valid_uuid(self, value):
"""Check if the value is a valid UUID."""
Expand Down

0 comments on commit 385e087

Please sign in to comment.