Compare commits

...

8 Commits

@ -0,0 +1,391 @@
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
from uuslug import slugify
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:
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):
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):
pass
class Article(BaseModel):
"""鏂囩珷"""
#文章状态草稿d、已发布p默认已发布
STATUS_CHOICES = (
('d', _('Draft')),
('p', _('Published')),
)
# 评论状态开放o、关闭c默认开放
COMMENT_STATUS = (
('o', _('Open')),
('c', _('Close')),
)
# 文章类型普通文章a、独立页面p如关于页默认普通文章
TYPE = (
('a', _('Article')),
('p', _('Page')),
)
# 文章标题最大长度200唯一不重复
title = models.CharField(_('title'), max_length=200, unique=True)
# 文章内容markdown富文本字段支持排版格式
body = MDTextField(_('body'))
# 发布时间:非空,默认当前时间
pub_time = models.DateTimeField(
_('publish time'), blank=False, null=False, default=now)
# 文章状态关联STATUS_CHOICES存储单字符标识
status = models.CharField(
_('status'),
max_length=1,
choices=STATUS_CHOICES,
default='p')
# 评论状态关联COMMENT_STATUS存储单字符标识
comment_status = models.CharField(
_('comment status'),
max_length=1,
choices=COMMENT_STATUS,
default='o')
# 文章类型关联TYPE存储单字符标识
type = models.CharField(_('type'), max_length=1, choices=TYPE, default='a')
# 阅读量正整数默认0记录文章被查看次数
views = models.PositiveIntegerField(_('views'), default=0)
# 作者关联Django用户模型级联删除作者删除时文章也删除非空
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name=_('author'),
blank=False,
null=False,
on_delete=models.CASCADE)
# 文章排序整数默认0值越大在列表中越靠前
article_order = models.IntegerField(
_('order'), blank=False, null=False, default=0)
# 是否显示目录:布尔值,默认不显示,控制详情页是否展示目录
show_toc = models.BooleanField(_('show toc'), blank=False, null=False, default=False)
# 文章分类关联Category模型级联删除非空文章必须归属一个分类
category = models.ForeignKey(
'Category',
verbose_name=_('category'),
on_delete=models.CASCADE,
blank=False,
null=False)
# 文章标签多对多关联Tag模型允许为空文章可无标签
tags = models.ManyToManyField('Tag', verbose_name=_('tag'), blank=True)
def body_to_string(self):
return self.body
def __str__(self):
return self.title
class Meta:
ordering = ['-article_order', '-pub_time']
verbose_name = _('article')
verbose_name_plural = verbose_name
get_latest_by = 'id'
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
})
@cache_decorator(60 * 60 * 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 save(self, *args, **kwargs):
super().save(*args, **kwargs)
def viewed(self):
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)
logger.info('set article comments:{id}'.format(id=self.id))
return comments
def get_admin_url(self):
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):
"""
Get the first image url from article.body.
:return:
"""
match = re.search(r'!\[.*?\]\((.+?)\)', self.body)
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']
verbose_name = _('category')
verbose_name_plural = verbose_name
def get_absolute_url(self):
return reverse(
'blog:category_detail', kwargs={
'category_name': self.slug})
def __str__(self):
return self.name
@cache_decorator(60 * 60 * 10)
def get_category_tree(self):
"""
閫掑綊鑾峰緱鍒嗙被鐩<EFBFBD>綍鐨勭埗绾?
: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):
"""
鑾峰緱褰撳墠鍒嗙被鐩<EFBFBD>綍鎵鏈夊瓙闆?
: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):
"""鏂囩珷鏍囩<EFBFBD>"""
name = models.CharField(_('tag name'), max_length=30, unique=True)
slug = models.SlugField(default='no-slug', max_length=60, blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('blog:tag_detail', kwargs={'tag_name': self.slug})
@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, blank=False, null=False)
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']
verbose_name = _('link')
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class SideBar(models.Model):
"""渚ц竟鏍?,鍙<>互灞曠ず涓€浜沨tml鍐呭<E98D90>"""
name = models.CharField(_('title'), max_length=100)
content = models.TextField(_('content'))
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
def __str__(self):
return self.name
class BlogSettings(models.Model):
"""blog鐨勯厤缃?"""
site_name = models.CharField(
_('site name'),
max_length=200,
null=False,
blank=False,
default='')
site_description = models.TextField(
_('site description'),
max_length=1000,
null=False,
blank=False,
default='')
site_seo_description = models.TextField(
_('site seo description'), max_length=1000, null=False, blank=False, default='')
site_keywords = models.TextField(
_('site keywords'),
max_length=1000,
null=False,
blank=False,
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, null=True, blank=True, default='')
open_site_comment = models.BooleanField(_('open site comment'), default=True)
global_header = models.TextField("<EFBFBD>叡澶撮儴", null=True, blank=True, default='')
global_footer = models.TextField("<EFBFBD>叡灏鹃儴", null=True, blank=True, default='')
beian_code = models.CharField(
'澶囨<EFBFBD>鍙?',
max_length=2000,
null=True,
blank=True,
default='')
analytics_code = models.TextField(
"缃戠珯缁熻<EFBFBD>",
max_length=1000,
null=False,
blank=False,
default='')
show_gongan_code = models.BooleanField(
'<EFBFBD>惁鏄剧ず鍏<EFBFBD>畨澶囨<EFBFBD>鍙?', default=False, null=False)
gongan_beiancode = models.TextField(
'<EFBFBD>畨澶囨<EFBFBD>鍙?',
max_length=2000,
null=True,
blank=True,
default='')
comment_need_review = models.BooleanField(
'璇勮<EFBFBD><EFBFBD>惁闇€瑕佸<EFBFBD>鏍?', default=False, null=False)
class Meta:
verbose_name = _('Website configuration')
verbose_name_plural = verbose_name
def __str__(self):
return self.site_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()

@ -0,0 +1,417 @@
import logging
import os
import uuid
from django.conf import settings·
from django.core.paginator import Paginator
from django.http import HttpResponse, HttpResponseForbidden
from django.shortcuts import get_object_or_404
from django.shortcuts import render
from django.templatetags.static import static
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from haystack.views import SearchView
# 导入目标模型Article文章、Category分类、Tag标签及其他关联模型
from blog.models import Article, Category, LinkShowType, Links, Tag
from comments.forms import CommentForm
from djangoblog.plugin_manage import hooks
from djangoblog.plugin_manage.hook_constants import ARTICLE_CONTENT_HOOK_NAME
from djangoblog.utils import cache, get_blog_setting, get_sha256
logger = logging.getLogger(__name__)
# 导入目标模型Article文章、Category分类、Tag标签及其他关联模型
class ArticleListView(ListView):
# template_name灞炴€х敤浜庢寚瀹氫娇鐢ㄥ摢涓<E691A2>ā鏉胯繘琛屾覆鏌?
template_name = 'blog/article_index.html'
# context_object_name灞炴€х敤浜庣粰涓婁笅鏂囧彉閲忓彇鍚嶏紙鍦ㄦā鏉夸腑浣跨敤璇ュ悕瀛楋級
context_object_name = 'article_list'
# 上下文变量名,对应模板中遍历的“文章列表”
# 椤甸潰绫诲瀷锛屽垎绫荤洰褰曟垨鏍囩<E98F8D>鍒楄〃绛?
page_type = ''
paginate_by = settings.PAGINATE_BY
# 每页显示文章数量关联Article模型的“列表展示”逻辑
page_kwarg = 'page'
link_type = LinkShowType.L
# 省略基类中不涉及模型字段的通用方法
def get_view_cache_key(self):
return self.request.get['pages']
@property
def page_number(self):
page_kwarg = self.page_kwarg
page = self.kwargs.get(
page_kwarg) or self.request.GET.get(page_kwarg) or 1
return page
def get_queryset_cache_key(self):
"""
瀛愮被閲嶅啓.鑾峰緱queryset鐨勭紦瀛榢ey
"""
raise NotImplementedError()
def get_queryset_data(self):
"""
瀛愮被閲嶅啓.鑾峰彇queryset鐨勬暟鎹?
"""
raise NotImplementedError()
def get_queryset_from_cache(self, cache_key):
'''
缂撳瓨椤甸潰鏁版嵁
:param cache_key: 缂撳瓨key
:return:
'''
value = cache.get(cache_key)
if value:
logger.info('get view cache.key:{key}'.format(key=cache_key))
return value
else:
article_list = self.get_queryset_data()
cache.set(cache_key, article_list)
logger.info('set view cache.key:{key}'.format(key=cache_key))
return article_list
def get_queryset(self):
'''
閲嶅啓榛樿<EFBFBD>锛屼粠缂撳瓨鑾峰彇鏁版嵁
:return:
'''
key = self.get_queryset_cache_key()
value = self.get_queryset_from_cache(key)
return value
def get_context_data(self, **kwargs):
kwargs['linktype'] = self.link_type
return super(ArticleListView, self).get_context_data(**kwargs)
# 分类详情页视图(继承文章列表基类)
class IndexView(ArticleListView):
'''
棣栭
'''
# 鍙嬫儏閾炬帴绫诲瀷
link_type = LinkShowType.I
# 从URL参数获取分类的slug对应Category.slug字段分类友好URL标识
def get_queryset_data(self):
article_list = Article.objects.filter(type='a', status='p')
return article_list
def get_queryset_cache_key(self):
cache_key = 'index_{page}'.format(page=self.page_number)
return cache_key
# 作者详情页视图涉及Article.author字段此处仅作关联说明
class ArticleDetailView(DetailView):
'''
鏂囩珷璇儏椤甸潰
'''
template_name = 'blog/article_detail.html'
model = Article
pk_url_kwarg = 'article_id'
context_object_name = "article"
# 归档页不分页,显示所有文章
def get_context_data(self, **kwargs):
# 筛选Article模型数据status='p'(仅已发布文章),无分页返回所有数据
# 归档逻辑依赖Article.create_time字段文章创建时间模板中按时间分组展示
comment_form = CommentForm()
article_comments = self.object.comment_list()
parent_comments = article_comments.filter(parent_comment=None)
blog_setting = get_blog_setting()
paginator = Paginator(parent_comments, blog_setting.article_comment_count)
page = self.request.GET.get('comment_page', '1')
if not page.isnumeric():
page = 1
else:
page = int(page)
if page < 1:
page = 1
if page > paginator.num_pages:
page = paginator.num_pages
p_comments = paginator.page(page)
next_page = p_comments.next_page_number() if p_comments.has_next() else None
prev_page = p_comments.previous_page_number() if p_comments.has_previous() else None
if next_page:
kwargs[
'comment_next_page_url'] = self.object.get_absolute_url() + f'?comment_page={next_page}#commentlist-container'
if prev_page:
kwargs[
'comment_prev_page_url'] = self.object.get_absolute_url() + f'?comment_page={prev_page}#commentlist-container'
kwargs['form'] = comment_form
kwargs['article_comments'] = article_comments
kwargs['p_comments'] = p_comments
kwargs['comment_count'] = len(
article_comments) if article_comments else 0
kwargs['next_article'] = self.object.next_article
kwargs['prev_article'] = self.object.prev_article
context = super(ArticleDetailView, self).get_context_data(**kwargs)
article = self.object
# Action Hook, 閫氱煡鎻掍欢"鏂囩珷璇︽儏宸茶幏鍙?"
hooks.run_action('after_article_body_get', article=article, request=self.request)
# # Filter Hook, 鍏佽<E98D8F>鎻掍欢淇<E6ACA2>敼鏂囩珷姝
article.body = hooks.apply_filters(ARTICLE_CONTENT_HOOK_NAME, article.body, article=article,
request=self.request)
return context
class CategoryDetailView(ArticleListView):
'''
鍒嗙被鐩<EFBFBD>綍鍒楄
'''
page_type = "鍒嗙被鐩<EFBFBD>綍褰掓。"
def get_queryset_data(self):
# 从URL参数获取分类的slug对应Category.slug字段分类友好URL标识
slug = self.kwargs['category_name']
# 通过slug查询唯一分类get_object_or_404表示不存在则返回404
# 关联Category.slug字段分类的URL唯一标识避免中文/特殊字符问题)
category = get_object_or_404(Category, slug=slug)
categoryname = category.name
# 获取分类名称关联Category.name字段分类显示名称
self.categoryname = categoryname
# 获取当前分类的所有子分类名称调用Category模型的自定义方法get_sub_categorys()
# 关联Category.parent字段分类自关联实现多级分类如“技术→Python”
categorynames = list(
map(lambda c: c.name, category.get_sub_categorys()))
# 筛选Article模型数据
# category__name__in=categorynames匹配Article.category.name字段文章所属分类名称
# 表示“文章所属分类在‘当前分类+子分类’列表中”
# status='p'匹配Article.status字段仅显示已发布文章
article_list = Article.objects.filter(
category__name__in=categorynames, status='p')
return article_list
# 省略缓存key生成、上下文添加方法...
# 作者详情页视图涉及Article.author字段此处仅作关联说明
def get_queryset_cache_key(self):
slug = self.kwargs['category_name']
category = get_object_or_404(Category, slug=slug)
categoryname = category.name
self.categoryname = categoryname
cache_key = 'category_list_{categoryname}_{page}'.format(
categoryname=categoryname, page=self.page_number)
return cache_key
def get_context_data(self, **kwargs):
categoryname = self.categoryname
try:
categoryname = categoryname.split('/')[-1]
except BaseException:
pass
kwargs['page_type'] = CategoryDetailView.page_type
kwargs['tag_name'] = categoryname
return super(CategoryDetailView, self).get_context_data(**kwargs)
class AuthorDetailView(ArticleListView):
'''
浣滆<EFBFBD>鎯呴
'''
page_type = '浣滆€呮枃绔犲綊妗?'
def get_queryset_cache_key(self):
from uuslug import slugify
author_name = slugify(self.kwargs['author_name'])
# 筛选Article模型数据
# author__username=author_name匹配Article.author.username字段文章作者的用户名
# 关联Article.author字段文章与用户的一对多关系一篇文章对应一个作者
# type='a'、status='p':同首页,筛选“已发布的普通文章”
cache_key = 'author_{author_name}_{page}'.format(
author_name=author_name, page=self.page_number)
return cache_key
def get_queryset_data(self):
author_name = self.kwargs['author_name']
article_list = Article.objects.filter(
author__username=author_name, type='a', status='p')
return article_list
# 省略其他方法...
.0# 标签详情页视图(继承文章列表基类)
def get_context_data(self, **kwargs):
author_name = self.kwargs['author_name']
kwargs['page_type'] = AuthorDetailView.page_type
kwargs['tag_name'] = author_name
return super(AuthorDetailView, self).get_context_data(**kwargs)
class TagDetailView(ArticleListView):
'''
鏍囩<EFBFBD>鍒楄椤甸潰
'''
page_type = '鍒嗙被鏍囩<EFBFBD>褰掓。'
def get_queryset_data(self):
# 从URL参数获取标签的slug对应Tag.slug字段标签友好URL标识
slug = self.kwargs['tag_name']
# 通过slug查询唯一标签关联Tag.slug字段标签的URL唯一标识
tag = get_object_or_404(Tag, slug=slug)
tag_name = tag.name
# 获取标签名称关联Tag.name字段标签显示名称
self.name = tag_name
# 筛选Article模型数据
# tags__name=tag_name匹配Article.tags.name字段文章关联的标签名称
# 关联Article.tags字段文章与标签的多对多关系一篇文章可关联多个标签一个标签可关联多篇文章
# type='a'、status='p':筛选“已发布的普通文章”
article_list = Article.objects.filter(
tags__name=tag_name, type='a', status='p')
return article_list
def get_queryset_cache_key(self):
slug = self.kwargs['tag_name']
tag = get_object_or_404(Tag, slug=slug)
tag_name = tag.name
self.name = tag_name
cache_key = 'tag_{tag_name}_{page}'.format(
tag_name=tag_name, page=self.page_number)
return cache_key
# 省略缓存key生成、上下文添加方法...
def get_context_data(self, **kwargs):
# tag_name = self.kwargs['tag_name']
tag_name = self.name
kwargs['page_type'] = TagDetailView.page_type
kwargs['tag_name'] = tag_name
return super(TagDetailView, self).get_context_data(**kwargs)
# 文章归档页视图
class ArchivesView(ArticleListView):
'''
鏂囩珷褰掓椤甸潰
'''
page_type = '鏂囩珷褰掓。'
paginate_by = None
# 归档页不分页,显示所有文章
page_kwarg = None
template_name = 'blog/article_archives.html'
def get_queryset_data(self):
# 筛选Article模型数据status='p'(仅已发布文章),无分页返回所有数据
# 归档逻辑依赖Article.create_time字段文章创建时间模板中按时间分组展示
return Article.objects.filter(status='p').all()
# 省略缓存key生成方法...
# 以下为不涉及文章/分类/标签模型字段的视图(如链接列表、搜索、文件上传、错误页等),省略注释...
def get_queryset_cache_key(self):
cache_key = 'archives'
return cache_key
class LinkListView(ListView):
model = Links
template_name = 'blog/links_list.html'
def get_queryset(self):
return Links.objects.filter(is_enable=True)
class EsSearchView(SearchView):
# 省略搜索视图逻辑若涉及文章搜索实际关联Article.title/body字段此处代码未直接体现...
def get_context(self):
paginator, page = self.build_page()
context = {
"query": self.query,
"form": self.form,
"page": page,
"paginator": paginator,
"suggestion": None,
}
if hasattr(self.results, "query") and self.results.query.backend.include_spelling:
context["suggestion"] = self.results.query.get_spelling_suggestion()
context.update(self.extra_context())
return context
@csrf_exempt
def fileupload(request):
# 省略文件上传逻辑...
"""
璇ユ柟娉曢渶鑷<EFBFBD>繁鍐欒皟鐢ㄧ<EFBFBD>鏉ヤ笂浼犲浘鐗囷紝璇ユ柟娉曚粎鎻愪緵鍥惧簥鍔熻兘
:param request:
:return:
"""
if request.method == 'POST':
sign = request.GET.get('sign', None)
if not sign:
return HttpResponseForbidden()
if not sign == get_sha256(get_sha256(settings.SECRET_KEY)):
return HttpResponseForbidden()
response = []
for filename in request.FILES:
timestr = timezone.now().strftime('%Y/%m/%d')
imgextensions = ['jpg', 'png', 'jpeg', 'bmp']
fname = u''.join(str(filename))
isimage = len([i for i in imgextensions if fname.find(i) >= 0]) > 0
base_dir = os.path.join(settings.STATICFILES, "files" if not isimage else "image", timestr)
if not os.path.exists(base_dir):
os.makedirs(base_dir)
savepath = os.path.normpath(os.path.join(base_dir, f"{uuid.uuid4().hex}{os.path.splitext(filename)[-1]}"))
if not savepath.startswith(base_dir):
return HttpResponse("only for post")
with open(savepath, 'wb+') as wfile:
for chunk in request.FILES[filename].chunks():
wfile.write(chunk)
if isimage:
from PIL import Image
image = Image.open(savepath)
image.save(savepath, quality=20, optimize=True)
url = static(savepath)
response.append(url)
return HttpResponse(response)
else:
return HttpResponse("only for post")
def page_not_found_view(
request,
exception,
template_name='blog/error_page.html'):
if exception:
logger.error(exception)
url = request.get_full_path()
return render(request,
template_name,
{'message': _('Sorry, the page you requested is not found, please click the home page to see other?'),
'statuscode': '404'},
status=404)
def server_error_view(request, template_name='blog/error_page.html'):
return render(request,
template_name,
{'message': _('Sorry, the server is busy, please click the home page to see other?'),
'statuscode': '500'},
status=500)
def permission_denied_view(
request,
exception,
template_name='blog/error_page.html'):
if exception:
logger.error(exception)
return render(
request, template_name, {
'message': _('Sorry, you do not have permission to access this page?'),
'statuscode': '403'}, status=403)
def clean_cache_view(request):
cache.clear()
return HttpResponse('ok')

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save