From f7e4af627817f608d3ab555d2a3df1590b8ce937 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Mon, 6 Apr 2020 15:56:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BD=BF=E7=94=A8autopep8=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DjangoBlog/admin_site.py | 2 +- DjangoBlog/blog_signals.py | 29 +- DjangoBlog/elasticsearch_backend.py | 28 +- DjangoBlog/logentryadmin.py | 8 +- DjangoBlog/settings.py | 20 +- DjangoBlog/spider_notify.py | 2 +- DjangoBlog/tests.py | 20 +- DjangoBlog/urls.py | 31 +- DjangoBlog/utils.py | 30 +- DjangoBlog/whoosh_cn_backend.py | 288 +++++++++++++----- accounts/admin.py | 9 +- accounts/forms.py | 9 +- accounts/models.py | 7 +- accounts/tests.py | 23 +- accounts/urls.py | 19 +- accounts/user_login_backend.py | 2 +- accounts/views.py | 24 +- blog/admin.py | 19 +- blog/context_processors.py | 8 +- blog/documents.py | 59 ++-- blog/forms.py | 2 +- blog/management/commands/build_index.py | 2 +- .../management/commands/build_search_words.py | 5 +- blog/management/commands/clear_cache.py | 2 +- blog/management/commands/create_testdata.py | 23 +- blog/management/commands/ping_baidu.py | 16 +- blog/management/commands/sync_user_avatar.py | 6 +- blog/middleware.py | 11 +- blog/models.py | 129 ++++++-- blog/search_indexes.py | 2 +- blog/templatetags/blog_tags.py | 71 +++-- blog/tests.py | 29 +- blog/urls.py | 77 +++-- blog/views.py | 64 ++-- comments/admin.py | 11 +- comments/forms.py | 15 +- comments/models.py | 20 +- comments/tests.py | 28 +- comments/urls.py | 5 +- comments/utils.py | 5 +- comments/views.py | 10 +- oauth/admin.py | 20 +- oauth/forms.py | 5 +- oauth/models.py | 21 +- oauth/oauthmanager.py | 40 ++- oauth/templatetags/__init__.py | 4 +- oauth/templatetags/oauth_tags.py | 7 +- oauth/urls.py | 25 +- oauth/views.py | 22 +- owntracks/tests.py | 16 +- owntracks/urls.py | 2 +- owntracks/views.py | 22 +- servermanager/Api/__init__.py | 4 +- servermanager/Api/blogapi.py | 2 +- servermanager/Api/commonapi.py | 2 +- servermanager/MemcacheStorage.py | 2 +- servermanager/admin.py | 7 +- servermanager/robot.py | 20 +- servermanager/tests.py | 6 +- servermanager/urls.py | 2 +- 60 files changed, 975 insertions(+), 424 deletions(-) diff --git a/DjangoBlog/admin_site.py b/DjangoBlog/admin_site.py index 87b008a..d90ec5e 100644 --- a/DjangoBlog/admin_site.py +++ b/DjangoBlog/admin_site.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/DjangoBlog/blog_signals.py b/DjangoBlog/blog_signals.py index 198f3ff..22260c9 100644 --- a/DjangoBlog/blog_signals.py +++ b/DjangoBlog/blog_signals.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -34,7 +34,8 @@ import logging logger = logging.getLogger(__name__) oauth_user_login_signal = django.dispatch.Signal(providing_args=['id']) -send_email_signal = django.dispatch.Signal(providing_args=['emailto', 'title', 'content']) +send_email_signal = django.dispatch.Signal( + providing_args=['emailto', 'title', 'content']) @receiver(send_email_signal) @@ -43,7 +44,11 @@ def send_email_signal_handler(sender, **kwargs): title = kwargs['title'] content = kwargs['content'] - msg = EmailMultiAlternatives(title, content, from_email=settings.DEFAULT_FROM_EMAIL, to=emailto) + msg = EmailMultiAlternatives( + title, + content, + from_email=settings.DEFAULT_FROM_EMAIL, + to=emailto) msg.content_subtype = "html" from servermanager.models import EmailSendLog @@ -77,7 +82,14 @@ def oauth_user_login_signal_handler(sender, **kwargs): @receiver(post_save) -def model_post_save_callback(sender, instance, created, raw, using, update_fields, **kwargs): +def model_post_save_callback( + sender, + instance, + created, + raw, + using, + update_fields, + **kwargs): clearcache = False if isinstance(instance, LogEntry): return @@ -98,10 +110,15 @@ def model_post_save_callback(sender, instance, created, raw, using, update_field if site.find(':') > 0: site = site[0:site.find(':')] - expire_view_cache(path, servername=site, serverport=80, key_prefix='blogdetail') + expire_view_cache( + path, + servername=site, + serverport=80, + key_prefix='blogdetail') if cache.get('seo_processor'): cache.delete('seo_processor') - comment_cache_key = 'article_comments_{id}'.format(id=instance.article.id) + comment_cache_key = 'article_comments_{id}'.format( + id=instance.article.id) cache.delete(comment_cache_key) delete_sidebar_cache(instance.author.username) delete_view_cache('article_comments', [str(instance.article.pk)]) diff --git a/DjangoBlog/elasticsearch_backend.py b/DjangoBlog/elasticsearch_backend.py index e896653..4728ad8 100644 --- a/DjangoBlog/elasticsearch_backend.py +++ b/DjangoBlog/elasticsearch_backend.py @@ -29,7 +29,11 @@ logger = logging.getLogger(__name__) class ElasticSearchBackend(BaseSearchBackend): def __init__(self, connection_alias, **connection_options): - super(ElasticSearchBackend, self).__init__(connection_alias, **connection_options) + super( + ElasticSearchBackend, + self).__init__( + connection_alias, + **connection_options) self.manager = ArticleDocumentManager() # try: # self._rebuild(None) @@ -75,16 +79,14 @@ class ElasticSearchBackend(BaseSearchBackend): start_offset = kwargs.get('start_offset') end_offset = kwargs.get('end_offset') - q = Q('bool', - should=[Q('match', body=query_string), Q('match', title=query_string)], - minimum_should_match="70%" - ) + q = Q('bool', should=[Q('match', body=query_string), Q( + 'match', title=query_string)], minimum_should_match="70%") search = ArticleDocument.search() \ - .query('bool', filter=[q]) \ - .filter('term', status='p') \ - .filter('term', type='a') \ - .source(False)[start_offset: end_offset] + .query('bool', filter=[q]) \ + .filter('term', status='p') \ + .filter('term', type='a') \ + .source(False)[start_offset: end_offset] results = search.execute() hits = results['hits'].total @@ -99,8 +101,12 @@ class ElasticSearchBackend(BaseSearchBackend): result_class = SearchResult - result = result_class(app_label, model_name, raw_result['_id'], raw_result['_score'], - **additional_fields) + result = result_class( + app_label, + model_name, + raw_result['_id'], + raw_result['_score'], + **additional_fields) raw_results.append(result) facets = {} spelling_suggestion = None diff --git a/DjangoBlog/logentryadmin.py b/DjangoBlog/logentryadmin.py index 45b3390..b8a3931 100644 --- a/DjangoBlog/logentryadmin.py +++ b/DjangoBlog/logentryadmin.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -83,9 +83,9 @@ class LogEntryAdmin(admin.ModelAdmin): def has_change_permission(self, request, obj=None): return ( - request.user.is_superuser or - request.user.has_perm('admin.change_logentry') - ) and request.method != 'POST' + request.user.is_superuser or + request.user.has_perm('admin.change_logentry') + ) and request.method != 'POST' def has_delete_permission(self, request, obj=None): return False diff --git a/DjangoBlog/settings.py b/DjangoBlog/settings.py index fd7d47d..ffa0dd2 100644 --- a/DjangoBlog/settings.py +++ b/DjangoBlog/settings.py @@ -26,7 +26,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY') or 'n9ceqv38)#&mwuat@(mjb_p%em$e8$qyr#fw9ot!=ba6lijx-6' +SECRET_KEY = os.environ.get( + 'DJANGO_SECRET_KEY') or 'n9ceqv38)#&mwuat@(mjb_p%em$e8$qyr#fw9ot!=ba6lijx-6' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = env_to_bool('DJANGO_DEBUG', True) # DEBUG = False @@ -108,10 +109,11 @@ DATABASES = { 'USER': os.environ.get('DJANGO_MYSQL_USER') or 'root', 'PASSWORD': os.environ.get('DJANGO_MYSQL_PASSWORD') or 'djangoblog_123', 'HOST': os.environ.get('DJANGO_MYSQL_HOST') or '127.0.0.1', - 'PORT': int(os.environ.get('DJANGO_MYSQL_PORT') or 3306), - 'OPTIONS': {'charset': 'utf8mb4'}, - } -} + 'PORT': int( + os.environ.get('DJANGO_MYSQL_PORT') or 3306), + 'OPTIONS': { + 'charset': 'utf8mb4'}, + }} # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators @@ -157,7 +159,8 @@ HAYSTACK_CONNECTIONS = { # Automatically update searching index HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' # Allow user login with username and password -AUTHENTICATION_BACKENDS = ['accounts.user_login_backend.EmailOrUsernameModelBackend'] +AUTHENTICATION_BACKENDS = [ + 'accounts.user_login_backend.EmailOrUsernameModelBackend'] STATIC_ROOT = os.path.join(SITE_ROOT, 'collectedstatic') @@ -195,7 +198,7 @@ CACHES = { SITE_ID = 1 BAIDU_NOTIFY_URL = os.environ.get('DJANGO_BAIDU_NOTIFY_URL') \ - or 'http://data.zz.baidu.com/urls?site=https://www.lylinux.net&token=1uAOGrMsUm5syDGn' + or 'http://data.zz.baidu.com/urls?site=https://www.lylinux.net&token=1uAOGrMsUm5syDGn' # Email: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' @@ -210,7 +213,8 @@ SERVER_EMAIL = EMAIL_HOST_USER # Setting debug=false did NOT handle except email notifications ADMINS = [('admin', os.environ.get('DJANGO_ADMIN_EMAIL') or 'admin@admin.com')] # WX ADMIN password(Two times md5) -WXADMIN = os.environ.get('DJANGO_WXADMIN_PASSWORD') or '995F03AC401D6CABABAEF756FC4D43C7' +WXADMIN = os.environ.get( + 'DJANGO_WXADMIN_PASSWORD') or '995F03AC401D6CABABAEF756FC4D43C7' LOGGING = { 'version': 1, diff --git a/DjangoBlog/spider_notify.py b/DjangoBlog/spider_notify.py index e83ccb1..f88db4e 100644 --- a/DjangoBlog/spider_notify.py +++ b/DjangoBlog/spider_notify.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/DjangoBlog/tests.py b/DjangoBlog/tests.py index dfbaa20..5c673bc 100644 --- a/DjangoBlog/tests.py +++ b/DjangoBlog/tests.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -30,17 +30,17 @@ class DjangoBlogTest(TestCase): md5 = get_md5('test') self.assertIsNotNone(md5) c = CommonMarkdown.get_markdown(''' - # Title1 - + # Title1 + ```python import os - ``` - - [url](https://www.lylinux.net/) - - [ddd](http://www.baidu.com) - - + ``` + + [url](https://www.lylinux.net/) + + [ddd](http://www.baidu.com) + + ''') self.assertIsNotNone(c) d = { diff --git a/DjangoBlog/urls.py b/DjangoBlog/urls.py index a760104..0bedda9 100644 --- a/DjangoBlog/urls.py +++ b/DjangoBlog/urls.py @@ -37,19 +37,20 @@ handler404 = 'blog.views.page_not_found_view' handler500 = 'blog.views.server_error_view' handle403 = 'blog.views.permission_denied_view' urlpatterns = [ - url(r'^admin/', admin_site.urls), - url(r'', include('blog.urls', namespace='blog')), - url(r'mdeditor/', include('mdeditor.urls')), - 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'^rss/$', DjangoBlogFeed()), - url(r'^search', include('haystack.urls'), name='search'), - url(r'', include('servermanager.urls', namespace='servermanager')), - url(r'', include('owntracks.urls', namespace='owntracks')) - ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + url(r'^admin/', admin_site.urls), + url(r'', include('blog.urls', namespace='blog')), + url(r'mdeditor/', include('mdeditor.urls')), + 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'^rss/$', DjangoBlogFeed()), + url(r'^search', include('haystack.urls'), name='search'), + url(r'', include('servermanager.urls', namespace='servermanager')), + url(r'', include('owntracks.urls', namespace='owntracks')) +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) if settings.DEBUG: - urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += static(settings.MEDIA_URL, + document_root=settings.MEDIA_ROOT) diff --git a/DjangoBlog/utils.py b/DjangoBlog/utils.py index 48ef113..3946dd6 100644 --- a/DjangoBlog/utils.py +++ b/DjangoBlog/utils.py @@ -45,7 +45,7 @@ def cache_decorator(expiration=3 * 60): try: view = args[0] key = view.get_cache_key() - except: + except BaseException: key = None if not key: unique_str = repr((func, args, kwargs)) @@ -60,7 +60,9 @@ def cache_decorator(expiration=3 * 60): else: return value else: - logger.info('cache_decorator set cache:%s key:%s' % (func.__name__, key)) + logger.info( + 'cache_decorator set cache:%s key:%s' % + (func.__name__, key)) value = func(*args, **kwargs) if value is None: cache.set(key, '__default_cache_value__', expiration) @@ -120,7 +122,7 @@ def block_code(text, lang, inlinestyles=False, linenos=False): if linenos: return '
%s
\n' % code return code - except: + except BaseException: return '
%s
\n' % ( lang, mistune.escape(text) ) @@ -163,7 +165,8 @@ class BlogMarkDownRenderer(mistune.Renderer): if not title: return '%s' % (link, nofollow, text) title = escape(title, quote=True) - return '%s' % (link, title, nofollow, text) + return '%s' % ( + link, title, nofollow, text) class CommonMarkdown(): @@ -177,7 +180,11 @@ class CommonMarkdown(): def send_email(emailto, title, content): from DjangoBlog.blog_signals import send_email_signal - send_email_signal.send(send_email.__class__, emailto=emailto, title=title, content=content) + send_email_signal.send( + send_email.__class__, + emailto=emailto, + title=title, + content=content) def parse_dict_to_url(dict): @@ -225,15 +232,17 @@ def save_user_avatar(url): try: imgname = url.split('/')[-1] if imgname: - path = r'{basedir}/avatar/{img}'.format(basedir=setting.resource_path, img=imgname) + path = r'{basedir}/avatar/{img}'.format( + basedir=setting.resource_path, img=imgname) if os.path.exists(path): os.remove(path) - except: + except BaseException: pass try: rsp = requests.get(url, timeout=2) if rsp.status_code == 200: - basepath = r'{basedir}/avatar/'.format(basedir=setting.resource_path) + basepath = r'{basedir}/avatar/'.format( + basedir=setting.resource_path) if not os.path.exists(basepath): os.makedirs(basepath) @@ -253,7 +262,10 @@ def save_user_avatar(url): def delete_sidebar_cache(username): from django.core.cache.utils import make_template_fragment_key from blog.models import LINK_SHOW_TYPE - keys = (make_template_fragment_key('sidebar', [username + x[0]]) for x in LINK_SHOW_TYPE) + keys = ( + make_template_fragment_key( + 'sidebar', [ + username + x[0]]) for x in LINK_SHOW_TYPE) for k in keys: logger.info('delete sidebar key:' + k) cache.delete(k) diff --git a/DjangoBlog/whoosh_cn_backend.py b/DjangoBlog/whoosh_cn_backend.py index 5b29a9a..4979e08 100644 --- a/DjangoBlog/whoosh_cn_backend.py +++ b/DjangoBlog/whoosh_cn_backend.py @@ -1,6 +1,16 @@ # encoding: utf-8 from __future__ import absolute_import, division, print_function, unicode_literals +from whoosh.writing import AsyncWriter +from whoosh.searching import ResultsPage +from whoosh.qparser import QueryParser +from whoosh.highlight import ContextFragmenter, HtmlFormatter +from whoosh.highlight import highlight as whoosh_highlight +from whoosh.filedb.filestore import FileStorage, RamStorage +from whoosh.fields import BOOLEAN, DATETIME, IDLIST, KEYWORD, NGRAM, NGRAMWORDS, NUMERIC, Schema, TEXT +from whoosh.fields import ID as WHOOSH_ID +from whoosh.analysis import StemmingAnalyzer +from whoosh import index from jieba.analyse import ChineseAnalyzer import json import os @@ -32,19 +42,10 @@ except ImportError: # Handle minimum requirement. if not hasattr(whoosh, '__version__') or whoosh.__version__ < (2, 5, 0): - raise MissingDependency("The 'whoosh' backend requires version 2.5.0 or greater.") + raise MissingDependency( + "The 'whoosh' backend requires version 2.5.0 or greater.") # Bubble up the correct error. -from whoosh import index -from whoosh.analysis import StemmingAnalyzer -from whoosh.fields import ID as WHOOSH_ID -from whoosh.fields import BOOLEAN, DATETIME, IDLIST, KEYWORD, NGRAM, NGRAMWORDS, NUMERIC, Schema, TEXT -from whoosh.filedb.filestore import FileStorage, RamStorage -from whoosh.highlight import highlight as whoosh_highlight -from whoosh.highlight import ContextFragmenter, HtmlFormatter -from whoosh.qparser import QueryParser -from whoosh.searching import ResultsPage -from whoosh.writing import AsyncWriter DATETIME_REGEX = re.compile( '^(?P\d{4})-(?P\d{2})-(?P\d{2})T(?P\d{2}):(?P\d{2}):(?P\d{2})(\.\d{3,6}Z?)?$') @@ -71,17 +72,25 @@ class WhooshSearchBackend(BaseSearchBackend): ) # Characters reserved by Whoosh for special use. - # The '\\' must come first, so as not to overwrite the other slash replacements. + # The '\\' must come first, so as not to overwrite the other slash + # replacements. RESERVED_CHARACTERS = ( '\\', '+', '-', '&&', '||', '!', '(', ')', '{', '}', '[', ']', '^', '"', '~', '*', '?', ':', '.', ) def __init__(self, connection_alias, **connection_options): - super(WhooshSearchBackend, self).__init__(connection_alias, **connection_options) + super( + WhooshSearchBackend, + self).__init__( + connection_alias, + **connection_options) self.setup_complete = False self.use_file_storage = True - self.post_limit = getattr(connection_options, 'POST_LIMIT', 128 * 1024 * 1024) + self.post_limit = getattr( + connection_options, + 'POST_LIMIT', + 128 * 1024 * 1024) self.path = connection_options.get('PATH') if connection_options.get('STORAGE', 'file') != 'file': @@ -89,7 +98,8 @@ class WhooshSearchBackend(BaseSearchBackend): if self.use_file_storage and not self.path: raise ImproperlyConfigured( - "You must specify a 'PATH' in your settings for connection '%s'." % connection_alias) + "You must specify a 'PATH' in your settings for connection '%s'." % + connection_alias) self.log = logging.getLogger('haystack') @@ -106,7 +116,9 @@ class WhooshSearchBackend(BaseSearchBackend): new_index = True if self.use_file_storage and not os.access(self.path, os.W_OK): - raise IOError("The path to your Whoosh index '%s' is not writable for the current user/group." % self.path) + raise IOError( + "The path to your Whoosh index '%s' is not writable for the current user/group." % + self.path) if self.use_file_storage: self.storage = FileStorage(self.path) @@ -146,32 +158,35 @@ class WhooshSearchBackend(BaseSearchBackend): for field_name, field_class in fields.items(): if field_class.is_multivalued: if field_class.indexed is False: - schema_fields[field_class.index_fieldname] = IDLIST(stored=True, field_boost=field_class.boost) + schema_fields[field_class.index_fieldname] = IDLIST( + stored=True, field_boost=field_class.boost) else: - schema_fields[field_class.index_fieldname] = KEYWORD(stored=True, commas=True, scorable=True, - field_boost=field_class.boost) + schema_fields[field_class.index_fieldname] = KEYWORD( + stored=True, commas=True, scorable=True, field_boost=field_class.boost) elif field_class.field_type in ['date', 'datetime']: - schema_fields[field_class.index_fieldname] = DATETIME(stored=field_class.stored, sortable=True) + schema_fields[field_class.index_fieldname] = DATETIME( + stored=field_class.stored, sortable=True) elif field_class.field_type == 'integer': - schema_fields[field_class.index_fieldname] = NUMERIC(stored=field_class.stored, numtype=int, - field_boost=field_class.boost) + schema_fields[field_class.index_fieldname] = NUMERIC( + stored=field_class.stored, numtype=int, field_boost=field_class.boost) elif field_class.field_type == 'float': - schema_fields[field_class.index_fieldname] = NUMERIC(stored=field_class.stored, numtype=float, - field_boost=field_class.boost) + schema_fields[field_class.index_fieldname] = NUMERIC( + stored=field_class.stored, numtype=float, field_boost=field_class.boost) elif field_class.field_type == 'boolean': # Field boost isn't supported on BOOLEAN as of 1.8.2. - schema_fields[field_class.index_fieldname] = BOOLEAN(stored=field_class.stored) + schema_fields[field_class.index_fieldname] = BOOLEAN( + stored=field_class.stored) elif field_class.field_type == 'ngram': - schema_fields[field_class.index_fieldname] = NGRAM(minsize=3, maxsize=15, stored=field_class.stored, - field_boost=field_class.boost) + schema_fields[field_class.index_fieldname] = NGRAM( + minsize=3, maxsize=15, stored=field_class.stored, field_boost=field_class.boost) elif field_class.field_type == 'edge_ngram': schema_fields[field_class.index_fieldname] = NGRAMWORDS(minsize=2, maxsize=15, at='start', stored=field_class.stored, field_boost=field_class.boost) else: # schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True) - schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), - field_boost=field_class.boost, sortable=True) + schema_fields[field_class.index_fieldname] = TEXT( + stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True) if field_class.document is True: content_field_name = field_class.index_fieldname schema_fields[field_class.index_fieldname].spelling = True @@ -215,12 +230,18 @@ class WhooshSearchBackend(BaseSearchBackend): # We'll log the object identifier but won't include the actual object # to avoid the possibility of that generating encoding errors while # processing the log message: - self.log.error(u"%s while preparing object for update" % e.__class__.__name__, - exc_info=True, extra={"data": {"index": index, - "object": get_identifier(obj)}}) + self.log.error( + u"%s while preparing object for update" % + e.__class__.__name__, + exc_info=True, + extra={ + "data": { + "index": index, + "object": get_identifier(obj)}}) if len(iterable) > 0: - # For now, commit no matter what, as we run into locking issues otherwise. + # For now, commit no matter what, as we run into locking issues + # otherwise. writer.commit() def remove(self, obj_or_string, commit=True): @@ -231,12 +252,19 @@ class WhooshSearchBackend(BaseSearchBackend): whoosh_id = get_identifier(obj_or_string) try: - self.index.delete_by_query(q=self.parser.parse(u'%s:"%s"' % (ID, whoosh_id))) + self.index.delete_by_query( + q=self.parser.parse( + u'%s:"%s"' % + (ID, whoosh_id))) except Exception as e: if not self.silently_fail: raise - self.log.error("Failed to remove document '%s' from Whoosh: %s", whoosh_id, e, exc_info=True) + self.log.error( + "Failed to remove document '%s' from Whoosh: %s", + whoosh_id, + e, + exc_info=True) def clear(self, models=None, commit=True): if not self.setup_complete: @@ -254,18 +282,26 @@ class WhooshSearchBackend(BaseSearchBackend): models_to_delete = [] for model in models: - models_to_delete.append(u"%s:%s" % (DJANGO_CT, get_model_ct(model))) + models_to_delete.append( + u"%s:%s" % + (DJANGO_CT, get_model_ct(model))) - self.index.delete_by_query(q=self.parser.parse(u" OR ".join(models_to_delete))) + self.index.delete_by_query( + q=self.parser.parse( + u" OR ".join(models_to_delete))) except Exception as e: if not self.silently_fail: raise if models is not None: - self.log.error("Failed to clear Whoosh index of models '%s': %s", ','.join(models_to_delete), - e, exc_info=True) + self.log.error( + "Failed to clear Whoosh index of models '%s': %s", + ','.join(models_to_delete), + e, + exc_info=True) else: - self.log.error("Failed to clear Whoosh index: %s", e, exc_info=True) + self.log.error( + "Failed to clear Whoosh index: %s", e, exc_info=True) def delete_index(self): # Per the Whoosh mailing list, if wiping out everything from the index, @@ -288,7 +324,7 @@ class WhooshSearchBackend(BaseSearchBackend): def calculate_page(self, start_offset=0, end_offset=None): # Prevent against Whoosh throwing an error. Requires an end_offset # greater than 0. - if not end_offset is None and end_offset <= 0: + if end_offset is not None and end_offset <= 0: end_offset = 1 # Determine the page. @@ -310,11 +346,26 @@ class WhooshSearchBackend(BaseSearchBackend): return page_num, page_length @log_query - def search(self, query_string, sort_by=None, start_offset=0, end_offset=None, - fields='', highlight=False, facets=None, date_facets=None, query_facets=None, - narrow_queries=None, spelling_query=None, within=None, - dwithin=None, distance_point=None, models=None, - limit_to_registered_models=None, result_class=None, **kwargs): + def search( + self, + query_string, + sort_by=None, + start_offset=0, + end_offset=None, + fields='', + highlight=False, + facets=None, + date_facets=None, + query_facets=None, + narrow_queries=None, + spelling_query=None, + within=None, + dwithin=None, + distance_point=None, + models=None, + limit_to_registered_models=None, + result_class=None, + **kwargs): if not self.setup_complete: self.setup() @@ -367,19 +418,29 @@ class WhooshSearchBackend(BaseSearchBackend): sort_by = sort_by_list[0] if facets is not None: - warnings.warn("Whoosh does not handle faceting.", Warning, stacklevel=2) + warnings.warn( + "Whoosh does not handle faceting.", + Warning, + stacklevel=2) if date_facets is not None: - warnings.warn("Whoosh does not handle date faceting.", Warning, stacklevel=2) + warnings.warn( + "Whoosh does not handle date faceting.", + Warning, + stacklevel=2) if query_facets is not None: - warnings.warn("Whoosh does not handle query faceting.", Warning, stacklevel=2) + warnings.warn( + "Whoosh does not handle query faceting.", + Warning, + stacklevel=2) narrowed_results = None self.index = self.index.refresh() if limit_to_registered_models is None: - limit_to_registered_models = getattr(settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True) + limit_to_registered_models = getattr( + settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True) if models and len(models): model_choices = sorted(get_model_ct(model) for model in models) @@ -394,17 +455,19 @@ class WhooshSearchBackend(BaseSearchBackend): if narrow_queries is None: narrow_queries = set() - narrow_queries.add(' OR '.join(['%s:%s' % (DJANGO_CT, rm) for rm in model_choices])) + narrow_queries.add(' OR '.join( + ['%s:%s' % (DJANGO_CT, rm) for rm in model_choices])) narrow_searcher = None if narrow_queries is not None: - # Potentially expensive? I don't see another way to do it in Whoosh... + # Potentially expensive? I don't see another way to do it in + # Whoosh... narrow_searcher = self.index.searcher() for nq in narrow_queries: - recent_narrowed_results = narrow_searcher.search(self.parser.parse(force_text(nq)), - limit=None) + recent_narrowed_results = narrow_searcher.search( + self.parser.parse(force_text(nq)), limit=None) if len(recent_narrowed_results) <= 0: return { @@ -430,7 +493,8 @@ class WhooshSearchBackend(BaseSearchBackend): 'hits': 0, } - page_num, page_length = self.calculate_page(start_offset, end_offset) + page_num, page_length = self.calculate_page( + start_offset, end_offset) search_kwargs = { 'pagelen': page_length, @@ -467,8 +531,12 @@ class WhooshSearchBackend(BaseSearchBackend): 'spelling_suggestion': None, } - results = self._process_results(raw_page, highlight=highlight, query_string=query_string, - spelling_query=spelling_query, result_class=result_class) + results = self._process_results( + raw_page, + highlight=highlight, + query_string=query_string, + spelling_query=spelling_query, + result_class=result_class) searcher.close() if hasattr(narrow_searcher, 'close'): @@ -478,9 +546,11 @@ class WhooshSearchBackend(BaseSearchBackend): else: if self.include_spelling: if spelling_query: - spelling_suggestion = self.create_spelling_suggestion(spelling_query) + spelling_suggestion = self.create_spelling_suggestion( + spelling_query) else: - spelling_suggestion = self.create_spelling_suggestion(query_string) + spelling_suggestion = self.create_spelling_suggestion( + query_string) else: spelling_suggestion = None @@ -490,9 +560,16 @@ class WhooshSearchBackend(BaseSearchBackend): 'spelling_suggestion': spelling_suggestion, } - def more_like_this(self, model_instance, additional_query_string=None, - start_offset=0, end_offset=None, models=None, - limit_to_registered_models=None, result_class=None, **kwargs): + def more_like_this( + self, + model_instance, + additional_query_string=None, + start_offset=0, + end_offset=None, + models=None, + limit_to_registered_models=None, + result_class=None, + **kwargs): if not self.setup_complete: self.setup() @@ -506,7 +583,8 @@ class WhooshSearchBackend(BaseSearchBackend): self.index = self.index.refresh() if limit_to_registered_models is None: - limit_to_registered_models = getattr(settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True) + limit_to_registered_models = getattr( + settings, 'HAYSTACK_LIMIT_TO_REGISTERED_MODELS', True) if models and len(models): model_choices = sorted(get_model_ct(model) for model in models) @@ -521,7 +599,8 @@ class WhooshSearchBackend(BaseSearchBackend): if narrow_queries is None: narrow_queries = set() - narrow_queries.add(' OR '.join(['%s:%s' % (DJANGO_CT, rm) for rm in model_choices])) + narrow_queries.add(' OR '.join( + ['%s:%s' % (DJANGO_CT, rm) for rm in model_choices])) if additional_query_string and additional_query_string != '*': narrow_queries.add(additional_query_string) @@ -529,12 +608,13 @@ class WhooshSearchBackend(BaseSearchBackend): narrow_searcher = None if narrow_queries is not None: - # Potentially expensive? I don't see another way to do it in Whoosh... + # Potentially expensive? I don't see another way to do it in + # Whoosh... narrow_searcher = self.index.searcher() for nq in narrow_queries: - recent_narrowed_results = narrow_searcher.search(self.parser.parse(force_text(nq)), - limit=None) + recent_narrowed_results = narrow_searcher.search( + self.parser.parse(force_text(nq)), limit=None) if len(recent_narrowed_results) <= 0: return { @@ -559,7 +639,8 @@ class WhooshSearchBackend(BaseSearchBackend): results = searcher.search(parsed_query) if len(results): - raw_results = results[0].more_like_this(field_name, top=end_offset) + raw_results = results[0].more_like_this( + field_name, top=end_offset) # Handle the case where the results have been narrowed. if narrowed_results is not None and hasattr(raw_results, 'filter'): @@ -594,7 +675,13 @@ class WhooshSearchBackend(BaseSearchBackend): return results - def _process_results(self, raw_page, highlight=False, query_string='', spelling_query=None, result_class=None): + def _process_results( + self, + raw_page, + highlight=False, + query_string='', + spelling_query=None, + result_class=None): from haystack import connections results = [] @@ -621,15 +708,18 @@ class WhooshSearchBackend(BaseSearchBackend): index = unified_index.get_index(model) string_key = str(key) - if string_key in index.fields and hasattr(index.fields[string_key], 'convert'): + if string_key in index.fields and hasattr( + index.fields[string_key], 'convert'): # Special-cased due to the nature of KEYWORD fields. if index.fields[string_key].is_multivalued: if value is None or len(value) == 0: additional_fields[string_key] = [] else: - additional_fields[string_key] = value.split(',') + additional_fields[string_key] = value.split( + ',') else: - additional_fields[string_key] = index.fields[string_key].convert(value) + additional_fields[string_key] = index.fields[string_key].convert( + value) else: additional_fields[string_key] = self._to_python(value) @@ -652,16 +742,23 @@ class WhooshSearchBackend(BaseSearchBackend): self.content_field_name: [whoosh_result], } - result = result_class(app_label, model_name, raw_result[DJANGO_ID], score, **additional_fields) + result = result_class( + app_label, + model_name, + raw_result[DJANGO_ID], + score, + **additional_fields) results.append(result) else: hits -= 1 if self.include_spelling: if spelling_query: - spelling_suggestion = self.create_spelling_suggestion(spelling_query) + spelling_suggestion = self.create_spelling_suggestion( + spelling_query) else: - spelling_suggestion = self.create_spelling_suggestion(query_string) + spelling_suggestion = self.create_spelling_suggestion( + query_string) return { 'results': results, @@ -742,17 +839,30 @@ class WhooshSearchBackend(BaseSearchBackend): for dk, dv in date_values.items(): date_values[dk] = int(dv) - return datetime(date_values['year'], date_values['month'], date_values['day'], date_values['hour'], - date_values['minute'], date_values['second']) + return datetime( + date_values['year'], + date_values['month'], + date_values['day'], + date_values['hour'], + date_values['minute'], + date_values['second']) try: # Attempt to use json to load the values. converted_value = json.loads(value) # Try to handle most built-in types. - if isinstance(converted_value, (list, tuple, set, dict, six.integer_types, float, complex)): + if isinstance( + converted_value, + (list, + tuple, + set, + dict, + six.integer_types, + float, + complex)): return converted_value - except: + except BaseException: # If it fails (SyntaxError or its ilk) or we don't trust it, # continue on. pass @@ -823,7 +933,8 @@ class WhooshSearchQuery(BaseSearchQuery): if field == 'content': index_fieldname = '' else: - index_fieldname = u'%s:' % connections[self._using].get_unified_index().get_index_fieldname(field) + index_fieldname = u'%s:' % connections[self._using].get_unified_index( + ).get_index_fieldname(field) filter_types = { 'content': '%s', @@ -841,23 +952,32 @@ class WhooshSearchQuery(BaseSearchQuery): if value.post_process is False: query_frag = prepared_value else: - if filter_type in ['content', 'contains', 'startswith', 'endswith', 'fuzzy']: + if filter_type in [ + 'content', + 'contains', + 'startswith', + 'endswith', + 'fuzzy']: if value.input_type_name == 'exact': query_frag = prepared_value else: - # Iterate over terms & incorportate the converted form of each into the query. + # Iterate over terms & incorportate the converted form of + # each into the query. terms = [] if isinstance(prepared_value, six.string_types): possible_values = prepared_value.split(' ') else: if is_datetime is True: - prepared_value = self._convert_datetime(prepared_value) + prepared_value = self._convert_datetime( + prepared_value) possible_values = [prepared_value] for possible_value in possible_values: - terms.append(filter_types[filter_type] % self.backend._from_python(possible_value)) + terms.append( + filter_types[filter_type] % + self.backend._from_python(possible_value)) if len(terms) == 1: query_frag = terms[0] diff --git a/accounts/admin.py b/accounts/admin.py index 67226e4..45ab895 100644 --- a/accounts/admin.py +++ b/accounts/admin.py @@ -58,6 +58,13 @@ class BlogUserChangeForm(UserChangeForm): class BlogUserAdmin(UserAdmin): form = BlogUserChangeForm add_form = BlogUserCreationForm - list_display = ('id', 'nickname', 'username', 'email', 'last_login', 'date_joined', 'source') + list_display = ( + 'id', + 'nickname', + 'username', + 'email', + 'last_login', + 'date_joined', + 'source') list_display_links = ('id', 'username') ordering = ('-id',) diff --git a/accounts/forms.py b/accounts/forms.py index d8621b0..1f60cd4 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -22,7 +22,8 @@ from django.core.exceptions import ValidationError class LoginForm(AuthenticationForm): def __init__(self, *args, **kwargs): super(LoginForm, self).__init__(*args, **kwargs) - self.fields['username'].widget = widgets.TextInput(attrs={'placeholder': "username", "class": "form-control"}) + self.fields['username'].widget = widgets.TextInput( + attrs={'placeholder': "username", "class": "form-control"}) self.fields['password'].widget = widgets.PasswordInput( attrs={'placeholder': "password", "class": "form-control"}) @@ -31,8 +32,10 @@ class RegisterForm(UserCreationForm): def __init__(self, *args, **kwargs): super(RegisterForm, self).__init__(*args, **kwargs) - self.fields['username'].widget = widgets.TextInput(attrs={'placeholder': "username", "class": "form-control"}) - self.fields['email'].widget = widgets.EmailInput(attrs={'placeholder': "email", "class": "form-control"}) + self.fields['username'].widget = widgets.TextInput( + attrs={'placeholder': "username", "class": "form-control"}) + self.fields['email'].widget = widgets.EmailInput( + attrs={'placeholder': "email", "class": "form-control"}) self.fields['password1'].widget = widgets.PasswordInput( attrs={'placeholder': "password", "class": "form-control"}) self.fields['password2'].widget = widgets.PasswordInput( diff --git a/accounts/models.py b/accounts/models.py index e292dc8..ff6241e 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -14,14 +14,17 @@ class BlogUser(AbstractUser): source = models.CharField("创建来源", max_length=100, blank=True) def get_absolute_url(self): - return reverse('blog:author_detail', kwargs={'author_name': self.username}) + return reverse( + 'blog:author_detail', kwargs={ + 'author_name': self.username}) def __str__(self): return self.email def get_full_url(self): site = get_current_site().domain - url = "https://{site}{path}".format(site=site, path=self.get_absolute_url()) + url = "https://{site}{path}".format(site=site, + path=self.get_absolute_url()) return url class Meta: diff --git a/accounts/tests.py b/accounts/tests.py index 37bbcee..77d5e9b 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -18,11 +18,15 @@ class AccountTest(TestCase): def test_validate_account(self): site = get_current_site().domain - user = BlogUser.objects.create_superuser(email="liangliangyy1@gmail.com", - username="liangliangyy1", password="qwer!@#$ggg") + user = BlogUser.objects.create_superuser( + email="liangliangyy1@gmail.com", + username="liangliangyy1", + password="qwer!@#$ggg") testuser = BlogUser.objects.get(username='liangliangyy1') - loginresult = self.client.login(username='liangliangyy1', password='qwer!@#$ggg') + loginresult = self.client.login( + username='liangliangyy1', + password='qwer!@#$ggg') self.assertEqual(loginresult, True) response = self.client.get('/admin/') self.assertEqual(response.status_code, 200) @@ -46,18 +50,25 @@ class AccountTest(TestCase): self.assertEqual(response.status_code, 200) def test_validate_register(self): - self.assertEquals(0, len(BlogUser.objects.filter(email='user123@user.com'))) + self.assertEquals( + 0, len( + BlogUser.objects.filter( + email='user123@user.com'))) response = self.client.post(reverse('account:register'), { 'username': 'user1233', 'email': 'user123@user.com', 'password1': 'password123!q@wE#R$T', 'password2': 'password123!q@wE#R$T', }) - self.assertEquals(1, len(BlogUser.objects.filter(email='user123@user.com'))) + self.assertEquals( + 1, len( + BlogUser.objects.filter( + email='user123@user.com'))) user = BlogUser.objects.filter(email='user123@user.com')[0] sign = get_md5(get_md5(settings.SECRET_KEY + str(user.id))) path = reverse('accounts:result') - url = '{path}?type=validation&id={id}&sign={sign}'.format(path=path, id=user.id, sign=sign) + url = '{path}?type=validation&id={id}&sign={sign}'.format( + path=path, id=user.id, sign=sign) response = self.client.get(url) self.assertEqual(response.status_code, 200) diff --git a/accounts/urls.py b/accounts/urls.py index a8d1832..a10ff00 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -21,9 +21,16 @@ 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'), - url(r'^logout/$', views.LogoutView.as_view(), name='logout'), - path(r'account/result.html', views.account_result, name='result') -] +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'), + url(r'^logout/$', + views.LogoutView.as_view(), + name='logout'), + path(r'account/result.html', + views.account_result, + name='result')] diff --git a/accounts/user_login_backend.py b/accounts/user_login_backend.py index 74b464a..d26ad09 100644 --- a/accounts/user_login_backend.py +++ b/accounts/user_login_backend.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/accounts/views.py b/accounts/views.py index 77a5e4c..6e5f538 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -41,22 +41,28 @@ class RegisterView(FormView): if settings.DEBUG: site = '127.0.0.1:8000' path = reverse('account:result') - url = "http://{site}{path}?type=validation&id={id}&sign={sign}".format(site=site, path=path, id=user.id, - sign=sign) + url = "http://{site}{path}?type=validation&id={id}&sign={sign}".format( + site=site, path=path, id=user.id, sign=sign) content = """

请点击下面链接验证您的邮箱

- + {url} - + 再次感谢您!
如果上面链接无法打开,请将此链接复制至浏览器。 {url} """.format(url=url) - send_email(emailto=[user.email, ], title='验证您的电子邮箱', content=content) - - url = reverse('accounts:result') + '?type=register&id=' + str(user.id) + send_email( + emailto=[ + user.email, + ], + title='验证您的电子邮箱', + content=content) + + url = reverse('accounts:result') + \ + '?type=register&id=' + str(user.id) return HttpResponseRedirect(url) else: return self.render_to_response({ @@ -119,7 +125,9 @@ class LoginView(FormView): def get_success_url(self): redirect_to = self.request.POST.get(self.redirect_field_name) - if not is_safe_url(url=redirect_to, allowed_hosts=[self.request.get_host()]): + if not is_safe_url( + url=redirect_to, allowed_hosts=[ + self.request.get_host()]): redirect_to = self.success_url return redirect_to diff --git a/blog/admin.py b/blog/admin.py index 898686e..f5604bd 100644 --- a/blog/admin.py +++ b/blog/admin.py @@ -60,13 +60,25 @@ class ArticlelAdmin(admin.ModelAdmin): search_fields = ('body', 'title') form = ArticleForm list_display = ( - 'id', 'title', 'author', 'link_to_category', 'created_time', 'views', 'status', 'type', 'article_order') + 'id', + 'title', + 'author', + 'link_to_category', + 'created_time', + 'views', + 'status', + 'type', + 'article_order') list_display_links = ('id', 'title') list_filter = (ArticleListFilter, 'status', 'type', 'category', 'tags') filter_horizontal = ('tags',) exclude = ('created_time', 'last_mod_time') view_on_site = True - actions = [makr_article_publish, draft_article, close_article_commentstatus, open_article_commentstatus] + actions = [ + makr_article_publish, + draft_article, + close_article_commentstatus, + open_article_commentstatus] def link_to_category(self, obj): info = (obj.category._meta.app_label, obj.category._meta.model_name) @@ -77,7 +89,8 @@ class ArticlelAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): form = super(ArticlelAdmin, self).get_form(request, obj, **kwargs) - form.base_fields['author'].queryset = get_user_model().objects.filter(is_superuser=True) + form.base_fields['author'].queryset = get_user_model( + ).objects.filter(is_superuser=True) return form def save_model(self, request, obj, form, change): diff --git a/blog/context_processors.py b/blog/context_processors.py index 00c8c88..2fb2ad7 100644 --- a/blog/context_processors.py +++ b/blog/context_processors.py @@ -39,14 +39,14 @@ def seo_processor(requests): 'SITE_BASE_URL': requests.scheme + '://' + requests.get_host() + '/', 'ARTICLE_SUB_LENGTH': setting.article_sub_length, 'nav_category_list': Category.objects.all(), - 'nav_pages': Article.objects.filter(type='p', status='p'), + 'nav_pages': Article.objects.filter( + type='p', + status='p'), 'OPEN_SITE_COMMENT': setting.open_site_comment, 'BEIAN_CODE': setting.beiancode, 'ANALYTICS_CODE': setting.analyticscode, "BEIAN_CODE_GONGAN": setting.gongan_beiancode, "SHOW_GONGAN_CODE": setting.show_gongan_code, - "CURRENT_YEAR": datetime.now().year - - } + "CURRENT_YEAR": datetime.now().year} cache.set(key, value, 60 * 60 * 10) return value diff --git a/blog/documents.py b/blog/documents.py index 0ea6618..e5fa9e8 100644 --- a/blog/documents.py +++ b/blog/documents.py @@ -3,13 +3,14 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @file: documents.py @time: 2019-04-05 13:05 """ +from elasticsearch_dsl.connections import connections import time from blog.models import Article, Category, Tag from elasticsearch_dsl import Document, Date, Integer, Keyword, Text, Object, Boolean @@ -18,10 +19,10 @@ from django.conf import settings ELASTICSEARCH_ENABLED = hasattr(settings, 'ELASTICSEARCH_DSL') -from elasticsearch_dsl.connections import connections if ELASTICSEARCH_ENABLED: - connections.create_connection(hosts=[settings.ELASTICSEARCH_DSL['default']['hosts']]) + connections.create_connection( + hosts=[settings.ELASTICSEARCH_DSL['default']['hosts']]) class ElapsedTimeDocument(Document): @@ -49,8 +50,17 @@ class ElaspedTimeDocumentManager(): # if not hasattr(ElaspedTimeDocumentManager, 'mapping_created'): # ElapsedTimeDocument.init() # setattr(ElaspedTimeDocumentManager, 'mapping_created', True) - doc = ElapsedTimeDocument(meta={'id': int(round(time.time() * 1000))}, url=url, time_taken=time_taken, - log_datetime=log_datetime, type=type, useragent=useragent) + doc = ElapsedTimeDocument( + meta={ + 'id': int( + round( + time.time() * + 1000))}, + url=url, + time_taken=time_taken, + log_datetime=log_datetime, + type=type, + useragent=useragent) doc.save() @@ -103,23 +113,28 @@ class ArticleDocumentManager(): es.indices.delete(index='blog', ignore=[400, 404]) def convert_to_doc(self, articles): - return [ArticleDocument(meta={'id': article.id}, body=article.body, title=article.title, - author={ - 'nikename': article.author.username, - 'id': article.author.id - }, - category={ - 'name': article.category.name, - 'id': article.category.id - }, - tags=[{'name': t.name, 'id': t.id} for t in article.tags.all()], - pub_time=article.pub_time, - status=article.status, - comment_status=article.comment_status, - type=article.type, - views=article.views, - article_order=article.article_order - ) for article in articles] + return [ + ArticleDocument( + meta={ + 'id': article.id}, + body=article.body, + title=article.title, + author={ + 'nikename': article.author.username, + 'id': article.author.id}, + category={ + 'name': article.category.name, + 'id': article.category.id}, + tags=[ + { + 'name': t.name, + 'id': t.id} for t in article.tags.all()], + pub_time=article.pub_time, + status=article.status, + comment_status=article.comment_status, + type=article.type, + views=article.views, + article_order=article.article_order) for article in articles] def rebuild(self, articles=None): ArticleDocument.init() diff --git a/blog/forms.py b/blog/forms.py index 1df8023..5cb1086 100644 --- a/blog/forms.py +++ b/blog/forms.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/blog/management/commands/build_index.py b/blog/management/commands/build_index.py index f97a1e0..d8fb12f 100644 --- a/blog/management/commands/build_index.py +++ b/blog/management/commands/build_index.py @@ -3,7 +3,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/blog/management/commands/build_search_words.py b/blog/management/commands/build_search_words.py index 976b2a9..f955ffe 100644 --- a/blog/management/commands/build_search_words.py +++ b/blog/management/commands/build_search_words.py @@ -3,7 +3,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -20,5 +20,6 @@ class Command(BaseCommand): help = 'build search words' def handle(self, *args, **options): - datas = set([t.name for t in Tag.objects.all()] + [t.name for t in Category.objects.all()]) + datas = set([t.name for t in Tag.objects.all()] + + [t.name for t in Category.objects.all()]) print('\n'.join(datas)) diff --git a/blog/management/commands/clear_cache.py b/blog/management/commands/clear_cache.py index f941bf4..0cddbf8 100644 --- a/blog/management/commands/clear_cache.py +++ b/blog/management/commands/clear_cache.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/blog/management/commands/create_testdata.py b/blog/management/commands/create_testdata.py index c77ef6a..24a578f 100644 --- a/blog/management/commands/create_testdata.py +++ b/blog/management/commands/create_testdata.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -24,24 +24,25 @@ class Command(BaseCommand): help = 'create test datas' def handle(self, *args, **options): - user = \ - get_user_model().objects.get_or_create(email='test@test.com', username='测试用户', - password='test!q@w#eTYU')[0] + user = get_user_model().objects.get_or_create( + email='test@test.com', username='测试用户', password='test!q@w#eTYU')[0] - pcategory = Category.objects.get_or_create(name='我是父类目', parent_category=None)[0] + pcategory = Category.objects.get_or_create( + name='我是父类目', parent_category=None)[0] - category = Category.objects.get_or_create(name='子类目', parent_category=pcategory)[0] + category = Category.objects.get_or_create( + name='子类目', parent_category=pcategory)[0] category.save() basetag = Tag() basetag.name = "标签" basetag.save() for i in range(1, 20): - article = Article.objects.get_or_create(category=category, - title='nice title ' + str(i), - body='nice content ' + str(i), - author=user - )[0] + article = Article.objects.get_or_create( + category=category, + title='nice title ' + str(i), + body='nice content ' + str(i), + author=user)[0] tag = Tag() tag.name = "标签" + str(i) tag.save() diff --git a/blog/management/commands/ping_baidu.py b/blog/management/commands/ping_baidu.py index e97bd0a..14235a0 100644 --- a/blog/management/commands/ping_baidu.py +++ b/blog/management/commands/ping_baidu.py @@ -25,8 +25,15 @@ class Command(BaseCommand): help = 'notify baidu url' def add_arguments(self, parser): - parser.add_argument('data_type', type=str, choices=['all', 'article', 'tag', 'category'], - help='article : all article,tag : all tag,category: all category,all: All of these') + parser.add_argument( + 'data_type', + type=str, + choices=[ + 'all', + 'article', + 'tag', + 'category'], + help='article : all article,tag : all tag,category: all category,all: All of these') def get_full_url(self, path): url = "https://{site}{path}".format(site=site, path=path) @@ -49,6 +56,9 @@ class Command(BaseCommand): url = category.get_absolute_url() urls.append(self.get_full_url(url)) - self.stdout.write(self.style.SUCCESS('start notify %d urls' % len(urls))) + self.stdout.write( + self.style.SUCCESS( + 'start notify %d urls' % + len(urls))) SpiderNotify.baidu_notify(urls) self.stdout.write(self.style.SUCCESS('finish notify')) diff --git a/blog/management/commands/sync_user_avatar.py b/blog/management/commands/sync_user_avatar.py index 24bf108..0fe86cc 100644 --- a/blog/management/commands/sync_user_avatar.py +++ b/blog/management/commands/sync_user_avatar.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -30,7 +30,9 @@ class Command(BaseCommand): url = u.picture url = save_user_avatar(url) if url: - self.stdout.write('结束同步:{id}.url:{url}'.format(id=u.nikename, url=url)) + self.stdout.write( + '结束同步:{id}.url:{url}'.format( + id=u.nikename, url=url)) u.picture = url u.save() self.stdout.write('结束同步') diff --git a/blog/middleware.py b/blog/middleware.py index b30d42a..265e9c4 100644 --- a/blog/middleware.py +++ b/blog/middleware.py @@ -41,9 +41,14 @@ class OnlineMiddleware(object): url = request.path from django.utils import timezone - ElaspedTimeDocumentManager.create(url=url, time_taken=time_taken, log_datetime=timezone.now(), - type='blog', useragent=http_user_agent) - response.content = response.content.replace(b'', str.encode(str(cast_time)[:5])) + ElaspedTimeDocumentManager.create( + url=url, + time_taken=time_taken, + log_datetime=timezone.now(), + type='blog', + useragent=http_user_agent) + response.content = response.content.replace( + b'', str.encode(str(cast_time)[:5])) except Exception as e: logger.error("Error OnlineMiddleware: %s" % e) return response diff --git a/blog/models.py b/blog/models.py index 720e911..78deeae 100644 --- a/blog/models.py +++ b/blog/models.py @@ -29,19 +29,23 @@ class BaseModel(models.Model): last_mod_time = models.DateTimeField('修改时间', default=now) def save(self, *args, **kwargs): - is_update_views = isinstance(self, Article) and 'update_fields' in kwargs and kwargs['update_fields'] == [ - 'views'] + is_update_views = isinstance( + self, + Article) and 'update_fields' in kwargs and kwargs['update_fields'] == ['views'] if is_update_views: Article.objects.filter(pk=self.pk).update(views=self.views) else: if 'slug' in self.__dict__: - slug = getattr(self, 'title') if 'title' in self.__dict__ else getattr(self, 'name') + slug = getattr( + self, 'title') if 'title' in self.__dict__ else getattr( + self, 'name') setattr(self, 'slug', slugify(slug)) super().save(*args, **kwargs) def get_full_url(self): site = get_current_site().domain - url = "https://{site}{path}".format(site=site, path=self.get_absolute_url()) + url = "https://{site}{path}".format(site=site, + path=self.get_absolute_url()) return url class Meta: @@ -68,15 +72,34 @@ class Article(BaseModel): ) title = models.CharField('标题', max_length=200, unique=True) body = MDTextField('正文') - pub_time = models.DateTimeField('发布时间', blank=False, null=False, default=now) - status = models.CharField('文章状态', max_length=1, choices=STATUS_CHOICES, default='p') - comment_status = models.CharField('评论状态', max_length=1, choices=COMMENT_STATUS, default='o') + pub_time = models.DateTimeField( + '发布时间', blank=False, null=False, default=now) + status = models.CharField( + '文章状态', + max_length=1, + choices=STATUS_CHOICES, + default='p') + comment_status = models.CharField( + '评论状态', + max_length=1, + choices=COMMENT_STATUS, + default='o') type = models.CharField('类型', max_length=1, choices=TYPE, default='a') views = models.PositiveIntegerField('浏览量', default=0) - author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者', blank=False, null=False, - on_delete=models.CASCADE) - article_order = models.IntegerField('排序,数字越大越靠前', blank=False, null=False, default=0) - category = models.ForeignKey('Category', verbose_name='分类', on_delete=models.CASCADE, blank=False, null=False) + author = models.ForeignKey( + settings.AUTH_USER_MODEL, + verbose_name='作者', + blank=False, + null=False, + on_delete=models.CASCADE) + article_order = models.IntegerField( + '排序,数字越大越靠前', blank=False, null=False, default=0) + category = models.ForeignKey( + 'Category', + verbose_name='分类', + on_delete=models.CASCADE, + blank=False, + null=False) tags = models.ManyToManyField('Tag', verbose_name='标签集合', blank=True) def body_to_string(self): @@ -132,7 +155,8 @@ class Article(BaseModel): @cache_decorator(expiration=60 * 100) def next_article(self): # 下一篇 - return Article.objects.filter(id__gt=self.id, status='p').order_by('id').first() + return Article.objects.filter( + id__gt=self.id, status='p').order_by('id').first() @cache_decorator(expiration=60 * 100) def prev_article(self): @@ -143,7 +167,12 @@ 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, on_delete=models.CASCADE) + parent_category = models.ForeignKey( + 'self', + verbose_name="父级分类", + blank=True, + null=True, + on_delete=models.CASCADE) slug = models.SlugField(default='no-slug', max_length=60, blank=True) class Meta: @@ -152,7 +181,9 @@ class Category(BaseModel): verbose_name_plural = verbose_name def get_absolute_url(self): - return reverse('blog:category_detail', kwargs={'category_name': self.slug}) + return reverse( + 'blog:category_detail', kwargs={ + 'category_name': self.slug}) def __str__(self): return self.name @@ -161,7 +192,7 @@ class Category(BaseModel): def get_category_tree(self): """ 递归获得分类目录的父级 - :return: + :return: """ categorys = [] @@ -177,7 +208,7 @@ class Category(BaseModel): def get_sub_categorys(self): """ 获得当前分类目录所有子集 - :return: + :return: """ categorys = [] all_categorys = Category.objects.all() @@ -222,8 +253,13 @@ class Links(models.Model): name = models.CharField('链接名称', max_length=30, unique=True) link = models.URLField('链接地址') sequence = models.IntegerField('排序', unique=True) - is_enable = models.BooleanField('是否显示', default=True, blank=False, null=False) - show_type = models.CharField('显示类型', max_length=1, choices=LINK_SHOW_TYPE, default='i') + is_enable = models.BooleanField( + '是否显示', default=True, blank=False, null=False) + show_type = models.CharField( + '显示类型', + max_length=1, + choices=LINK_SHOW_TYPE, + default='i') created_time = models.DateTimeField('创建时间', default=now) last_mod_time = models.DateTimeField('修改时间', default=now) @@ -256,21 +292,58 @@ class SideBar(models.Model): class BlogSettings(models.Model): '''站点设置 ''' - sitename = models.CharField("网站名称", max_length=200, null=False, blank=False, default='') - site_description = models.TextField("网站描述", max_length=1000, null=False, blank=False, default='') - site_seo_description = models.TextField("网站SEO描述", max_length=1000, null=False, blank=False, default='') - site_keywords = models.TextField("网站关键字", max_length=1000, null=False, blank=False, default='') + sitename = models.CharField( + "网站名称", + max_length=200, + null=False, + blank=False, + default='') + site_description = models.TextField( + "网站描述", + max_length=1000, + null=False, + blank=False, + default='') + site_seo_description = models.TextField( + "网站SEO描述", max_length=1000, null=False, blank=False, default='') + site_keywords = models.TextField( + "网站关键字", + max_length=1000, + null=False, + blank=False, + default='') article_sub_length = models.IntegerField("文章摘要长度", default=300) sidebar_article_count = models.IntegerField("侧边栏文章数目", default=10) sidebar_comment_count = models.IntegerField("侧边栏评论数目", default=5) show_google_adsense = models.BooleanField('是否显示谷歌广告', default=False) - google_adsense_codes = models.TextField('广告内容', max_length=2000, null=True, blank=True, default='') + google_adsense_codes = models.TextField( + '广告内容', max_length=2000, null=True, blank=True, default='') open_site_comment = models.BooleanField('是否打开网站评论功能', default=True) - beiancode = models.CharField('备案号', max_length=2000, null=True, blank=True, default='') - analyticscode = models.TextField("网站统计代码", max_length=1000, null=False, blank=False, default='') - show_gongan_code = models.BooleanField('是否显示公安备案号', default=False, null=False) - gongan_beiancode = models.TextField('公安备案号', max_length=2000, null=True, blank=True, default='') - resource_path = models.CharField("静态文件保存地址", max_length=300, null=False, default='/var/www/resource/') + beiancode = models.CharField( + '备案号', + max_length=2000, + null=True, + blank=True, + default='') + analyticscode = models.TextField( + "网站统计代码", + max_length=1000, + null=False, + blank=False, + default='') + show_gongan_code = models.BooleanField( + '是否显示公安备案号', default=False, null=False) + gongan_beiancode = models.TextField( + '公安备案号', + max_length=2000, + null=True, + blank=True, + default='') + resource_path = models.CharField( + "静态文件保存地址", + max_length=300, + null=False, + default='/var/www/resource/') class Meta: verbose_name = '网站配置' diff --git a/blog/search_indexes.py b/blog/search_indexes.py index ed80e65..e14349e 100644 --- a/blog/search_indexes.py +++ b/blog/search_indexes.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/blog/templatetags/blog_tags.py b/blog/templatetags/blog_tags.py index 760f8d5..dc8ee3a 100644 --- a/blog/templatetags/blog_tags.py +++ b/blog/templatetags/blog_tags.py @@ -135,13 +135,18 @@ def load_sidebar(user, linktype): logger.info('load sidebar') from DjangoBlog.utils import get_blog_setting blogsetting = get_blog_setting() - recent_articles = Article.objects.filter(status='p')[:blogsetting.sidebar_article_count] + recent_articles = Article.objects.filter( + status='p')[:blogsetting.sidebar_article_count] sidebar_categorys = Category.objects.all() - extra_sidebars = SideBar.objects.filter(is_enable=True).order_by('sequence') - most_read_articles = Article.objects.filter(status='p').order_by('-views')[:blogsetting.sidebar_article_count] + extra_sidebars = SideBar.objects.filter( + is_enable=True).order_by('sequence') + most_read_articles = Article.objects.filter(status='p').order_by( + '-views')[:blogsetting.sidebar_article_count] dates = Article.objects.datetimes('created_time', 'month', order='DESC') - links = Links.objects.filter(is_enable=True).filter(Q(show_type=str(linktype)) | Q(show_type='a')) - commment_list = Comment.objects.filter(is_enable=True).order_by('-id')[:blogsetting.sidebar_comment_count] + links = Links.objects.filter(is_enable=True).filter( + Q(show_type=str(linktype)) | Q(show_type='a')) + commment_list = Comment.objects.filter(is_enable=True).order_by( + '-id')[:blogsetting.sidebar_comment_count] # 标签云 计算字体大小 # 根据总数计算出平均值 大小为 (数目/平均值)*步长 increment = 5 @@ -152,7 +157,8 @@ def load_sidebar(user, linktype): count = sum([t[1] for t in s]) dd = 1 if (count == 0 or not len(tags)) else count / len(tags) import random - sidebar_tags = list(map(lambda x: (x[0], x[1], (x[1] / dd) * increment + 10), s)) + sidebar_tags = list( + map(lambda x: (x[0], x[1], (x[1] / dd) * increment + 10), s)) random.shuffle(sidebar_tags) return { @@ -195,33 +201,57 @@ def load_pagination_info(page_obj, page_type, tag_name): next_url = reverse('blog:index_page', kwargs={'page': next_number}) if page_obj.has_previous(): previous_number = page_obj.previous_page_number() - previous_url = reverse('blog:index_page', kwargs={'page': previous_number}) + previous_url = reverse( + 'blog:index_page', kwargs={ + 'page': previous_number}) if page_type == '分类标签归档': tag = get_object_or_404(Tag, name=tag_name) if page_obj.has_next(): next_number = page_obj.next_page_number() - next_url = reverse('blog:tag_detail_page', kwargs={'page': next_number, 'tag_name': tag.slug}) + next_url = reverse( + 'blog:tag_detail_page', + kwargs={ + 'page': next_number, + 'tag_name': tag.slug}) if page_obj.has_previous(): previous_number = page_obj.previous_page_number() - previous_url = reverse('blog:tag_detail_page', kwargs={'page': previous_number, 'tag_name': tag.slug}) + previous_url = reverse( + 'blog:tag_detail_page', + kwargs={ + 'page': previous_number, + 'tag_name': tag.slug}) if page_type == '作者文章归档': if page_obj.has_next(): next_number = page_obj.next_page_number() - next_url = reverse('blog:author_detail_page', kwargs={'page': next_number, 'author_name': tag_name}) + next_url = reverse( + 'blog:author_detail_page', + kwargs={ + 'page': next_number, + 'author_name': tag_name}) if page_obj.has_previous(): previous_number = page_obj.previous_page_number() - previous_url = reverse('blog:author_detail_page', kwargs={'page': previous_number, 'author_name': tag_name}) + previous_url = reverse( + 'blog:author_detail_page', + kwargs={ + 'page': previous_number, + 'author_name': tag_name}) if page_type == '分类目录归档': category = get_object_or_404(Category, name=tag_name) if page_obj.has_next(): next_number = page_obj.next_page_number() - next_url = reverse('blog:category_detail_page', - kwargs={'page': next_number, 'category_name': category.slug}) + next_url = reverse( + 'blog:category_detail_page', + kwargs={ + 'page': next_number, + 'category_name': category.slug}) if page_obj.has_previous(): previous_number = page_obj.previous_page_number() - previous_url = reverse('blog:category_detail_page', - kwargs={'page': previous_number, 'category_name': category.slug}) + previous_url = reverse( + 'blog:category_detail_page', + kwargs={ + 'page': previous_number, + 'category_name': category.slug}) return { 'previous_url': previous_url, @@ -275,10 +305,11 @@ def gravatar_url(email, size=40): return o[0].picture email = email.encode('utf-8') - default = "https://resource.lylinux.net/image/2017/03/26/120117.jpg".encode('utf-8') + default = "https://resource.lylinux.net/image/2017/03/26/120117.jpg".encode( + 'utf-8') - url = "https://www.gravatar.com/avatar/%s?%s" % ( - hashlib.md5(email.lower()).hexdigest(), urllib.parse.urlencode({'d': default, 's': str(size)})) + url = "https://www.gravatar.com/avatar/%s?%s" % (hashlib.md5( + email.lower()).hexdigest(), urllib.parse.urlencode({'d': default, 's': str(size)})) cache.set(cachekey, url, 60 * 60 * 10) return url @@ -287,7 +318,9 @@ def gravatar_url(email, size=40): def gravatar(email, size=40): """获得gravatar头像""" url = gravatar_url(email, size) - return mark_safe('' % (url, size, size)) + return mark_safe( + '' % + (url, size, size)) @register.simple_tag diff --git a/blog/tests.py b/blog/tests.py index 876fbe7..d1ce069 100644 --- a/blog/tests.py +++ b/blog/tests.py @@ -22,7 +22,9 @@ class ArticleTest(TestCase): def test_validate_article(self): site = get_current_site().domain - user = BlogUser.objects.get_or_create(email="liangliangyy@gmail.com", username="liangliangyy")[0] + user = BlogUser.objects.get_or_create( + email="liangliangyy@gmail.com", + username="liangliangyy")[0] user.set_password("liangliangyy") user.is_staff = True user.is_superuser = True @@ -104,7 +106,9 @@ class ArticleTest(TestCase): p = Paginator(Article.objects.filter(tags=tag), 2) self.__check_pagination__(p, '分类标签归档', tag.slug) - p = Paginator(Article.objects.filter(author__username='liangliangyy'), 2) + p = Paginator( + Article.objects.filter( + author__username='liangliangyy'), 2) self.__check_pagination__(p, '作者文章归档', 'liangliangyy') p = Paginator(Article.objects.filter(category=category), 2) @@ -120,7 +124,10 @@ class ArticleTest(TestCase): u = gravatar_url('liangliangyy@gmail.com') u = gravatar('liangliangyy@gmail.com') - link = Links(sequence=1, name="lylinux", link='https://wwww.lylinux.net') + link = Links( + sequence=1, + name="lylinux", + link='https://wwww.lylinux.net') link.save() response = self.client.get('/links.html') self.assertEqual(response.status_code, 200) @@ -141,7 +148,9 @@ class ArticleTest(TestCase): self.assertEqual(response.status_code, 200) def test_validate_feed(self): - user = BlogUser.objects.get_or_create(email="liangliangyy12@gmail.com", username="liangliangyy")[0] + user = BlogUser.objects.get_or_create( + email="liangliangyy12@gmail.com", + username="liangliangyy")[0] user.set_password("liangliangyy") user.save() self.client.login(username='liangliangyy', password='liangliangyy') @@ -157,7 +166,8 @@ class ArticleTest(TestCase): def test_image(self): import requests - rsp = requests.get('https://www.python.org/static/img/python-logo@2x.png') + rsp = requests.get( + 'https://www.python.org/static/img/python-logo@2x.png') imagepath = os.path.join(settings.BASE_DIR, 'python.png') with open(imagepath, 'wb') as file: file.write(rsp.content) @@ -165,14 +175,17 @@ class ArticleTest(TestCase): self.assertEqual(rsp.status_code, 403) sign = get_md5(get_md5(settings.SECRET_KEY)) with open(imagepath, 'rb') as file: - imgfile = SimpleUploadedFile('python.png', file.read(), content_type='image/jpg') + imgfile = SimpleUploadedFile( + 'python.png', file.read(), content_type='image/jpg') form_data = {'python.png': imgfile} - rsp = self.client.post('/upload?sign=' + sign, form_data, follow=True) + rsp = self.client.post( + '/upload?sign=' + sign, form_data, follow=True) self.assertEqual(rsp.status_code, 200) from DjangoBlog.utils import save_user_avatar, send_email send_email(['qq@qq.com'], 'testTitle', 'testContent') - save_user_avatar('https://www.python.org/static/img/python-logo@2x.png') + save_user_avatar( + 'https://www.python.org/static/img/python-logo@2x.png') """ data = SimpleUploadedFile(imagepath, b'file_content', content_type='image/jpg') rsp = self.client.post('/upload', {'django.jpg': data}) diff --git a/blog/urls.py b/blog/urls.py index df2e6a8..883847c 100644 --- a/blog/urls.py +++ b/blog/urls.py @@ -22,26 +22,57 @@ from haystack.views import SearchView app_name = "blog" urlpatterns = [ - path(r'', views.IndexView.as_view(), name='index'), - path(r'page//', views.IndexView.as_view(), name='index_page'), - - path(r'article////.html', - views.ArticleDetailView.as_view(), - name='detailbyid'), - - path(r'category/.html', views.CategoryDetailView.as_view(), name='category_detail'), - path(r'category//.html', views.CategoryDetailView.as_view(), - name='category_detail_page'), - - path(r'author/.html', views.AuthorDetailView.as_view(), name='author_detail'), - path(r'author//.html', views.AuthorDetailView.as_view(), - name='author_detail_page'), - - path(r'tag/.html', views.TagDetailView.as_view(), name='tag_detail'), - path(r'tag//.html', views.TagDetailView.as_view(), name='tag_detail_page'), - path('archives.html', cache_page(60 * 60)(views.ArchivesView.as_view()), name='archives'), - path('links.html', views.LinkListView.as_view(), name='links'), - path(r'upload', views.fileupload, name='upload'), - path(r'refresh', views.refresh_memcache, name='refresh') - -] + path( + r'', + views.IndexView.as_view(), + name='index'), + path( + r'page//', + views.IndexView.as_view(), + name='index_page'), + path( + r'article////.html', + views.ArticleDetailView.as_view(), + name='detailbyid'), + path( + r'category/.html', + views.CategoryDetailView.as_view(), + name='category_detail'), + path( + r'category//.html', + views.CategoryDetailView.as_view(), + name='category_detail_page'), + path( + r'author/.html', + views.AuthorDetailView.as_view(), + name='author_detail'), + path( + r'author//.html', + views.AuthorDetailView.as_view(), + name='author_detail_page'), + path( + r'tag/.html', + views.TagDetailView.as_view(), + name='tag_detail'), + path( + r'tag//.html', + views.TagDetailView.as_view(), + name='tag_detail_page'), + path( + 'archives.html', + cache_page( + 60 * 60)( + views.ArchivesView.as_view()), + name='archives'), + path( + 'links.html', + views.LinkListView.as_view(), + name='links'), + path( + r'upload', + views.fileupload, + name='upload'), + path( + r'refresh', + views.refresh_memcache, + name='refresh')] diff --git a/blog/views.py b/blog/views.py index adb225a..19f5275 100644 --- a/blog/views.py +++ b/blog/views.py @@ -38,7 +38,8 @@ class ArticleListView(ListView): @property def page_number(self): page_kwarg = self.page_kwarg - page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1 + page = self.kwargs.get( + page_kwarg) or self.request.GET.get(page_kwarg) or 1 return page def get_queryset_cache_key(self): @@ -131,7 +132,8 @@ class ArticleDetailView(DetailView): kwargs['form'] = comment_form kwargs['article_comments'] = article_comments - kwargs['comment_count'] = len(article_comments) if article_comments else 0 + kwargs['comment_count'] = len( + article_comments) if article_comments else 0 kwargs['next_article'] = self.object.next_article kwargs['prev_article'] = self.object.prev_article @@ -151,8 +153,10 @@ class CategoryDetailView(ArticleListView): categoryname = category.name self.categoryname = categoryname - categorynames = list(map(lambda c: c.name, category.get_sub_categorys())) - article_list = Article.objects.filter(category__name__in=categorynames, status='p') + categorynames = list( + map(lambda c: c.name, category.get_sub_categorys())) + article_list = Article.objects.filter( + category__name__in=categorynames, status='p') return article_list def get_queryset_cache_key(self): @@ -160,7 +164,8 @@ class CategoryDetailView(ArticleListView): category = get_object_or_404(Category, slug=slug) categoryname = category.name self.categoryname = categoryname - cache_key = 'category_list_{categoryname}_{page}'.format(categoryname=categoryname, page=self.page_number) + cache_key = 'category_list_{categoryname}_{page}'.format( + categoryname=categoryname, page=self.page_number) return cache_key def get_context_data(self, **kwargs): @@ -168,7 +173,7 @@ class CategoryDetailView(ArticleListView): categoryname = self.categoryname try: categoryname = categoryname.split('/')[-1] - except: + except BaseException: pass kwargs['page_type'] = CategoryDetailView.page_type kwargs['tag_name'] = categoryname @@ -183,12 +188,14 @@ class AuthorDetailView(ArticleListView): def get_queryset_cache_key(self): author_name = self.kwargs['author_name'] - cache_key = 'author_{author_name}_{page}'.format(author_name=author_name, page=self.page_number) + cache_key = 'author_{author_name}_{page}'.format( + author_name=author_name, page=self.page_number) return cache_key def get_queryset_data(self): author_name = self.kwargs['author_name'] - article_list = Article.objects.filter(author__username=author_name, type='a', status='p') + article_list = Article.objects.filter( + author__username=author_name, type='a', status='p') return article_list def get_context_data(self, **kwargs): @@ -209,7 +216,8 @@ class TagDetailView(ArticleListView): tag = get_object_or_404(Tag, slug=slug) tag_name = tag.name self.name = tag_name - article_list = Article.objects.filter(tags__name=tag_name, type='a', status='p') + article_list = Article.objects.filter( + tags__name=tag_name, type='a', status='p') return article_list def get_queryset_cache_key(self): @@ -217,7 +225,8 @@ class TagDetailView(ArticleListView): tag = get_object_or_404(Tag, slug=slug) tag_name = tag.name self.name = tag_name - cache_key = 'tag_{tag_name}_{page}'.format(tag_name=tag_name, page=self.page_number) + cache_key = 'tag_{tag_name}_{page}'.format( + tag_name=tag_name, page=self.page_number) return cache_key def get_context_data(self, **kwargs): @@ -274,8 +283,10 @@ def fileupload(request): isimage = len([i for i in imgextensions if fname.find(i) >= 0]) > 0 blogsetting = get_blog_setting() - basepath = r'{basedir}/{type}/{timestr}'.format(basedir=blogsetting.resource_path, - type='files' if not isimage else 'image', timestr=timestr) + basepath = r'{basedir}/{type}/{timestr}'.format( + basedir=blogsetting.resource_path, + 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( @@ -313,21 +324,34 @@ def refresh_memcache(request): return HttpResponse(e) -def page_not_found_view(request, exception, template_name='blog/error_page.html'): +def page_not_found_view( + request, + exception, + template_name='blog/error_page.html'): if exception: logger.error(exception) url = request.get_full_path() - return render(request, template_name, - {'message': '哎呀,您访问的地址 ' + url + ' 是一个未知的地方。请点击首页看看别的?', 'statuscode': '404'}, status=404) + return render(request, + template_name, + {'message': '哎呀,您访问的地址 ' + url + ' 是一个未知的地方。请点击首页看看别的?', + 'statuscode': '404'}, + status=404) def server_error_view(request, template_name='blog/error_page.html'): - return render(request, template_name, - {'message': '哎呀,出错了,我已经收集到了错误信息,之后会抓紧抢修,请点击首页看看别的?', 'statuscode': '500'}, status=500) + return render(request, + template_name, + {'message': '哎呀,出错了,我已经收集到了错误信息,之后会抓紧抢修,请点击首页看看别的?', + 'statuscode': '500'}, + status=500) -def permission_denied_view(request, exception, template_name='blog/error_page.html'): +def permission_denied_view( + request, + exception, + template_name='blog/error_page.html'): if exception: logger.error(exception) - return render(request, template_name, - {'message': '哎呀,您没有权限访问此页面,请点击首页看看别的?', 'statuscode': '403'}, status=403) + return render( + request, template_name, { + 'message': '哎呀,您没有权限访问此页面,请点击首页看看别的?', 'statuscode': '403'}, status=403) diff --git a/comments/admin.py b/comments/admin.py index b0cf3f4..79f024d 100644 --- a/comments/admin.py +++ b/comments/admin.py @@ -19,7 +19,13 @@ enable_commentstatus.short_description = '启用评论' class CommentAdmin(admin.ModelAdmin): list_per_page = 20 - list_display = ('id', 'body', 'link_to_userinfo', 'link_to_article', 'is_enable', 'created_time') + list_display = ( + 'id', + 'body', + 'link_to_userinfo', + 'link_to_article', + 'is_enable', + 'created_time') list_display_links = ('id', 'body') list_filter = ('author', 'article', 'is_enable') exclude = ('created_time', 'last_mod_time') @@ -29,7 +35,8 @@ class CommentAdmin(admin.ModelAdmin): info = (obj.author._meta.app_label, obj.author._meta.model_name) link = reverse('admin:%s_%s_change' % info, args=(obj.author.id,)) return format_html( - u'%s' % (link, obj.author.nickname if obj.author.nickname else obj.author.email)) + u'%s' % + (link, obj.author.nickname if obj.author.nickname else obj.author.email)) def link_to_article(self, obj): info = (obj.author._meta.app_label, obj.author._meta.model_name) diff --git a/comments/forms.py b/comments/forms.py index 74751f1..ef8249e 100644 --- a/comments/forms.py +++ b/comments/forms.py @@ -22,11 +22,16 @@ from django.contrib.auth import get_user_model class CommentForm(ModelForm): url = forms.URLField(label='网址', required=False) email = forms.EmailField(label='电子邮箱', required=True) - name = forms.CharField(label='姓名', widget=forms.TextInput(attrs= - {'value': "", 'size': "30", 'maxlength': "245", - 'aria-required': 'true'} - )) - parent_comment_id = forms.IntegerField(widget=forms.HiddenInput, required=False) + name = forms.CharField( + label='姓名', + widget=forms.TextInput( + attrs={ + 'value': "", + 'size': "30", + 'maxlength': "245", + 'aria-required': 'true'})) + parent_comment_id = forms.IntegerField( + widget=forms.HiddenInput, required=False) class Meta: model = Comment diff --git a/comments/models.py b/comments/models.py index e825322..4ffb3c9 100644 --- a/comments/models.py +++ b/comments/models.py @@ -10,10 +10,22 @@ class Comment(models.Model): body = models.TextField('正文', max_length=300) created_time = models.DateTimeField('创建时间', default=now) 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, on_delete=models.CASCADE) - is_enable = models.BooleanField('是否显示', default=True, blank=False, null=False) + 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, + on_delete=models.CASCADE) + is_enable = models.BooleanField( + '是否显示', default=True, blank=False, null=False) class Meta: ordering = ['id'] diff --git a/comments/tests.py b/comments/tests.py index baeee53..ff70206 100644 --- a/comments/tests.py +++ b/comments/tests.py @@ -18,8 +18,10 @@ class CommentsTest(TestCase): def test_validate_comment(self): site = get_current_site().domain - user = BlogUser.objects.create_superuser(email="liangliangyy1@gmail.com", - username="liangliangyy1", password="liangliangyy1") + user = BlogUser.objects.create_superuser( + email="liangliangyy1@gmail.com", + username="liangliangyy1", + password="liangliangyy1") self.client.login(username='liangliangyy1', password='liangliangyy1') @@ -38,7 +40,9 @@ class CommentsTest(TestCase): article.status = 'p' article.save() - commenturl = reverse('comments:postcomment', kwargs={'article_id': article.id}) + commenturl = reverse( + 'comments:postcomment', kwargs={ + 'article_id': article.id}) response = self.client.post(commenturl, { @@ -66,17 +70,17 @@ class CommentsTest(TestCase): response = self.client.post(commenturl, { 'body': ''' - # Title1 - + # Title1 + ```python import os - ``` - - [url](https://www.lylinux.net/) - - [ddd](http://www.baidu.com) - - + ``` + + [url](https://www.lylinux.net/) + + [ddd](http://www.baidu.com) + + ''', 'email': user.email, 'name': user.username, diff --git a/comments/urls.py b/comments/urls.py index 0579ccc..79b9c83 100644 --- a/comments/urls.py +++ b/comments/urls.py @@ -19,5 +19,8 @@ from . import views app_name = "comments" urlpatterns = [ # url(r'^po456stcomment/(?P\d+)$', views.CommentPostView.as_view(), name='postcomment'), - path('article//postcomment', views.CommentPostView.as_view(), name='postcomment'), + path( + 'article//postcomment', + views.CommentPostView.as_view(), + name='postcomment'), ] diff --git a/comments/utils.py b/comments/utils.py index 38375b0..353f372 100644 --- a/comments/utils.py +++ b/comments/utils.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -23,7 +23,8 @@ logger = logging.getLogger(__name__) def send_comment_email(comment): site = get_current_site().domain subject = '感谢您发表的评论' - article_url = "https://{site}{path}".format(site=site, path=comment.article.get_absolute_url()) + article_url = "https://{site}{path}".format( + site=site, path=comment.article.get_absolute_url()) html_content = """

非常感谢您在本站发表评论

您可以访问 diff --git a/comments/views.py b/comments/views.py index 21b4955..1295175 100644 --- a/comments/views.py +++ b/comments/views.py @@ -50,7 +50,8 @@ class CommentPostView(FormView): email = form.cleaned_data['email'] username = form.cleaned_data['name'] - user = get_user_model().objects.get_or_create(username=username, email=email)[0] + user = get_user_model().objects.get_or_create( + username=username, email=email)[0] # auth.login(self.request, user) comment = form.save(False) comment.article = article @@ -58,8 +59,11 @@ class CommentPostView(FormView): comment.author = user if form.cleaned_data['parent_comment_id']: - parent_comment = Comment.objects.get(pk=form.cleaned_data['parent_comment_id']) + parent_comment = Comment.objects.get( + pk=form.cleaned_data['parent_comment_id']) comment.parent_comment = parent_comment comment.save(True) - return HttpResponseRedirect("%s#div-comment-%d" % (article.get_absolute_url(), comment.pk)) + return HttpResponseRedirect( + "%s#div-comment-%d" % + (article.get_absolute_url(), comment.pk)) diff --git a/oauth/admin.py b/oauth/admin.py index f778918..4708962 100644 --- a/oauth/admin.py +++ b/oauth/admin.py @@ -11,15 +11,22 @@ logger = logging.getLogger(__name__) class OAuthUserAdmin(admin.ModelAdmin): search_fields = ('nikename', 'email') list_per_page = 20 - list_display = ('id', 'nikename', 'link_to_usermodel', 'show_user_image', 'type', 'email',) + list_display = ( + 'id', + 'nikename', + 'link_to_usermodel', + 'show_user_image', + 'type', + 'email', + ) list_display_links = ('id', 'nikename') list_filter = ('author', 'type',) readonly_fields = [] def get_readonly_fields(self, request, obj=None): return list(self.readonly_fields) + \ - [field.name for field in obj._meta.fields] + \ - [field.name for field in obj._meta.many_to_many] + [field.name for field in obj._meta.fields] + \ + [field.name for field in obj._meta.many_to_many] def has_add_permission(self, request): return False @@ -29,11 +36,14 @@ class OAuthUserAdmin(admin.ModelAdmin): info = (obj.author._meta.app_label, obj.author._meta.model_name) link = reverse('admin:%s_%s_change' % info, args=(obj.author.id,)) return format_html( - u'%s' % (link, obj.author.nickname if obj.author.nickname else obj.author.email)) + u'%s' % + (link, obj.author.nickname if obj.author.nickname else obj.author.email)) def show_user_image(self, obj): img = obj.picture - return format_html(u'' % (img)) + return format_html( + u'' % + (img)) link_to_usermodel.short_description = '用户' show_user_image.short_description = '用户头像' diff --git a/oauth/forms.py b/oauth/forms.py index ccf8494..a64f9c8 100644 --- a/oauth/forms.py +++ b/oauth/forms.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -23,4 +23,5 @@ class RequireEmailForm(forms.Form): def __init__(self, *args, **kwargs): super(RequireEmailForm, self).__init__(*args, **kwargs) - self.fields['email'].widget = widgets.EmailInput(attrs={'placeholder': "email", "class": "form-control"}) + self.fields['email'].widget = widgets.EmailInput( + attrs={'placeholder': "email", "class": "form-control"}) diff --git a/oauth/models.py b/oauth/models.py index 66594bb..cbe73ff 100644 --- a/oauth/models.py +++ b/oauth/models.py @@ -8,8 +8,12 @@ from django.utils.translation import gettext_lazy as _ class OAuthUser(models.Model): - author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='用户', blank=True, null=True, - on_delete=models.CASCADE) + 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) @@ -40,13 +44,20 @@ class OAuthConfig(models.Model): type = models.CharField('类型', max_length=10, choices=TYPE, default='a') appkey = models.CharField(max_length=200, verbose_name='AppKey') appsecret = models.CharField(max_length=200, verbose_name='AppSecret') - callback_url = models.CharField(max_length=200, verbose_name='回调地址', blank=False, default='http://www.baidu.com') - is_enable = models.BooleanField('是否显示', default=True, blank=False, null=False) + callback_url = models.CharField( + max_length=200, + verbose_name='回调地址', + blank=False, + default='http://www.baidu.com') + is_enable = models.BooleanField( + '是否显示', default=True, blank=False, null=False) created_time = models.DateTimeField('创建时间', default=now) last_mod_time = models.DateTimeField('修改时间', default=now) def clean(self): - if OAuthConfig.objects.filter(type=self.type).exclude(id=self.id).count(): + if OAuthConfig.objects.filter( + type=self.type).exclude( + id=self.id).count(): raise ValidationError(_(self.type + '已经存在')) def __str__(self): diff --git a/oauth/oauthmanager.py b/oauth/oauthmanager.py index a0bb803..5d897ef 100644 --- a/oauth/oauthmanager.py +++ b/oauth/oauthmanager.py @@ -91,7 +91,11 @@ class WBOauthManager(BaseOauthManager): self.client_id = config.appkey if config else '' self.client_secret = config.appsecret if config else '' self.callback_url = config.callback_url if config else '' - super(WBOauthManager, self).__init__(access_token=access_token, openid=openid) + super( + WBOauthManager, + self).__init__( + access_token=access_token, + openid=openid) def get_authorization_url(self, nexturl='/'): params = { @@ -158,7 +162,11 @@ class GoogleOauthManager(BaseOauthManager): self.client_id = config.appkey if config else '' self.client_secret = config.appsecret if config else '' self.callback_url = config.callback_url if config else '' - super(GoogleOauthManager, self).__init__(access_token=access_token, openid=openid) + super( + GoogleOauthManager, + self).__init__( + access_token=access_token, + openid=openid) def get_authorization_url(self, nexturl='/'): params = { @@ -229,7 +237,11 @@ class GitHubOauthManager(BaseOauthManager): self.client_id = config.appkey if config else '' self.client_secret = config.appsecret if config else '' self.callback_url = config.callback_url if config else '' - super(GitHubOauthManager, self).__init__(access_token=access_token, openid=openid) + super( + GitHubOauthManager, + self).__init__( + access_token=access_token, + openid=openid) def get_authorization_url(self, nexturl='/'): params = { @@ -295,7 +307,11 @@ class FaceBookOauthManager(BaseOauthManager): self.client_id = config.appkey if config else '' self.client_secret = config.appsecret if config else '' self.callback_url = config.callback_url if config else '' - super(FaceBookOauthManager, self).__init__(access_token=access_token, openid=openid) + super( + FaceBookOauthManager, + self).__init__( + access_token=access_token, + openid=openid) def get_authorization_url(self, nexturl='/'): params = { @@ -362,7 +378,11 @@ class QQOauthManager(BaseOauthManager): self.client_id = config.appkey if config else '' self.client_secret = config.appsecret if config else '' self.callback_url = config.callback_url if config else '' - super(QQOauthManager, self).__init__(access_token=access_token, openid=openid) + super( + QQOauthManager, + self).__init__( + access_token=access_token, + openid=openid) def get_authorization_url(self, nexturl='/'): params = { @@ -398,7 +418,10 @@ class QQOauthManager(BaseOauthManager): } rsp = self.do_get(self.OPEN_ID_URL, params) if rsp: - rsp = rsp.replace('callback(', '').replace(')', '').replace(';', '') + rsp = rsp.replace( + 'callback(', '').replace( + ')', '').replace( + ';', '') obj = json.loads(rsp) openid = str(obj['openid']) self.openid = openid @@ -442,7 +465,10 @@ def get_oauth_apps(): def get_manager_by_type(type): applications = get_oauth_apps() if applications: - finds = list(filter(lambda x: x.ICON_NAME.lower() == type.lower(), applications)) + finds = list( + filter( + lambda x: x.ICON_NAME.lower() == type.lower(), + applications)) if finds: return finds[0] return None diff --git a/oauth/templatetags/__init__.py b/oauth/templatetags/__init__.py index fd534e9..fa0f602 100644 --- a/oauth/templatetags/__init__.py +++ b/oauth/templatetags/__init__.py @@ -5,10 +5,10 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @file: __init__.py @time: 2017/3/4 下午3:22 -""" \ No newline at end of file +""" diff --git a/oauth/templatetags/oauth_tags.py b/oauth/templatetags/oauth_tags.py index 8ab09d3..54067de 100644 --- a/oauth/templatetags/oauth_tags.py +++ b/oauth/templatetags/oauth_tags.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -27,9 +27,8 @@ def load_oauth_applications(request): baseurl = reverse('oauth:oauthlogin') path = request.get_full_path() - apps = list(map(lambda x: (x.ICON_NAME, - '{baseurl}?type={type}&next_url={next}' - .format(baseurl=baseurl, type=x.ICON_NAME, next=path)), applications)) + apps = list(map(lambda x: (x.ICON_NAME, '{baseurl}?type={type}&next_url={next}' .format( + baseurl=baseurl, type=x.ICON_NAME, next=path)), applications)) else: apps = [] return { diff --git a/oauth/urls.py b/oauth/urls.py index 9afa523..7820f60 100644 --- a/oauth/urls.py +++ b/oauth/urls.py @@ -19,9 +19,22 @@ from . import views app_name = "oauth" urlpatterns = [ - path(r'oauth/authorize', views.authorize), - path(r'oauth/requireemail/.html', views.RequireEmailView.as_view(), name='require_email'), - path(r'oauth/emailconfirm//.html', views.emailconfirm, name='email_confirm'), - path(r'oauth/bindsuccess/.html', views.bindsuccess, name='bindsuccess'), - path(r'oauth/oauthlogin', views.oauthlogin, name='oauthlogin') -] + path( + r'oauth/authorize', + views.authorize), + path( + r'oauth/requireemail/.html', + views.RequireEmailView.as_view(), + name='require_email'), + path( + r'oauth/emailconfirm//.html', + views.emailconfirm, + name='email_confirm'), + path( + r'oauth/bindsuccess/.html', + views.bindsuccess, + name='bindsuccess'), + path( + r'oauth/oauthlogin', + views.oauthlogin, + name='oauthlogin')] diff --git a/oauth/views.py b/oauth/views.py index 720cd29..9ac49cd 100644 --- a/oauth/views.py +++ b/oauth/views.py @@ -104,7 +104,8 @@ def authorize(request): user.author = author user.save() - oauth_user_login_signal.send(sender=authorize.__class__, id=user.id) + oauth_user_login_signal.send( + sender=authorize.__class__, id=user.id) login(request, author) return HttpResponseRedirect(nexturl) else: @@ -121,7 +122,10 @@ def authorize(request): def emailconfirm(request, id, sign): if not sign: return HttpResponseForbidden() - if not get_md5(settings.SECRET_KEY + str(id) + settings.SECRET_KEY).upper() == sign.upper(): + if not get_md5( + settings.SECRET_KEY + + str(id) + + settings.SECRET_KEY).upper() == sign.upper(): return HttpResponseForbidden() oauthuser = get_object_or_404(OAuthUser, pk=id) with transaction.atomic(): @@ -132,12 +136,14 @@ def emailconfirm(request, id, sign): author = result[0] if result[1]: author.source = 'emailconfirm' - author.username = oauthuser.nikename.strip() if oauthuser.nikename.strip() else "djangoblog" + datetime.datetime.now().strftime( - '%y%m%d%I%M%S') + author.username = oauthuser.nikename.strip() if oauthuser.nikename.strip( + ) else "djangoblog" + datetime.datetime.now().strftime('%y%m%d%I%M%S') author.save() oauthuser.author = author oauthuser.save() - oauth_user_login_signal.send(sender=emailconfirm.__class__, id=oauthuser.id) + oauth_user_login_signal.send( + sender=emailconfirm.__class__, + id=oauthuser.id) login(request, author) site = get_current_site().domain @@ -193,7 +199,8 @@ class RequireEmailView(FormView): oauthuser = get_object_or_404(OAuthUser, pk=oauthid) oauthuser.email = email oauthuser.save() - sign = get_md5(settings.SECRET_KEY + str(oauthuser.id) + settings.SECRET_KEY) + sign = get_md5(settings.SECRET_KEY + + str(oauthuser.id) + settings.SECRET_KEY) site = get_current_site().domain if settings.DEBUG: site = '127.0.0.1:8000' @@ -229,7 +236,8 @@ def bindsuccess(request, oauthid): content = "恭喜您,还差一步就绑定成功了,请登录您的邮箱查看邮件完成绑定,谢谢。" else: title = '绑定成功' - content = "恭喜您绑定成功,您以后可以使用{type}来直接免密码登录本站啦,感谢您对本站对关注。".format(type=oauthuser.type) + content = "恭喜您绑定成功,您以后可以使用{type}来直接免密码登录本站啦,感谢您对本站对关注。".format( + type=oauthuser.type) return render(request, 'oauth/bindsuccess.html', { 'title': title, 'content': content diff --git a/owntracks/tests.py b/owntracks/tests.py index b5c4950..2a679bc 100644 --- a/owntracks/tests.py +++ b/owntracks/tests.py @@ -19,7 +19,10 @@ class OwnTrackLogTest(TestCase): 'lon': 134.341 } - self.client.post('/owntracks/logtracks', json.dumps(o), content_type='application/json') + self.client.post( + '/owntracks/logtracks', + json.dumps(o), + content_type='application/json') length = len(OwnTrackLog.objects.all()) self.assertEqual(length, 1) @@ -28,15 +31,20 @@ class OwnTrackLogTest(TestCase): 'lat': 123.123 } - self.client.post('/owntracks/logtracks', json.dumps(o), content_type='application/json') + self.client.post( + '/owntracks/logtracks', + json.dumps(o), + content_type='application/json') length = len(OwnTrackLog.objects.all()) self.assertEqual(length, 1) rsp = self.client.get('/owntracks/show_maps') self.assertEqual(rsp.status_code, 302) - user = BlogUser.objects.create_superuser(email="liangliangyy1@gmail.com", - username="liangliangyy1", password="liangliangyy1") + user = BlogUser.objects.create_superuser( + email="liangliangyy1@gmail.com", + username="liangliangyy1", + password="liangliangyy1") self.client.login(username='liangliangyy1', password='liangliangyy1') s = OwnTrackLog() diff --git a/owntracks/urls.py b/owntracks/urls.py index ee44cf5..7225c0a 100644 --- a/owntracks/urls.py +++ b/owntracks/urls.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/owntracks/views.py b/owntracks/views.py index 74f8285..e820c88 100644 --- a/owntracks/views.py +++ b/owntracks/views.py @@ -25,7 +25,9 @@ def manage_owntrack_log(request): lat = s['lat'] lon = s['lon'] - logger.info('tid:{tid}.lat:{lat}.lon:{lon}'.format(tid=tid, lat=lat, lon=lon)) + logger.info( + 'tid:{tid}.lat:{lat}.lon:{lon}'.format( + tid=tid, lat=lat, lon=lon)) if tid and lat and lon: m = OwnTrackLog() m.tid = tid @@ -71,7 +73,8 @@ def convert_to_amap(locations): item = list(itertools.islice(it, 30)) while item: - datas = ';'.join(set(map(lambda x: str(x.lon) + ',' + str(x.lat), item))) + datas = ';'.join( + set(map(lambda x: str(x.lon) + ',' + str(x.lat), item))) key = '8440a376dfc9743d8924bf0ad141f28e' api = 'http://restapi.amap.com/v3/assistant/coordinate/convert' @@ -94,20 +97,25 @@ def get_datas(request): from django.utils.timezone import utc now = django.utils.timezone.now().replace(tzinfo=utc) - querydate = django.utils.timezone.datetime(now.year, now.month, now.day, 0, 0, 0) + querydate = django.utils.timezone.datetime( + now.year, now.month, now.day, 0, 0, 0) if request.GET.get('date', None): date = list(map(lambda x: int(x), request.GET.get('date').split('-'))) - querydate = django.utils.timezone.datetime(date[0], date[1], date[2], 0, 0, 0) + querydate = django.utils.timezone.datetime( + date[0], date[1], date[2], 0, 0, 0) nextdate = querydate + datetime.timedelta(days=1) - models = OwnTrackLog.objects.filter(created_time__range=(querydate, nextdate)) + models = OwnTrackLog.objects.filter( + created_time__range=(querydate, nextdate)) result = list() if models and len(models): - for tid, item in groupby(sorted(models, key=lambda k: k.tid), key=lambda k: k.tid): + for tid, item in groupby( + sorted(models, key=lambda k: k.tid), key=lambda k: k.tid): d = dict() d["name"] = tid paths = list() - locations = convert_to_amap(sorted(item, key=lambda x: x.created_time)) + locations = convert_to_amap( + sorted(item, key=lambda x: x.created_time)) for i in locations.split(';'): paths.append(i.split(',')) d["path"] = paths diff --git a/servermanager/Api/__init__.py b/servermanager/Api/__init__.py index 667e57e..990c2c0 100644 --- a/servermanager/Api/__init__.py +++ b/servermanager/Api/__init__.py @@ -5,10 +5,10 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @file: __init__.py.py @time: 2017/8/27 上午11:40 -""" \ No newline at end of file +""" diff --git a/servermanager/Api/blogapi.py b/servermanager/Api/blogapi.py index b1ba05b..24b3fea 100644 --- a/servermanager/Api/blogapi.py +++ b/servermanager/Api/blogapi.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/servermanager/Api/commonapi.py b/servermanager/Api/commonapi.py index bd55923..7669dde 100644 --- a/servermanager/Api/commonapi.py +++ b/servermanager/Api/commonapi.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/servermanager/MemcacheStorage.py b/servermanager/MemcacheStorage.py index e0e233a..d068814 100644 --- a/servermanager/MemcacheStorage.py +++ b/servermanager/MemcacheStorage.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm diff --git a/servermanager/admin.py b/servermanager/admin.py index 3233927..7897041 100644 --- a/servermanager/admin.py +++ b/servermanager/admin.py @@ -9,7 +9,12 @@ class CommandsAdmin(admin.ModelAdmin): class EmailSendLogAdmin(admin.ModelAdmin): list_display = ('title', 'emailto', 'send_result', 'created_time') - readonly_fields = ('title', 'emailto', 'send_result', 'created_time', 'content') + readonly_fields = ( + 'title', + 'emailto', + 'send_result', + 'created_time', + 'content') def has_add_permission(self, request): return False diff --git a/servermanager/robot.py b/servermanager/robot.py index fbee94c..75c1602 100644 --- a/servermanager/robot.py +++ b/servermanager/robot.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm @@ -26,7 +26,8 @@ from django.conf import settings import jsonpickle from servermanager.models import commands -robot = WeRoBot(token=os.environ.get('DJANGO_WEROBOT_TOKEN') or 'lylinux', enable_session=True) +robot = WeRoBot(token=os.environ.get('DJANGO_WEROBOT_TOKEN') + or 'lylinux', enable_session=True) memstorage = MemcacheStorage() if memstorage.is_available: robot.config['SESSION_STORAGE'] = memstorage @@ -114,12 +115,12 @@ def help(message, session): ''' -@robot.filter(re.compile('^weather\:.*$', re.I)) +@robot.filter(re.compile(r'^weather\:.*$', re.I)) def weather(message, session): return "建设中..." -@robot.filter(re.compile('^idcard\:.*$', re.I)) +@robot.filter(re.compile(r'^idcard\:.*$', re.I)) def idcard(message, session): return "建设中..." @@ -135,7 +136,10 @@ class CommandHandler(): self.commands = commands.objects.all() def run(self, title): - cmd = list(filter(lambda x: x.title.upper() == title.upper(), self.commands)) + cmd = list( + filter( + lambda x: x.title.upper() == title.upper(), + self.commands)) if cmd: return self.__run_command__(cmd[0].command) else: @@ -145,7 +149,7 @@ class CommandHandler(): try: str = os.popen(cmd).read() return str - except: + except BaseException: return '命令执行出错!' def get_help(self): @@ -167,7 +171,7 @@ class MessageHandler(): try: info = session[userid] self.userinfo = jsonpickle.decode(info) - except: + except BaseException: userinfo = WxUserInfo() self.userinfo = userinfo @@ -197,7 +201,7 @@ class MessageHandler(): if self.userinfo.isAdmin and not self.userinfo.isPasswordSet: passwd = settings.WXADMIN if settings.TESTING: - passwd='123' + passwd = '123' if passwd.upper() == get_md5(get_md5(info)).upper(): self.userinfo.isPasswordSet = True self.savesession() diff --git a/servermanager/tests.py b/servermanager/tests.py index 5932a1d..dd741bd 100644 --- a/servermanager/tests.py +++ b/servermanager/tests.py @@ -23,8 +23,10 @@ class ServerManagerTest(TestCase): def test_validate_comment(self): site = get_current_site().domain - user = BlogUser.objects.create_superuser(email="liangliangyy1@gmail.com", - username="liangliangyy1", password="liangliangyy1") + user = BlogUser.objects.create_superuser( + email="liangliangyy1@gmail.com", + username="liangliangyy1", + password="liangliangyy1") self.client.login(username='liangliangyy1', password='liangliangyy1') diff --git a/servermanager/urls.py b/servermanager/urls.py index a5a075c..8600186 100644 --- a/servermanager/urls.py +++ b/servermanager/urls.py @@ -5,7 +5,7 @@ """ @version: ?? @author: liangliangyy -@license: MIT Licence +@license: MIT Licence @contact: liangliangyy@gmail.com @site: https://www.lylinux.net/ @software: PyCharm From 5fd38fd046421aec013483da80f187199f1a1c2e Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Mon, 6 Apr 2020 16:44:34 +0800 Subject: [PATCH 2/3] close #289 --- blog/documents.py | 8 +++----- docs/es.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 docs/es.md diff --git a/blog/documents.py b/blog/documents.py index e5fa9e8..fa382d5 100644 --- a/blog/documents.py +++ b/blog/documents.py @@ -13,13 +13,12 @@ from elasticsearch_dsl.connections import connections import time from blog.models import Article, Category, Tag -from elasticsearch_dsl import Document, Date, Integer, Keyword, Text, Object, Boolean +from elasticsearch_dsl import Document, Date, Integer, Long, Keyword, Text, Object, Boolean from django.conf import settings ELASTICSEARCH_ENABLED = hasattr(settings, 'ELASTICSEARCH_DSL') - if ELASTICSEARCH_ENABLED: connections.create_connection( hosts=[settings.ELASTICSEARCH_DSL['default']['hosts']]) @@ -27,7 +26,7 @@ if ELASTICSEARCH_ENABLED: class ElapsedTimeDocument(Document): url = Text() - time_taken = Integer() + time_taken = Long() log_datetime = Date() type = Text(analyzer='ik_max_word') useragent = Text() @@ -101,8 +100,7 @@ class ArticleDocument(Document): class ArticleDocumentManager(): def __init__(self): - pass - # ArticleDocument.init() + self.create_index() def create_index(self): ArticleDocument.init() diff --git a/docs/es.md b/docs/es.md new file mode 100644 index 0000000..68ce49e --- /dev/null +++ b/docs/es.md @@ -0,0 +1,28 @@ +# 集成Elasticsearch +如果你已经有了`Elasticsearch`环境,那么可以将搜索从`Whoosh`换成`Elasticsearch`,集成方式也很简单, +首先需要注意如下几点: +1. 你的`Elasticsearch`支持`ik`中文分词 +2. 你的`Elasticsearch`版本>=7.3.0 + +接下来在`settings.py`做如下改动即可: +- 增加es链接,如下所示: +```python +ELASTICSEARCH_DSL = { + 'default': { + 'hosts': '127.0.0.1:9200' + }, +} +``` +- 修改`HAYSTACK`配置: +```python +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'DjangoBlog.elasticsearch_backend.ElasticSearchEngine', + }, +} +``` +然后终端执行: +```shell script +./manage.py build_index +``` +这将会在你的es中创建两个索引,分别是`blog`和`performance`,其中`blog`索引就是搜索所使用的,而`performance`会记录每个请求的响应时间,以供将来优化使用。 \ No newline at end of file From a332ce2280f210d0c04f92ad46e008597bddb494 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Mon, 6 Apr 2020 16:50:09 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b5f5d94..91a8916 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ CREATE DATABASE `djangoblog` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8 浏览器打开: http://127.0.0.1:8000/ 就可以看到效果了。 ## 更多配置: [更多配置介绍](/docs/config.md) +[集成elasticsearch](/docs/es.md) ## 问题相关