Compare commits

...

15 Commits

@ -0,0 +1,172 @@
#zf导入Django表单模块
from django import forms
#zf导入Django管理后台模块
from django.contrib import admin
#zf导入获取用户模型的函数
from django.contrib.auth import get_user_model
#zf导入URL反向解析函数
from django.urls import reverse
#zf导入HTML格式化函数
from django.utils.html import format_html
#zf导入国际化翻译函数
from django.utils.translation import gettext_lazy as _
#zf导入博客应用的Article模型
from .models import Article
#zf定义文章表单类继承自ModelForm
class ArticleForm(forms.ModelForm):
#zf被注释掉的代码使用AdminPagedownWidget作为body字段的widget
# body = forms.CharField(widget=AdminPagedownWidget())
class Meta:
model = Article
#zf包含所有字段
fields = '__all__'
#zf定义批量发布文章的操作函数
def makr_article_publish(modeladmin, request, queryset):
#zf将选中文章的状态更新为'p'(已发布)
queryset.update(status='p')
#zf定义批量将文章设为草稿的操作函数
def draft_article(modeladmin, request, queryset):
#zf将选中文章的状态更新为'd'(草稿)
queryset.update(status='d')
#zf定义批量关闭文章评论的操作函数
def close_article_commentstatus(modeladmin, request, queryset):
#zf将选中文章的评论状态更新为'c'(关闭)
queryset.update(comment_status='c')
#zf定义批量开启文章评论的操作函数
def open_article_commentstatus(modeladmin, request, queryset):
#zf将选中文章的评论状态更新为'o'(开启)
queryset.update(comment_status='o')
#zf为操作函数设置描述信息用于在管理后台显示支持国际化
makr_article_publish.short_description = _('Publish selected articles')
draft_article.short_description = _('Draft selected articles')
close_article_commentstatus.short_description = _('Close article comments')
open_article_commentstatus.short_description = _('Open article comments')
#zf定义文章管理类继承自ModelAdmin
class ArticlelAdmin(admin.ModelAdmin):
#zf每页显示20条记录
list_per_page = 20
#zf设置可搜索的字段为body和title
search_fields = ('body', 'title')
#zf使用自定义的ArticleForm
form = ArticleForm
#zf设置在列表页显示的字段
list_display = (
'id',
'title',
'author',
#zf自定义的分类链接字段
'link_to_category',
'creation_time',
'views',
'status',
'type',
'article_order')
#zf设置哪些字段可以作为链接点击进入编辑页
list_display_links = ('id', 'title')
#zf设置右侧的过滤器字段
list_filter = ('status', 'type', 'category')
#zf对tags字段使用水平过滤器
filter_horizontal = ('tags',)
#zf在表单中排除这些字段由系统自动管理
exclude = ('creation_time', 'last_modify_time')
#zf启用"在站点上查看"功能
view_on_site = True
#zf注册自定义的管理操作
actions = [
makr_article_publish,
draft_article,
close_article_commentstatus,
open_article_commentstatus]
#zf自定义字段显示分类链接
def link_to_category(self, obj):
#zf获取分类模型的app_label和model_name
info = (obj.category._meta.app_label, obj.category._meta.model_name)
#zf生成分类编辑页的URL
link = reverse('admin:%s_%s_change' % info, args=(obj.category.id,))
#zf返回HTML链接
return format_html(u'<a href="%s">%s</a>' % (link, obj.category.name))
#zf设置字段显示名称
link_to_category.short_description = _('category')
#zf自定义表单获取方法
def get_form(self, request, obj=None, **kwargs):
form = super(ArticlelAdmin, self).get_form(request, obj, **kwargs)
#zf限制作者字段只能选择超级用户
form.base_fields['author'].queryset = get_user_model(
).objects.filter(is_superuser=True)
return form
#zf保存模型的方法
def save_model(self, request, obj, form, change):
super(ArticlelAdmin, self).save_model(request, obj, form, change)
#zf获取在站点上查看的URL
def get_view_on_site_url(self, obj=None):
if obj:
#zf获取文章的完整URL
url = obj.get_full_url()
return url
else:
from djangoblog.utils import get_current_site
#zf获取当前站点域名
site = get_current_site().domain
return site
#zf定义标签管理类
class TagAdmin(admin.ModelAdmin):
#zf排除这些字段由系统自动管理
exclude = ('slug', 'last_mod_time', 'creation_time')
#zf定义分类管理类
class CategoryAdmin(admin.ModelAdmin):
#zf设置在列表页显示的字段
list_display = ('name', 'parent_category', 'index')
#zf排除这些字段由系统自动管理
exclude = ('slug', 'last_mod_time', 'creation_time')
#zf定义链接管理类
class LinksAdmin(admin.ModelAdmin):
#zf排除这些字段由系统自动管理
exclude = ('last_mod_time', 'creation_time')
#zf定义侧边栏管理类
class SideBarAdmin(admin.ModelAdmin):
#zf设置在列表页显示的字段
list_display = ('name', 'content', 'is_enable', 'sequence')
#zf排除这些字段由系统自动管理
exclude = ('last_mod_time', 'creation_time')
#zf定义博客设置管理类
class BlogSettingsAdmin(admin.ModelAdmin):
#zf没有特殊配置
pass
#zf注册模型到管理后台
#zf注意在你提供的代码中模型注册部分被省略了通常应该包含如下代码
#zfadmin.site.register(Article, ArticlelAdmin)
#zfadmin.site.register(Tag, TagAdmin)
#zfadmin.site.register(Category, CategoryAdmin)
#zfadmin.site.register(Links, LinksAdmin)
#zfadmin.site.register(SideBar, SideBarAdmin)
#zfadmin.site.register(BlogSettings, BlogSettingsAdmin)

@ -0,0 +1,9 @@
#zf导入Django的应用配置基类
from django.apps import AppConfig
#zf定义博客应用的配置类继承自AppConfig
class BlogConfig(AppConfig):
#zf设置应用的名称为'blog'
#zf这个名称需要与Django项目中应用的目录名称保持一致
name = 'blog'

@ -0,0 +1,79 @@
#zf导入日志模块用于记录日志信息
import logging
#zf导入Django时区模块用于获取当前时间
from django.utils import timezone
#zf从djangoblog.utils模块导入缓存和获取博客设置的工具函数
from djangoblog.utils import cache, get_blog_setting
#zf从当前包导入Category和Article模型
from .models import Category, Article
#zf创建日志记录器
logger = logging.getLogger(__name__)
#zf定义SEO处理器函数作为Django的上下文处理器
def seo_processor(requests):
#zf设置缓存键名
key = 'seo_processor'
#zf尝试从缓存中获取数据
value = cache.get(key)
#zf如果缓存中有数据直接返回
if value:
return value
else:
#zf如果缓存中没有数据记录日志
logger.info('set processor cache.')
#zf获取博客设置
setting = get_blog_setting()
#zf构造要返回的上下文数据字典
value = {
#zf网站名称
'SITE_NAME': setting.site_name,
#zf是否显示谷歌广告
'SHOW_GOOGLE_ADSENSE': setting.show_google_adsense,
#zf谷歌广告代码
'GOOGLE_ADSENSE_CODES': setting.google_adsense_codes,
#zf网站SEO描述
'SITE_SEO_DESCRIPTION': setting.site_seo_description,
#zf网站描述
'SITE_DESCRIPTION': setting.site_description,
#zf网站关键词
'SITE_KEYWORDS': setting.site_keywords,
#zf网站基础URL协议+主机名+/
'SITE_BASE_URL': requests.scheme + '://' + requests.get_host() + '/',
#zf文章摘要长度
'ARTICLE_SUB_LENGTH': setting.article_sub_length,
#zf导航分类列表所有分类
'nav_category_list': Category.objects.all(),
#zf导航页面所有已发布的页面类型文章
'nav_pages': Article.objects.filter(
type='p', #zf类型为页面('p')
status='p'), #zf状态为已发布('p')
#zf是否开启网站评论功能
'OPEN_SITE_COMMENT': setting.open_site_comment,
#zf备案号
'BEIAN_CODE': setting.beian_code,
#zf网站统计代码
'ANALYTICS_CODE': setting.analytics_code,
#zf公安备案号
"BEIAN_CODE_GONGAN": setting.gongan_beiancode,
#zf是否显示公安备案号
"SHOW_GONGAN_CODE": setting.show_gongan_code,
#zf当前年份用于版权信息等
"CURRENT_YEAR": timezone.now().year,
#zf全局头部内容
"GLOBAL_HEADER": setting.global_header,
#zf全局尾部内容
"GLOBAL_FOOTER": setting.global_footer,
#zf评论是否需要审核
"COMMENT_NEED_REVIEW": setting.comment_need_review,
}
#zf将数据缓存10小时60秒*60分钟*10小时
cache.set(key, value, 60 * 60 * 10)
#zf返回构造的数据
return value

@ -0,0 +1,328 @@
#zf导入时间模块用于生成时间戳
import time
#zf导入elasticsearch客户端模块
import elasticsearch.client
#zf导入Django配置模块
from django.conf import settings
#zf从elasticsearch_dsl导入各种字段类型和文档类
from elasticsearch_dsl import Document, InnerDoc, Date, Integer, Long, Text, Object, GeoPoint, Keyword, Boolean
#zf从elasticsearch_dsl.connections导入连接管理器
from elasticsearch_dsl.connections import connections
#zf从blog.models导入Article模型
from blog.models import Article
#zf检查是否启用了Elasticsearch功能通过检查settings中是否有ELASTICSEARCH_DSL配置
ELASTICSEARCH_ENABLED = hasattr(settings, 'ELASTICSEARCH_DSL')
#zf如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf创建Elasticsearch连接
connections.create_connection(
hosts=[settings.ELASTICSEARCH_DSL['default']['hosts']])
#zf导入Elasticsearch客户端
from elasticsearch import Elasticsearch
#zf创建Elasticsearch实例
es = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
#zf导入IngestClient用于管理管道
from elasticsearch.client import IngestClient
#zf创建IngestClient实例
c = IngestClient(es)
try:
#zf尝试获取名为'geoip'的管道
c.get_pipeline('geoip')
except elasticsearch.exceptions.NotFoundError:
#zf如果管道不存在则创建一个geoip管道
#zf该管道用于根据IP地址添加地理位置信息
c.put_pipeline('geoip', body='''{
"description" : "Add geoip info",
"processors" : [
{
"geoip" : {
"field" : "ip"
}
}
]
}''')
#zf定义GeoIp内部文档类用于存储地理位置信息
class GeoIp(InnerDoc):
#zf大洲名称
continent_name = Keyword()
#zf国家ISO代码
country_iso_code = Keyword()
#zf国家名称
country_name = Keyword()
#zf地理位置坐标
location = GeoPoint()
#zf定义UserAgentBrowser内部文档类用于存储浏览器信息
class UserAgentBrowser(InnerDoc):
#zf浏览器家族
Family = Keyword()
#zf浏览器版本
Version = Keyword()
#zf定义UserAgentOS内部文档类继承自UserAgentBrowser用于存储操作系统信息
class UserAgentOS(UserAgentBrowser):
pass
#zf定义UserAgentDevice内部文档类用于存储设备信息
class UserAgentDevice(InnerDoc):
#zf设备家族
Family = Keyword()
#zf设备品牌
Brand = Keyword()
#zf设备型号
Model = Keyword()
#zf定义UserAgent内部文档类用于存储用户代理信息
class UserAgent(InnerDoc):
#zf浏览器信息
browser = Object(UserAgentBrowser, required=False)
#zf操作系统信息
os = Object(UserAgentOS, required=False)
#zf设备信息
device = Object(UserAgentDevice, required=False)
#zf完整的User-Agent字符串
string = Text()
#zf是否为机器人
is_bot = Boolean()
#zf定义ElapsedTimeDocument文档类用于存储页面性能数据
class ElapsedTimeDocument(Document):
#zfURL地址
url = Keyword()
#zf耗时毫秒
time_taken = Long()
#zf记录时间
log_datetime = Date()
#zfIP地址
ip = Keyword()
#zf地理位置信息
geoip = Object(GeoIp, required=False)
#zf用户代理信息
useragent = Object(UserAgent, required=False)
#zf定义索引配置
class Index:
#zf索引名称
name = 'performance'
settings = {
#zf分片数量
"number_of_shards": 1,
#zf副本数量
"number_of_replicas": 0
}
#zf定义文档元数据
class Meta:
#zf文档类型
doc_type = 'ElapsedTime'
#zf定义ElapsedTime文档管理器类
class ElaspedTimeDocumentManager:
#zf静态方法构建索引
@staticmethod
def build_index():
from elasticsearch import Elasticsearch
#zf创建Elasticsearch客户端
client = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
#zf检查performance索引是否存在
res = client.indices.exists(index="performance")
if not res:
#zf如果不存在则初始化索引
ElapsedTimeDocument.init()
#zf静态方法删除索引
@staticmethod
def delete_index():
from elasticsearch import Elasticsearch
#zf创建Elasticsearch实例
es = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
#zf删除performance索引忽略400和404错误
es.indices.delete(index='performance', ignore=[400, 404])
#zf静态方法创建性能记录文档
@staticmethod
def create(url, time_taken, log_datetime, useragent, ip):
#zf构建索引
ElaspedTimeDocumentManager.build_index()
#zf创建UserAgent对象并填充数据
ua = UserAgent()
ua.browser = UserAgentBrowser()
ua.browser.Family = useragent.browser.family
ua.browser.Version = useragent.browser.version_string
ua.os = UserAgentOS()
ua.os.Family = useragent.os.family
ua.os.Version = useragent.os.version_string
ua.device = UserAgentDevice()
ua.device.Family = useragent.device.family
ua.device.Brand = useragent.device.brand
ua.device.Model = useragent.device.model
ua.string = useragent.ua_string
ua.is_bot = useragent.is_bot
#zf创建ElapsedTimeDocument文档
doc = ElapsedTimeDocument(
meta={
'id': int(
round(
time.time() *
1000)) #zf使用当前时间戳作为ID
},
url=url,
time_taken=time_taken,
log_datetime=log_datetime,
useragent=ua,
ip=ip)
#zf保存文档并使用geoip管道处理
doc.save(pipeline="geoip")
#zf定义ArticleDocument文档类用于存储文章搜索数据
class ArticleDocument(Document):
#zf文章正文使用ik_max_word分词器进行索引ik_smart进行搜索
body = Text(analyzer='ik_max_word', search_analyzer='ik_smart')
#zf文章标题使用ik_max_word分词器进行索引ik_smart进行搜索
title = Text(analyzer='ik_max_word', search_analyzer='ik_smart')
#zf作者信息
author = Object(properties={
#zf昵称
'nickname': Text(analyzer='ik_max_word', search_analyzer='ik_smart'),
#zfID
'id': Integer()
})
#zf分类信息
category = Object(properties={
#zf分类名
'name': Text(analyzer='ik_max_word', search_analyzer='ik_smart'),
#zfID
'id': Integer()
})
#zf标签信息
tags = Object(properties={
#zf标签名
'name': Text(analyzer='ik_max_word', search_analyzer='ik_smart'),
#zfID
'id': Integer()
})
#zf发布时间
pub_time = Date()
#zf文章状态
status = Text()
#zf评论状态
comment_status = Text()
#zf文章类型
type = Text()
#zf浏览量
views = Integer()
#zf文章排序
article_order = Integer()
#zf定义索引配置
class Index:
#zf索引名称
name = 'blog'
settings = {
#zf分片数量
"number_of_shards": 1,
#zf副本数量
"number_of_replicas": 0
}
#zf定义文档元数据
class Meta:
#zf文档类型
doc_type = 'Article'
#zf定义ArticleDocument管理器类
class ArticleDocumentManager():
#zf初始化方法
def __init__(self):
self.create_index()
#zf创建索引方法
def create_index(self):
ArticleDocument.init()
#zf删除索引方法
def delete_index(self):
from elasticsearch import Elasticsearch
#zf创建Elasticsearch实例
es = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
#zf删除blog索引忽略400和404错误
es.indices.delete(index='blog', ignore=[400, 404])
#zf将文章对象转换为文档对象的方法
def convert_to_doc(self, articles):
return [
ArticleDocument(
meta={
#zf使用文章ID作为文档ID
'id': article.id},
#zf文章正文
body=article.body,
#zf文章标题
title=article.title,
author={
#zf作者昵称
'nickname': article.author.username,
#zf作者ID
'id': article.author.id},
category={
#zf分类名
'name': article.category.name,
#zf分类ID
'id': article.category.id},
tags=[
{
#zf标签名
'name': t.name,
#zf标签ID
'id': t.id} for t in article.tags.all()],
#zf发布时间
pub_time=article.pub_time,
#zf文章状态
status=article.status,
#zf评论状态
comment_status=article.comment_status,
#zf文章类型
type=article.type,
#zf浏览量
views=article.views,
#zf排序
article_order=article.article_order) for article in articles]
#zf重建索引方法
def rebuild(self, articles=None):
#zf初始化索引
ArticleDocument.init()
#zf如果没有提供文章列表则获取所有文章
articles = articles if articles else Article.objects.all()
#zf转换文章为文档对象
docs = self.convert_to_doc(articles)
#zf保存所有文档
for doc in docs:
doc.save()
#zf更新文档方法
def update_docs(self, docs):
#zf保存所有文档
for doc in docs:
doc.save()

@ -0,0 +1,34 @@
# 导入日志模块,用于记录日志信息
import logging
# 导入Django表单模块
from django import forms
# 从haystack.forms导入SearchForm用于实现搜索功能
from haystack.forms import SearchForm
# 创建日志记录器
logger = logging.getLogger(__name__)
# 定义博客搜索表单类继承自Haystack的SearchForm
class BlogSearchForm(SearchForm):
# 定义搜索查询字段,设置为必填项
querydata = forms.CharField(required=True)
# 重写search方法实现自定义搜索逻辑
def search(self):
# 调用父类的search方法获取搜索结果
datas = super(BlogSearchForm, self).search()
# 检查表单数据是否有效
if not self.is_valid():
# 如果无效,返回无查询结果
return self.no_query_found()
# 如果查询数据存在
if self.cleaned_data['querydata']:
# 记录查询关键字到日志中
logger.info(self.cleaned_data['querydata'])
# 返回搜索结果
return datas

@ -0,0 +1,406 @@
#zf导入os模块用于文件路径操作
import os
#zf从django.conf导入settings配置
from django.conf import settings
#zf从django.core.files.uploadedfile导入SimpleUploadedFile用于模拟文件上传
from django.core.files.uploadedfile import SimpleUploadedFile
#zf从django.core.management导入call_command用于调用Django管理命令
from django.core.management import call_command
#zf从django.core.paginator导入Paginator用于分页功能测试
from django.core.paginator import Paginator
#zf从django.templatetags.static导入static函数用于处理静态文件
from django.templatetags.static import static
#zf从django.test导入Client, RequestFactory, TestCase用于测试
from django.test import Client, RequestFactory, TestCase
#zf从django.urls导入reverse用于URL反向解析
from django.urls import reverse
#zf从django.utils导入timezone用于处理时区
from django.utils import timezone
#zf从accounts.models导入BlogUser博客用户模型
from accounts.models import BlogUser
#zf从blog.forms导入BlogSearchForm博客搜索表单
from blog.forms import BlogSearchForm
#zf从blog.models导入Article, Category, Tag, SideBar, Links博客相关模型
from blog.models import Article, Category, Tag, SideBar, Links
#zf从blog.templatetags.blog_tags导入load_pagination_info, load_articletags模板标签
from blog.templatetags.blog_tags import load_pagination_info, load_articletags
#zf从djangoblog.utils导入get_current_site, get_sha256工具函数
from djangoblog.utils import get_current_site, get_sha256
#zf从oauth.models导入OAuthUser, OAuthConfig OAuth认证相关模型
from oauth.models import OAuthUser, OAuthConfig
#zf创建你的测试用例
#zf定义ArticleTest测试类继承自Django的TestCase
class ArticleTest(TestCase):
#zf测试初始化方法在每个测试方法执行前运行
def setUp(self):
#zf创建测试客户端用于模拟HTTP请求
self.client = Client()
#zf创建请求工厂用于创建请求对象
self.factory = RequestFactory()
#zf测试文章验证功能
def test_validate_article(self):
#zf获取当前站点域名
site = get_current_site().domain
#zf创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf设置用户密码
user.set_password("liangliangyy")
#zf设置用户为管理员
user.is_staff = True
#zf设置用户为超级用户
user.is_superuser = True
#zf保存用户
user.save()
#zf测试访问用户个人页面
response = self.client.get(user.get_absolute_url())
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问管理后台邮件发送日志
response = self.client.get('/admin/servermanager/emailsendlog/')
#zf测试访问管理后台日志条目
response = self.client.get('admin/admin/logentry/')
#zf创建侧边栏对象
s = SideBar()
#zf设置侧边栏排序
s.sequence = 1
#zf设置侧边栏名称
s.name = 'test'
#zf设置侧边栏内容
s.content = 'test content'
#zf设置侧边栏启用状态
s.is_enable = True
#zf保存侧边栏
s.save()
#zf创建分类对象
category = Category()
#zf设置分类名称
category.name = "category"
#zf设置分类创建时间
category.creation_time = timezone.now()
#zf设置分类最后修改时间
category.last_mod_time = timezone.now()
#zf保存分类
category.save()
#zf创建标签对象
tag = Tag()
#zf设置标签名称
tag.name = "nicetag"
#zf保存标签
tag.save()
#zf创建文章对象
article = Article()
#zf设置文章标题
article.title = "nicetitle"
#zf设置文章正文
article.body = "nicecontent"
#zf设置文章作者
article.author = user
#zf设置文章分类
article.category = category
#zf设置文章类型为文章
article.type = 'a'
#zf设置文章状态为已发布
article.status = 'p'
#zf保存文章
article.save()
#zf断言文章标签数量为0
self.assertEqual(0, article.tags.count())
#zf给文章添加标签
article.tags.add(tag)
#zf保存文章
article.save()
#zf断言文章标签数量为1
self.assertEqual(1, article.tags.count())
#zf循环创建20篇文章用于分页测试
for i in range(20):
article = Article()
#zf设置文章标题
article.title = "nicetitle" + str(i)
#zf设置文章正文
article.body = "nicetitle" + str(i)
#zf设置文章作者
article.author = user
#zf设置文章分类
article.category = category
#zf设置文章类型为文章
article.type = 'a'
#zf设置文章状态为已发布
article.status = 'p'
#zf保存文章
article.save()
#zf给文章添加标签
article.tags.add(tag)
#zf保存文章
article.save()
#zf从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf调用build_index管理命令构建搜索索引
call_command("build_index")
#zf测试搜索功能
response = self.client.get('/search', {'q': 'nicetitle'})
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问文章详情页
response = self.client.get(article.get_absolute_url())
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf从djangoblog.spider_notify导入SpiderNotify用于通知搜索引擎
from djangoblog.spider_notify import SpiderNotify
#zf通知搜索引擎爬虫
SpiderNotify.notify(article.get_absolute_url())
#zf测试访问标签详情页
response = self.client.get(tag.get_absolute_url())
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问分类详情页
response = self.client.get(category.get_absolute_url())
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试搜索功能
response = self.client.get('/search', {'q': 'django'})
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf加载文章标签
s = load_articletags(article)
#zf断言结果不为None
self.assertIsNotNone(s)
#zf用户登录
self.client.login(username='liangliangyy', password='liangliangyy')
#zf测试访问文章归档页
response = self.client.get(reverse('blog:archives'))
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf创建所有文章的分页器
p = Paginator(Article.objects.all(), settings.PAGINATE_BY)
#zf检查分页功能
self.check_pagination(p, '', '')
#zf创建按标签筛选的分页器
p = Paginator(Article.objects.filter(tags=tag), settings.PAGINATE_BY)
#zf检查标签归档分页功能
self.check_pagination(p, '分类标签归档', tag.slug)
#zf创建按作者筛选的分页器
p = Paginator(
Article.objects.filter(
author__username='liangliangyy'), settings.PAGINATE_BY)
#zf检查作者归档分页功能
self.check_pagination(p, '作者文章归档', 'liangliangyy')
#zf创建按分类筛选的分页器
p = Paginator(Article.objects.filter(category=category), settings.PAGINATE_BY)
#zf检查分类归档分页功能
self.check_pagination(p, '分类目录归档', category.slug)
#zf创建博客搜索表单实例
f = BlogSearchForm()
#zf执行搜索
f.search()
#zf从djangoblog.spider_notify导入SpiderNotify
from djangoblog.spider_notify import SpiderNotify
#zf通知百度搜索引擎
SpiderNotify.baidu_notify([article.get_full_url()])
#zf从blog.templatetags.blog_tags导入gravatar_url, gravatar函数
from blog.templatetags.blog_tags import gravatar_url, gravatar
#zf获取gravatar头像URL
u = gravatar_url('liangliangyy@gmail.com')
#zf获取gravatar头像HTML
u = gravatar('liangliangyy@gmail.com')
#zf创建友情链接对象
link = Links(
sequence=1,
name="lylinux",
link='https://wwww.lylinux.net')
#zf保存友情链接
link.save()
#zf测试访问友情链接页面
response = self.client.get('/links.html')
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问RSS订阅页面
response = self.client.get('/feed/')
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问站点地图
response = self.client.get('/sitemap.xml')
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试访问管理后台文章删除页面
self.client.get("/admin/blog/article/1/delete/")
#zf测试访问管理后台邮件发送日志
self.client.get('/admin/servermanager/emailsendlog/')
#zf测试访问管理后台日志条目
self.client.get('/admin/admin/logentry/')
#zf测试访问管理后台日志条目修改页面
self.client.get('/admin/admin/logentry/1/change/')
#zf检查分页功能的方法
def check_pagination(self, p, type, value):
#zf遍历所有分页
for page in range(1, p.num_pages + 1):
#zf加载分页信息
s = load_pagination_info(p.page(page), type, value)
#zf断言分页信息不为None
self.assertIsNotNone(s)
#zf如果有上一页URL
if s['previous_url']:
#zf测试访问上一页
response = self.client.get(s['previous_url'])
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf如果有下一页URL
if s['next_url']:
#zf测试访问下一页
response = self.client.get(s['next_url'])
#zf断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf测试图片上传功能
def test_image(self):
#zf导入requests模块用于下载图片
import requests
#zf下载Python官网Logo图片
rsp = requests.get(
'https://www.python.org/static/img/python-logo.png')
#zf设置图片保存路径
imagepath = os.path.join(settings.BASE_DIR, 'python.png')
#zf将图片保存到本地
with open(imagepath, 'wb') as file:
file.write(rsp.content)
#zf测试未登录上传图片应该被拒绝
rsp = self.client.post('/upload')
#zf断言响应状态码为403禁止访问
self.assertEqual(rsp.status_code, 403)
#zf生成上传签名
sign = get_sha256(get_sha256(settings.SECRET_KEY))
#zf打开图片文件准备上传
with open(imagepath, 'rb') as file:
#zf创建上传文件对象
imgfile = SimpleUploadedFile(
'python.png', file.read(), content_type='image/jpg')
#zf构造表单数据
form_data = {'python.png': imgfile}
#zf测试带签名上传图片
rsp = self.client.post(
'/upload?sign=' + sign, form_data, follow=True)
#zf断言响应状态码为200
self.assertEqual(rsp.status_code, 200)
#zf删除临时图片文件
os.remove(imagepath)
#zf从djangoblog.utils导入save_user_avatar, send_email工具函数
from djangoblog.utils import save_user_avatar, send_email
#zf测试发送邮件功能
send_email(['qq@qq.com'], 'testTitle', 'testContent')
#zf测试保存用户头像功能
save_user_avatar(
'https://www.python.org/static/img/python-logo.png')
#zf测试错误页面
def test_errorpage(self):
#zf测试访问不存在的页面
rsp = self.client.get('/eee')
#zf断言响应状态码为404
self.assertEqual(rsp.status_code, 404)
#zf测试管理命令
def test_commands(self):
#zf创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf设置用户密码
user.set_password("liangliangyy")
#zf设置用户为管理员
user.is_staff = True
#zf设置用户为超级用户
user.is_superuser = True
#zf保存用户
user.save()
#zf创建OAuth配置对象
c = OAuthConfig()
#zf设置OAuth类型为QQ
c.type = 'qq'
#zf设置应用密钥
c.appkey = 'appkey'
#zf设置应用密钥
c.appsecret = 'appsecret'
#zf保存配置
c.save()
#zf创建OAuth用户对象
u = OAuthUser()
#zf设置OAuth类型为QQ
u.type = 'qq'
#zf设置openid
u.openid = 'openid'
#zf关联博客用户
u.user = user
#zf设置头像为静态图片
u.picture = static("/blog/img/avatar.png")
#zf设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf保存OAuth用户
u.save()
#zf创建另一个OAuth用户对象
u = OAuthUser()
#zf设置OAuth类型为QQ
u.type = 'qq'
#zf设置openid
u.openid = 'openid1'
#zf设置头像URL
u.picture = 'https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30'
#zf设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf保存OAuth用户
u.save()
#zf从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf调用build_index命令构建搜索索引
call_command("build_index")
#zf调用ping_baidu命令通知百度搜索引擎
call_command("ping_baidu", "all")
#zf调用create_testdata命令创建测试数据
call_command("create_testdata")
#zf调用clear_cache命令清除缓存
call_command("clear_cache")
#zf调用sync_user_avatar命令同步用户头像
call_command("sync_user_avatar")
#zf调用build_search_words命令构建搜索词
call_command("build_search_words")

@ -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()

@ -0,0 +1,21 @@
#zf:从haystack导入索引相关模块
from haystack import indexes
#zf:从blog.models导入Article模型
from blog.models import Article
#zf:定义文章索引类继承自SearchIndex和Indexable
class ArticleIndex(indexes.SearchIndex, indexes.Indexable):
#zf:定义文本字段,作为文档字段,使用模板来确定索引内容
text = indexes.CharField(document=True, use_template=True)
#zf:获取模型类的方法
def get_model(self):
#zf:返回Article模型
return Article
#zf:定义索引查询集,确定哪些数据会被索引
def index_queryset(self, using=None):
#zf:返回所有状态为已发布('p')的文章
return self.get_model().objects.filter(status='p')

@ -0,0 +1,406 @@
#zf:导入操作系统相关模块
import os
#zf:从django.conf导入settings配置
from django.conf import settings
#zf:从django.core.files.uploadedfile导入SimpleUploadedFile用于文件上传测试
from django.core.files.uploadedfile import SimpleUploadedFile
#zf:从django.core.management导入call_command用于调用管理命令
from django.core.management import call_command
#zf:从django.core.paginator导入Paginator用于分页测试
from django.core.paginator import Paginator
#zf:从django.templatetags.static导入static用于静态文件处理
from django.templatetags.static import static
#zf:从django.test导入Client, RequestFactory, TestCase用于测试
from django.test import Client, RequestFactory, TestCase
#zf:从django.urls导入reverse用于URL反向解析
from django.urls import reverse
#zf:从django.utils导入timezone用于时间处理
from django.utils import timezone
#zf:从accounts.models导入BlogUser用户模型
from accounts.models import BlogUser
#zf:从blog.forms导入BlogSearchForm搜索表单
from blog.forms import BlogSearchForm
#zf:从blog.models导入Article, Category, Tag, SideBar, Links模型
from blog.models import Article, Category, Tag, SideBar, Links
#zf:从blog.templatetags.blog_tags导入load_pagination_info, load_articletags模板标签
from blog.templatetags.blog_tags import load_pagination_info, load_articletags
#zf:从djangoblog.utils导入get_current_site, get_sha256工具函数
from djangoblog.utils import get_current_site, get_sha256
#zf:从oauth.models导入OAuthUser, OAuthConfig OAuth相关模型
from oauth.models import OAuthUser, OAuthConfig
#zf:创建你的测试用例
#zf:定义文章测试类继承自TestCase
class ArticleTest(TestCase):
#zf:测试初始化方法
def setUp(self):
#zf:创建测试客户端
self.client = Client()
#zf:创建请求工厂
self.factory = RequestFactory()
#zf:测试验证文章功能
def test_validate_article(self):
#zf:获取当前站点域名
site = get_current_site().domain
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为职员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:测试获取用户绝对URL
response = self.client.get(user.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问管理后台日志页面
response = self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目页面
response = self.client.get('admin/admin/logentry/')
#zf:创建侧边栏对象
s = SideBar()
#zf:设置侧边栏排序
s.sequence = 1
#zf:设置侧边栏名称
s.name = 'test'
#zf:设置侧边栏内容
s.content = 'test content'
#zf:设置侧边栏启用状态
s.is_enable = True
#zf:保存侧边栏
s.save()
#zf:创建分类对象
category = Category()
#zf:设置分类名称
category.name = "category"
#zf:设置分类创建时间
category.creation_time = timezone.now()
#zf:设置分类最后修改时间
category.last_mod_time = timezone.now()
#zf:保存分类
category.save()
#zf:创建标签对象
tag = Tag()
#zf:设置标签名称
tag.name = "nicetag"
#zf:保存标签
tag.save()
#zf:创建文章对象
article = Article()
#zf:设置文章标题
article.title = "nicetitle"
#zf:设置文章正文
article.body = "nicecontent"
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型
article.type = 'a'
#zf:设置文章状态
article.status = 'p'
#zf:保存文章
article.save()
#zf:断言文章标签数量为0
self.assertEqual(0, article.tags.count())
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:断言文章标签数量为1
self.assertEqual(1, article.tags.count())
#zf:循环创建20篇文章用于测试
for i in range(20):
article = Article()
#zf:设置文章标题
article.title = "nicetitle" + str(i)
#zf:设置文章正文
article.body = "nicetitle" + str(i)
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型
article.type = 'a'
#zf:设置文章状态
article.status = 'p'
#zf:保存文章
article.save()
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用构建索引命令
call_command("build_index")
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'nicetitle'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试获取文章绝对URL
response = self.client.get(article.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:从djangoblog.spider_notify导入SpiderNotify
from djangoblog.spider_notify import SpiderNotify
#zf:通知搜索引擎爬虫
SpiderNotify.notify(article.get_absolute_url())
#zf:测试获取标签绝对URL
response = self.client.get(tag.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试获取分类绝对URL
response = self.client.get(category.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'django'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:加载文章标签
s = load_articletags(article)
#zf:断言结果不为None
self.assertIsNotNone(s)
#zf:用户登录
self.client.login(username='liangliangyy', password='liangliangyy')
#zf:测试获取归档页面
response = self.client.get(reverse('blog:archives'))
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:创建所有文章的分页器
p = Paginator(Article.objects.all(), settings.PAGINATE_BY)
#zf:检查分页功能
self.check_pagination(p, '', '')
#zf:创建按标签筛选文章的分页器
p = Paginator(Article.objects.filter(tags=tag), settings.PAGINATE_BY)
#zf:检查分页功能,类型为分类标签归档
self.check_pagination(p, '分类标签归档', tag.slug)
#zf:创建按作者筛选文章的分页器
p = Paginator(
Article.objects.filter(
author__username='liangliangyy'), settings.PAGINATE_BY)
#zf:检查分页功能,类型为作者文章归档
self.check_pagination(p, '作者文章归档', 'liangliangyy')
#zf:创建按分类筛选文章的分页器
p = Paginator(Article.objects.filter(category=category), settings.PAGINATE_BY)
#zf:检查分页功能,类型为分类目录归档
self.check_pagination(p, '分类目录归档', category.slug)
#zf:创建博客搜索表单实例
f = BlogSearchForm()
#zf:执行搜索
f.search()
#zf:从djangoblog.spider_notify导入SpiderNotify
from djangoblog.spider_notify import SpiderNotify
#zf:通知百度搜索引擎
SpiderNotify.baidu_notify([article.get_full_url()])
#zf:从blog.templatetags.blog_tags导入gravatar_url, gravatar
from blog.templatetags.blog_tags import gravatar_url, gravatar
#zf:获取gravatar头像URL
u = gravatar_url('liangliangyy@gmail.com')
#zf:获取gravatar头像
u = gravatar('liangliangyy@gmail.com')
#zf:创建链接对象
link = Links(
sequence=1,
name="lylinux",
link='https://wwww.lylinux.net')
#zf:保存链接
link.save()
#zf:测试获取链接页面
response = self.client.get('/links.html')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试获取RSS订阅页面
response = self.client.get('/feed/')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试获取站点地图
response = self.client.get('/sitemap.xml')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试删除文章
self.client.get("/admin/blog/article/1/delete/")
#zf:测试访问管理后台日志页面
self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目页面
self.client.get('/admin/admin/logentry/')
#zf:测试访问管理后台日志条目修改页面
self.client.get('/admin/admin/logentry/1/change/')
#zf:检查分页功能的方法
def check_pagination(self, p, type, value):
#zf:遍历所有页面
for page in range(1, p.num_pages + 1):
#zf:加载分页信息
s = load_pagination_info(p.page(page), type, value)
#zf:断言结果不为None
self.assertIsNotNone(s)
#zf:如果有上一页URL
if s['previous_url']:
#zf:测试访问上一页
response = self.client.get(s['previous_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:如果有下一页URL
if s['next_url']:
#zf:测试访问下一页
response = self.client.get(s['next_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试图片上传功能
def test_image(self):
#zf:导入requests模块
import requests
#zf:获取Python官网Logo图片
rsp = requests.get(
'https://www.python.org/static/img/python-logo.png')
#zf:设置图片保存路径
imagepath = os.path.join(settings.BASE_DIR, 'python.png')
#zf:将图片保存到本地
with open(imagepath, 'wb') as file:
file.write(rsp.content)
#zf:测试未登录上传图片
rsp = self.client.post('/upload')
#zf:断言响应状态码为403(禁止访问)
self.assertEqual(rsp.status_code, 403)
#zf:生成上传签名
sign = get_sha256(get_sha256(settings.SECRET_KEY))
#zf:打开图片文件
with open(imagepath, 'rb') as file:
#zf:创建上传文件对象
imgfile = SimpleUploadedFile(
'python.png', file.read(), content_type='image/jpg')
#zf:构造表单数据
form_data = {'python.png': imgfile}
#zf:测试带签名上传图片
rsp = self.client.post(
'/upload?sign=' + sign, form_data, follow=True)
#zf:断言响应状态码为200
self.assertEqual(rsp.status_code, 200)
#zf:删除临时图片文件
os.remove(imagepath)
#zf:从djangoblog.utils导入save_user_avatar, send_email工具函数
from djangoblog.utils import save_user_avatar, send_email
#zf:测试发送邮件
send_email(['qq@qq.com'], 'testTitle', 'testContent')
#zf:测试保存用户头像
save_user_avatar(
'https://www.python.org/static/img/python-logo.png')
#zf:测试错误页面
def test_errorpage(self):
#zf:测试访问不存在的页面
rsp = self.client.get('/eee')
#zf:断言响应状态码为404
self.assertEqual(rsp.status_code, 404)
#zf:测试管理命令
def test_commands(self):
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为职员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:创建OAuth配置对象
c = OAuthConfig()
#zf:设置OAuth类型
c.type = 'qq'
#zf:设置应用密钥
c.appkey = 'appkey'
#zf:设置应用密钥
c.appsecret = 'appsecret'
#zf:保存配置
c.save()
#zf:创建OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型
u.type = 'qq'
#zf:设置openid
u.openid = 'openid'
#zf:关联用户
u.user = user
#zf:设置头像
u.picture = static("/blog/img/avatar.png")
#zf:设置元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:创建另一个OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型
u.type = 'qq'
#zf:设置openid
u.openid = 'openid1'
#zf:设置头像URL
u.picture = 'https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30'
#zf:设置元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用构建索引命令
call_command("build_index")
#zf:调用通知百度搜索引擎命令
call_command("ping_baidu", "all")
#zf:调用创建测试数据命令
call_command("create_testdata")
#zf:调用清除缓存命令
call_command("clear_cache")
#zf:调用同步用户头像命令
call_command("sync_user_avatar")
#zf:调用构建搜索词命令
call_command("build_search_words")

@ -0,0 +1,406 @@
#zf:导入os模块用于文件路径操作
import os
#zf:从django.conf导入settings配置
from django.conf import settings
#zf:从django.core.files.uploadedfile导入SimpleUploadedFile用于模拟文件上传
from django.core.files.uploadedfile import SimpleUploadedFile
#zf:从django.core.management导入call_command用于调用Django管理命令
from django.core.management import call_command
#zf:从django.core.paginator导入Paginator用于分页功能测试
from django.core.paginator import Paginator
#zf:从django.templatetags.static导入static函数用于处理静态文件
from django.templatetags.static import static
#zf:从django.test导入Client, RequestFactory, TestCase用于测试
from django.test import Client, RequestFactory, TestCase
#zf:从django.urls导入reverse用于URL反向解析
from django.urls import reverse
#zf:从django.utils导入timezone用于处理时区
from django.utils import timezone
#zf:从accounts.models导入BlogUser博客用户模型
from accounts.models import BlogUser
#zf:从blog.forms导入BlogSearchForm博客搜索表单
from blog.forms import BlogSearchForm
#zf:从blog.models导入Article, Category, Tag, SideBar, Links博客相关模型
from blog.models import Article, Category, Tag, SideBar, Links
#zf:从blog.templatetags.blog_tags导入load_pagination_info, load_articletags模板标签
from blog.templatetags.blog_tags import load_pagination_info, load_articletags
#zf:从djangoblog.utils导入get_current_site, get_sha256工具函数
from djangoblog.utils import get_current_site, get_sha256
#zf:从oauth.models导入OAuthUser, OAuthConfig OAuth认证相关模型
from oauth.models import OAuthUser, OAuthConfig
#zf:创建你的测试用例
#zf:定义ArticleTest测试类继承自Django的TestCase
class ArticleTest(TestCase):
#zf:测试初始化方法,在每个测试方法执行前运行
def setUp(self):
#zf:创建测试客户端用于模拟HTTP请求
self.client = Client()
#zf:创建请求工厂,用于创建请求对象
self.factory = RequestFactory()
#zf:测试文章验证功能
def test_validate_article(self):
#zf:获取当前站点域名
site = get_current_site().domain
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为管理员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:测试访问用户个人页面
response = self.client.get(user.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问管理后台邮件发送日志
response = self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目
response = self.client.get('admin/admin/logentry/')
#zf:创建侧边栏对象
s = SideBar()
#zf:设置侧边栏排序
s.sequence = 1
#zf:设置侧边栏名称
s.name = 'test'
#zf:设置侧边栏内容
s.content = 'test content'
#zf:设置侧边栏启用状态
s.is_enable = True
#zf:保存侧边栏
s.save()
#zf:创建分类对象
category = Category()
#zf:设置分类名称
category.name = "category"
#zf:设置分类创建时间
category.creation_time = timezone.now()
#zf:设置分类最后修改时间
category.last_mod_time = timezone.now()
#zf:保存分类
category.save()
#zf:创建标签对象
tag = Tag()
#zf:设置标签名称
tag.name = "nicetag"
#zf:保存标签
tag.save()
#zf:创建文章对象
article = Article()
#zf:设置文章标题
article.title = "nicetitle"
#zf:设置文章正文
article.body = "nicecontent"
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型为文章
article.type = 'a'
#zf:设置文章状态为已发布
article.status = 'p'
#zf:保存文章
article.save()
#zf:断言文章标签数量为0
self.assertEqual(0, article.tags.count())
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:断言文章标签数量为1
self.assertEqual(1, article.tags.count())
#zf:循环创建20篇文章用于分页测试
for i in range(20):
article = Article()
#zf:设置文章标题
article.title = "nicetitle" + str(i)
#zf:设置文章正文
article.body = "nicetitle" + str(i)
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型为文章
article.type = 'a'
#zf:设置文章状态为已发布
article.status = 'p'
#zf:保存文章
article.save()
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用build_index管理命令构建搜索索引
call_command("build_index")
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'nicetitle'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问文章详情页
response = self.client.get(article.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:从djangoblog.spider_notify导入SpiderNotify用于通知搜索引擎
from djangoblog.spider_notify import SpiderNotify
#zf:通知搜索引擎爬虫
SpiderNotify.notify(article.get_absolute_url())
#zf:测试访问标签详情页
response = self.client.get(tag.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问分类详情页
response = self.client.get(category.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'django'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:加载文章标签
s = load_articletags(article)
#zf:断言结果不为None
self.assertIsNotNone(s)
#zf:用户登录
self.client.login(username='liangliangyy', password='liangliangyy')
#zf:测试访问文章归档页
response = self.client.get(reverse('blog:archives'))
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:创建所有文章的分页器
p = Paginator(Article.objects.all(), settings.PAGINATE_BY)
#zf:检查分页功能
self.check_pagination(p, '', '')
#zf:创建按标签筛选的分页器
p = Paginator(Article.objects.filter(tags=tag), settings.PAGINATE_BY)
#zf:检查标签归档分页功能
self.check_pagination(p, '分类标签归档', tag.slug)
#zf:创建按作者筛选的分页器
p = Paginator(
Article.objects.filter(
author__username='liangliangyy'), settings.PAGINATE_BY)
#zf:检查作者归档分页功能
self.check_pagination(p, '作者文章归档', 'liangliangyy')
#zf:创建按分类筛选的分页器
p = Paginator(Article.objects.filter(category=category), settings.PAGINATE_BY)
#zf:检查分类归档分页功能
self.check_pagination(p, '分类目录归档', category.slug)
#zf:创建博客搜索表单实例
f = BlogSearchForm()
#zf:执行搜索
f.search()
#zf:从djangoblog.spider_notify导入SpiderNotify
from djangoblog.spider_notify import SpiderNotify
#zf:通知百度搜索引擎
SpiderNotify.baidu_notify([article.get_full_url()])
#zf:从blog.templatetags.blog_tags导入gravatar_url, gravatar函数
from blog.templatetags.blog_tags import gravatar_url, gravatar
#zf:获取gravatar头像URL
u = gravatar_url('liangliangyy@gmail.com')
#zf:获取gravatar头像HTML
u = gravatar('liangliangyy@gmail.com')
#zf:创建友情链接对象
link = Links(
sequence=1,
name="lylinux",
link='https://wwww.lylinux.net')
#zf:保存友情链接
link.save()
#zf:测试访问友情链接页面
response = self.client.get('/links.html')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问RSS订阅页面
response = self.client.get('/feed/')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问站点地图
response = self.client.get('/sitemap.xml')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问管理后台文章删除页面
self.client.get("/admin/blog/article/1/delete/")
#zf:测试访问管理后台邮件发送日志
self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目
self.client.get('/admin/admin/logentry/')
#zf:测试访问管理后台日志条目修改页面
self.client.get('/admin/admin/logentry/1/change/')
#zf:检查分页功能的方法
def check_pagination(self, p, type, value):
#zf:遍历所有分页
for page in range(1, p.num_pages + 1):
#zf:加载分页信息
s = load_pagination_info(p.page(page), type, value)
#zf:断言分页信息不为None
self.assertIsNotNone(s)
#zf:如果有上一页URL
if s['previous_url']:
#zf:测试访问上一页
response = self.client.get(s['previous_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:如果有下一页URL
if s['next_url']:
#zf:测试访问下一页
response = self.client.get(s['next_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试图片上传功能
def test_image(self):
#zf:导入requests模块用于下载图片
import requests
#zf:下载Python官网Logo图片
rsp = requests.get(
'https://www.python.org/static/img/python-logo.png')
#zf:设置图片保存路径
imagepath = os.path.join(settings.BASE_DIR, 'python.png')
#zf:将图片保存到本地
with open(imagepath, 'wb') as file:
file.write(rsp.content)
#zf:测试未登录上传图片(应该被拒绝)
rsp = self.client.post('/upload')
#zf:断言响应状态码为403禁止访问
self.assertEqual(rsp.status_code, 403)
#zf:生成上传签名
sign = get_sha256(get_sha256(settings.SECRET_KEY))
#zf:打开图片文件准备上传
with open(imagepath, 'rb') as file:
#zf:创建上传文件对象
imgfile = SimpleUploadedFile(
'python.png', file.read(), content_type='image/jpg')
#zf:构造表单数据
form_data = {'python.png': imgfile}
#zf:测试带签名上传图片
rsp = self.client.post(
'/upload?sign=' + sign, form_data, follow=True)
#zf:断言响应状态码为200
self.assertEqual(rsp.status_code, 200)
#zf:删除临时图片文件
os.remove(imagepath)
#zf:从djangoblog.utils导入save_user_avatar, send_email工具函数
from djangoblog.utils import save_user_avatar, send_email
#zf:测试发送邮件功能
send_email(['qq@qq.com'], 'testTitle', 'testContent')
#zf:测试保存用户头像功能
save_user_avatar(
'https://www.python.org/static/img/python-logo.png')
#zf:测试错误页面
def test_errorpage(self):
#zf:测试访问不存在的页面
rsp = self.client.get('/eee')
#zf:断言响应状态码为404
self.assertEqual(rsp.status_code, 404)
#zf:测试管理命令
def test_commands(self):
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为管理员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:创建OAuth配置对象
c = OAuthConfig()
#zf:设置OAuth类型为QQ
c.type = 'qq'
#zf:设置应用密钥
c.appkey = 'appkey'
#zf:设置应用密钥
c.appsecret = 'appsecret'
#zf:保存配置
c.save()
#zf:创建OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型为QQ
u.type = 'qq'
#zf:设置openid
u.openid = 'openid'
#zf:关联博客用户
u.user = user
#zf:设置头像为静态图片
u.picture = static("/blog/img/avatar.png")
#zf:设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:创建另一个OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型为QQ
u.type = 'qq'
#zf:设置openid
u.openid = 'openid1'
#zf:设置头像URL
u.picture = 'https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30'
#zf:设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用build_index命令构建搜索索引
call_command("build_index")
#zf:调用ping_baidu命令通知百度搜索引擎
call_command("ping_baidu", "all")
#zf:调用create_testdata命令创建测试数据
call_command("create_testdata")
#zf:调用clear_cache命令清除缓存
call_command("clear_cache")
#zf:调用sync_user_avatar命令同步用户头像
call_command("sync_user_avatar")
#zf:调用build_search_words命令构建搜索词
call_command("build_search_words")

@ -0,0 +1,406 @@
#zf:导入os模块用于文件操作
import os
#zf:从django.conf导入settings配置
from django.conf import settings
#zf:从django.core.files.uploadedfile导入SimpleUploadedFile用于文件上传测试
from django.core.files.uploadedfile import SimpleUploadedFile
#zf:从django.core.management导入call_command用于调用管理命令
from django.core.management import call_command
#zf:从django.core.paginator导入Paginator用于分页测试
from django.core.paginator import Paginator
#zf:从django.templatetags.static导入static用于处理静态文件
from django.templatetags.static import static
#zf:从django.test导入Client, RequestFactory, TestCase用于测试
from django.test import Client, RequestFactory, TestCase
#zf:从django.urls导入reverse用于URL反向解析
from django.urls import reverse
#zf:从django.utils导入timezone用于时区处理
from django.utils import timezone
#zf:从accounts.models导入BlogUser博客用户模型
from accounts.models import BlogUser
#zf:从blog.forms导入BlogSearchForm博客搜索表单
from blog.forms import BlogSearchForm
#zf:从blog.models导入Article, Category, Tag, SideBar, Links博客相关模型
from blog.models import Article, Category, Tag, SideBar, Links
#zf:从blog.templatetags.blog_tags导入load_pagination_info, load_articletags模板标签
from blog.templatetags.blog_tags import load_pagination_info, load_articletags
#zf:从djangoblog.utils导入get_current_site, get_sha256工具函数
from djangoblog.utils import get_current_site, get_sha256
#zf:从oauth.models导入OAuthUser, OAuthConfig OAuth相关模型
from oauth.models import OAuthUser, OAuthConfig
#zf:创建你的测试用例
#zf:定义ArticleTest测试类继承自TestCase
class ArticleTest(TestCase):
#zf:测试初始化方法,在每个测试方法执行前运行
def setUp(self):
#zf:创建测试客户端
self.client = Client()
#zf:创建请求工厂
self.factory = RequestFactory()
#zf:测试验证文章功能
def test_validate_article(self):
#zf:获取当前站点域名
site = get_current_site().domain
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为管理员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:测试访问用户绝对URL
response = self.client.get(user.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问管理后台邮件发送日志
response = self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目
response = self.client.get('admin/admin/logentry/')
#zf:创建侧边栏对象
s = SideBar()
#zf:设置侧边栏排序
s.sequence = 1
#zf:设置侧边栏名称
s.name = 'test'
#zf:设置侧边栏内容
s.content = 'test content'
#zf:设置侧边栏启用状态
s.is_enable = True
#zf:保存侧边栏
s.save()
#zf:创建分类对象
category = Category()
#zf:设置分类名称
category.name = "category"
#zf:设置分类创建时间
category.creation_time = timezone.now()
#zf:设置分类最后修改时间
category.last_mod_time = timezone.now()
#zf:保存分类
category.save()
#zf:创建标签对象
tag = Tag()
#zf:设置标签名称
tag.name = "nicetag"
#zf:保存标签
tag.save()
#zf:创建文章对象
article = Article()
#zf:设置文章标题
article.title = "nicetitle"
#zf:设置文章正文
article.body = "nicecontent"
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型为文章
article.type = 'a'
#zf:设置文章状态为已发布
article.status = 'p'
#zf:保存文章
article.save()
#zf:断言文章标签数量为0
self.assertEqual(0, article.tags.count())
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:断言文章标签数量为1
self.assertEqual(1, article.tags.count())
#zf:循环创建20篇文章用于测试
for i in range(20):
article = Article()
#zf:设置文章标题
article.title = "nicetitle" + str(i)
#zf:设置文章正文
article.body = "nicetitle" + str(i)
#zf:设置文章作者
article.author = user
#zf:设置文章分类
article.category = category
#zf:设置文章类型为文章
article.type = 'a'
#zf:设置文章状态为已发布
article.status = 'p'
#zf:保存文章
article.save()
#zf:给文章添加标签
article.tags.add(tag)
#zf:保存文章
article.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用build_index管理命令
call_command("build_index")
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'nicetitle'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问文章绝对URL
response = self.client.get(article.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:从djangoblog.spider_notify导入SpiderNotify用于通知搜索引擎
from djangoblog.spider_notify import SpiderNotify
#zf:通知搜索引擎爬虫
SpiderNotify.notify(article.get_absolute_url())
#zf:测试访问标签绝对URL
response = self.client.get(tag.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问分类绝对URL
response = self.client.get(category.get_absolute_url())
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试搜索功能
response = self.client.get('/search', {'q': 'django'})
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:加载文章标签
s = load_articletags(article)
#zf:断言结果不为None
self.assertIsNotNone(s)
#zf:用户登录
self.client.login(username='liangliangyy', password='liangliangyy')
#zf:测试访问文章归档页面
response = self.client.get(reverse('blog:archives'))
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:创建所有文章的分页器
p = Paginator(Article.objects.all(), settings.PAGINATE_BY)
#zf:检查分页功能
self.check_pagination(p, '', '')
#zf:创建按标签过滤的文章分页器
p = Paginator(Article.objects.filter(tags=tag), settings.PAGINATE_BY)
#zf:检查标签归档分页功能
self.check_pagination(p, '分类标签归档', tag.slug)
#zf:创建按作者过滤的文章分页器
p = Paginator(
Article.objects.filter(
author__username='liangliangyy'), settings.PAGINATE_BY)
#zf:检查作者归档分页功能
self.check_pagination(p, '作者文章归档', 'liangliangyy')
#zf:创建按分类过滤的文章分页器
p = Paginator(Article.objects.filter(category=category), settings.PAGINATE_BY)
#zf:检查分类归档分页功能
self.check_pagination(p, '分类目录归档', category.slug)
#zf:创建博客搜索表单实例
f = BlogSearchForm()
#zf:执行搜索
f.search()
#zf:从djangoblog.spider_notify导入SpiderNotify
from djangoblog.spider_notify import SpiderNotify
#zf:通知百度搜索引擎
SpiderNotify.baidu_notify([article.get_full_url()])
#zf:从blog.templatetags.blog_tags导入gravatar_url, gravatar函数
from blog.templatetags.blog_tags import gravatar_url, gravatar
#zf:获取gravatar头像URL
u = gravatar_url('liangliangyy@gmail.com')
#zf:获取gravatar头像HTML
u = gravatar('liangliangyy@gmail.com')
#zf:创建链接对象
link = Links(
sequence=1,
name="lylinux",
link='https://wwww.lylinux.net')
#zf:保存链接
link.save()
#zf:测试访问链接页面
response = self.client.get('/links.html')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问RSS订阅
response = self.client.get('/feed/')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问站点地图
response = self.client.get('/sitemap.xml')
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试访问管理后台文章删除页面
self.client.get("/admin/blog/article/1/delete/")
#zf:测试访问管理后台邮件发送日志
self.client.get('/admin/servermanager/emailsendlog/')
#zf:测试访问管理后台日志条目
self.client.get('/admin/admin/logentry/')
#zf:测试访问管理后台日志条目修改页面
self.client.get('/admin/admin/logentry/1/change/')
#zf:检查分页功能的方法
def check_pagination(self, p, type, value):
#zf:遍历所有页面
for page in range(1, p.num_pages + 1):
#zf:加载分页信息
s = load_pagination_info(p.page(page), type, value)
#zf:断言分页信息不为None
self.assertIsNotNone(s)
#zf:如果有上一页URL
if s['previous_url']:
#zf:测试访问上一页
response = self.client.get(s['previous_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:如果有下一页URL
if s['next_url']:
#zf:测试访问下一页
response = self.client.get(s['next_url'])
#zf:断言响应状态码为200
self.assertEqual(response.status_code, 200)
#zf:测试图片功能
def test_image(self):
#zf:导入requests模块
import requests
#zf:获取Python官网Logo图片
rsp = requests.get(
'https://www.python.org/static/img/python-logo.png')
#zf:设置图片保存路径
imagepath = os.path.join(settings.BASE_DIR, 'python.png')
#zf:将图片内容写入文件
with open(imagepath, 'wb') as file:
file.write(rsp.content)
#zf:测试未授权上传图片
rsp = self.client.post('/upload')
#zf:断言响应状态码为403
self.assertEqual(rsp.status_code, 403)
#zf:生成上传签名
sign = get_sha256(get_sha256(settings.SECRET_KEY))
#zf:打开图片文件准备上传
with open(imagepath, 'rb') as file:
#zf:创建上传文件对象
imgfile = SimpleUploadedFile(
'python.png', file.read(), content_type='image/jpg')
#zf:构造表单数据
form_data = {'python.png': imgfile}
#zf:测试带签名上传图片
rsp = self.client.post(
'/upload?sign=' + sign, form_data, follow=True)
#zf:断言响应状态码为200
self.assertEqual(rsp.status_code, 200)
#zf:删除临时图片文件
os.remove(imagepath)
#zf:从djangoblog.utils导入save_user_avatar, send_email工具函数
from djangoblog.utils import save_user_avatar, send_email
#zf:测试发送邮件
send_email(['qq@qq.com'], 'testTitle', 'testContent')
#zf:测试保存用户头像
save_user_avatar(
'https://www.python.org/static/img/python-logo.png')
#zf:测试错误页面
def test_errorpage(self):
#zf:测试访问不存在的页面
rsp = self.client.get('/eee')
#zf:断言响应状态码为404
self.assertEqual(rsp.status_code, 404)
#zf:测试管理命令
def test_commands(self):
#zf:创建或获取测试用户
user = BlogUser.objects.get_or_create(
email="liangliangyy@gmail.com",
username="liangliangyy")[0]
#zf:设置用户密码
user.set_password("liangliangyy")
#zf:设置用户为管理员
user.is_staff = True
#zf:设置用户为超级用户
user.is_superuser = True
#zf:保存用户
user.save()
#zf:创建OAuth配置对象
c = OAuthConfig()
#zf:设置OAuth类型为QQ
c.type = 'qq'
#zf:设置应用密钥
c.appkey = 'appkey'
#zf:设置应用密钥
c.appsecret = 'appsecret'
#zf:保存配置
c.save()
#zf:创建OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型为QQ
u.type = 'qq'
#zf:设置openid
u.openid = 'openid'
#zf:关联博客用户
u.user = user
#zf:设置头像为静态图片
u.picture = static("/blog/img/avatar.png")
#zf:设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:创建另一个OAuth用户对象
u = OAuthUser()
#zf:设置OAuth类型为QQ
u.type = 'qq'
#zf:设置openid
u.openid = 'openid1'
#zf:设置头像URL
u.picture = 'https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30'
#zf:设置用户元数据
u.metadata = '''
{
"figureurl": "https://qzapp.qlogo.cn/qzapp/101513904/C740E30B4113EAA80E0D9918ABC78E82/30"
}'''
#zf:保存OAuth用户
u.save()
#zf:从blog.documents导入ELASTICSEARCH_ENABLED常量
from blog.documents import ELASTICSEARCH_ENABLED
#zf:如果启用了Elasticsearch
if ELASTICSEARCH_ENABLED:
#zf:调用build_index命令构建索引
call_command("build_index")
#zf:调用ping_baidu命令通知百度
call_command("ping_baidu", "all")
#zf:调用create_testdata命令创建测试数据
call_command("create_testdata")
#zf:调用clear_cache命令清除缓存
call_command("clear_cache")
#zf:调用sync_user_avatar命令同步用户头像
call_command("sync_user_avatar")
#zf:调用build_search_words命令构建搜索词
call_command("build_search_words")
Loading…
Cancel
Save