Compare commits

...

No commits in common. 'master' and 'lxl_branch' have entirely different histories.

@ -0,0 +1,2 @@
# software_DjangoBlog

@ -1,6 +0,0 @@
blog/static/* linguist-vendored
*.js linguist-vendored
*.css linguist-vendored
* text=auto
*.sh text eol=lf
*.conf text eol=lf

80
src/.gitignore vendored

@ -1,80 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.pot
# Django stuff:
*.log
logs/
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# PyCharm
# http://www.jetbrains.com/pycharm/webhelp/project.html
.idea
.iml
# virtualenv
venv/
collectedstatic/
djangoblog/whoosh_index/
google93fd32dbd906620a.html
baidu_verify_FlHL7cUyC9.html
BingSiteAuth.xml
cb9339dbe2ff86a5aa169d28dba5f615.txt
werobot_session.*
django.jpg
uploads/
settings_production.py
werobot_session.db
bin/datas/
myenv/

@ -1 +0,0 @@
Subproject commit ef67f8db4fafce7e84c0e7bae23d5c5bf8869fac

@ -0,0 +1,10 @@
[run]
source = .
include = *.py
omit =
*migrations*
*tests*
*.html
*whoosh_cn_backend*
*settings.py*
*venv*

@ -8,5 +8,4 @@ settings_production.py
*.md
docs/
logs/
static/
.github/
static/

@ -3,9 +3,9 @@
<component name="FacetManager">
<facet type="django" name="Django">
<configuration>
<option name="rootFolder" value="$MODULE_DIR$/src" />
<option name="settingsModule" value="settings.py" />
<option name="manageScript" value="$MODULE_DIR$/src/manage.py" />
<option name="rootFolder" value="$MODULE_DIR$" />
<option name="settingsModule" value="djangoblog/settings.py" />
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
<option name="environment" value="&lt;map/&gt;" />
<option name="doNotUseTestRunner" value="false" />
<option name="trackFilePattern" value="migrations" />
@ -14,9 +14,9 @@
</component>
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10 (DjangoBlog)" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="DjangoBlogENV" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
@ -24,14 +24,11 @@
<option name="myDocStringFormat" value="Plain" />
</component>
<component name="TemplatesService">
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
<option name="TEMPLATE_CONFIGURATION" value="Django" />
<option name="TEMPLATE_FOLDERS">
<list>
<option value="$MODULE_DIR$/src/templates" />
<option value="$MODULE_DIR$/templates" />
</list>
</option>
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="py.test" />
</component>
</module>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="@localhost" uuid="6f245c9c-684e-430b-9b96-15363ef9803f">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (DjangoBlog)" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="DjangoBlogENV" project-jdk-type="Python SDK" />
</project>

@ -2,5 +2,6 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

@ -0,0 +1,59 @@
from django import forms
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.forms import UsernameField
from django.utils.translation import gettext_lazy as _
# Register your models here.
from .models import BlogUser
class BlogUserCreationForm(forms.ModelForm):
password1 = forms.CharField(label=_('password'), widget=forms.PasswordInput)
password2 = forms.CharField(label=_('Enter password again'), widget=forms.PasswordInput)
class Meta:
model = BlogUser
fields = ('email',)
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(_("passwords do not match"))
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.source = 'adminsite'
user.save()
return user
class BlogUserChangeForm(UserChangeForm):
class Meta:
model = BlogUser
fields = '__all__'
field_classes = {'username': UsernameField}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class BlogUserAdmin(UserAdmin):
form = BlogUserChangeForm
add_form = BlogUserCreationForm
list_display = (
'id',
'nickname',
'username',
'email',
'last_login',
'date_joined',
'source')
list_display_links = ('id', 'username')
ordering = ('-id',)

@ -0,0 +1,35 @@
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.urls import reverse
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from djangoblog.utils import get_current_site
# Create your models here.
class BlogUser(AbstractUser):
nickname = models.CharField(_('nick name'), max_length=100, blank=True)
creation_time = models.DateTimeField(_('creation time'), default=now)
last_modify_time = models.DateTimeField(_('last modify time'), default=now)
source = models.CharField(_('create source'), max_length=100, blank=True)
def get_absolute_url(self):
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())
return url
class Meta:
ordering = ['-id']
verbose_name = _('user')
verbose_name_plural = verbose_name
get_latest_by = 'id'

@ -0,0 +1,26 @@
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class EmailOrUsernameModelBackend(ModelBackend):
"""
允许使用用户名或邮箱登录
"""
def authenticate(self, request, username=None, password=None, **kwargs):
if '@' in username:
kwargs = {'email': username}
else:
kwargs = {'username': username}
try:
user = get_user_model().objects.get(**kwargs)
if user.check_password(password):
return user
except get_user_model().DoesNotExist:
return None
def get_user(self, username):
try:
return get_user_model().objects.get(pk=username)
except get_user_model().DoesNotExist:
return None

@ -1,7 +1,3 @@
# 模块说明:
# 该模块定义了与用户账户相关的视图,包括注册、登录、注销、忘记密码等功能。
# 使用 Django 的类视图和表单视图来处理用户请求。
import logging
from django.utils.translation import gettext_lazy as _
from django.conf import settings
@ -32,24 +28,23 @@ from .models import BlogUser
logger = logging.getLogger(__name__)
# 注册视图
# Create your views here.
class RegisterView(FormView):
# 使用注册表单和模板
form_class = RegisterForm
template_name = 'account/registration_form.html'
@method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
# 确保请求受 CSRF 保护
return super(RegisterView, self).dispatch(*args, **kwargs)
def form_valid(self, form):
# 表单验证通过后处理注册逻辑
if form.is_valid():
user = form.save(False) # 创建用户但不保存到数据库
user.is_active = False # 设置用户为未激活状态
user.source = 'Register' # 标记用户来源
user.save(True) # 保存用户到数据库
user = form.save(False)
user.is_active = False
user.source = 'Register'
user.save(True)
site = get_current_site().domain
sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
@ -75,74 +70,82 @@ class RegisterView(FormView):
],
title='验证您的电子邮箱',
content=content)
# 重定向到结果页面
url = reverse('accounts:result') + '?type=register&id=' + str(user.id)
url = reverse('accounts:result') + \
'?type=register&id=' + str(user.id)
return HttpResponseRedirect(url)
else:
# 如果表单无效,重新渲染表单
return self.render_to_response({'form': form})
return self.render_to_response({
'form': form
})
# 注销视图
class LogoutView(RedirectView):
url = '/login/' # 注销后重定向到登录页面
url = '/login/'
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
# 确保注销后页面不被缓存
return super(LogoutView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
logout(request) # 执行注销操作
delete_sidebar_cache() # 清除侧边栏缓存
logout(request)
delete_sidebar_cache()
return super(LogoutView, self).get(request, *args, **kwargs)
# 登录视图
class LoginView(FormView):
# 使用登录表单和模板
form_class = LoginForm
template_name = 'account/login.html'
success_url = '/' # 登录成功后重定向的默认地址
success_url = '/'
redirect_field_name = REDIRECT_FIELD_NAME
login_ttl = 2626560 # 设置会话过期时间为一个月
login_ttl = 2626560 # 一个月的时间
@method_decorator(sensitive_post_parameters('password'))
@method_decorator(csrf_protect)
@method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
# 确保密码字段敏感、请求受 CSRF 保护且页面不被缓存
return super(LoginView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
# 获取上下文数据,添加重定向地址
redirect_to = self.request.GET.get(self.redirect_field_name, '/')
redirect_to = self.request.GET.get(self.redirect_field_name)
if redirect_to is None:
redirect_to = '/'
kwargs['redirect_to'] = redirect_to
return super(LoginView, self).get_context_data(**kwargs)
def form_valid(self, form):
# 表单验证通过后处理登录逻辑
form = AuthenticationForm(data=self.request.POST, request=self.request)
if form.is_valid():
delete_sidebar_cache() # 清除侧边栏缓存
auth.login(self.request, form.get_user()) # 执行登录操作
delete_sidebar_cache()
logger.info(self.redirect_field_name)
auth.login(self.request, form.get_user())
if self.request.POST.get("remember"):
self.request.session.set_expiry(self.login_ttl) # 设置会话过期时间
self.request.session.set_expiry(self.login_ttl)
return super(LoginView, self).form_valid(form)
# return HttpResponseRedirect('/')
else:
# 如果表单无效,重新渲染表单
return self.render_to_response({'form': form})
return self.render_to_response({
'form': form
})
def get_success_url(self):
# 获取登录成功后的重定向地址
redirect_to = self.request.POST.get(self.redirect_field_name, self.success_url)
if not url_has_allowed_host_and_scheme(url=redirect_to, allowed_hosts=[self.request.get_host()]):
redirect_to = self.request.POST.get(self.redirect_field_name)
if not url_has_allowed_host_and_scheme(
url=redirect_to, allowed_hosts=[
self.request.get_host()]):
redirect_to = self.success_url
return redirect_to
# 账户结果视图
def account_result(request):
# 处理注册或验证结果
type = request.GET.get('type')
id = request.GET.get('id')
user = get_object_or_404(get_user_model(), id=id)
logger.info(type)
if user.is_active:
@ -157,8 +160,8 @@ def account_result(request):
c_sign = get_sha256(get_sha256(settings.SECRET_KEY + str(user.id)))
sign = request.GET.get('sign')
if sign != c_sign:
return HttpResponseForbidden() # 验证失败返回 403
user.is_active = True # 激活用户
return HttpResponseForbidden()
user.is_active = True
user.save()
content = '''
恭喜您已经成功的完成邮箱验证您现在可以使用您的账号来登录本站
@ -171,30 +174,31 @@ def account_result(request):
else:
return HttpResponseRedirect('/')
# 忘记密码视图
class ForgetPasswordView(FormView):
form_class = ForgetPasswordForm
template_name = 'account/forget_password.html'
def form_valid(self, form):
# 表单验证通过后处理密码重置逻辑
if form.is_valid():
blog_user = BlogUser.objects.filter(email=form.cleaned_data.get("email")).get()
blog_user.password = make_password(form.cleaned_data["new_password2"]) # 设置新密码
blog_user.password = make_password(form.cleaned_data["new_password2"])
blog_user.save()
return HttpResponseRedirect('/login/') # 重定向到登录页面
return HttpResponseRedirect('/login/')
else:
return self.render_to_response({'form': form})
# 忘记密码验证码视图
class ForgetPasswordEmailCode(View):
def post(self, request: HttpRequest):
# 处理验证码发送请求
form = ForgetPasswordCodeForm(request.POST)
if not form.is_valid():
return HttpResponse("错误的邮箱")
to_email = form.cleaned_data["email"]
code = generate_code() # 生成验证码
utils.send_verify_email(to_email, code) # 发送验证码邮件
utils.set_code(to_email, code) # 缓存验证码
code = generate_code()
utils.send_verify_email(to_email, code)
utils.set_code(to_email, code)
return HttpResponse("ok")

@ -0,0 +1,125 @@
from django import forms
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.urls import reverse
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
# 注册你的模型到admin后台
# Register your models here.
from .models import Article
class ArticleForm(forms.ModelForm):
# 文章表单类可在这里自定义文章模型对应的表单字段等当前示例中暂时没有额外自定义字段原body字段的AdminPagedownWidget注释掉了
class Meta:
model = Article # 关联的模型是Article
fields = '__all__' # 表单包含模型的所有字段
# 定义将选中文章发布的动作函数
def makr_article_publish(modeladmin, request, queryset):
queryset.update(status='p') # 将选中文章的状态更新为'p'(发布状态)
# 定义将选中文章设为草稿的动作函数
def draft_article(modeladmin, request, queryset):
queryset.update(status='d') # 将选中文章的状态更新为'd'(草稿状态)
# 定义关闭文章评论的动作函数
def close_article_commentstatus(modeladmin, request, queryset):
queryset.update(comment_status='c') # 将选中文章的评论状态更新为'c'(关闭状态)
# 定义开启文章评论的动作函数
def open_article_commentstatus(modeladmin, request, queryset):
queryset.update(comment_status='o') # 将选中文章的评论状态更新为'o'(开启状态)
# 为各个动作函数设置在admin界面显示的简短描述
makr_article_publish.short_description = _('Publish selected articles')
draft_article.short_description = _('Draft selected articles')
close_article_commentstatus.short_description = _('Close article comments')
open_article_commentstatus.short_description = _('Open article comments')
class ArticlelAdmin(admin.ModelAdmin):
list_per_page = 20 # 管理员列表页每页显示20条记录
search_fields = ('body', 'title') # 可搜索的字段,按文章内容和标题搜索
form = ArticleForm # 使用自定义的ArticleForm作为表单
# 列表页显示的字段
list_display = (
'id',
'title',
'author',
'link_to_category', # 自定义的显示分类链接的字段
'creation_time',
'views',
'status',
'type',
'article_order')
list_display_links = ('id', 'title') # 列表页中可点击跳转详情的字段
list_filter = ('status', 'type', 'category') # 可用于筛选的字段
filter_horizontal = ('tags',) # 水平过滤选择的字段(用于多对多关系,如文章和标签)
exclude = ('creation_time', 'last_modify_time') # 编辑页排除的字段(不显示这两个时间字段)
view_on_site = True # 开启在站点查看文章的功能
actions = [
# 配置admin界面的动作选项即上面定义的几个动作函数
makr_article_publish,
draft_article,
close_article_commentstatus,
open_article_commentstatus]
# 自定义显示分类为可点击链接的方法
def link_to_category(self, obj):
# 获取分类模型的app_label和model_name用于生成admin后台分类编辑页面的链接
info = (obj.category._meta.app_label, obj.category._meta.model_name)
link = reverse('admin:%s_%s_change' % info, args=(obj.category.id,))
# 格式化生成带链接的分类名称
return format_html(u'<a href="%s">%s</a>' % (link, obj.category.name))
link_to_category.short_description = _('category') # 该自定义字段在列表页的显示名称
# 重写获取表单的方法,用于自定义作者字段的查询集
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)
return form
# 重写保存模型的方法,可在这里添加自定义的保存逻辑,当前示例中调用父类方法进行默认保存
def save_model(self, request, obj, form, change):
super(ArticlelAdmin, self).save_model(request, obj, form, change)
# 重写获取站点查看链接的方法返回文章在站点的完整URL
def get_view_on_site_url(self, obj=None):
if obj:
url = obj.get_full_url()
return url
else:
from djangoblog.utils import get_current_site
site = get_current_site().domain
return site
class TagAdmin(admin.ModelAdmin):
exclude = ('slug', 'last_mod_time', 'creation_time') # 标签编辑页排除的字段
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name', 'parent_category', 'index') # 分类列表页显示的字段
exclude = ('slug', 'last_mod_time', 'creation_time') # 分类编辑页排除的字段
class LinksAdmin(admin.ModelAdmin):
exclude = ('last_mod_time', 'creation_time') # 链接编辑页排除的字段
class SideBarAdmin(admin.ModelAdmin):
list_display = ('name', 'content', 'is_enable', 'sequence') # 侧边栏列表页显示的字段
exclude = ('last_mod_time', 'creation_time') # 侧边栏编辑页排除的字段
class BlogSettingsAdmin(admin.ModelAdmin):
pass # 博客设置的admin类暂时没有额外配置

@ -7,11 +7,9 @@ from elasticsearch_dsl.connections import connections
from blog.models import Article
# 检查是否启用了 Elasticsearch
ELASTICSEARCH_ENABLED = hasattr(settings, 'ELASTICSEARCH_DSL')
if ELASTICSEARCH_ENABLED:
# 创建 Elasticsearch 连接
connections.create_connection(
hosts=[settings.ELASTICSEARCH_DSL['default']['hosts']])
from elasticsearch import Elasticsearch
@ -21,10 +19,8 @@ if ELASTICSEARCH_ENABLED:
c = IngestClient(es)
try:
# 检查是否存在名为 'geoip' 的 pipeline
c.get_pipeline('geoip')
except elasticsearch.exceptions.NotFoundError:
# 如果不存在,则创建 'geoip' pipeline
c.put_pipeline('geoip', body='''{
"description" : "Add geoip info",
"processors" : [
@ -37,7 +33,6 @@ if ELASTICSEARCH_ENABLED:
}''')
# 定义 GeoIP 信息的内部文档
class GeoIp(InnerDoc):
continent_name = Keyword()
country_iso_code = Keyword()
@ -45,25 +40,21 @@ class GeoIp(InnerDoc):
location = GeoPoint()
# 定义用户代理浏览器信息的内部文档
class UserAgentBrowser(InnerDoc):
Family = Keyword()
Version = Keyword()
# 定义用户代理操作系统信息的内部文档
class UserAgentOS(UserAgentBrowser):
pass
# 定义用户代理设备信息的内部文档
class UserAgentDevice(InnerDoc):
Family = Keyword()
Brand = Keyword()
Model = Keyword()
# 定义用户代理信息的内部文档
class UserAgent(InnerDoc):
browser = Object(UserAgentBrowser, required=False)
os = Object(UserAgentOS, required=False)
@ -72,7 +63,6 @@ class UserAgent(InnerDoc):
is_bot = Boolean()
# 定义性能日志的 Elasticsearch 文档
class ElapsedTimeDocument(Document):
url = Keyword()
time_taken = Long()
@ -82,7 +72,6 @@ class ElapsedTimeDocument(Document):
useragent = Object(UserAgent, required=False)
class Index:
# 定义索引名称和设置
name = 'performance'
settings = {
"number_of_shards": 1,
@ -93,11 +82,9 @@ class ElapsedTimeDocument(Document):
doc_type = 'ElapsedTime'
# 定义性能日志文档的管理器
class ElaspedTimeDocumentManager:
@staticmethod
def build_index():
# 创建 Elasticsearch 索引
from elasticsearch import Elasticsearch
client = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
res = client.indices.exists(index="performance")
@ -106,14 +93,12 @@ class ElaspedTimeDocumentManager:
@staticmethod
def delete_index():
# 删除 Elasticsearch 索引
from elasticsearch import Elasticsearch
es = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
es.indices.delete(index='performance', ignore=[400, 404])
@staticmethod
def create(url, time_taken, log_datetime, useragent, ip):
# 创建性能日志文档
ElaspedTimeDocumentManager.build_index()
ua = UserAgent()
ua.browser = UserAgentBrowser()
@ -145,7 +130,6 @@ class ElaspedTimeDocumentManager:
doc.save(pipeline="geoip")
# 定义文章的 Elasticsearch 文档
class ArticleDocument(Document):
body = Text(analyzer='ik_max_word', search_analyzer='ik_smart')
title = Text(analyzer='ik_max_word', search_analyzer='ik_smart')
@ -170,7 +154,6 @@ class ArticleDocument(Document):
article_order = Integer()
class Index:
# 定义索引名称和设置
name = 'blog'
settings = {
"number_of_shards": 1,
@ -181,25 +164,20 @@ class ArticleDocument(Document):
doc_type = 'Article'
# 定义文章文档的管理器
class ArticleDocumentManager():
def __init__(self):
# 初始化时创建索引
self.create_index()
def create_index(self):
# 创建 Elasticsearch 索引
ArticleDocument.init()
def delete_index(self):
# 删除 Elasticsearch 索引
from elasticsearch import Elasticsearch
es = Elasticsearch(settings.ELASTICSEARCH_DSL['default']['hosts'])
es.indices.delete(index='blog', ignore=[400, 404])
def convert_to_doc(self, articles):
# 将文章对象转换为 Elasticsearch 文档
return [
ArticleDocument(
meta={
@ -224,7 +202,6 @@ class ArticleDocumentManager():
article_order=article.article_order) for article in articles]
def rebuild(self, articles=None):
# 重建索引并重新保存文档
ArticleDocument.init()
articles = articles if articles else Article.objects.all()
docs = self.convert_to_doc(articles)
@ -232,6 +209,5 @@ class ArticleDocumentManager():
doc.save()
def update_docs(self, docs):
# 更新文档
for doc in docs:
doc.save()
doc.save()

@ -0,0 +1,42 @@
import logging
import time
from ipware import get_client_ip
from user_agents import parse
from blog.documents import ELASTICSEARCH_ENABLED, ElaspedTimeDocumentManager
logger = logging.getLogger(__name__)
class OnlineMiddleware(object):
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def __call__(self, request):
''' page render time '''
start_time = time.time()
response = self.get_response(request)
http_user_agent = request.META.get('HTTP_USER_AGENT', '')
ip, _ = get_client_ip(request)
user_agent = parse(http_user_agent)
if not response.streaming:
try:
cast_time = time.time() - start_time
if ELASTICSEARCH_ENABLED:
time_taken = round((cast_time) * 1000, 2)
url = request.path
from django.utils import timezone
ElaspedTimeDocumentManager.create(
url=url,
time_taken=time_taken,
log_datetime=timezone.now(),
useragent=user_agent,
ip=ip)
response.content = response.content.replace(
b'<!!LOAD_TIMES!!>', str.encode(str(cast_time)[:5]))
except Exception as e:
logger.error("Error OnlineMiddleware: %s" % e)
return response

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 221 B

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save