From 2c1a2dc2835959cd7ec5c8e76c74f870b51548b0 Mon Sep 17 00:00:00 2001 From: Junwei Zhao Date: Fri, 21 Feb 2025 17:54:20 +1100 Subject: [PATCH] Rename newsletter to post --- data/db.sqlite3 | Bin 356352 -> 356352 bytes links/api_urls.py | 6 +- links/forms.py | 6 +- ...name_newsletter_post_alter_post_options.py | 21 +++++ links/models.py | 14 ++-- links/{newsletter_views.py => post_views.py} | 76 +++++++++--------- links/search_views.py | 28 +++---- links/serializers.py | 6 +- ...m_delete.html => post_confirm_delete.html} | 6 +- ...ewsletter_detail.html => post_detail.html} | 46 +++++------ .../{newsletter_form.html => post_form.html} | 10 +-- .../{newsletter_list.html => post_list.html} | 34 ++++---- ...ublic_newsletter.html => public_post.html} | 18 ++--- links/templates/links/search.html | 8 +- links/urls.py | 22 ++--- templates/base.html | 21 ++--- 16 files changed, 168 insertions(+), 154 deletions(-) create mode 100644 links/migrations/0030_rename_newsletter_post_alter_post_options.py rename links/{newsletter_views.py => post_views.py} (63%) rename links/templates/links/{newsletter_confirm_delete.html => post_confirm_delete.html} (94%) rename links/templates/links/{newsletter_detail.html => post_detail.html} (86%) rename links/templates/links/{newsletter_form.html => post_form.html} (94%) rename links/templates/links/{newsletter_list.html => post_list.html} (81%) rename links/templates/links/{public_newsletter.html => public_post.html} (63%) diff --git a/data/db.sqlite3 b/data/db.sqlite3 index 88ebd56d40008e13e08f467b8b9c2b07dafd5c0a..344d391af282c53ffeba0a3fcf4613f7af1be9c2 100644 GIT binary patch delta 786 zcmYjPO-vI}5Pq-w)?M53rZucZ1ZhJ|59MdOYoXyF)~0khm{f(3Kw`Vn4OB}(TI3*! zL`{ft!K?|9iyk<5v}{Z{Krk_0Fh&v*qaF;NJi*y$V%+Y=mPuwZ^X7Z=zjz=l9tbOE zy&;6qh{^wHjmFe0<1bDp$=*)r~UhM1viB8z;vSUy*{T@*!GOwVcsbxKPY zwE1FQE0wg_^vrazlveXKb$X_hn=TY3QHpemQl}L5i#>f8dirFkOOj+c8Z|tPE;nv6 zTKu~dpVEJJg#>toP9Q|jFad0(vV!Wt?s2T>%iX1r=!8z>rDX(1@BzNTHoSx!@brj& zp*yeuSK%_q&_v6yYeh4q7c#kM+M}6tbyvmmc$MGx2P~N| zroKP>(Fz^r_+KM9gs-p*Tkry&z&)6R6vRNPoO_EY2==@iTm<<9Ym3!^S7M*=`xQQp z*abF8;uV^4w37%z_;mI9u%{}k^Z*ZXzCZv!yi!tc=C%42)V0-2)*%pki|)wkjR{BF z(tg%qGE>>l68R6|5yP8z``gjr{)^D_Ii5#>z{W^L7-!en%9}~HpL0jTeX`sY4M%%L F@gD*o+p7Qo delta 465 zcmZp8AlmRibb_>?1_J{_I1s}?|3n>QMvaXLOZb`fSp+7t3&d|WG+4#FSwMuFhf!#= zjKV2C#ubyF>uHOMNHXg(=49q&7suzNmKW!wmXxFxO;*=WW^|d{tzV+8&jmD7kZ&Uc z|2zKE{I~e`@-N`eAiplZ6TbxCM*i;2f(h+>lQ-Jch={O=D?$uK zGSkuiFtZD**<^NyPM~9!v1~STJ;%lD!j(0dJs_BkXA{pXo|erS0sA>8Hwbud&Wf5< z%Iw0IJDL4L)aJ|!Z+L;C3Y&B9O?fB_cF+a}{z!5_fy$gi_q z?f@enzo;-b3xl{K*k1@IYg-t2>L~cD@8AWfp@bVNZ5(U0ufJ$dbgQ zoK*C%K<8^rH_T=d;X;@?*^$R|dR#h_eEa1TCLm_semRB3_%{m=12fO&LV;gQf;|5q p@iMcJgM&d)ag+ac!DQAYtlM{Huv)Y87@Am_n(CQYnwgjz0stz0k9`0D diff --git a/links/api_urls.py b/links/api_urls.py index 4be69cf..ff6ba7d 100644 --- a/links/api_urls.py +++ b/links/api_urls.py @@ -1,13 +1,15 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter from . import page_views -from . import newsletter_views +from . import post_views from . import api_views # Create a router and register our viewsets with it router = DefaultRouter(trailing_slash=False) router.register('pages', page_views.PageViewSet, basename='api-pages') -router.register('newsletters', newsletter_views.NewsletterViewSet, basename='api-newsletters') +# for API compatibility +router.register('newsletters', post_views.PostViewSet, basename='api-newsletters') +router.register('posts', post_views.PostViewSet, basename='api-posts') router.register('music', api_views.MusicViewSet, basename='api-music') # The API URLs are determined automatically by the router diff --git a/links/forms.py b/links/forms.py index b8d47cb..78d52e8 100644 --- a/links/forms.py +++ b/links/forms.py @@ -1,5 +1,5 @@ from django import forms -from .models import Link, Page, Newsletter, ImageCollection, Image, IPTVChannel, Tag +from .models import Link, Page, Post, ImageCollection, Image, IPTVChannel, Tag from simplemde.fields import SimpleMDEField from django.utils.translation import gettext_lazy as _ from django.core.validators import URLValidator @@ -62,9 +62,9 @@ class PageForm(forms.ModelForm): 'tags': forms.SelectMultiple(attrs={'class': 'select2'}), } -class NewsletterForm(forms.ModelForm): +class PostForm(forms.ModelForm): class Meta: - model = Newsletter + model = Post fields = ['title', 'type', 'content'] widgets = { 'content': forms.Textarea(attrs={'rows': 20}), diff --git a/links/migrations/0030_rename_newsletter_post_alter_post_options.py b/links/migrations/0030_rename_newsletter_post_alter_post_options.py new file mode 100644 index 0000000..2453406 --- /dev/null +++ b/links/migrations/0030_rename_newsletter_post_alter_post_options.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.10 on 2025-02-21 06:46 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('links', '0029_page_tags'), + ] + + operations = [ + migrations.RenameModel( + old_name='Newsletter', + new_name='Post', + ), + migrations.AlterModelOptions( + name='post', + options={'ordering': ['-created_at'], 'verbose_name': 'Post', 'verbose_name_plural': 'Posts'}, + ), + ] diff --git a/links/models.py b/links/models.py index f9263fd..9768967 100644 --- a/links/models.py +++ b/links/models.py @@ -244,8 +244,8 @@ class Screenshot(models.Model): return os.path.join(settings.MEDIA_URL, self.path) return None -class Newsletter(models.Model): - class NewsletterType(models.TextChoices): +class Post(models.Model): + class PostType(models.TextChoices): TECHNOLOGY = 'technology', _('Technology') WORLD_NEWS = 'world_news', _('World News') LOCAL_NEWS = 'local_news', _('Local News') @@ -254,8 +254,8 @@ class Newsletter(models.Model): type = models.CharField( _('Type'), max_length=20, - choices=NewsletterType.choices, - default=NewsletterType.TECHNOLOGY + choices=PostType.choices, + default=PostType.TECHNOLOGY ) content = models.TextField(_('Content')) created_at = models.DateTimeField(_('Created at'), auto_now_add=True) @@ -263,14 +263,14 @@ class Newsletter(models.Model): class Meta: ordering = ['-created_at'] - verbose_name = _('Newsletter') - verbose_name_plural = _('Newsletters') + verbose_name = _('Post') + verbose_name_plural = _('Posts') def __str__(self): return self.title def get_absolute_url(self): - return reverse('newsletter-detail', kwargs={'pk': self.pk}) + return reverse('post-detail', kwargs={'pk': self.pk}) class ImageCollection(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) diff --git a/links/newsletter_views.py b/links/post_views.py similarity index 63% rename from links/newsletter_views.py rename to links/post_views.py index a580d33..d99bdfb 100644 --- a/links/newsletter_views.py +++ b/links/post_views.py @@ -7,23 +7,23 @@ from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination from django.utils import timezone from datetime import datetime -from .models import Newsletter -from .forms import NewsletterForm -from .serializers import NewsletterSerializer +from .models import Post +from .forms import PostForm +from .serializers import PostSerializer -class NewsletterListView(ListView): - model = Newsletter - template_name = 'links/newsletter_list.html' - context_object_name = 'newsletters' +class PostListView(ListView): + model = Post + template_name = 'links/post_list.html' + context_object_name = 'posts' paginate_by = 10 def get_queryset(self): - queryset = Newsletter.objects.all().order_by('-created_at') + queryset = Post.objects.all().order_by('-created_at') # Type filter - newsletter_type = self.request.GET.get('type') - if newsletter_type: - queryset = queryset.filter(type=newsletter_type) + post_type = self.request.GET.get('type') + if post_type: + queryset = queryset.filter(type=post_type) # Date range filter date_from = self.request.GET.get('date_from') @@ -48,8 +48,8 @@ class NewsletterListView(ListView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # Add newsletter types for dropdown - context['newsletter_types'] = Newsletter.NewsletterType.choices + # Add post types for dropdown + context['post_types'] = Post.PostType.choices # Add selected filters to context context['selected_type'] = self.request.GET.get('type', '') @@ -65,46 +65,46 @@ class NewsletterListView(ListView): return context -class NewsletterDetailView(DetailView): - model = Newsletter - template_name = 'links/newsletter_detail.html' +class PostDetailView(DetailView): + model = Post + template_name = 'links/post_detail.html' -class NewsletterCreateView(CreateView): - model = Newsletter - form_class = NewsletterForm - template_name = 'links/newsletter_form.html' - success_url = reverse_lazy('newsletter-list') +class PostCreateView(CreateView): + model = Post + form_class = PostForm + template_name = 'links/post_form.html' + success_url = reverse_lazy('post-list') -class NewsletterUpdateView(UpdateView): - model = Newsletter - form_class = NewsletterForm - template_name = 'links/newsletter_form.html' - success_url = reverse_lazy('newsletter-list') +class PostUpdateView(UpdateView): + model = Post + form_class = PostForm + template_name = 'links/post_form.html' + success_url = reverse_lazy('post-list') -class NewsletterDeleteView(DeleteView): - model = Newsletter - template_name = 'links/newsletter_confirm_delete.html' - success_url = reverse_lazy('newsletter-list') +class PostDeleteView(DeleteView): + model = Post + template_name = 'links/post_confirm_delete.html' + success_url = reverse_lazy('post-list') -class PublicNewsletterView(DetailView): - model = Newsletter - template_name = 'links/public_newsletter.html' - context_object_name = 'newsletter' +class PublicPostView(DetailView): + model = Post + template_name = 'links/public_post.html' + context_object_name = 'post' def get_object(self, queryset=None): try: return super().get_object(queryset) except Http404: - raise Http404("Newsletter not found") + raise Http404("Post not found") class StandardResultsSetPagination(PageNumberPagination): page_size = 10 page_size_query_param = 'page_size' max_page_size = 100 -class NewsletterViewSet(viewsets.ModelViewSet): - queryset = Newsletter.objects.all().order_by('-created_at') - serializer_class = NewsletterSerializer +class PostViewSet(viewsets.ModelViewSet): + queryset = Post.objects.all().order_by('-created_at') + serializer_class = PostSerializer pagination_class = StandardResultsSetPagination def create(self, request, *args, **kwargs): diff --git a/links/search_views.py b/links/search_views.py index 5b430d7..f12cea6 100644 --- a/links/search_views.py +++ b/links/search_views.py @@ -5,7 +5,7 @@ from django.views.generic import ListView from django.db.models import Q, Value, CharField from django.db import models from django.utils.text import slugify -from .models import Link, Page, Newsletter +from .models import Link, Page, Post logger = logging.getLogger(__name__) @@ -28,8 +28,8 @@ class SearchView(ListView): results = self._get_link_results(query) elif type_filter == 'page': results = self._get_page_results(query) - elif type_filter == 'newsletter': - results = self._get_newsletter_results(query) + elif type_filter == 'post': + results = self._get_post_results(query) else: # Get all results results = self._get_all_results(query) @@ -59,19 +59,19 @@ class SearchView(ListView): model_type=Value('page', output_field=CharField()) ) - def _get_newsletter_results(self, query): - return Newsletter.objects.filter( + def _get_post_results(self, query): + return Post.objects.filter( Q(title__icontains=query) | Q(content__icontains=query) ).values('id', 'title', 'type', 'created_at').annotate( - model_type=Value('newsletter', output_field=CharField()) + model_type=Value('post', output_field=CharField()) ) def _get_all_results(self, query): links = self._get_link_results(query) pages = self._get_page_results(query) - newsletters = self._get_newsletter_results(query) - return list(chain(links, pages, newsletters)) + posts = self._get_post_results(query) + return list(chain(links, pages, posts)) def _sort_results(self, results, sort_order): if sort_order == 'newest': @@ -107,16 +107,16 @@ def search(request): 'url': link.original_url } for link in links]) - # Search newsletters - newsletters = Newsletter.objects.filter( + # Search posts + posts = Post.objects.filter( Q(title__icontains=query) | Q(content__icontains=query) )[:5] results.extend([{ - 'type': 'newsletter', - 'title': newsletter.title, - 'url': f'/ui/newsletters/{newsletter.id}' - } for newsletter in newsletters]) + 'type': 'post', + 'title': post.title, + 'url': f'/ui/posts/{post.id}' + } for post in posts]) else: results = [] diff --git a/links/serializers.py b/links/serializers.py index 75d020e..02bf653 100644 --- a/links/serializers.py +++ b/links/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import Page, Newsletter, ImageCollection, Image +from .models import Page, Post, ImageCollection, Image class PageSerializer(serializers.ModelSerializer): class Meta: @@ -9,9 +9,9 @@ class PageSerializer(serializers.ModelSerializer): read_only_fields = ['id', 'screenshot_path', 'process_status', 'created_at', 'updated_at'] -class NewsletterSerializer(serializers.ModelSerializer): +class PostSerializer(serializers.ModelSerializer): class Meta: - model = Newsletter + model = Post fields = ['id', 'title', 'type', 'content', 'created_at', 'updated_at'] read_only_fields = ['id', 'created_at', 'updated_at'] extra_kwargs = { diff --git a/links/templates/links/newsletter_confirm_delete.html b/links/templates/links/post_confirm_delete.html similarity index 94% rename from links/templates/links/newsletter_confirm_delete.html rename to links/templates/links/post_confirm_delete.html index 228b490..ef3d19d 100644 --- a/links/templates/links/newsletter_confirm_delete.html +++ b/links/templates/links/post_confirm_delete.html @@ -17,11 +17,11 @@

- {% trans "Delete Newsletter" %} + {% trans "Delete Post" %}

- {% trans "Are you sure you want to delete this newsletter?" %} + {% trans "Are you sure you want to delete this post?" %}

"{{ object.title }}" @@ -35,7 +35,7 @@

- {% trans "Cancel" %} diff --git a/links/templates/links/newsletter_detail.html b/links/templates/links/post_detail.html similarity index 86% rename from links/templates/links/newsletter_detail.html rename to links/templates/links/post_detail.html index e683fab..a62beb9 100644 --- a/links/templates/links/newsletter_detail.html +++ b/links/templates/links/post_detail.html @@ -31,7 +31,7 @@ margin: 1rem; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); } - + /* Think Panel Styles */ .think-panel { border: 1px solid #e5e7eb; @@ -39,7 +39,7 @@ margin: 1rem 0; overflow: hidden; } - + .think-header { background-color: #f9fafb; padding: 1rem; @@ -50,28 +50,28 @@ font-size: 1rem; color: #374151; } - + .think-header:hover { background-color: #f3f4f6; } - + .think-content { padding: 0; max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out, padding 0.3s ease-out; } - + .think-content.expanded { padding: 1rem; max-height: 2000px; /* Adjust based on your needs */ transition: max-height 0.5s ease-in, padding 0.3s ease-in; } - + .think-icon { transition: transform 0.3s ease; } - + .think-icon.expanded { transform: rotate(180deg); } @@ -84,13 +84,13 @@