需求分析:
接口日志在数据库分表备份存储,由于每日数据量较大,采用按日期备份接口日志表(即每天一个日志表)的策略,表名格式:ws_Event_日期后缀,例如:ws_Event_20240101。
当前实时接口日志存放在不加后缀的ws_Event表,T+1日后使用作业处理备份到日志分表中。
要求实现在Django管理网站对接口日志进行查询管理,不允许对日志进行修改和删除。
实现步骤:
1. 定义日志模型抽象基类(抽象模型在数据迁移时不会创建数据库表)
# 在应用程序目录下的models.py中
from typing import Any
from django.db import models
from django.db import connection
class Ws_Event_Base(models.Model):
'''接口日志基类模型'''
class Meta:
abstract = True # 不会创建数据库表
EventID = models.BigAutoField(primary_key=True, db_column='EventID', verbose_name='接口日志ID')
E_DateTime = models.DateTimeField(auto_now_add=True, db_column='E_DateTime', verbose_name='接口日志时间')
E_From = models.CharField(max_length=255, null=True, blank=True, db_column="E_From", verbose_name='接口名称')
def __str__(self) -> str:
return f"事件日志ID:{self.EventID}"
@staticmethod
def is_exists(table_name):
'''数据表是否存在'''
return table_name in connection.introspection.table_names()
@staticmethod
def create_split_model(model_name):
'''创建新的分表模型'''
class Meta:
db_table = model_name
verbose_name = f"接口日志{model_name.split('_')[-1]}"
verbose_name_plural = verbose_name
# 设置分表的属性
attrs = {'__module__': Ws_Event_Base.__module__, 'Meta': Meta}
# 创建分表模型
model = type(model_name, (Ws_Event_Base,), attrs)
return model
2. 创建日志工作表模型
主要用于数据迁移时创建数据表,工作表用于存放实时日志。
再执行数据迁移命令创建数据库表。
# models.py
class Ws_Event(Ws_Event_Base):
class Meta:
# 数据库表名
db_table = 'ws_Event'
# 模型对象的显示名称
verbose_name = '接口日志'
# 模型对象的复数显示名称
verbose_name_plural = verbose_name
# 获取模型对象默认排序方式
ordering = ['-E_DateTime']
@classmethod
def update_table_model(cls, table_name):
'''切换模型关联的数据分表
table_name -> str: 分表或工作表名称(区分大小写)
'''
cls._meta.db_table = table_name
suffix = table_name.split('_')[-1]
if suffix.isdigit():
cls._meta.verbose_name = f"接口日志{suffix}"
else:
cls._meta.verbose_name = "接口日志"
cls._meta.verbose_name_plural = cls._meta.verbose_name
with connection.cursor() as cur:
if not cls.is_exists(table_name):
with connection.schema_editor() as schema_editor:
schema_editor.create_model(cls)
3. 根据数据库中已存在的日志分表动态建立日志分表模型并注册到Django管理网站
如不需要在Django管理网站进行管理则不需要进行此操作。
# 在应用程序目录下的admin.py中
class Ws_EventAdmin(admin.ModelAdmin):
'''自定义Ws_Event的管理页面'''
# 设置编辑页面显示的字段
fields = (('E_WSName','E_From'), 'E_DateTime', 'E_IP', 'E_BegDatetime', 'E_EndDatetime', 'E_Interval', 'E_Input', 'E_Output')
# 设置只读字段
readonly_fields = ('E_WSName','E_From', 'E_DateTime', 'E_IP', 'E_BegDatetime', 'E_EndDatetime', 'E_Interval', 'E_Input', 'E_Output')
# 设置显示列
list_display = ('EventID',WsEvent_Display_DateTime,'E_WSName', 'E_From','E_IP','E_BegDatetime','E_EndDatetime','E_Interval')
# 设置字段链接
list_display_links = ('E_WSName','E_From')
# 设置每页展示记录条数
list_per_page = 10
# 设置查询条件字段
search_fields = ('E_WSName','E_From','E_IP','E_Input','E_Output')
# 设置过滤字段
list_filter = ('E_WSName',)
def get_queryset(self, request):
# 获取默认的查询集合
queryset = super().get_queryset(request)
# 添加自定义的查询条件
if 'E_WSName' in self.list_filter:
field_value = request.GET.get('E_WSName')
if field_value is not None and len(field_value) > 0:
queryset = queryset.filter(your_field=field_value)
return queryset
def has_add_permission(self, request):
""" 取消后台添加功能 """
return False
def has_delete_permission(self, request, obj=None):
""" 取消后台删除功能 """
return False
def save_model(self, request, obj, form, change):
""" 取消后台编辑功能 """
return False
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['show_save_and_continue'] = False
extra_context['show_save'] = False
return super(Ws_EventAdmin, self).changeform_view(request, object_id, extra_context=extra_context)
# 在管理网站中注册工作日志模型
admin.site.register(Ws_Event, Ws_EventAdmin)
def Ws_Event_Create_Register_Model():
'''创建分表模型,并注册到管理网站'''
sql_query_ws_event_table_name = """select table_name from INFORMATION_SCHEMA.TABLES
where table_name like 'ws[_]Event[_][1-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]'"""
with connection.cursor() as cur:
cur.execute(sql_query_ws_event_table_name)
history_tables = cur.fetchall()
for t in history_tables:
admin.site.register(Ws_Event_Base.create_split_model(t[0]), Ws_EventAdmin)
Ws_Event_Create_Register_Model() # 创建分表模型,并注册到管理网站
至此,运行应用后就可在管理网站的列表页中看到数据库中已存在的日志表。