from django.db import models from django.conf import settings from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey from typing import List, Type def get_trackable_fields(model_class: Type[models.Model]) -> List[models.Field]: """Get fields that should be tracked in history.""" if getattr(model_class, '_is_historical_model', False): # For historical models, only return core history fields return [ models.BigAutoField(name='id', primary_key=True), models.DateTimeField(name='history_date'), models.CharField(name='history_change_reason', max_length=100, null=True), models.CharField(name='history_type', max_length=1), models.ForeignKey( to=settings.AUTH_USER_MODEL, name='history_user', null=True, on_delete=models.SET_NULL ) ] trackable_fields = [] excluded_fields = { 'comment_threads', 'comments', 'photos', 'reviews', 'thread', 'content_type', 'object_id', 'content_object' } for field in model_class._meta.get_fields(): # Skip fields we don't want to track if any([ isinstance(field, (GenericRelation, GenericForeignKey)), field.name in excluded_fields, field.is_relation and hasattr(field.remote_field.model, '_meta') and 'commentthread' in field.remote_field.model._meta.model_name.lower() ]): continue trackable_fields.append(field) return trackable_fields class HistoricalFieldsMixin: """Mixin that controls which fields are copied to historical models.""" @classmethod def get_fields_to_track(cls) -> List[models.Field]: """Get fields that should be tracked in history.""" return get_trackable_fields(cls)