2023-02-16 07:55:33 +00:00
|
|
|
import copy
|
2023-03-08 03:21:15 +00:00
|
|
|
from datetime import datetime
|
2023-09-13 08:52:11 +00:00
|
|
|
from itertools import chain
|
2022-11-04 06:22:38 +00:00
|
|
|
|
2023-12-05 03:16:34 +00:00
|
|
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
2022-11-04 06:22:38 +00:00
|
|
|
from django.db import models
|
2022-05-05 06:42:09 +00:00
|
|
|
|
2023-06-09 10:19:04 +00:00
|
|
|
from common.db.fields import RelatedManager
|
2023-09-13 08:52:11 +00:00
|
|
|
from common.utils import validate_ip, get_ip_city, get_logger
|
|
|
|
from common.utils.timezone import as_current_tz
|
2022-11-04 06:22:38 +00:00
|
|
|
from .const import DEFAULT_CITY
|
2022-05-05 06:42:09 +00:00
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
2019-03-22 07:17:22 +00:00
|
|
|
|
|
|
|
|
2019-11-05 10:46:29 +00:00
|
|
|
def write_login_log(*args, **kwargs):
|
|
|
|
from audits.models import UserLoginLog
|
2021-09-27 11:06:26 +00:00
|
|
|
|
2019-11-05 10:46:29 +00:00
|
|
|
ip = kwargs.get('ip') or ''
|
|
|
|
if not (ip and validate_ip(ip)):
|
|
|
|
ip = ip[:15]
|
2021-09-27 11:06:26 +00:00
|
|
|
city = DEFAULT_CITY
|
2019-11-05 10:46:29 +00:00
|
|
|
else:
|
2021-09-27 11:06:26 +00:00
|
|
|
city = get_ip_city(ip) or DEFAULT_CITY
|
2019-11-05 10:46:29 +00:00
|
|
|
kwargs.update({'ip': ip, 'city': city})
|
2023-09-13 08:52:11 +00:00
|
|
|
return UserLoginLog.objects.create(**kwargs)
|
2022-05-05 06:42:09 +00:00
|
|
|
|
|
|
|
|
2023-01-16 11:02:09 +00:00
|
|
|
def _get_instance_field_value(
|
|
|
|
instance, include_model_fields,
|
|
|
|
model_need_continue_fields, exclude_fields=None
|
2022-11-04 06:22:38 +00:00
|
|
|
):
|
|
|
|
data = {}
|
2023-01-16 11:02:09 +00:00
|
|
|
opts = getattr(instance, '_meta', None)
|
|
|
|
if opts is not None:
|
|
|
|
for f in chain(opts.concrete_fields, opts.private_fields):
|
|
|
|
if not include_model_fields and not getattr(f, 'primary_key', False):
|
|
|
|
continue
|
|
|
|
|
2023-12-19 10:42:44 +00:00
|
|
|
if isinstance(f, GenericForeignKey):
|
|
|
|
continue
|
|
|
|
|
2023-01-16 11:02:09 +00:00
|
|
|
if isinstance(f, (models.FileField, models.ImageField)):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if getattr(f, 'attname', None) in model_need_continue_fields:
|
|
|
|
continue
|
2022-11-04 06:22:38 +00:00
|
|
|
|
2023-06-21 02:58:14 +00:00
|
|
|
value = getattr(instance, f.name, None) or getattr(instance, f.attname, None)
|
2023-01-16 11:02:09 +00:00
|
|
|
if not isinstance(value, bool) and not value:
|
|
|
|
continue
|
2022-11-04 06:22:38 +00:00
|
|
|
|
2023-01-16 11:02:09 +00:00
|
|
|
if getattr(f, 'primary_key', False):
|
|
|
|
f.verbose_name = 'id'
|
2023-05-22 06:24:22 +00:00
|
|
|
elif isinstance(value, list):
|
2023-02-16 07:55:33 +00:00
|
|
|
value = copy.deepcopy(value)
|
2023-05-22 06:24:22 +00:00
|
|
|
elif isinstance(value, dict):
|
|
|
|
value = dict(copy.deepcopy(value))
|
2023-03-08 03:21:15 +00:00
|
|
|
elif isinstance(value, datetime):
|
|
|
|
value = as_current_tz(value).strftime('%Y-%m-%d %H:%M:%S')
|
2023-06-09 10:19:04 +00:00
|
|
|
elif isinstance(value, RelatedManager):
|
|
|
|
value = value.value
|
2023-01-16 11:02:09 +00:00
|
|
|
elif isinstance(f, models.OneToOneField) and isinstance(value, models.Model):
|
|
|
|
nested_data = _get_instance_field_value(
|
|
|
|
value, include_model_fields, model_need_continue_fields, ('id',)
|
|
|
|
)
|
|
|
|
for k, v in nested_data.items():
|
|
|
|
if exclude_fields and k in exclude_fields:
|
|
|
|
continue
|
|
|
|
data.setdefault(k, v)
|
|
|
|
continue
|
2023-12-05 03:16:34 +00:00
|
|
|
elif isinstance(f, GenericRelation):
|
|
|
|
value = [str(v) for v in value.all()]
|
|
|
|
elif isinstance(f, GenericForeignKey):
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
data.setdefault(str(f.verbose_name), value)
|
|
|
|
except Exception as e:
|
|
|
|
print(f.__dict__)
|
|
|
|
raise e
|
2023-01-16 11:02:09 +00:00
|
|
|
return data
|
2022-11-04 06:22:38 +00:00
|
|
|
|
|
|
|
|
2023-12-05 09:26:47 +00:00
|
|
|
def model_to_dict_for_operate_log(
|
|
|
|
instance, include_model_fields=True, include_related_fields=None
|
|
|
|
):
|
|
|
|
def get_related_values(f):
|
|
|
|
value = []
|
|
|
|
if instance.pk is not None:
|
|
|
|
related_name = getattr(f, 'attname', '') or getattr(f, 'related_name', '')
|
|
|
|
if not related_name or related_name in ['history_passwords']:
|
|
|
|
return
|
|
|
|
try:
|
|
|
|
value = [str(i) for i in getattr(instance, related_name).all()]
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
if not value:
|
|
|
|
return
|
|
|
|
try:
|
|
|
|
field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name
|
|
|
|
data.setdefault(str(field_key), value)
|
|
|
|
except:
|
|
|
|
pass
|
2023-01-16 11:02:09 +00:00
|
|
|
|
|
|
|
data = _get_instance_field_value(
|
2023-12-05 09:26:47 +00:00
|
|
|
instance, include_model_fields, ['date_updated']
|
2023-01-16 11:02:09 +00:00
|
|
|
)
|
2022-11-04 06:22:38 +00:00
|
|
|
|
|
|
|
if include_related_fields:
|
2023-01-16 11:02:09 +00:00
|
|
|
opts = instance._meta
|
2023-12-05 09:26:47 +00:00
|
|
|
for f in chain(opts.many_to_many, opts.related_objects):
|
|
|
|
related_model = getattr(f, 'related_model', None)
|
|
|
|
if related_model not in include_related_fields:
|
2022-11-04 06:22:38 +00:00
|
|
|
continue
|
2023-12-05 09:26:47 +00:00
|
|
|
get_related_values(f)
|
|
|
|
|
2022-11-04 06:22:38 +00:00
|
|
|
return data
|