ADD file via upload

zf_branch
ptgkifnrw 4 months ago
parent 7d5c5ccd04
commit 90ffcf644a

@ -0,0 +1,553 @@
#zf导入日志模块用于记录日志信息
import logging
#zf导入正则表达式模块用于匹配文章中的图片
import re
#zf从abc模块导入abstractmethod装饰器
from abc import abstractmethod
#zf导入Django配置模块
from django.conf import settings
#zf导入Django验证错误异常
from django.core.exceptions import ValidationError
#zf导入Django数据库模型模块
from django.db import models
#zf导入Django URL反向解析函数
from django.urls import reverse
#zf导入Django时区工具
from django.utils.timezone import now
#zf导入Django国际化翻译函数
from django.utils.translation import gettext_lazy as _
#zf导入Markdown编辑器字段
from mdeditor.fields import MDTextField
#zf导入slugify函数用于生成slug
from uuslug import slugify
#zf从djangoblog.utils导入缓存装饰器和缓存工具
from djangoblog.utils import cache_decorator, cache
#zf从djangoblog.utils导入获取当前站点的函数
from djangoblog.utils import get_current_site
#zf创建日志记录器
logger = logging.getLogger(__name__)
#zf定义链接显示类型枚举类继承自TextChoices
class LinkShowType(models.TextChoices):
#zf首页显示
I = ('i', _('index'))
#zf列表页显示
L = ('l', _('list'))
#zf文章页显示
P = ('p', _('post'))
#zf全站显示
A = ('a', _('all'))
#zf幻灯片显示
S = ('s', _('slide'))
#zf定义基础模型类继承自Django的Model类
class BaseModel(models.Model):
#zf主键字段
id = models.AutoField(primary_key=True)
#zf创建时间字段
creation_time = models.DateTimeField(_('creation time'), default=now)
#zf最后修改时间字段
last_modify_time = models.DateTimeField(_('modify time'), default=now)
#zf重写save方法
def save(self, *args, **kwargs):
#zf检查是否是更新文章浏览量的特殊情况
is_update_views = isinstance(
self,
Article) and 'update_fields' in kwargs and kwargs['update_fields'] == ['views']
if is_update_views:
#zf如果是更新浏览量则直接更新数据库避免触发其他逻辑
Article.objects.filter(pk=self.pk).update(views=self.views)
else:
#zf如果有slug字段则生成slug
if 'slug' in self.__dict__:
slug = getattr(
self, 'title') if 'title' in self.__dict__ else getattr(
self, 'name')
setattr(self, 'slug', slugify(slug))
#zf调用父类的save方法
super().save(*args, **kwargs)
#zf获取完整URL方法
def get_full_url(self):
#zf获取当前站点域名
site = get_current_site().domain
#zf拼接完整URL
url = "https://{site}{path}".format(site=site,
path=self.get_absolute_url())
return url
#zf设置为抽象类
class Meta:
abstract = True
#zf定义抽象方法子类必须实现
@abstractmethod
def get_absolute_url(self):
pass
#zf定义文章模型类继承自BaseModel
class Article(BaseModel):
"""文章"""
#zf文章状态选项
STATUS_CHOICES = (
#zf草稿
('d', _('Draft')),
#zf已发布
('p', _('Published')),
)
#zf评论状态选项
COMMENT_STATUS = (
#zf开启评论
('o', _('Open')),
#zf关闭评论
('c', _('Close')),
)
#zf文章类型选项
TYPE = (
#zf文章
('a', _('Article')),
#zf页面
('p', _('Page')),
)
#zf标题字段
title = models.CharField(_('title'), max_length=200, unique=True)
#zf正文字段使用Markdown编辑器
body = MDTextField(_('body'))
#zf发布时间字段
pub_time = models.DateTimeField(
_('publish time'), blank=False, null=False, default=now)
#zf状态字段
status = models.CharField(
_('status'),
max_length=1,
choices=STATUS_CHOICES,
default='p')
#zf评论状态字段
comment_status = models.CharField(
_('comment status'),
max_length=1,
choices=COMMENT_STATUS,
default='o')
#zf类型字段
type = models.CharField(_('type'), max_length=1, choices=TYPE, default='a')
#zf浏览量字段
views = models.PositiveIntegerField(_('views'), default=0)
#zf作者字段外键关联到用户模型
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name=_('author'),
blank=False,
null=False,
on_delete=models.CASCADE)
#zf文章排序字段
article_order = models.IntegerField(
_('order'), blank=False, null=False, default=0)
#zf是否显示目录字段
show_toc = models.BooleanField(_('show toc'), blank=False, null=False, default=False)
#zf分类字段外键关联到Category模型
category = models.ForeignKey(
'Category',
verbose_name=_('category'),
on_delete=models.CASCADE,
blank=False,
null=False)
#zf标签字段多对多关联到Tag模型
tags = models.ManyToManyField('Tag', verbose_name=_('tag'), blank=True)
#zf将文章正文转换为字符串
def body_to_string(self):
return self.body
#zf字符串表示方法
def __str__(self):
return self.title
#zf模型元数据
class Meta:
#zf排序规则
ordering = ['-article_order', '-pub_time']
#zf单数形式显示名称
verbose_name = _('article')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zflatest()方法使用的字段
get_latest_by = 'id'
#zf获取绝对URL方法
def get_absolute_url(self):
return reverse('blog:detailbyid', kwargs={
'article_id': self.id,
'year': self.creation_time.year,
'month': self.creation_time.month,
'day': self.creation_time.day
})
#zf获取分类树方法使用缓存装饰器缓存10小时
@cache_decorator(60 * 60 * 10)
def get_category_tree(self):
#zf获取分类的分类树
tree = self.category.get_category_tree()
#zf将分类名称和URL组成元组列表
names = list(map(lambda c: (c.name, c.get_absolute_url()), tree))
return names
#zf保存方法
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
#zf增加浏览量方法
def viewed(self):
self.views += 1
self.save(update_fields=['views'])
#zf获取评论列表方法
def comment_list(self):
#zf构造缓存键名
cache_key = 'article_comments_{id}'.format(id=self.id)
#zf从缓存中获取评论列表
value = cache.get(cache_key)
if value:
#zf如果缓存中有数据记录日志并返回
logger.info('get article comments:{id}'.format(id=self.id))
return value
else:
#zf如果缓存中没有数据从数据库查询并缓存
comments = self.comment_set.filter(is_enable=True).order_by('-id')
cache.set(cache_key, comments, 60 * 100)
logger.info('set article comments:{id}'.format(id=self.id))
return comments
#zf获取管理后台URL方法
def get_admin_url(self):
#zf获取模型的app_label和model_name
info = (self._meta.app_label, self._meta.model_name)
#zf生成管理后台编辑页面的URL
return reverse('admin:%s_%s_change' % info, args=(self.pk,))
#zf获取下一篇文章方法使用缓存装饰器缓存100分钟
@cache_decorator(expiration=60 * 100)
def next_article(self):
#zf下一篇
return Article.objects.filter(
id__gt=self.id, status='p').order_by('id').first()
#zf获取上一篇文章方法使用缓存装饰器缓存100分钟
@cache_decorator(expiration=60 * 100)
def prev_article(self):
#zf前一篇
return Article.objects.filter(id__lt=self.id, status='p').first()
#zf获取文章中第一张图片的URL方法
def get_first_image_url(self):
"""
Get the first image url from article.body.
:return:
"""
#zf使用正则表达式匹配Markdown图片语法
match = re.search(r'!\[.*?\]\((.+?)\)', self.body)
if match:
#zf如果匹配到图片返回图片URL
return match.group(1)
#zf如果没有匹配到图片返回空字符串
return ""
#zf定义分类模型类继承自BaseModel
class Category(BaseModel):
"""文章分类"""
#zf分类名称字段
name = models.CharField(_('category name'), max_length=30, unique=True)
#zf父级分类字段外键关联到自身
parent_category = models.ForeignKey(
'self',
verbose_name=_('parent category'),
blank=True,
null=True,
on_delete=models.CASCADE)
#zfslug字段
slug = models.SlugField(default='no-slug', max_length=60, blank=True)
#zf索引字段用于排序
index = models.IntegerField(default=0, verbose_name=_('index'))
#zf模型元数据
class Meta:
#zf按索引降序排列
ordering = ['-index']
#zf单数形式显示名称
verbose_name = _('category')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zf获取绝对URL方法
def get_absolute_url(self):
return reverse(
'blog:category_detail', kwargs={
'category_name': self.slug})
#zf字符串表示方法
def __str__(self):
return self.name
#zf获取分类树方法使用缓存装饰器缓存10小时
@cache_decorator(60 * 60 * 10)
def get_category_tree(self):
"""
递归获得分类目录的父级
:return:
"""
#zf初始化分类列表
categorys = []
#zf递归解析分类树的内部函数
def parse(category):
#zf将当前分类添加到列表
categorys.append(category)
#zf如果有父级分类递归处理父级分类
if category.parent_category:
parse(category.parent_category)
#zf从当前分类开始解析
parse(self)
return categorys
#zf获取子分类方法使用缓存装饰器缓存10小时
@cache_decorator(60 * 60 * 10)
def get_sub_categorys(self):
"""
获得当前分类目录所有子集
:return:
"""
#zf初始化分类列表
categorys = []
#zf获取所有分类
all_categorys = Category.objects.all()
#zf递归解析子分类的内部函数
def parse(category):
#zf如果分类不在列表中添加到列表
if category not in categorys:
categorys.append(category)
#zf获取当前分类的子分类
childs = all_categorys.filter(parent_category=category)
#zf遍历子分类
for child in childs:
#zf如果子分类不在列表中添加到列表
if category not in categorys:
categorys.append(child)
#zf递归处理子分类
parse(child)
#zf从当前分类开始解析
parse(self)
return categorys
#zf定义标签模型类继承自BaseModel
class Tag(BaseModel):
"""文章标签"""
#zf标签名称字段
name = models.CharField(_('tag name'), max_length=30, unique=True)
#zfslug字段
slug = models.SlugField(default='no-slug', max_length=60, blank=True)
#zf字符串表示方法
def __str__(self):
return self.name
#zf获取绝对URL方法
def get_absolute_url(self):
return reverse('blog:tag_detail', kwargs={'tag_name': self.slug})
#zf获取文章数量方法使用缓存装饰器缓存10小时
@cache_decorator(60 * 60 * 10)
def get_article_count(self):
#zf统计包含该标签的文章数量
return Article.objects.filter(tags__name=self.name).distinct().count()
#zf模型元数据
class Meta:
#zf按名称升序排列
ordering = ['name']
#zf单数形式显示名称
verbose_name = _('tag')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zf定义友情链接模型类
class Links(models.Model):
"""友情链接"""
#zf链接名称字段
name = models.CharField(_('link name'), max_length=30, unique=True)
#zf链接地址字段
link = models.URLField(_('link'))
#zf排序字段
sequence = models.IntegerField(_('order'), unique=True)
#zf是否显示字段
is_enable = models.BooleanField(
_('is show'), default=True, blank=False, null=False)
#zf显示类型字段
show_type = models.CharField(
_('show type'),
max_length=1,
choices=LinkShowType.choices,
default=LinkShowType.I)
#zf创建时间字段
creation_time = models.DateTimeField(_('creation time'), default=now)
#zf最后修改时间字段
last_mod_time = models.DateTimeField(_('modify time'), default=now)
#zf模型元数据
class Meta:
#zf按排序字段升序排列
ordering = ['sequence']
#zf单数形式显示名称
verbose_name = _('link')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zf字符串表示方法
def __str__(self):
return self.name
#zf定义侧边栏模型类
class SideBar(models.Model):
"""侧边栏,可以展示一些html内容"""
#zf标题字段
name = models.CharField(_('title'), max_length=100)
#zf内容字段
content = models.TextField(_('content'))
#zf排序字段
sequence = models.IntegerField(_('order'), unique=True)
#zf是否启用字段
is_enable = models.BooleanField(_('is enable'), default=True)
#zf创建时间字段
creation_time = models.DateTimeField(_('creation time'), default=now)
#zf最后修改时间字段
last_mod_time = models.DateTimeField(_('modify time'), default=now)
#zf模型元数据
class Meta:
#zf按排序字段升序排列
ordering = ['sequence']
#zf单数形式显示名称
verbose_name = _('sidebar')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zf字符串表示方法
def __str__(self):
return self.name
#zf定义博客设置模型类
class BlogSettings(models.Model):
"""blog的配置"""
#zf网站名称字段
site_name = models.CharField(
_('site name'),
max_length=200,
null=False,
blank=False,
default='')
#zf网站描述字段
site_description = models.TextField(
_('site description'),
max_length=1000,
null=False,
blank=False,
default='')
#zf网站SEO描述字段
site_seo_description = models.TextField(
_('site seo description'), max_length=1000, null=False, blank=False, default='')
#zf网站关键词字段
site_keywords = models.TextField(
_('site keywords'),
max_length=1000,
null=False,
blank=False,
default='')
#zf文章摘要长度字段
article_sub_length = models.IntegerField(_('article sub length'), default=300)
#zf侧边栏文章数量字段
sidebar_article_count = models.IntegerField(_('sidebar article count'), default=10)
#zf侧边栏评论数量字段
sidebar_comment_count = models.IntegerField(_('sidebar comment count'), default=5)
#zf文章页面默认显示评论数量字段
article_comment_count = models.IntegerField(_('article comment count'), default=5)
#zf是否显示谷歌广告字段
show_google_adsense = models.BooleanField(_('show adsense'), default=False)
#zf谷歌广告代码字段
google_adsense_codes = models.TextField(
_('adsense code'), max_length=2000, null=True, blank=True, default='')
#zf是否开启网站评论功能字段
open_site_comment = models.BooleanField(_('open site comment'), default=True)
#zf全局头部内容字段
global_header = models.TextField("公共头部", null=True, blank=True, default='')
#zf全局尾部内容字段
global_footer = models.TextField("公共尾部", null=True, blank=True, default='')
#zf备案号字段
beian_code = models.CharField(
'备案号',
max_length=2000,
null=True,
blank=True,
default='')
#zf网站统计代码字段
analytics_code = models.TextField(
"网站统计代码",
max_length=1000,
null=False,
blank=False,
default='')
#zf是否显示公安备案号字段
show_gongan_code = models.BooleanField(
'是否显示公安备案号', default=False, null=False)
#zf公安备案号字段
gongan_beiancode = models.TextField(
'公安备案号',
max_length=2000,
null=True,
blank=True,
default='')
#zf评论是否需要审核字段
comment_need_review = models.BooleanField(
'评论是否需要审核', default=False, null=False)
#zf模型元数据
class Meta:
#zf单数形式显示名称
verbose_name = _('Website configuration')
#zf复数形式显示名称
verbose_name_plural = verbose_name
#zf字符串表示方法
def __str__(self):
return self.site_name
#zf数据验证方法
def clean(self):
#zf检查是否已存在其他配置记录
if BlogSettings.objects.exclude(id=self.id).count():
#zf如果已存在其他配置记录抛出验证错误
raise ValidationError(_('There can only be one configuration'))
#zf保存方法
def save(self, *args, **kwargs):
#zf调用父类的保存方法
super().save(*args, **kwargs)
#zf导入缓存工具
from djangoblog.utils import cache
#zf清除所有缓存
cache.clear()
Loading…
Cancel
Save