升级至django 2.0 😌

liangliang 8 years ago
parent 082886884b
commit ab333f7159

@ -9,11 +9,6 @@ services:
env:
global:
- DJANGO_SETTINGS_MODULE="travis_test.travis_settings"
matrix:
- DJANGO="Django==1.8"
- DJANGO="Django==1.9"
- DJANGO="Django==1.10"
- DJANGO="Django==1.11"
branches:
only:
- master

@ -49,7 +49,7 @@ INSTALLED_APPS = [
'compressor'
]
MIDDLEWARE_CLASSES = [
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.gzip.GZipMiddleware',

@ -17,7 +17,7 @@ from django.contrib.sitemaps import Sitemap
from blog.models import Article, Category, Tag
from accounts.models import BlogUser
from django.contrib.sitemaps import GenericSitemap
from django.core.urlresolvers import reverse
from django.urls import reverse
class StaticViewSitemap(Sitemap):

@ -17,7 +17,7 @@ from django.test import Client, RequestFactory, TestCase
from blog.models import Article, Category, Tag
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.urls import reverse
import datetime
from DjangoBlog.utils import *

@ -36,14 +36,14 @@ handler500 = 'blog.views.server_error_view'
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include('blog.urls', namespace='blog', app_name='blog')),
url(r'', include('blog.urls', namespace='blog')),
url(r'', include('comments.urls', namespace='comment', app_name='comments')),
url(r'', include('accounts.urls', namespace='account', app_name='accounts')),
url(r'', include('oauth.urls', namespace='oauth', app_name='oauth')),
url(r'', include('comments.urls', namespace='comment')),
url(r'', include('accounts.urls', namespace='account')),
url(r'', include('oauth.urls', namespace='oauth')),
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps},
name='django.contrib.sitemaps.views.sitemap'),
url(r'^feed/$', DjangoBlogFeed()),
url(r'^search', include('haystack.urls'), name='search'),
url(r'', include('servermanager.urls', namespace='servermanager', app_name='servermanagers'))
url(r'', include('servermanager.urls', namespace='servermanager'))
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

@ -1,8 +1,8 @@
# DjangoBlog
基于`python3.5`和`Django1.10`的博客。
基于`python3.5`和`Django2.0`的博客。
[![Build Status](https://travis-ci.org/liangliangyy/DjangoBlog.svg?branch=master)](https://travis-ci.org/liangliangyy/DjangoBlog) [![Coverage Status](https://coveralls.io/repos/github/liangliangyy/DjangoBlog/badge.svg?branch=master)](https://coveralls.io/github/liangliangyy/DjangoBlog?branch=master) [![Requirements Status](https://requires.io/github/liangliangyy/DjangoBlog/requirements.svg?branch=master)](https://requires.io/github/liangliangyy/DjangoBlog/requirements/?branch=master) [![license](https://img.shields.io/github/license/liangliangyy/djangoblog.svg)]() [![GitHub release](https://img.shields.io/github/release/liangliangyy/djangoblog.svg)]() [![python3.5](https://img.shields.io/badge/python-3.5-brightgreen.svg)]() [![django1.10](https://img.shields.io/badge/django-1.10-brightgreen.svg)]()
[![Build Status](https://travis-ci.org/liangliangyy/DjangoBlog.svg?branch=master)](https://travis-ci.org/liangliangyy/DjangoBlog) [![Coverage Status](https://coveralls.io/repos/github/liangliangyy/DjangoBlog/badge.svg?branch=master)](https://coveralls.io/github/liangliangyy/DjangoBlog?branch=master) [![Requirements Status](https://requires.io/github/liangliangyy/DjangoBlog/requirements.svg?branch=master)](https://requires.io/github/liangliangyy/DjangoBlog/requirements/?branch=master) [![license](https://img.shields.io/github/license/liangliangyy/djangoblog.svg)]() [![GitHub release](https://img.shields.io/github/release/liangliangyy/djangoblog.svg)]() [![python3.5](https://img.shields.io/badge/python-3.5-brightgreen.svg)]() [![django1.10](https://img.shields.io/badge/django-2.0-brightgreen.svg)]()
## 主要功能:
- 文章,页面,分类目录,标签的添加,删除,编辑等。文章及页面支持`Markdown`,支持代码高亮。
@ -14,7 +14,6 @@
- 简单的SEO功能新建文章等会自动通知Google和百度。
- 集成了简单的图床功能。
- 集成`django-compressor`,自动压缩`css``js`。
- 基于`python3`,支持`Django`多版本。`Django`的1.8,1.9,1.10,1.11均测试通过。
- 网站异常邮件提醒,若有未捕捉到的异常会自动发送提醒邮件。
- 集成了微信公众号功能现在可以使用微信公众号来管理你的vps了。
## 安装

@ -1,6 +1,6 @@
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.contrib.sites.models import Site
from django.utils.timezone import now
@ -9,6 +9,7 @@ from django.utils.timezone import now
class BlogUser(AbstractUser):
nickname = models.CharField('昵称', max_length=50, blank=True)
nickname = models.CharField('昵称', max_length=100, blank=True)
mugshot = models.ImageField('头像', upload_to='upload/mugshots', blank=True)
created_time = models.DateTimeField('创建时间', default=now)
last_mod_time = models.DateTimeField('修改时间', default=now)

@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
import datetime
from accounts.models import BlogUser
from django.core.urlresolvers import reverse
from django.urls import reverse
# Create your tests here.

@ -19,6 +19,8 @@ from django.contrib.auth import views as auth_view
from . import views
from .forms import LoginForm
app_name="accounts"
urlpatterns = [
url(r'^login/$', views.LoginView.as_view(success_url='/'), name='login', kwargs={'authentication_form': LoginForm}),
url(r'^register/$', views.RegisterView.as_view(success_url="/"), name='register'),

@ -6,7 +6,7 @@ from django.contrib.auth import authenticate, login, logout
from django.views.generic import FormView, RedirectView
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.views.decorators.csrf import csrf_protect

@ -19,33 +19,17 @@ from DjangoBlog.utils import cache
class OnlineMiddleware(object):
def process_request(self, request):
self.start_time = time.time()
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def process_view(self, request, view_func, view_args, view_kwargs):
"""
处理当前在线人数
"""
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
http_user_agent = request.META.get('HTTP_USER_AGENT', [])
if 'Spider' in http_user_agent or 'spider' in http_user_agent:
return
return response
online_ips = cache.get("online_ips", [])
if online_ips:
online_ips = cache.get_many(online_ips).keys()
online_ips = list(online_ips)
ip = get_real_ip(request)
cache.set(ip, 0, 5 * 60)
if ip not in online_ips:
online_ips.append(ip)
s = type(online_ips)
cache.set("online_ips", online_ips)
def process_response(self, request, response):
cast_time = 0.921
if self.__dict__ and 'start_time' in self.__dict__:
cast_time = time.time() - self.start_time
cast_time = time.time() - start_time
response.content = response.content.replace(b'<!!LOAD_TIMES!!>', str.encode(str(cast_time)[:5]))
return response

@ -1,5 +1,5 @@
from django.db import models
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.conf import settings
from uuslug import slugify
@ -125,7 +125,7 @@ class Article(BaseModel):
class Category(BaseModel):
"""文章分类"""
name = models.CharField('分类名', max_length=30, unique=True)
parent_category = models.ForeignKey('self', verbose_name="父级分类", blank=True, null=True)
parent_category = models.ForeignKey('self', verbose_name="父级分类", blank=True, null=True, on_delete=models.CASCADE)
class Meta:
ordering = ['name']

@ -18,7 +18,7 @@ from django.conf import settings
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
import random
from django.core.urlresolvers import reverse
from django.urls import reverse
from blog.models import Article, Category, Tag, Links, SideBar
from django.utils.encoding import force_text
from django.shortcuts import get_object_or_404
@ -266,7 +266,7 @@ def gravatar(email, size=40):
return mark_safe('<img src="%s" height="%d" width="%d">' % (url, size, size))
@register.assignment_tag
@register.simple_tag
def query(qs, **kwargs):
""" template tag which allows queryset filtering. Usage:
{% query books author=author as mybooks %}
@ -275,3 +275,5 @@ def query(qs, **kwargs):
{% endfor %}
"""
return qs.filter(**kwargs)

@ -13,38 +13,32 @@
@time: 2016/11/2 下午7:15
"""
from django.conf.urls import url
from django.urls import path
from django.views.decorators.cache import cache_page
from . import views
from haystack.forms import ModelSearchForm
from haystack.query import SearchQuerySet
from haystack.views import SearchView
app_name = "blog"
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^page/(?P<page>\d+)$', views.IndexView.as_view(), name='index_page'),
path(r'', views.IndexView.as_view(), name='index'),
path(r'page/<int:page>/', views.IndexView.as_view(), name='index_page'),
url(r'^article/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/(?P<article_id>\d+).html$',
views.ArticleDetailView.as_view(),
name='detailbyid'),
path(r'article/<int:year>/<int:month>/<int:day>/<int:article_id>.html',
views.ArticleDetailView.as_view(),
name='detailbyid'),
url(r'^blogpage/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)/(?P<page_id>\d+)-(?P<slug>[\w-]+).html$',
views.ArticleDetailView.as_view(),
name='pagedetail'),
path(r'category/<slug:category_name>.html', views.CategoryDetailView.as_view(), name='category_detail'),
path(r'category/<slug:category_name>/<int:page>.html', views.CategoryDetailView.as_view(),
name='category_detail_page'),
url(r'^category/(?P<category_name>[\w-]+).html$', views.CategoryDetailView.as_view(), name='category_detail'),
url(r'^category/(?P<category_name>[\w-]+)/(?P<page>\d+).html$', views.CategoryDetailView.as_view(),
name='category_detail_page'),
# url(r'^category/(?P<category_name>[\w-]+)/(?P<page>\d+).html$', views.CategoryDetailView.as_view(),
# name='category_detail'),
path(r'author/<author_name>.html', views.AuthorDetailView.as_view(), name='author_detail'),
path(r'author/<author_name>/<int:page>).html', views.AuthorDetailView.as_view(),
name='author_detail_page'),
url(r'^author/(?P<author_name>\w+).html$', views.AuthorDetailView.as_view(), name='author_detail'),
url(r'^author/(?P<author_name>\w+)/(?P<page>\d+).html$', views.AuthorDetailView.as_view(),
name='author_detail_page'),
url(r'^tag/(?P<tag_name>[\w-]+).html$', views.TagDetailView.as_view(), name='tag_detail'),
url(r'^tag/(?P<tag_name>[\w-]+)/(?P<page>\d+).html$', views.TagDetailView.as_view(), name='tag_detail_page'),
url(r'^upload', views.fileupload, name='upload'),
url(r'^refresh', views.refresh_memcache, name='refresh')
path(r'tag/<slug:tag_name>.html', views.TagDetailView.as_view(), name='tag_detail'),
path(r'tag/<slug:tag_name>/<int:page>).html', views.TagDetailView.as_view(), name='tag_detail_page'),
path(r'upload', views.fileupload, name='upload'),
path(r'refresh', views.refresh_memcache, name='refresh')
]

@ -218,11 +218,11 @@ def fileupload(request):
isimage = len([i for i in imgextensions if fname.find(i) >= 0]) > 0
basepath = r'/var/www/resource/{type}/{timestr}'.format(
type='files' if not isimage else'image', timestr=timestr)
type='files' if not isimage else 'image', timestr=timestr)
if settings.TESTING:
basepath = settings.BASE_DIR + '/uploads'
url = 'https://resource.lylinux.net/{type}/{timestr}/{filename}'.format(
type='files' if not isimage else'image', timestr=timestr, filename=filename)
type='files' if not isimage else 'image', timestr=timestr, filename=filename)
if not os.path.exists(basepath):
os.makedirs(basepath)
savepath = os.path.join(basepath, filename)
@ -256,17 +256,23 @@ def refresh_memcache(request):
return HttpResponse(e)
def page_not_found_view(request):
def page_not_found_view(request, exception):
if exception:
logger.error(exception)
url = request.get_full_path()
return render(request, 'blog/error_page.html',
{'message': '哎呀,您访问的地址 ' + url + ' 是一个未知的地方。请点击首页看看别的?', 'statuscode': '404'})
def server_error_view(request):
def server_error_view(request, exception):
if exception:
logger.error(exception)
return render(request, 'blog/error_page.html',
{'message': '哎呀,出错了,我已经收集到了错误信息,之后会抓紧抢修,请点击首页看看别的?', 'statuscode': '500'})
def permission_denied_view(request):
def permission_denied_view(request, exception):
if exception:
logger.error(exception)
return render(request, 'blog/error_page.html',
{'message': '哎呀,您没有权限访问此页面,请点击首页看看别的?', 'statuscode': '403'})

@ -13,7 +13,7 @@ class Comment(models.Model):
last_mod_time = models.DateTimeField('修改时间', default=now)
author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者', on_delete=models.CASCADE)
article = models.ForeignKey(Article, verbose_name='文章', on_delete=models.CASCADE)
parent_comment = models.ForeignKey('self', verbose_name="上级评论", blank=True, null=True)
parent_comment = models.ForeignKey('self', verbose_name="上级评论", blank=True, null=True, on_delete=models.CASCADE)
is_enable = models.BooleanField('是否显示', default=True, blank=False, null=False)
class Meta:

@ -22,7 +22,7 @@ from comments.forms import CommentForm
register = template.Library()
@register.assignment_tag
@register.simple_tag
def parse_commenttree(commentlist, comment):
"""获得当前评论子评论的列表
用法: {% parse_commenttree article_comments comment as childcomments %}

@ -2,7 +2,7 @@ from django.test import Client, RequestFactory, TestCase
from blog.models import Article, Category, Tag
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.urls import reverse
import datetime
from accounts.models import BlogUser
from comments.templatetags.comments_tags import *

@ -13,10 +13,11 @@
@time: 2016/11/12 下午3:03
"""
from django.conf.urls import url
from django.urls import path
from . import views
app_name = "comments"
urlpatterns = [
# url(r'^postcomment/(?P<article_id>\d+)$', views.CommentPostView.as_view(), name='postcomment'),
url(r'^article/(?P<article_id>\d+)/postcomment$', views.CommentPostView.as_view(), name='postcomment'),
# url(r'^po456stcomment/(?P<article_id>\d+)$', views.CommentPostView.as_view(), name='postcomment'),
path('article/<int:article_id>/postcomment', views.CommentPostView.as_view(), name='postcomment'),
]

@ -46,7 +46,7 @@ class CommentPostView(FormView):
article_id = self.kwargs['article_id']
article = Article.objects.get(pk=article_id)
if not self.request.user.is_authenticated():
if not self.request.user.is_authenticated:
email = form.cleaned_data['email']
username = form.cleaned_data['name']
@ -64,12 +64,8 @@ class CommentPostView(FormView):
comment.save(True)
from DjangoBlog.blog_signals import comment_save_signal
port = 80
try:
# django1.8 没有这个方法...
port = self.request.get_port()
except:
pass
port = self.request.get_port()
username = self.request.user.username if self.request.user else ''
comment_save_signal.send(sender=self.__class__, comment_id=comment.id, username=username, serverport=port)
return HttpResponseRedirect("%s#div-comment-%d" % (article.get_absolute_url(), comment.pk))

@ -6,7 +6,8 @@ from django.utils.timezone import now
class OAuthUser(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='用户', blank=True, null=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='用户', blank=True, null=True,
on_delete=models.CASCADE)
openid = models.CharField(max_length=50)
nikename = models.CharField(max_length=50, verbose_name='昵称')
token = models.CharField(max_length=150, null=True, blank=True)

@ -13,7 +13,7 @@
@time: 2017/3/4 下午3:22
"""
from oauth.oauthmanager import get_oauth_apps
from django.core.urlresolvers import reverse
from django.urls import reverse
from django import template
from django.conf import settings

@ -13,14 +13,15 @@
@time: 2016/11/26 下午5:25
"""
from django.conf.urls import url
from django.urls import path
from django.views.decorators.cache import cache_page
from . import views
app_name = "oauth"
urlpatterns = [
url(r'^oauth/authorize$', views.authorize),
url(r'^oauth/requireemail/(?P<oauthid>\d+).html', views.RequireEmailView.as_view(), name='require_email'),
url(r'^oauth/emailconfirm/(?P<id>\d+)/(?P<sign>\S+).html', views.emailconfirm, name='email_confirm'),
url(r'^oauth/bindsuccess/(?P<oauthid>\d+).html', views.bindsuccess, name='bindsuccess'),
url(r'^oauth/oauthlogin$', views.oauthlogin,name='oauthlogin')
path(r'oauth/authorize', views.authorize),
path(r'oauth/requireemail/<int:oauthid>.html', views.RequireEmailView.as_view(), name='require_email'),
path(r'oauth/emailconfirm/<int:id>)/<sign>.html', views.emailconfirm, name='email_confirm'),
path(r'oauth/bindsuccess/<int:oauthid>.html', views.bindsuccess, name='bindsuccess'),
path(r'oauth/oauthlogin', views.oauthlogin, name='oauthlogin')
]

@ -10,7 +10,7 @@ from django.contrib.auth import login
from django.shortcuts import get_object_or_404
from django.views.generic import FormView, RedirectView
from oauth.forms import RequireEmailForm
from django.core.urlresolvers import reverse
from django.urls import reverse
from DjangoBlog.utils import send_email, get_md5
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist

@ -1,23 +1,27 @@
appdirs==1.4.3
coverage==4.4.1
Django==1.11.7
bottle==0.12.13
certifi==2017.11.5
chardet==3.0.4
coverage==4.4.2
Django==2.0.1
django-appconf==1.0.2
django-autoslug==1.9.3
django-compressor==2.2
django-debug-toolbar==1.9.1
django-haystack==2.6.1
django-ipware==1.1.6
django-pagedown==0.1.3
django-pagedown==1.0.4
django-uuslug==1.1.8
idna==2.6
jieba==0.39
jsonpickle==0.9.5
markdown2==2.3.5
mistune==0.8.1
mistune==0.8.3
olefile==0.44
packaging==16.8
Pillow==4.3.0
Pillow==5.0.0
Pygments==2.2.0
PyMySQL==0.7.11
PyMySQL==0.8.0
pyparsing==2.2.0
python-memcached==1.58
python-slugify==1.2.4
@ -27,8 +31,9 @@ requests==2.18.4
rjsmin==1.0.12
six==1.11.0
sqlparse==0.2.4
Unidecode==0.4.21
Unidecode==1.0.22
urllib3==1.22
webencodings==0.5.1
WeRoBot==1.1.1
WeRoBot==1.2.0
Whoosh==2.7.4
xmltodict==0.11.0

@ -13,11 +13,12 @@
@time: 2017/8/27 上午2:27
"""
from django.conf.urls import url
from django.urls import path
from werobot.contrib.django import make_view
from .robot import robot
app_name = "servermanager"
urlpatterns = [
url(r'^robot/', make_view(robot)),
path(r'robot', make_view(robot)),
]

Loading…
Cancel
Save