├── .gitignore ├── LICENSE ├── README.md ├── apps ├── __init__.py ├── about │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── account │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── blog │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── comment │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── homepage │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── interest │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── photo │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py └── ueditor │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── loonblog ├── __init__.py ├── urls.py └── wsgi.py ├── manage.py ├── requirement ├── common.txt ├── dev.txt ├── pro.txt └── test.txt ├── services ├── __init__.py ├── about │ ├── __init__.py │ └── about_service.py ├── base_service.py ├── blog │ ├── __init__.py │ ├── blog_service.py │ ├── blog_tag_service.py │ ├── category_service.py │ ├── tag_service.py │ └── topic_service.py ├── comment │ ├── __init__.py │ └── comment_service.py └── common │ ├── __init__.py │ ├── auto_log_service.py │ ├── context_processors.py │ ├── ip_service.py │ └── msg_service.py ├── settings ├── __init__.py ├── common.py ├── dev.py └── test.py ├── static ├── css │ ├── about.css │ ├── base.css │ ├── blog.css │ ├── bootstrap-multiselect.css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap-theme.min.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── dataTables.bootstrap.css │ ├── dataTables.bootstrap.min.css │ ├── index.css │ ├── jquery.dataTables.css │ └── jquery.dataTables.min.css ├── fonts │ ├── Arial.ttf │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── image │ ├── LOGO.png │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-icon.png │ ├── davatar.png │ ├── favicon.ico │ └── s_icon.png ├── images │ ├── Sorting icons.psd │ ├── blogedit.png │ ├── bloglist.png │ ├── favicon.ico │ ├── homepage.png │ ├── sort_asc.png │ ├── sort_asc_disabled.png │ ├── sort_both.png │ ├── sort_desc.png │ └── sort_desc_disabled.png ├── js │ ├── bootstrap-multiselect.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── dataTables.bootstrap.js │ ├── dataTables.bootstrap.min.js │ ├── jquery-3.2.1.min.js │ ├── jquery.dataTables.js │ ├── jquery.dataTables.min.js │ ├── jquery.validate.min.js │ ├── loonapp.js │ ├── npm.js │ ├── placeholder.js │ └── syntaxhighlighter_autoloads.js ├── syntaxhighlighter │ ├── css │ │ ├── shCore.css │ │ ├── shCoreDefault.css │ │ ├── shCoreDjango.css │ │ ├── shCoreEclipse.css │ │ ├── shCoreEmacs.css │ │ ├── shCoreFadeToGrey.css │ │ ├── shCoreMDUltra.css │ │ ├── shCoreMidnight.css │ │ ├── shCoreRDark.css │ │ ├── shThemeDefault.css │ │ ├── shThemeDjango.css │ │ ├── shThemeEclipse.css │ │ ├── shThemeEmacs.css │ │ ├── shThemeFadeToGrey.css │ │ ├── shThemeMDUltra.css │ │ ├── shThemeMidnight.css │ │ └── shThemeRDark.css │ └── js │ │ ├── XRegExp.js │ │ ├── shAutoloader.js │ │ ├── shBrushAS3.js │ │ ├── shBrushAppleScript.js │ │ ├── shBrushBash.js │ │ ├── shBrushCSharp.js │ │ ├── shBrushColdFusion.js │ │ ├── shBrushCpp.js │ │ ├── shBrushCss.js │ │ ├── shBrushDelphi.js │ │ ├── shBrushDiff.js │ │ ├── shBrushErlang.js │ │ ├── shBrushGroovy.js │ │ ├── shBrushHaxe.js │ │ ├── shBrushJScript.js │ │ ├── shBrushJava.js │ │ ├── shBrushJavaFX.js │ │ ├── shBrushPerl.js │ │ ├── shBrushPhp.js │ │ ├── shBrushPlain.js │ │ ├── shBrushPowerShell.js │ │ ├── shBrushPython.js │ │ ├── shBrushRuby.js │ │ ├── shBrushSass.js │ │ ├── shBrushScala.js │ │ ├── shBrushSql.js │ │ ├── shBrushVb.js │ │ ├── shBrushXml.js │ │ ├── shCore.js │ │ └── shLegacy.js └── ueditor │ ├── dialogs │ ├── anchor │ │ └── anchor.html │ ├── attachment │ │ ├── attachment.css │ │ ├── attachment.html │ │ ├── attachment.js │ │ ├── fileTypeImages │ │ │ ├── icon_chm.gif │ │ │ ├── icon_default.png │ │ │ ├── icon_doc.gif │ │ │ ├── icon_exe.gif │ │ │ ├── icon_jpg.gif │ │ │ ├── icon_mp3.gif │ │ │ ├── icon_mv.gif │ │ │ ├── icon_pdf.gif │ │ │ ├── icon_ppt.gif │ │ │ ├── icon_psd.gif │ │ │ ├── icon_rar.gif │ │ │ ├── icon_txt.gif │ │ │ └── icon_xls.gif │ │ └── images │ │ │ ├── alignicon.gif │ │ │ ├── alignicon.png │ │ │ ├── bg.png │ │ │ ├── file-icons.gif │ │ │ ├── file-icons.png │ │ │ ├── icons.gif │ │ │ ├── icons.png │ │ │ ├── image.png │ │ │ ├── progress.png │ │ │ ├── success.gif │ │ │ └── success.png │ ├── background │ │ ├── background.css │ │ ├── background.html │ │ ├── background.js │ │ └── images │ │ │ ├── bg.png │ │ │ └── success.png │ ├── charts │ │ ├── chart.config.js │ │ ├── charts.css │ │ ├── charts.html │ │ ├── charts.js │ │ └── images │ │ │ ├── charts0.png │ │ │ ├── charts1.png │ │ │ ├── charts2.png │ │ │ ├── charts3.png │ │ │ ├── charts4.png │ │ │ └── charts5.png │ ├── emotion │ │ ├── emotion.css │ │ ├── emotion.html │ │ ├── emotion.js │ │ └── images │ │ │ ├── 0.gif │ │ │ ├── bface.gif │ │ │ ├── cface.gif │ │ │ ├── fface.gif │ │ │ ├── jxface2.gif │ │ │ ├── neweditor-tab-bg.png │ │ │ ├── tface.gif │ │ │ ├── wface.gif │ │ │ └── yface.gif │ ├── gmap │ │ └── gmap.html │ ├── help │ │ ├── help.css │ │ ├── help.html │ │ └── help.js │ ├── image │ │ ├── image.css │ │ ├── image.html │ │ ├── image.js │ │ └── images │ │ │ ├── alignicon.jpg │ │ │ ├── bg.png │ │ │ ├── icons.gif │ │ │ ├── icons.png │ │ │ ├── image.png │ │ │ ├── progress.png │ │ │ ├── success.gif │ │ │ └── success.png │ ├── insertframe │ │ └── insertframe.html │ ├── internal.js │ ├── link │ │ └── link.html │ ├── map │ │ ├── map.html │ │ └── show.html │ ├── music │ │ ├── music.css │ │ ├── music.html │ │ └── music.js │ ├── preview │ │ └── preview.html │ ├── scrawl │ │ ├── images │ │ │ ├── addimg.png │ │ │ ├── brush.png │ │ │ ├── delimg.png │ │ │ ├── delimgH.png │ │ │ ├── empty.png │ │ │ ├── emptyH.png │ │ │ ├── eraser.png │ │ │ ├── redo.png │ │ │ ├── redoH.png │ │ │ ├── scale.png │ │ │ ├── scaleH.png │ │ │ ├── size.png │ │ │ ├── undo.png │ │ │ └── undoH.png │ │ ├── scrawl.css │ │ ├── scrawl.html │ │ └── scrawl.js │ ├── searchreplace │ │ ├── searchreplace.html │ │ └── searchreplace.js │ ├── snapscreen │ │ └── snapscreen.html │ ├── spechars │ │ ├── spechars.html │ │ └── spechars.js │ ├── table │ │ ├── dragicon.png │ │ ├── edittable.css │ │ ├── edittable.html │ │ ├── edittable.js │ │ ├── edittd.html │ │ └── edittip.html │ ├── template │ │ ├── config.js │ │ ├── images │ │ │ ├── bg.gif │ │ │ ├── pre0.png │ │ │ ├── pre1.png │ │ │ ├── pre2.png │ │ │ ├── pre3.png │ │ │ └── pre4.png │ │ ├── template.css │ │ ├── template.html │ │ └── template.js │ ├── video │ │ ├── images │ │ │ ├── bg.png │ │ │ ├── center_focus.jpg │ │ │ ├── file-icons.gif │ │ │ ├── file-icons.png │ │ │ ├── icons.gif │ │ │ ├── icons.png │ │ │ ├── image.png │ │ │ ├── left_focus.jpg │ │ │ ├── none_focus.jpg │ │ │ ├── progress.png │ │ │ ├── right_focus.jpg │ │ │ ├── success.gif │ │ │ └── success.png │ │ ├── video.css │ │ ├── video.html │ │ └── video.js │ ├── webapp │ │ └── webapp.html │ └── wordimage │ │ ├── fClipboard_ueditor.swf │ │ ├── imageUploader.swf │ │ ├── tangram.js │ │ ├── wordimage.html │ │ └── wordimage.js │ ├── index.html │ ├── lang │ ├── en │ │ ├── en.js │ │ └── images │ │ │ ├── addimage.png │ │ │ ├── alldeletebtnhoverskin.png │ │ │ ├── alldeletebtnupskin.png │ │ │ ├── background.png │ │ │ ├── button.png │ │ │ ├── copy.png │ │ │ ├── deletedisable.png │ │ │ ├── deleteenable.png │ │ │ ├── listbackground.png │ │ │ ├── localimage.png │ │ │ ├── music.png │ │ │ ├── rotateleftdisable.png │ │ │ ├── rotateleftenable.png │ │ │ ├── rotaterightdisable.png │ │ │ ├── rotaterightenable.png │ │ │ └── upload.png │ └── zh-cn │ │ ├── images │ │ ├── copy.png │ │ ├── localimage.png │ │ ├── music.png │ │ └── upload.png │ │ └── zh-cn.js │ ├── themes │ ├── default │ │ ├── css │ │ │ ├── ueditor.css │ │ │ └── ueditor.min.css │ │ ├── dialogbase.css │ │ └── images │ │ │ ├── anchor.gif │ │ │ ├── arrow.png │ │ │ ├── arrow_down.png │ │ │ ├── arrow_up.png │ │ │ ├── button-bg.gif │ │ │ ├── cancelbutton.gif │ │ │ ├── charts.png │ │ │ ├── cursor_h.gif │ │ │ ├── cursor_h.png │ │ │ ├── cursor_v.gif │ │ │ ├── cursor_v.png │ │ │ ├── dialog-title-bg.png │ │ │ ├── filescan.png │ │ │ ├── highlighted.gif │ │ │ ├── icons-all.gif │ │ │ ├── icons.gif │ │ │ ├── icons.png │ │ │ ├── loaderror.png │ │ │ ├── loading.gif │ │ │ ├── lock.gif │ │ │ ├── neweditor-tab-bg.png │ │ │ ├── pagebreak.gif │ │ │ ├── scale.png │ │ │ ├── sortable.png │ │ │ ├── spacer.gif │ │ │ ├── sparator_v.png │ │ │ ├── table-cell-align.png │ │ │ ├── tangram-colorpicker.png │ │ │ ├── toolbar_bg.png │ │ │ ├── unhighlighted.gif │ │ │ ├── upload.png │ │ │ ├── videologo.gif │ │ │ ├── word.gif │ │ │ └── wordpaste.png │ └── iframe.css │ ├── third-party │ ├── SyntaxHighlighter │ │ ├── shCore.js │ │ └── shCoreDefault.css │ ├── codemirror │ │ ├── codemirror.css │ │ └── codemirror.js │ ├── highcharts │ │ ├── adapters │ │ │ ├── mootools-adapter.js │ │ │ ├── mootools-adapter.src.js │ │ │ ├── prototype-adapter.js │ │ │ ├── prototype-adapter.src.js │ │ │ ├── standalone-framework.js │ │ │ └── standalone-framework.src.js │ │ ├── highcharts-more.js │ │ ├── highcharts-more.src.js │ │ ├── highcharts.js │ │ ├── highcharts.src.js │ │ ├── modules │ │ │ ├── annotations.js │ │ │ ├── annotations.src.js │ │ │ ├── canvas-tools.js │ │ │ ├── canvas-tools.src.js │ │ │ ├── data.js │ │ │ ├── data.src.js │ │ │ ├── drilldown.js │ │ │ ├── drilldown.src.js │ │ │ ├── exporting.js │ │ │ ├── exporting.src.js │ │ │ ├── funnel.js │ │ │ ├── funnel.src.js │ │ │ ├── heatmap.js │ │ │ ├── heatmap.src.js │ │ │ ├── map.js │ │ │ ├── map.src.js │ │ │ ├── no-data-to-display.js │ │ │ └── no-data-to-display.src.js │ │ └── themes │ │ │ ├── dark-blue.js │ │ │ ├── dark-green.js │ │ │ ├── gray.js │ │ │ ├── grid.js │ │ │ └── skies.js │ ├── jquery-1.10.2.js │ ├── jquery-1.10.2.min.js │ ├── jquery-1.10.2.min.map │ ├── snapscreen │ │ └── UEditorSnapscreen.exe │ ├── video-js │ │ ├── font │ │ │ ├── vjs.eot │ │ │ ├── vjs.svg │ │ │ ├── vjs.ttf │ │ │ └── vjs.woff │ │ ├── video-js.css │ │ ├── video-js.min.css │ │ ├── video-js.swf │ │ ├── video.dev.js │ │ └── video.js │ ├── webuploader │ │ ├── Uploader.swf │ │ ├── webuploader.css │ │ ├── webuploader.custom.js │ │ ├── webuploader.custom.min.js │ │ ├── webuploader.flashonly.js │ │ ├── webuploader.flashonly.min.js │ │ ├── webuploader.html5only.js │ │ ├── webuploader.html5only.min.js │ │ ├── webuploader.js │ │ ├── webuploader.min.js │ │ ├── webuploader.withoutimage.js │ │ └── webuploader.withoutimage.min.js │ ├── xss.min.js │ └── zeroclipboard │ │ ├── ZeroClipboard.js │ │ ├── ZeroClipboard.min.js │ │ └── ZeroClipboard.swf │ ├── ueditor.all.js │ ├── ueditor.all.min.js │ ├── ueditor.config.js │ ├── ueditor.parse.js │ └── ueditor.parse.min.js ├── templates ├── 403.html ├── 404.html ├── 500.html ├── about │ └── about.html ├── base.html ├── blog │ ├── blog_base.html │ ├── blog_edit.html │ ├── blog_index.html │ ├── blog_list.html │ ├── blog_view.html │ └── includes │ │ ├── blogbox.html │ │ ├── cmtdisplaybox.html │ │ ├── cmtformbox.html │ │ ├── paginator.html │ │ ├── replydisplaybox.html │ │ └── sidebar.html ├── index.html ├── interest │ └── index.html └── photo │ └── index.html └── uwsgi.ini /.gitignore: -------------------------------------------------------------------------------- 1 | /nohup.out 2 | *.pyc 3 | *.xml 4 | .idea 5 | .idea/* 6 | .idea/workspace.xml 7 | log/ 8 | settings/pro.py 9 | temp 10 | media/* 11 | os 12 | platform 13 | tests/*.json 14 | tests/cookies.pkl 15 | .DS_Store 16 | /.env 17 | venv/ 18 | .tags 19 | dump.rdb 20 | migrations/0* 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 blackholll 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # loonblog 2 | 基于django的个人博客系统 a blog base django 3 | 4 | ## 介绍 5 | - 本系统基于python(3.5)+ django(1.11.2)开发 6 | - 前端使用的是 http://www.dannysite.com/ 曾经的开源版本。 后端全部本人重写的 7 | - 项目demo见我的个人博客: http://www.loonapp.com 8 | - 欢迎访问我的个人博客 9 | ![首页](https://github.com/blackholll/loonblog/raw/master/static/images/homepage.png) 10 | ![文章列表](https://github.com/blackholll/loonblog/raw/master/static/images/bloglist.png) 11 | ![文章管理](https://github.com/blackholll/loonblog/raw/master/static/images/blogedit.png) 12 | 13 | 14 | 15 | ## 部署说明: 16 | - 目录结构说明 17 | 18 | apps: 功能模块列表,如博客、评论、图片、账号等等功能 19 | 20 | loonblog: 路由及wsgi配置 21 | 22 | media: 媒体文件,用于blog文章中的图片及附件保存路径 23 | 24 | requirement: 依赖说明,分为生产、开发、线上环境的依赖说明 25 | 26 | service: 服务层,具体的逻辑,与view分离 27 | 28 | settings: 配置文件,分为生产、开发、线上环境 29 | 30 | static: 静态文件 31 | 32 | templates: 模板文件 33 | 34 | - 安装依赖 35 | 1. 建议使用虚拟环境部署,请百度 virtualenv和virtualenvwrapper用法 36 | 2. 进入虚拟环境,cd到项目根目录,pip install -r requirement/pro.txt 37 | 38 | - 配置文件 39 | 1. 复制settings/dev.py为settings.pro,修改必要的配置,如DEBUG、MEDIA目录、数据库配置、日志文件路径等 40 | 41 | 42 | - 收集静态文件(本系统部分使用了django自带的admin后台的功能) 43 | 1. python manager collectstatic 44 | 45 | - 数据库初始化 46 | 1. python manage.py makemigrations 47 | 2. python manage.py migrate 48 | 49 | - 创建管理员账号 50 | 1. python manage.py creatsuperuser 51 | 52 | - 其他 53 | 1. 开发环境可以直接 python manager.py runserver 54 | 2. 线上环境建议使用nginx+uwsgi来部署.可参考 http://www.loonapp.com/blog/1/ 55 | 56 | ## 如何写博客 57 | 58 | - 登录管理员账号 59 | 1. 点击页面下方的"管理登录" 60 | 2. 使用上面创建的账号密码登录 61 | 62 | - 点击下方的"文章管理" 63 | 1. 注意:因为首页使用了缓存(默认5分钟),所以登录后还是显示的"管理登录"(这个后续会优化下),你可以登陆后访问系统首页,然后点击上方的"文章"后,页面下方就会出现"文章管理" 64 | 了 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/__init__.py -------------------------------------------------------------------------------- /apps/about/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/about/__init__.py -------------------------------------------------------------------------------- /apps/about/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/about/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AboutConfig(AppConfig): 5 | name = 'apps.about' 6 | -------------------------------------------------------------------------------- /apps/about/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/about/migrations/__init__.py -------------------------------------------------------------------------------- /apps/about/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | 5 | class AboutMe(models.Model): 6 | """ 7 | 关于我 8 | """ 9 | description = models.TextField('内容') 10 | 11 | creator = models.CharField('创建人', max_length=50) 12 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 13 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 14 | is_deleted = models.BooleanField('已删除', default=False) 15 | 16 | class AboutLoonapp(models.Model): 17 | """ 18 | 关于loonapp 19 | """ 20 | description = models.TextField('内容') 21 | 22 | creator = models.CharField('创建人', max_length=50) 23 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 24 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 25 | is_deleted = models.BooleanField('已删除', default=False) 26 | 27 | class AboutCopyright(models.Model): 28 | """ 29 | 关于版权 30 | """ 31 | description = models.TextField('内容') 32 | 33 | creator = models.CharField('创建人', max_length=50) 34 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 35 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 36 | is_deleted = models.BooleanField('已删除', default=False) 37 | 38 | -------------------------------------------------------------------------------- /apps/about/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/about/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.about import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | 7 | ] -------------------------------------------------------------------------------- /apps/about/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | from django.views.decorators.cache import cache_page 5 | 6 | from services.about.about_service import AboutService 7 | 8 | # @cache_page(300) 9 | def index(request): 10 | about_service_obj = AboutService() 11 | about_mes, msg = about_service_obj.get_about_me_list() 12 | about_loonapps, msg2 = about_service_obj.get_about_loonapp_list() 13 | about_copyrights, msg2 = about_service_obj.get_about_copyright_list() 14 | return render(request, 'about/about.html', dict(about_mes=about_mes, about_loonapps=about_loonapps, 15 | about_copyrights=about_copyrights)) 16 | -------------------------------------------------------------------------------- /apps/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/account/__init__.py -------------------------------------------------------------------------------- /apps/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.models import Group 3 | 4 | # Register your models here. 5 | 6 | 7 | admin.site.unregister(Group) 8 | -------------------------------------------------------------------------------- /apps/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | name = 'apps.account' 6 | -------------------------------------------------------------------------------- /apps/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/account/migrations/__init__.py -------------------------------------------------------------------------------- /apps/account/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.base_user import AbstractBaseUser,BaseUserManager 2 | from django.db import models 3 | 4 | # Create your models here. 5 | 6 | 7 | 8 | class MyUserManager(BaseUserManager): 9 | def create_user(self, email, username, password=None, dep=0): 10 | """ 11 | Creates and saves a User with the given email, date of 12 | birth and password. 13 | """ 14 | if not email: 15 | raise ValueError('Users must have an email address') 16 | 17 | user = self.model( 18 | username = username, 19 | email=self.normalize_email(email), 20 | 21 | ) 22 | 23 | user.set_password(password) 24 | user.save(using=self._db) 25 | return user 26 | 27 | def create_superuser(self, email, username,password): 28 | """ 29 | Creates and saves a superuser with the given email, date of 30 | birth and password. 31 | """ 32 | user = self.create_user( 33 | email=self.normalize_email(email), 34 | username=username, 35 | password=password, 36 | ) 37 | user.is_admin = True 38 | user.save(using=self._db) 39 | return user 40 | 41 | 42 | class MyUser(AbstractBaseUser): 43 | """ 44 | 用户模型 45 | """ 46 | username = models.CharField(u'用户名', max_length=20, unique=True) 47 | chinese_name = models.CharField(u'中文名',max_length=20) 48 | email = models.EmailField(u'邮箱', max_length=50, unique=True) 49 | 50 | is_staff = models.BooleanField(u'职员', default=True) 51 | is_active = models.BooleanField(u'激活', default=True) 52 | is_admin = models.BooleanField(u'管理员', default=False) 53 | objects = MyUserManager() 54 | 55 | USERNAME_FIELD = 'username' 56 | REQUIRED_FIELDS = ['email'] 57 | 58 | def get_chinese_name(self): 59 | # The user is identified by their email address 60 | return self.chinese_name 61 | 62 | def get_short_name(self): 63 | # The user is identified by their email address 64 | return self.chinese_name 65 | 66 | def get_username(self): 67 | # The user is identified by their email address 68 | return self.username 69 | 70 | def get_full_name(self): 71 | # The user is identified by their email address 72 | return self.chinese_name 73 | 74 | def has_perm(self, perm, obj=None): 75 | "Does the user have a specific permission?" 76 | # Simplest possible answer: Yes, always 77 | return True 78 | 79 | def has_module_perms(self, app_label): 80 | return True 81 | 82 | 83 | # On Python 3: def __str__(self): 84 | def __unicode__(self): 85 | return self.chinese_name 86 | 87 | 88 | -------------------------------------------------------------------------------- /apps/account/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/account/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /apps/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/blog/__init__.py -------------------------------------------------------------------------------- /apps/blog/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | from apps.blog.models import Topic, Category, Tag 5 | 6 | 7 | class TopicAdmin(admin.ModelAdmin): 8 | list_display = ('name', 'creator', 'gmt_created', 'is_deleted') 9 | search_fields = ('name',) 10 | fieldsets = ( 11 | (None, { 12 | 'fields': ('name', 'creator', 'gmt_created', 'gmt_modified', 'is_deleted') 13 | }),) 14 | 15 | def save_model(self, request, obj, form, change): 16 | obj.creator = request.user.username 17 | super(TopicAdmin, self).save_model(request, obj, form, change) 18 | 19 | def get_readonly_fields(self, request, obj=None): 20 | return ['gmt_created', 'gmt_modified', 'creator'] 21 | 22 | 23 | class CategoryAdmin(admin.ModelAdmin): 24 | list_display = ('name', 'creator', 'gmt_created', 'is_deleted') 25 | search_fields = ('name',) 26 | fieldsets = ( 27 | (None, { 28 | 'fields': ('name', 'creator', 'gmt_created', 'gmt_modified', 'is_deleted') 29 | }),) 30 | 31 | def save_model(self, request, obj, form, change): 32 | obj.creator = request.user.username 33 | super(CategoryAdmin, self).save_model(request, obj, form, change) 34 | 35 | def get_readonly_fields(self, request, obj=None): 36 | return ['gmt_created', 'gmt_modified', 'creator'] 37 | 38 | 39 | class TagAdmin(admin.ModelAdmin): 40 | list_display = ('name', 'creator', 'gmt_created', 'is_deleted') 41 | search_fields = ('name',) 42 | fieldsets = ( 43 | (None, { 44 | 'fields': ('name', 'creator', 'gmt_created', 'gmt_modified', 'is_deleted') 45 | }),) 46 | 47 | def save_model(self, request, obj, form, change): 48 | obj.creator = request.user.username 49 | super(TagAdmin, self).save_model(request, obj, form, change) 50 | 51 | def get_readonly_fields(self, request, obj=None): 52 | return ['gmt_created', 'gmt_modified', 'creator'] 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | admin.site.register(Topic, TopicAdmin) 61 | admin.site.register(Category, CategoryAdmin) 62 | admin.site.register(Tag, TagAdmin) 63 | 64 | -------------------------------------------------------------------------------- /apps/blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | name = 'apps.blog' 6 | -------------------------------------------------------------------------------- /apps/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/blog/migrations/__init__.py -------------------------------------------------------------------------------- /apps/blog/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | 5 | 6 | class Topic(models.Model): 7 | """ 8 | 专题 9 | """ 10 | name = models.CharField('名称', max_length=50) 11 | 12 | creator = models.CharField('创建人', max_length=50) 13 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 14 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 15 | is_deleted = models.BooleanField('已删除', default=False) 16 | 17 | class Meta: 18 | verbose_name = '专题' 19 | verbose_name_plural = '专题' 20 | 21 | 22 | 23 | class Category(models.Model): 24 | """ 25 | 分类 26 | """ 27 | name = models.CharField('名称', max_length=50) 28 | 29 | creator = models.CharField('创建人', max_length=50) 30 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 31 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 32 | is_deleted = models.BooleanField('已删除', default=False) 33 | 34 | class Meta: 35 | verbose_name = '分类' 36 | verbose_name_plural = '分类' 37 | 38 | 39 | 40 | class Tag(models.Model): 41 | """ 42 | 标签 43 | """ 44 | name = models.CharField('名称', max_length=50) 45 | 46 | creator = models.CharField('创建人', max_length=50) 47 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 48 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 49 | is_deleted = models.BooleanField('已删除', default=False) 50 | 51 | class Meta: 52 | verbose_name = '标签' 53 | verbose_name_plural = '标签' 54 | 55 | 56 | class Blog(models.Model): 57 | """ 58 | 博客 59 | """ 60 | title = models.CharField('名称', max_length=500) 61 | topic_id = models.IntegerField('主题id', null=True, blank=True) 62 | category_id = models.IntegerField('分类id') 63 | view_count = models.IntegerField('访问次数', default=0) # 非实时更新,请求次数写入redis。 当redis值大于10时候再更新数据库 64 | 65 | content = models.TextField('内容') 66 | creator = models.CharField('创建人', max_length=50) 67 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 68 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 69 | is_deleted = models.BooleanField('已删除', default=False) 70 | 71 | 72 | class BlogTag(models.Model): 73 | """ 74 | 博客标签 75 | """ 76 | blog_id = models.IntegerField('博客id') 77 | tag_id = models.IntegerField('标签id') 78 | 79 | creator = models.CharField('创建人', max_length=50) 80 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 81 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 82 | is_deleted = models.BooleanField('已删除', default=False) 83 | -------------------------------------------------------------------------------- /apps/blog/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/blog/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.blog import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | url(r'^(\d+)/$', views.blog_view, name='blog_view'), 7 | url(r'^list/$', views.blog_list, name='list'), 8 | url(r'^add/$', views.blog_add, name='add'), 9 | url(r'^get_json_list/$', views.get_json_list, name="get_json_list"), 10 | url(r'^edit/(\d+)/$', views.blog_edit, name="edit"), 11 | 12 | ] -------------------------------------------------------------------------------- /apps/comment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/comment/__init__.py -------------------------------------------------------------------------------- /apps/comment/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/comment/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CommentConfig(AppConfig): 5 | name = 'apps.comment' 6 | -------------------------------------------------------------------------------- /apps/comment/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/comment/migrations/__init__.py -------------------------------------------------------------------------------- /apps/comment/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | 5 | 6 | class Comment(models.Model): 7 | """ 8 | 评论 9 | """ 10 | obj_type_id = models.IntegerField('对象类别') # 1.博客 2.评论 11 | obj_id = models.IntegerField('对象id') 12 | username = models.CharField('用户名', max_length=50, null=True, blank=True) 13 | name = models.CharField('姓名', max_length=50, null=True, blank=True) 14 | email = models.EmailField('邮箱', null=True, blank=True) 15 | content = models.TextField('内容') 16 | source_ip = models.CharField('来源ip', max_length=20) 17 | 18 | creator = models.CharField('创建人', max_length=50) 19 | gmt_created = models.DateTimeField('创建时间', auto_now_add=True, help_text="") 20 | gmt_modified = models.DateTimeField('修改时间', auto_now=True, help_text="") 21 | is_deleted = models.BooleanField('已删除', default=False) 22 | 23 | def get_replys(self): 24 | """ 25 | 评论的回复 26 | :return: 27 | """ 28 | return Comment.objects.filter(obj_type_id=2, obj_id=self.id, is_deleted=False) 29 | -------------------------------------------------------------------------------- /apps/comment/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/comment/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.comment import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | url(r'^captcha/$', views.captcha, name='captcha'), 7 | url(r'^(\d+)/$', views.comment, name='comment'), 8 | 9 | ] -------------------------------------------------------------------------------- /apps/homepage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/homepage/__init__.py -------------------------------------------------------------------------------- /apps/homepage/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/homepage/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class HomepageConfig(AppConfig): 5 | name = 'apps.homepage' 6 | -------------------------------------------------------------------------------- /apps/homepage/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/homepage/migrations/__init__.py -------------------------------------------------------------------------------- /apps/homepage/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /apps/homepage/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/homepage/urls.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/homepage/urls.py -------------------------------------------------------------------------------- /apps/homepage/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | from django.views.decorators.cache import cache_page 5 | 6 | from services.blog.blog_service import BlogService 7 | from services.blog.category_service import CategoryService 8 | 9 | # @cache_page(300) 10 | def index(request): 11 | """ 12 | 首页- 13 | :param request: 14 | :return: 15 | """ 16 | top_categorys, msg = CategoryService.get_top_category() 17 | new_blogs, msg1 = BlogService.get_new_blog() 18 | hot_blogs, msg2 = BlogService.get_hot_blog() 19 | params = dict(top_categorys=top_categorys, new_blogs=new_blogs, hot_blogs=hot_blogs) 20 | return render(request, 'index.html', params) 21 | -------------------------------------------------------------------------------- /apps/interest/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/interest/__init__.py -------------------------------------------------------------------------------- /apps/interest/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/interest/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class InterestConfig(AppConfig): 5 | name = 'apps.interest' 6 | -------------------------------------------------------------------------------- /apps/interest/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/interest/migrations/__init__.py -------------------------------------------------------------------------------- /apps/interest/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /apps/interest/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/interest/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.interest import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | 7 | ] -------------------------------------------------------------------------------- /apps/interest/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | from django.views.decorators.cache import cache_page 5 | 6 | from services.about.about_service import AboutService 7 | 8 | @cache_page(300) 9 | def index(request): 10 | return render(request, 'interest/index.html') 11 | -------------------------------------------------------------------------------- /apps/photo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/photo/__init__.py -------------------------------------------------------------------------------- /apps/photo/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/photo/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PhotoConfig(AppConfig): 5 | name = 'apps.photo' 6 | -------------------------------------------------------------------------------- /apps/photo/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/photo/migrations/__init__.py -------------------------------------------------------------------------------- /apps/photo/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /apps/photo/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/photo/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.photo import views 3 | 4 | urlpatterns = [ 5 | url(r'^$', views.index, name='index'), 6 | 7 | ] -------------------------------------------------------------------------------- /apps/photo/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | 5 | from django.shortcuts import render 6 | 7 | # Create your views here. 8 | from django.views.decorators.cache import cache_page 9 | 10 | from services.about.about_service import AboutService 11 | 12 | @cache_page(300) 13 | def index(request): 14 | return render(request, 'photo/index.html') 15 | -------------------------------------------------------------------------------- /apps/ueditor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/ueditor/__init__.py -------------------------------------------------------------------------------- /apps/ueditor/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /apps/ueditor/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UeditorConfig(AppConfig): 5 | name = 'apps.ueditor' 6 | -------------------------------------------------------------------------------- /apps/ueditor/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/apps/ueditor/migrations/__init__.py -------------------------------------------------------------------------------- /apps/ueditor/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /apps/ueditor/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /apps/ueditor/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls import url 2 | from apps.ueditor.views import ueditor_index,ueditor_ImgUp, ueditor_FileUp 3 | 4 | 5 | urlpatterns = [ 6 | url(r'^$', ueditor_index), 7 | url(r'^ueditor_imgup/$', ueditor_ImgUp), 8 | url(r'^ueditor_fileup/$', ueditor_FileUp), 9 | ] 10 | -------------------------------------------------------------------------------- /loonblog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/loonblog/__init__.py -------------------------------------------------------------------------------- /loonblog/urls.py: -------------------------------------------------------------------------------- 1 | """loonblog URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import url, include 17 | from django.contrib import admin 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | from apps.homepage.views import index 21 | from apps.blog import urls as blog_urls 22 | from apps.ueditor import urls as ueditor_urls 23 | from apps.comment import urls as comment_urls 24 | from apps.about import urls as about_urls 25 | from apps.photo import urls as photo_urls 26 | from apps.interest import urls as interest_urls 27 | 28 | 29 | urlpatterns = [ 30 | url(r'^admin/', admin.site.urls), 31 | url(r'^$', index), 32 | url(r'^blog/', include(blog_urls, namespace="blog")), 33 | url(r'^ueditor/', include(ueditor_urls, namespace="ueditor")), 34 | url(r'^comment/', include(comment_urls, namespace="comment")), 35 | url(r'^about/', include(about_urls, namespace="about")), 36 | url(r'^photo/', include(photo_urls, namespace="photo")), 37 | url(r'^interest/', include(interest_urls, namespace="interest")), 38 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 39 | -------------------------------------------------------------------------------- /loonblog/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for loonblog project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.pro") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | 6 | if __name__ == "__main__": 7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.dev") 8 | try: 9 | from django.core.management import execute_from_command_line 10 | except ImportError: 11 | # The above import may fail for some other reason. Ensure that the 12 | # issue is really that Django is missing to avoid masking other 13 | # exceptions on Python 2. 14 | try: 15 | import django 16 | except ImportError: 17 | raise ImportError( 18 | "Couldn't import Django. Are you sure it's installed and " 19 | "available on your PYTHONPATH environment variable? Did you " 20 | "forget to activate a virtual environment?" 21 | ) 22 | raise 23 | execute_from_command_line(sys.argv) 24 | -------------------------------------------------------------------------------- /requirement/common.txt: -------------------------------------------------------------------------------- 1 | #python==3.5.3 2 | image==1.5.5 3 | django==1.11.2 4 | redis==2.10.5 5 | django-redis-cache==1.7.1 6 | mysqlclient==1.3.10 7 | django-widget-tweaks==1.4.1 8 | -------------------------------------------------------------------------------- /requirement/dev.txt: -------------------------------------------------------------------------------- 1 | #requirements/dev.txt 2 | -r common.txt -------------------------------------------------------------------------------- /requirement/pro.txt: -------------------------------------------------------------------------------- 1 | #requirements/pro.txt 2 | -r common.txt -------------------------------------------------------------------------------- /requirement/test.txt: -------------------------------------------------------------------------------- 1 | #requirements/test.txt 2 | -r common.txt -------------------------------------------------------------------------------- /services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/services/__init__.py -------------------------------------------------------------------------------- /services/about/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/services/about/__init__.py -------------------------------------------------------------------------------- /services/about/about_service.py: -------------------------------------------------------------------------------- 1 | from apps.about.models import AboutMe, AboutLoonapp, AboutCopyright 2 | from services.base_service import BaseService 3 | from services.common.auto_log_service import auto_log 4 | 5 | 6 | class AboutService(BaseService): 7 | def __init__(self): 8 | pass 9 | 10 | @staticmethod 11 | @auto_log 12 | def get_about_me_list(): 13 | """关于我""" 14 | return AboutMe.objects.filter(is_deleted=False), '' 15 | 16 | @staticmethod 17 | @auto_log 18 | def get_about_loonapp_list(): 19 | """关于lonnapp""" 20 | return AboutLoonapp.objects.filter(is_deleted=False), '' 21 | 22 | @staticmethod 23 | @auto_log 24 | def get_about_copyright_list(): 25 | """关于""" 26 | return AboutCopyright.objects.filter(is_deleted=False), '' 27 | -------------------------------------------------------------------------------- /services/base_service.py: -------------------------------------------------------------------------------- 1 | 2 | class BaseService(object): 3 | """ 4 | 基础service 5 | """ 6 | def __init__(self): 7 | pass 8 | -------------------------------------------------------------------------------- /services/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/services/blog/__init__.py -------------------------------------------------------------------------------- /services/blog/blog_tag_service.py: -------------------------------------------------------------------------------- 1 | from apps.blog.models import BlogTag 2 | from services.base_service import BaseService 3 | from services.blog.tag_service import TagService 4 | from services.common.auto_log_service import auto_log 5 | 6 | 7 | class BlogTagService(BaseService): 8 | """ 9 | 标签service 10 | """ 11 | 12 | def __init__(self): 13 | pass 14 | 15 | @staticmethod 16 | @auto_log 17 | def get_tags_by_blog_id(blog_id): 18 | """ 19 | 获取文章的标签信息 20 | :param blog_id: 21 | :return: 22 | """ 23 | 24 | tag_list = [] 25 | tag_query = BlogTag.objects.filter(blog_id=blog_id) 26 | for tag_query0 in tag_query: 27 | tag_id = tag_query0.tag_id 28 | taginfo, msg = TagService.get_tag_by_id(tag_id) 29 | tag_name = taginfo[0].name 30 | tag_list.append(tag_name) 31 | return ','.join(tag_list), '' 32 | 33 | @staticmethod 34 | @auto_log 35 | def get_tag_list_by_blog_id(blog_id): 36 | """ 37 | 获取文章标签列表 38 | :param blog_id: 39 | :return: 40 | """ 41 | tag_list = [] 42 | tag_query = BlogTag.objects.filter(blog_id=blog_id) 43 | for tag_query0 in tag_query: 44 | tag_id = tag_query0.tag_id 45 | tag_info, msg = TagService.get_tag_by_id(tag_id) 46 | tag_id = tag_info[0].id 47 | tag_list.append(tag_id) 48 | return tag_list, '' 49 | 50 | @staticmethod 51 | @auto_log 52 | def get_tag_obj_list_by_blog_id(blog_id): 53 | """ 54 | 获取文章标签对象列表 55 | :param blog_id: 56 | :return: 57 | """ 58 | tag_query = BlogTag.objects.raw('select *, b.name as tag_name from blog_blogtag a join blog_tag b on ' 59 | 'a.`tag_id`=b.`id` where a.is_deleted=0 and a.blog_id= {}'.format(blog_id)) 60 | 61 | return tag_query, '' 62 | 63 | -------------------------------------------------------------------------------- /services/blog/category_service.py: -------------------------------------------------------------------------------- 1 | from apps.blog.models import Category 2 | from services.base_service import BaseService 3 | from services.common.auto_log_service import auto_log 4 | 5 | 6 | class CategoryService(BaseService): 7 | """ 8 | 分类service 9 | """ 10 | def __init__(self): 11 | pass 12 | 13 | @staticmethod 14 | @auto_log 15 | def get_category_list(): 16 | """ 17 | 获取分类列表 18 | :return: 19 | """ 20 | return Category.objects.filter(is_deleted=False), '' 21 | 22 | @staticmethod 23 | @auto_log 24 | def get_category_by_id(id): 25 | """ 26 | 获取分类信息 27 | :param id: 28 | :return: 29 | """ 30 | return Category.objects.filter(id=id), '' 31 | 32 | @staticmethod 33 | @auto_log 34 | def get_top_category(top=5): 35 | """ 36 | 获取具有数量最多blog的前top分类 37 | :return: 38 | """ 39 | result = Category.objects.raw("select b.id, b.name, count(*) as count from blog_blog a join blog_category b on a.`category_id`=b.id group by(category_id)") 40 | return result[:top], '' 41 | -------------------------------------------------------------------------------- /services/blog/tag_service.py: -------------------------------------------------------------------------------- 1 | from apps.blog.models import Tag 2 | from services.base_service import BaseService 3 | from services.common.auto_log_service import auto_log 4 | 5 | 6 | class TagService(BaseService): 7 | """ 8 | 标签service 9 | """ 10 | 11 | def __init__(self): 12 | pass 13 | 14 | @staticmethod 15 | @auto_log 16 | def get_tag_list(): 17 | """ 18 | 获取标签列表 19 | :return: 20 | """ 21 | return Tag.objects.filter(is_deleted=False), '' 22 | 23 | @staticmethod 24 | @auto_log 25 | def get_tag_by_id(id): 26 | """ 27 | 获取标签信息 28 | :param id: 29 | :return: 30 | """ 31 | return Tag.objects.filter(id=id), '' 32 | -------------------------------------------------------------------------------- /services/blog/topic_service.py: -------------------------------------------------------------------------------- 1 | from apps.blog.models import Topic 2 | from services.base_service import BaseService 3 | from services.common.auto_log_service import auto_log 4 | 5 | 6 | class TopicService(BaseService): 7 | """ 8 | 专题service 9 | """ 10 | 11 | def __init__(self): 12 | pass 13 | 14 | @staticmethod 15 | @auto_log 16 | def get_topic_list(): 17 | """ 18 | 获取主题列表 19 | :return: 20 | """ 21 | return Topic.objects.filter(is_deleted=False), '' 22 | 23 | @staticmethod 24 | @auto_log 25 | def get_topic_by_id(id): 26 | """ 27 | 获取主题信息 28 | :param id: 29 | :return: 30 | """ 31 | return Topic.objects.filter(id=id), '' 32 | -------------------------------------------------------------------------------- /services/comment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/services/comment/__init__.py -------------------------------------------------------------------------------- /services/comment/comment_service.py: -------------------------------------------------------------------------------- 1 | from services.base_service import BaseService 2 | from services.common.auto_log_service import auto_log 3 | from apps.comment.models import Comment 4 | from services.common.msg_service import MsgService 5 | import logging 6 | logger = logging.getLogger('default') 7 | 8 | 9 | class CommentService(BaseService): 10 | def __init__(self): 11 | pass 12 | 13 | @staticmethod 14 | @auto_log 15 | def get_comment_count_by_blog_id(obj_id, obj_type_id=1): 16 | """ 17 | 获取评论个数 18 | :param obj_id: 评论对象 19 | :param obj_type_id: 评论对象类别 #1.博客 2. 20 | :return: 21 | """ 22 | return Comment.objects.filter(obj_id=obj_id, obj_type_id=obj_type_id).count(), '' 23 | 24 | @staticmethod 25 | @auto_log 26 | def add_comment(kwargs): 27 | """ 28 | 新增评论 29 | :param kwargs: 30 | :return: 31 | """ 32 | # 不允许包含http 33 | if 'http://' in kwargs['content']: 34 | source_ip = kwargs['source_ip'] 35 | logger.info('*'*30) 36 | logger.info('评论中包含http,来源:%s' % source_ip) 37 | logger.info(kwargs['content']) 38 | logger.info('*' * 30) 39 | return False, '非法内容,禁止评论。如有疑问请直接联系博主(页面顶部"关于"中有联系方式)' 40 | 41 | blog_id = kwargs['blog_id'] 42 | recomment_email = kwargs['recomment_email'] 43 | kwargs.pop('blog_id') 44 | kwargs.pop('recomment_email') 45 | comment_obj = Comment(**kwargs) 46 | comment_obj.save() 47 | 48 | if kwargs['creator'] == 'admin' or kwargs['obj_type_id'] != 2: # 管理员留言或者给管理员留言的情况才发送邮件通知 49 | # MsgService().send_email_by_process('来自loonapp的留言提醒', 50 | # '你有一条新的留言,请登录查看: http://loonapp.com/blog/{}/'.format(blog_id), 51 | # [kwargs['email']]) 52 | 53 | MsgService().send_multi_email_by_process('来自loonapp的留言提醒', 54 | '

你有一条新的留言,请点击查看'.format(blog_id), 55 | [recomment_email]) 56 | 57 | return True, comment_obj 58 | 59 | @staticmethod 60 | @auto_log 61 | def get_comment_by_blog_id(obj_id, obj_type_id=1): 62 | """ 63 | 获取评论 64 | :param obj_id: 65 | :param obj_type_id: 66 | :return: 67 | """ 68 | return Comment.objects.filter(obj_id=obj_id, obj_type_id=obj_type_id, is_deleted=False), '' 69 | 70 | @staticmethod 71 | @auto_log 72 | def get_comment_by_id(comment_id): 73 | """ 74 | 获取评论 75 | :param comment_id: 76 | :return: 77 | """ 78 | return Comment.objects.filter(id=comment_id, is_deleted=False), '' 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /services/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/services/common/__init__.py -------------------------------------------------------------------------------- /services/common/auto_log_service.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import traceback 3 | 4 | logger = logging.getLogger('default') 5 | 6 | 7 | def auto_log(func): 8 | """ 9 | 自动记录日志的装饰器: 10 | :param func: 11 | :return: 12 | """ 13 | def _deco(*args, **kwargs): 14 | try: 15 | real_func = func(*args, **kwargs) 16 | return real_func 17 | except Exception as e: 18 | logger.error(traceback.format_exc()) 19 | return False, e.__str__() 20 | 21 | return _deco 22 | 23 | 24 | def auto_class_log(some_class): 25 | """ 26 | 类装饰器 27 | :param some_class: 28 | :return: 29 | """ 30 | pass 31 | # 貌似没法通过对类加装饰器实现类里面所有方法都加入装饰器处理, 以后有时间再研究下 -------------------------------------------------------------------------------- /services/common/context_processors.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def now_env(request): 5 | """ 6 | 获取当前环境 7 | :param request: 8 | :return: 9 | """ 10 | env = settings.ENV 11 | return {'now_env': env} 12 | -------------------------------------------------------------------------------- /services/common/ip_service.py: -------------------------------------------------------------------------------- 1 | from services.base_service import BaseService 2 | from services.common.auto_log_service import auto_log 3 | 4 | 5 | class IpService(BaseService): 6 | """ 7 | ip地址服务 8 | """ 9 | def __int__(self): 10 | pass 11 | 12 | @staticmethod 13 | @auto_log 14 | def get_client_ip(request): 15 | """ 16 | 获取客户端ip地址 17 | :param request: 18 | :return: 19 | """ 20 | x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') 21 | if x_forwarded_for: 22 | ip = x_forwarded_for.split(',')[-1].strip() 23 | else: 24 | ip = request.META.get('REMOTE_ADDR') 25 | return ip, '' 26 | -------------------------------------------------------------------------------- /services/common/msg_service.py: -------------------------------------------------------------------------------- 1 | import os 2 | import multiprocessing 3 | from multiprocessing import Process 4 | from django.core.mail import send_mail,EmailMultiAlternatives 5 | from services.base_service import BaseService 6 | from services.common.auto_log_service import auto_log 7 | import logging 8 | logger = logging.getLogger('default') 9 | 10 | class MsgService(BaseService): 11 | """ 12 | 消息服务 13 | """ 14 | def __init__(self): 15 | pass 16 | 17 | @staticmethod 18 | @auto_log 19 | def send_email_by_process(subject, content, mail_to_list): 20 | """ 21 | 发送邮件 22 | :param subject: 23 | :param content: 24 | :param mail_to_list:收件人 25 | :return: 26 | """ 27 | # logger.info('同步发送') 28 | # a = send_mail(subject, content, 'LOONAPP', mail_to_list) 29 | # logger.info(a) 30 | # logger.info('后台发送') 31 | logger.info('发送邮件:{}-{}-{}'.format(subject, content, mail_to_list)) 32 | p = multiprocessing.Process(target=send_mail, args=(subject, content, 'LOONAPP', mail_to_list)) 33 | p.start() 34 | return True, '' 35 | 36 | @staticmethod 37 | @auto_log 38 | def send_multi_email_by_process(subject, content, mail_to_list): 39 | logger.info('发送html邮件:{}-{}-{}'.format(subject, content, mail_to_list)) 40 | msg = EmailMultiAlternatives(subject, content,from_email='LOONAPP',to=mail_to_list) 41 | msg.content_subtype = "html" 42 | p = multiprocessing.Process(target=msg.send, args=()) 43 | p.start() 44 | 45 | 46 | if __name__ == '__main__': 47 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.dev") 48 | MsgService().send_email_by_process('test', 'testt',['blackholll@163.com']) 49 | MsgService().send_multi_email_by_process('test', '百度',['blackholll@163.com']) 50 | 51 | -------------------------------------------------------------------------------- /settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/settings/__init__.py -------------------------------------------------------------------------------- /settings/test.py: -------------------------------------------------------------------------------- 1 | from settings.common import * 2 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 3 | MEDIA_URL = '/media/' 4 | 5 | DEBUG = True 6 | ALLOWED_HOSTS = [] 7 | 8 | LOGGING = { 9 | 'version': 1, 10 | 'disable_existing_loggers': False, 11 | 'filters': { 12 | 'require_debug_true': { 13 | '()': 'django.utils.log.RequireDebugTrue', 14 | }, 15 | }, 16 | 'formatters': { 17 | 'standard': { 18 | 'format': '%(levelname)s %(asctime)s %(pathname)s %(filename)s %(module)s %(funcName)s %(lineno)d: %(message)s' 19 | }, 20 | }, 21 | 'handlers': { 22 | 'file_handler': { 23 | 'level': 'DEBUG', 24 | 'class': 'logging.FileHandler', 25 | 'filename': os.path.join(BASE_DIR, 'log/run.log'), 26 | 'formatter': 'standard' 27 | }, 28 | 'console': { 29 | 'level': 'DEBUG', 30 | 'filters': ['require_debug_true'], 31 | 'class': 'logging.StreamHandler', 32 | 'formatter': 'standard' 33 | }, 34 | }, 35 | 'loggers': { 36 | 'default': { 37 | 'handlers': ['file_handler', 'console'], 38 | 'propagate': True, 39 | 'level': 'INFO', 40 | }, 41 | 'django.request': { 42 | 'handlers': ['file_handler'], 43 | 'propagate': True, 44 | 'level': 'INFO', 45 | }, 46 | 'django.db.backends': { 47 | 'handlers': ['console'], 48 | 'propagate': True, 49 | 'level': 'INFO', 50 | } 51 | } 52 | } 53 | 54 | ENV = 'test' 55 | -------------------------------------------------------------------------------- /static/css/about.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | .themeBox { 3 | width: 100%; 4 | padding: 0; 5 | background-color: #1d8dcd; 6 | color: #FFF; 7 | position: relative; 8 | } 9 | .themeTitle { 10 | width: 189px; 11 | position: absolute; 12 | top: 50%; 13 | margin-top: -32px; 14 | *display: expression(style.display='block', 0); 15 | } 16 | .commTTxt { 17 | font-family: Arial, Tahoma, Helvetica, Simsun, STHeiti; 18 | height: 42px; 19 | color: #FFFFFF; 20 | } 21 | .themeTxt { 22 | font-family: Arial, Tahoma, Helvetica, Simsun, STHeiti; 23 | color: #FFF; 24 | height: 22px; 25 | } 26 | .aboutTxt { 27 | width: 761px; 28 | padding-top: 20px; 29 | padding-bottom: 20px; 30 | font-size: 16px; 31 | *margin-bottom: -1px; 32 | } 33 | .aboutTxt span { 34 | font-family: 'Microsoft Yahei', Tahoma, Arial, Helvetica, Simsun, STHeiti; 35 | padding-top: 18px; 36 | padding-bottom: 18px; 37 | padding-right: 30px; 38 | padding-left: 30px; 39 | font-size: 16px; 40 | color: #5e5e5e; 41 | } 42 | 43 | .aboutBox span { 44 | display: block; 45 | } 46 | #about_dannysite { 47 | left: 761px; 48 | } 49 | 50 | .contactNotice { 51 | padding-top: 18px; 52 | padding-bottom: 18px; 53 | padding-left: 10px; 54 | padding-right: 10px; 55 | } 56 | #contact_form_box { 57 | font-size: 16px; 58 | width: 598px; 59 | } 60 | #contact_form_box .inputBox { 61 | height: 48px; 62 | padding-left: 38px; 63 | padding-bottom: 18px; 64 | position: relative; 65 | } 66 | #contact_form_box .submitBox { 67 | padding-bottom: 25px; 68 | } 69 | #contact_form_box .textareaBox { 70 | padding-left: 38px; 71 | padding-bottom: 18px; 72 | position: relative; 73 | } 74 | #contact_form_box #captcha_desc_box { 75 | height: 25px; 76 | width: 100px; 77 | } 78 | 79 | #contact_form_box .inputBox #captcha_desc { 80 | position: absolute; 81 | bottom: 0px; 82 | } 83 | #contact_form_box .xsmallinput { 84 | *width: 119px; 85 | } 86 | #cutting_line { 87 | height: 310px; 88 | width: 2px; 89 | margin-top: 26px; 90 | } 91 | #im_tools { 92 | padding-left: 20px; 93 | padding-right: 20px; 94 | } 95 | #im_tools table tr{ 96 | height: 60px; 97 | vertical-align: middle; 98 | 99 | } 100 | #im_tools table tr a { 101 | padding-left: 5px; 102 | color: #1d8dcd; 103 | text-decoration: none; 104 | } 105 | #im_tools table tr a:hover { 106 | color: #f39800; 107 | } 108 | -------------------------------------------------------------------------------- /static/css/bootstrap-multiselect.css: -------------------------------------------------------------------------------- 1 | span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0} 2 | -------------------------------------------------------------------------------- /static/css/index.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | #my_focus { 4 | border-top-width: 2px; 5 | border-bottom-width: 2px; 6 | border-top-style: solid; 7 | border-bottom-style: solid; 8 | border-top-color: #eeeeee; 9 | border-bottom-color: #eeeeee; 10 | height: 280px; 11 | overflow: hidden; 12 | } 13 | #cover img { 14 | display: block; 15 | } 16 | #my_focus_title { 17 | text-align: right; 18 | width: 100%; 19 | padding-top: 8px; 20 | } 21 | #my_focus_weibo { 22 | text-align: right; 23 | } 24 | #my_focus_desc { 25 | padding-top: 32px; 26 | line-height: 26px; 27 | font-size: 16px; 28 | height: 155px; 29 | overflow: hidden; 30 | } 31 | #my_focus_txt { 32 | width: 654px; 33 | 34 | } 35 | #blog_nav_box { 36 | font-size: 16px; 37 | background-color: #fafafa; 38 | margin-top: 6px; 39 | } 40 | #photo_box img { 41 | display: block; 42 | float: left; 43 | } 44 | #photo_box #photo_right img { 45 | float: left; 46 | } 47 | #photo_box #photo_desc_layout { 48 | filter: alpha(opacity=30); 49 | -moz-opacity: 0.3; 50 | opacity: 0.3; 51 | position: absolute; 52 | background-color: #000; 53 | _background-color: #FFF; 54 | bottom: 0px; 55 | width: 100%; 56 | height: 132px; 57 | color: #FFF; 58 | padding: 10px 0px; 59 | } 60 | #photo_box #photo_nav_layout { 61 | position: absolute; 62 | bottom: 0px; 63 | width: 410px; 64 | height: 30px; 65 | color: #FFF; 66 | text-align: right; 67 | padding-top: 10px; 68 | padding-right: 20px; 69 | padding-bottom: 10px; 70 | padding-left: 20px; 71 | } 72 | #photo_box #photo_nav_layout a { 73 | color: #FFF; 74 | text-decoration: none; 75 | } 76 | #photo_box #photo_nav_layout a:hover { 77 | color: #CCC; 78 | text-decoration: none; 79 | } 80 | #photo_box #photo_desc_txt { 81 | position: absolute; 82 | bottom: 0px; 83 | width: 480px; 84 | height: 132px; 85 | color: #FFF; 86 | padding: 10px; 87 | } 88 | #blog_btn { 89 | font-size: 16px; 90 | padding-bottom: 13px; 91 | background-color: #fafafa; 92 | display: block; 93 | padding-top: 13px; 94 | } 95 | #blog_btn:hover { 96 | background-color: #eeeeee; 97 | } -------------------------------------------------------------------------------- /static/fonts/Arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/fonts/Arial.ttf -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /static/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /static/image/LOGO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/LOGO.png -------------------------------------------------------------------------------- /static/image/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /static/image/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/apple-touch-icon.png -------------------------------------------------------------------------------- /static/image/davatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/davatar.png -------------------------------------------------------------------------------- /static/image/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/favicon.ico -------------------------------------------------------------------------------- /static/image/s_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/image/s_icon.png -------------------------------------------------------------------------------- /static/images/Sorting icons.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/Sorting icons.psd -------------------------------------------------------------------------------- /static/images/blogedit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/blogedit.png -------------------------------------------------------------------------------- /static/images/bloglist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/bloglist.png -------------------------------------------------------------------------------- /static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/favicon.ico -------------------------------------------------------------------------------- /static/images/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/homepage.png -------------------------------------------------------------------------------- /static/images/sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/sort_asc.png -------------------------------------------------------------------------------- /static/images/sort_asc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/sort_asc_disabled.png -------------------------------------------------------------------------------- /static/images/sort_both.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/sort_both.png -------------------------------------------------------------------------------- /static/images/sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/sort_desc.png -------------------------------------------------------------------------------- /static/images/sort_desc_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blackholll/loonblog/63d1f06d04047f220f550de914e542f535bb61a3/static/images/sort_desc_disabled.png -------------------------------------------------------------------------------- /static/js/dataTables.bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 3 integration 3 | ©2011-2015 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});b.extend(f.ext.classes, 6 | {sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")}; 7 | l=0;for(h=f.length;l",{"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#", 8 | "aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('