Bear Blog:极简主义博客平台
Bear Blog是一个基于Django构建的博客平台,专注于提供免费、无废话、超级快速的博客体验。平台遵循极简主义设计理念,不包含JavaScript、样式表或追踪器,仅专注于内容本身。
功能特性
🎯 核心特点
- 极简设计:无JavaScript、无CSS框架、无追踪器,专注内容
- Markdown支持:所有文章内容使用Markdown格式编写,提供丰富的格式化选项
- 自定义域名:支持绑定自定义域名,享受个性化博客地址
- RSS订阅:内置完整的RSS/Atom订阅功能
- 数据分析:提供基本的访问统计和分析功能
- 媒体管理:集成媒体中心,支持图片、视频、音频等文件上传
📊 平台功能
- 多博客管理:单个用户可以创建和管理多个博客
- 用户权限系统:完整的用户认证和权限管理系统
- 主题定制:支持CSS自定义,可调整博客外观
- SEO优化:自动生成元标签和结构化数据
- 电子邮件订阅:内置邮件订阅系统
- Cloudflare集成:内置CDN缓存优化
🚀 性能优势
- 轻量级架构:极简的技术栈确保快速加载
- Heroku部署:云原生部署,自动扩展
- Redis缓存:使用Redis进行性能优化
- 数据库优化:精心设计的数据库索引和查询优化
安装指南
系统要求
- Python 3.9+
- PostgreSQL数据库
- Redis(可选,用于缓存)
- 虚拟环境支持
环境配置
- 克隆项目
gitclone<repository-url>cdbear-blog- 创建虚拟环境
python -m venv venvsourcevenv/bin/activate# Linux/Mac# 或 venv\Scripts\activate # Windows- 安装依赖
pipinstall-r requirements.txt- 环境变量设置
创建.env文件并配置必要变量:
SECRET_KEY=your_secret_key_hereDEBUG=True/FalseDATABASE_URL=postgres://user:password@localhost/dbnameREDISCLOUD_URL=redis://localhost:6379数据库设置
python manage.py migrate python manage.py createsuperuser运行开发服务器
python manage.py runserver使用说明
创建新博客
注册账户
访问注册页面,填写博客标题、子域名和初始内容。配置博客
# 示例:通过API创建博客(概念示例)blog=Blog.objects.create(title="我的博客",subdomain="myblog",content="Hello World!",user=request.user)- 自定义设置
- 导航菜单:通过Markdown格式添加导航链接
- 样式定制:通过CSS自定义博客外观
- 高级设置:配置分析、RSS、robots.txt等
编写文章
使用Markdown语法编写文章:
# 文章标题 这是文章内容,支持**粗体**、*斜体*和[链接](http://example.com)。 ## 二级标题 - 列表项1 - 列表项2 `代码片段`和数学公式支持。API使用
文章管理
# 创建新文章post=Post.objects.create(blog=blog,title="新文章标题",content="文章内容...",publish=True,published_date=timezone.now())访问统计
# 记录访问数据hit=Hit.objects.create(post=post,hash_id=hashed_user_id,browser=user_agent,country=geo_data,device=device_type)核心代码
1. 博客模型定义
# blogs/models.py - Blog模型核心部分classBlog(models.Model):""" 博客核心数据模型,存储博客的基本信息和配置 """user=models.ForeignKey(User,on_delete=models.CASCADE,blank=True,related_name='blogs')title=models.CharField(max_length=200)# 博客标题subdomain=models.SlugField(max_length=100,unique=True,db_index=True)# 子域名domain=models.CharField(max_length=128,blank=True,null=True,db_index=True)# 自定义域名content=models.TextField(blank=True,default='Hello World!')# 博客主页内容meta_description=models.CharField(blank=True,max_length=200)# SEO描述reviewed=models.BooleanField(db_index=True,default=False)# 审核状态hidden=models.BooleanField(db_index=True,default=False)# 隐藏状态# 样式和配置custom_styles=models.TextField(blank=True)# 自定义CSSnav=models.TextField(blank=True,default='[Home](/) [Blog](/blog/)')# 导航菜单# 高级设置robots_txt=models.TextField(blank=True,default='User-agent: *\nAllow: /')date_format=models.CharField(blank=True,default='d M, Y',max_length=32)analytics_active=models.BooleanField(default=True)# 分析功能开关classMeta:indexes=[models.Index(fields=['subdomain']),models.Index(fields=['domain']),models.Index(fields=['reviewed']),models.Index(fields=['hidden']),]def__str__(self):returnf'{self.title}({self.subdomain})'2. 文章模型
# blogs/models.py - Post模型核心部分classPost(models.Model):""" 文章数据模型,存储博客文章的所有信息 """blog=models.ForeignKey(Blog,on_delete=models.CASCADE,related_name='posts')title=models.CharField(max_length=200,db_index=True)# 文章标题slug=models.CharField(max_length=200,db_index=True)# URL标识content=models.TextField()# 文章内容(Markdown格式)# 发布状态publish=models.BooleanField(db_index=True,default=True)# 是否发布published_date=models.DateTimeField(blank=True,db_index=True)# 发布日期first_published_at=models.DateTimeField(blank=True,db_index=True,null=True)# 首次发布日期# SEO和元数据meta_description=models.CharField(max_length=200,blank=True)meta_image=models.CharField(max_length=200,blank=True)lang=models.CharField(blank=True,db_index=True,max_length=10)# 语言设置# 文章设置is_page=models.BooleanField(db_index=True,default=False)# 是否独立页面hidden=models.BooleanField(db_index=True,default=False)# 是否隐藏make_discoverable=models.BooleanField(db_index=True,default=True)# 是否可被发现# 互动数据upvotes=models.IntegerField(db_index=True,default=0)# 点赞数shadow_votes=models.IntegerField(db_index=True,default=0)# 影子投票数classMeta:ordering=['-published_date']indexes=[models.Index(fields=['blog','publish','published_date']),models.Index(fields=['publish','published_date']),models.Index(fields=['slug']),]def__str__(self):returnself.title3. 访问统计中间件
# blogs/middleware.py - 请求性能监控中间件classRequestPerformanceMiddleware:""" 请求性能监控中间件,记录API响应时间和数据库查询性能 """def__init__(self,get_response):self.get_response=get_response self.skip_methods={'HEAD','OPTIONS'}self.max_metrics=50deftrack_db_time(self):""" 跟踪数据库查询时间的上下文管理器 """_local.db_time=0.0defexecute_wrapper(execute,sql,params,many,context):start=time.time()try:returnexecute(sql,params,many,context)finally:_local.db_time+=time.time()-startwithconnection.execute_wrapper(execute_wrapper):yielddef__call__(self,request):""" 处理每个请求的性能监控 """# 跳过不需要监控的请求方法ifrequest.methodinself.skip_methods:returnself.get_response(request)# 开始性能跟踪start_time=time.time()# 跟踪数据库查询时间withself.track_db_time():response=self.get_response(request)# 计算性能指标total_time=time.time()-start_time db_time=getattr(_local,'db_time',0.0)# 记录性能数据到Redisifredis_client:pattern_name=self.get_pattern_name(request)ifpattern_name:metric_key=f"perf:{pattern_name}"metric_data={'total_time':total_time,'db_time':db_time,'timestamp':time.time()}redis_client.lpush(metric_key,json.dumps(metric_data))redis_client.ltrim(metric_key,0,self.max_metrics-1)returnresponse4. Markdown处理引擎
# blogs/templatetags/custom_tags.py - Markdown渲染器defmarkdown(text,blog=None,post=None):""" 自定义Markdown渲染函数,支持扩展语法和安全性过滤 """# 创建自定义渲染器classBearRenderer(HTMLRenderer):def__init__(self,**kwargs):super().__init__(**kwargs)defblock_code(self,code,lang=None):""" 处理代码块,支持语法高亮 """ifnotlang:returnf'<pre><code>{escape(code)}</code></pre>'try:lexer=get_lexer_by_name(lang,stripall=True)formatter=HtmlFormatter()returnhighlight(code,lexer,formatter)except:returnf'<pre><code>{escape(code)}</code></pre>'deflink(self,link,text=None,title=None):""" 安全地处理链接,防止XSS攻击 """iftextisNone:text=link# 验证链接安全性ifnotis_safe_url(link):returnescape(text)# 构建安全的链接标签result=f'<a href="{escape(link)}"'iftitle:result+=f' title="{escape(title)}"'result+=f'>{escape(text)}</a>'returnresult# 创建Markdown处理器md=create_markdown(renderer=BearRenderer(escape=False),plugins=['strikethrough','footnotes','table','url'])# 应用排版替换text=typographic_replacements(text)# 处理内嵌LaTeX数学公式text=replace_inline_latex(text)# 渲染Markdownreturnmd(text)5. 订阅管理视图
# blogs/views/emailer.py - 邮件订阅管理@csrf_exemptdefemail_subscribe(request):""" 处理邮件订阅请求,包含防垃圾邮件机制 """ifis_dodgy(request):returnHttpResponse("检测到可疑请求,请稍后重试。")# 解析请求地址对应的博客blog=resolve_address(request)ifnotblog:returnnot_found(request)ifrequest.method=="POST":email=request.POST.get("email")# 验证邮箱格式match=re.match(r'^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$',email)ifnotmatch:returnHttpResponse("邮箱地址格式不正确。")# 防止频繁订阅攻击recent_subscriptions=Subscriber.objects.filter(blog=blog,subscribed_date__gt=timezone.now()-timezone.timedelta(minutes=2)).count()ifrecent_subscriptions>10:returnHttpResponse("订阅过于频繁,请稍后再试。")# 创建或获取订阅者subscriber,created=Subscriber.objects.get_or_create(blog=blog,email_address=email)ifcreated:returnHttpResponse("订阅成功!")else:returnHttpResponse("您已经订阅过了。")returnHttpResponse("请求错误。")defis_dodgy(request):""" 检测可疑订阅请求(反垃圾邮件机制) """# 检查隐藏字段(蜜罐)ifrequest.POST.get("name"):returnTrue# 验证确认码ifrequest.POST.get("confirm")!="829389c2a9f0402b8a3600e52f2ad4e1":returnTrue# 检查邮件域名黑名单spam_domains=['@cleardex.io','@example.com']email=request.POST.get('email','')ifany(email.endswith(domain)fordomaininspam_domains):returnTruereturnFalse6. RSS订阅生成器
# blogs/views/feed.py - RSS/Atom订阅生成defgenerate_feed(blog,feed_type="atom",tag=None,page=0):""" 为博客生成RSS或Atom订阅源 """# 获取符合条件的文章all_posts=blog.posts.filter(publish=True,is_page=False,published_date__lte=timezone.now()).order_by('-published_date')# 按标签过滤iftag:all_posts=all_posts.filter(all_tags__icontains=tag)all_posts=[postforpostinall_postsiftaginpost.tags]# 分页处理first_post=page*10last_post=page*10+10all_posts=all_posts[first_post:last_post]all_posts=list(all_posts)[::-1]# 反转顺序# 创建Feed生成器fg=FeedGenerator()fg.id(blog.useful_domain)fg.author({'name':blog.subdomain,'email':'hidden'})fg.title(blog.title)fg.subtitle(blog.meta_descriptionorunmark(blog.content)[:157]+'...'orblog.title)fg.link(href=f"{blog.useful_domain}/",rel='alternate')# 添加文章条目forpostinall_posts:fe=fg.add_entry()fe.id(f"{blog.useful_domain}/{post.slug}/")fe.title(clean_string(post.title))fe.author({'name':blog.subdomain,'email':'hidden'})fe.link(href=f"{blog.useful_domain}/{post.slug}/")ifpost.meta_description:fe.summary(clean_string(post.meta_description))# 处理文章内容post_content=post.content.replace('{{ email-signup }}','')fe.content(clean_string(markdown(post_content,blog,post)),type="html")fe.published(post.published_date)fe.updated(post.last_modified)# 添加标签分类fortaginpost.tags:fe.category(term=tag)# 生成对应格式的订阅源iffeed_type=="atom":fg.link(href=f"{blog.useful_domain}/feed/",rel='self')returnfg.atom_str(pretty=True)eliffeed_type=="rss":fg.link(href=f"{blog.useful_domain}/feed/?type=rss",rel='self',type='application/rss+xml')fg.link(href=f"{blog.useful_domain}",rel='self')returnfg.rss_str(pretty=True)defclean_string(s):""" 清理字符串中的无效XML字符 """s=re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]','',s)s=re.sub(r'[\uFFFE\uFFFF\uFDD0-\uFDEF]','',s)returns这些核心代码展示了Bear Blog平台的关键功能实现,包括数据模型设计、性能优化、内容渲染和订阅管理等重要组件。平台采用Django框架构建,注重代码质量和性能表现,为博客作者提供稳定可靠的服务基础。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)