From a1f1c1265d4b2dcf1668445b9c04823fee671d51 Mon Sep 17 00:00:00 2001 From: piehnab5t <2692463272@qq.com> Date: Sun, 2 Nov 2025 10:15:19 +0800 Subject: [PATCH] Delete 'src/blog/models_annotated_yjy.py' --- src/blog/models_annotated_yjy.py | 301 ------------------------------- 1 file changed, 301 deletions(-) delete mode 100644 src/blog/models_annotated_yjy.py diff --git a/src/blog/models_annotated_yjy.py b/src/blog/models_annotated_yjy.py deleted file mode 100644 index 35f91df..0000000 --- a/src/blog/models_annotated_yjy.py +++ /dev/null @@ -1,301 +0,0 @@ -import logging -import re -from abc import abstractmethod - -from django.conf import settings -from django.core.exceptions import ValidationError -from django.db import models -from django.urls import reverse -from django.utils.timezone import now -from django.utils.translation import gettext_lazy as _ -from mdeditor.fields import MDTextField # Markdown编辑器字段 -from uuslug import slugify # 智能slug生成 - -from djangoblog.utils import cache_decorator, cache -from djangoblog.utils import get_current_site - -logger = logging.getLogger(__name__) - - -class LinkShowType(models.TextChoices): - """链接显示类型枚举""" - I = ('i', _('index')) # 首页 - L = ('l', _('list')) # 列表页 - P = ('p', _('post')) # 文章页 - A = ('a', _('all')) # 全站 - S = ('s', _('slide')) # 幻灯片 - - -class BaseModel(models.Model): - """抽象基模型,提供通用字段和方法""" - id = models.AutoField(primary_key=True) - creation_time = models.DateTimeField(_('creation time'), default=now) - last_modify_time = models.DateTimeField(_('modify time'), default=now) - - def save(self, *args, **kwargs): - # 特殊处理文章浏览量的更新,避免触发其他逻辑 - is_update_views = isinstance( - self, - Article) and 'update_fields' in kwargs and kwargs['update_fields'] == ['views'] - if is_update_views: - Article.objects.filter(pk=self.pk).update(views=self.views) - else: - # 自动生成slug,基于title或name字段 - if 'slug' in self.__dict__: - slug = getattr( - self, 'title') if 'title' in self.__dict__ else getattr( - self, 'name') - setattr(self, 'slug', slugify(slug)) - super().save(*args, **kwargs) - - def get_full_url(self): - """获取完整URL(包含域名)""" - site = get_current_site().domain - url = "https://{site}{path}".format(site=site, - path=self.get_absolute_url()) - return url - - class Meta: - abstract = True # 抽象基类,不会创建数据库表 - - @abstractmethod - def get_absolute_url(self): - """抽象方法,子类必须实现获取绝对URL的方法""" - pass - - -class Article(BaseModel): - """文章模型 - 核心内容模型""" - - # 状态选择项 - STATUS_CHOICES = ( - ('d', _('Draft')), # 草稿 - ('p', _('Published')), # 已发布 - ) - COMMENT_STATUS = ( - ('o', _('Open')), # 开放评论 - ('c', _('Close')), # 关闭评论 - ) - TYPE = ( - ('a', _('Article')), # 普通文章 - ('p', _('Page')), # 页面 - ) - - title = models.CharField(_('title'), max_length=200, unique=True) - body = MDTextField(_('body')) # Markdown内容字段 - pub_time = models.DateTimeField(_('publish time'), blank=False, null=False, default=now) - status = models.CharField(_('status'), max_length=1, choices=STATUS_CHOICES, default='p') - comment_status = models.CharField(_('comment status'), max_length=1, choices=COMMENT_STATUS, default='o') - type = models.CharField(_('type'), max_length=1, choices=TYPE, default='a') - views = models.PositiveIntegerField(_('views'), default=0) # 浏览量统计 - author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('author'), on_delete=models.CASCADE) - article_order = models.IntegerField(_('order'), blank=False, null=False, default=0) # 文章排序 - show_toc = models.BooleanField(_('show toc'), blank=False, null=False, default=False) # 是否显示目录 - category = models.ForeignKey('Category', verbose_name=_('category'), on_delete=models.CASCADE) - tags = models.ManyToManyField('Tag', verbose_name=_('tag'), blank=True) # 多对多标签关系 - - class Meta: - ordering = ['-article_order', '-pub_time'] # 默认排序:按order倒序,发布时间倒序 - verbose_name = _('article') - verbose_name_plural = verbose_name - get_latest_by = 'id' - - def get_absolute_url(self): - """生成文章详情页URL,包含年月日信息用于SEO""" - return reverse('blog:detailbyid', kwargs={ - 'article_id': self.id, - 'year': self.creation_time.year, - 'month': self.creation_time.month, - 'day': self.creation_time.day - }) - - @cache_decorator(60 * 60 * 10) # 缓存10小时 - def get_category_tree(self): - """获取分类树结构,用于面包屑导航""" - tree = self.category.get_category_tree() - names = list(map(lambda c: (c.name, c.get_absolute_url()), tree)) - return names - - def viewed(self): - """增加浏览量(优化更新,只更新views字段)""" - self.views += 1 - self.save(update_fields=['views']) - - def comment_list(self): - """获取文章评论列表(带缓存)""" - cache_key = 'article_comments_{id}'.format(id=self.id) - value = cache.get(cache_key) - if value: - logger.info('get article comments:{id}'.format(id=self.id)) - return value - else: - comments = self.comment_set.filter(is_enable=True).order_by('-id') - cache.set(cache_key, comments, 60 * 100) # 缓存100分钟 - return comments - - def get_admin_url(self): - """获取后台管理URL""" - info = (self._meta.app_label, self._meta.model_name) - return reverse('admin:%s_%s_change' % info, args=(self.pk,)) - - @cache_decorator(expiration=60 * 100) - def next_article(self): - """下一篇已发布文章(带缓存)""" - return Article.objects.filter( - id__gt=self.id, status='p').order_by('id').first() - - @cache_decorator(expiration=60 * 100) - def prev_article(self): - """上一篇已发布文章(带缓存)""" - return Article.objects.filter(id__lt=self.id, status='p').first() - - def get_first_image_url(self): - """从文章内容中提取第一张图片URL,用于缩略图等""" - match = re.search(r'!\[.*?\]\((.+?)\)', self.body) # 匹配Markdown图片语法 - if match: - return match.group(1) - return "" - - -class Category(BaseModel): - """文章分类模型,支持多级分类""" - name = models.CharField(_('category name'), max_length=30, unique=True) - parent_category = models.ForeignKey('self', verbose_name=_('parent category'), - blank=True, null=True, on_delete=models.CASCADE) # 自关联实现多级分类 - slug = models.SlugField(default='no-slug', max_length=60, blank=True) - index = models.IntegerField(default=0, verbose_name=_('index')) # 分类排序 - - class Meta: - ordering = ['-index'] # 按index倒序排列 - verbose_name = _('category') - verbose_name_plural = verbose_name - - @cache_decorator(60 * 60 * 10) - def get_category_tree(self): - """ - 递归获得分类目录的父级,用于构建面包屑导航 - :return: 分类树列表(从当前分类到根分类) - """ - categorys = [] - - def parse(category): - categorys.append(category) - if category.parent_category: - parse(category.parent_category) - - parse(self) - return categorys - - @cache_decorator(60 * 60 * 10) - def get_sub_categorys(self): - """ - 获得当前分类目录所有子集,用于分类导航 - :return: 所有子分类列表 - """ - categorys = [] - all_categorys = Category.objects.all() - - def parse(category): - if category not in categorys: - categorys.append(category) - childs = all_categorys.filter(parent_category=category) - for child in childs: - if category not in categorys: - categorys.append(child) - parse(child) - - parse(self) - return categorys - - -class Tag(BaseModel): - """文章标签模型""" - name = models.CharField(_('tag name'), max_length=30, unique=True) - slug = models.SlugField(default='no-slug', max_length=60, blank=True) - - @cache_decorator(60 * 60 * 10) - def get_article_count(self): - """获取标签下文章数量(带缓存)""" - return Article.objects.filter(tags__name=self.name).distinct().count() - - class Meta: - ordering = ['name'] # 按标签名排序 - verbose_name = _('tag') - verbose_name_plural = verbose_name - - -class Links(models.Model): - """友情链接模型""" - name = models.CharField(_('link name'), max_length=30, unique=True) - link = models.URLField(_('link')) - sequence = models.IntegerField(_('order'), unique=True) # 链接显示顺序 - is_enable = models.BooleanField(_('is show'), default=True) - show_type = models.CharField(_('show type'), max_length=1, - choices=LinkShowType.choices, default=LinkShowType.I) # 链接显示位置 - creation_time = models.DateTimeField(_('creation time'), default=now) - last_mod_time = models.DateTimeField(_('modify time'), default=now) - - class Meta: - ordering = ['sequence'] # 按sequence顺序排列 - verbose_name = _('link') - verbose_name_plural = verbose_name - - -class SideBar(models.Model): - """侧边栏模型,可以展示自定义HTML内容""" - name = models.CharField(_('title'), max_length=100) - content = models.TextField(_('content')) # HTML内容 - sequence = models.IntegerField(_('order'), unique=True) # 显示顺序 - is_enable = models.BooleanField(_('is enable'), default=True) - creation_time = models.DateTimeField(_('creation time'), default=now) - last_mod_time = models.DateTimeField(_('modify time'), default=now) - - class Meta: - ordering = ['sequence'] - verbose_name = _('sidebar') - verbose_name_plural = verbose_name - - -class BlogSettings(models.Model): - """博客全局配置模型(单例模式)""" - site_name = models.CharField(_('site name'), max_length=200, default='') - site_description = models.TextField(_('site description'), max_length=1000, default='') - site_seo_description = models.TextField(_('site seo description'), max_length=1000, default='') - site_keywords = models.TextField(_('site keywords'), max_length=1000, default='') - - # 显示设置 - article_sub_length = models.IntegerField(_('article sub length'), default=300) # 文章摘要长度 - sidebar_article_count = models.IntegerField(_('sidebar article count'), default=10) - sidebar_comment_count = models.IntegerField(_('sidebar comment count'), default=5) - article_comment_count = models.IntegerField(_('article comment count'), default=5) - - # 广告设置 - show_google_adsense = models.BooleanField(_('show adsense'), default=False) - google_adsense_codes = models.TextField(_('adsense code'), max_length=2000, default='') - - # 评论设置 - open_site_comment = models.BooleanField(_('open site comment'), default=True) - comment_need_review = models.BooleanField('评论是否需要审核', default=False) - - # 代码注入和备案 - global_header = models.TextField("公共头部", default='') # 全局HTML头部 - global_footer = models.TextField("公共尾部", default='') # 全局HTML尾部 - beian_code = models.CharField('备案号', max_length=2000, default='') # ICP备案号 - analytics_code = models.TextField("网站统计代码", max_length=1000, default='') # 统计代码 - show_gongan_code = models.BooleanField('是否显示公安备案号', default=False) - gongan_beiancode = models.TextField('公安备案号', max_length=2000, default='') - - class Meta: - verbose_name = _('Website configuration') - verbose_name_plural = verbose_name - - def clean(self): - """验证确保只能有一个配置实例""" - if BlogSettings.objects.exclude(id=self.id).count(): - raise ValidationError(_('There can only be one configuration')) - - def save(self, *args, **kwargs): - """保存时清空缓存,确保配置及时生效""" - super().save(*args, **kwargs) - from djangoblog.utils import cache - cache.clear() \ No newline at end of file