Django 实现日志分表Model,并在admin中进行注册管理

需求分析:

接口日志在数据库分表备份存储,由于每日数据量较大,采用按日期备份接口日志表(即每天一个日志表)的策略,表名格式: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()  # 创建分表模型,并注册到管理网站

至此,运行应用后就可在管理网站的列表页中看到数据库中已存在的日志表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值