# encoding: utf-8 from __future__ import absolute_import, unicode_literals from django.db.models.fields import reverse_related from apiview import model, admintools, descriptors from django.db import models from example.celery import async_call from . import constants class DeletedManager(models.Manager): def get_queryset(self): queryset = super(DeletedManager, self).get_queryset() return queryset.filter(delete_status=constants.DELETE_CODE.NORMAL.code) def get_all_queryset(self): return super(DeletedManager, self).get_queryset() class BaseModel(model.BaseModel): id = models.BigAutoField('主键ID', primary_key=True) create_time = models.DateTimeField('创建时间', auto_now_add=True, db_index=True, editable=False) modify_time = models.DateTimeField('修改时间', auto_now=True, db_index=True, editable=False) delete_status = models.BooleanField('删除状态', choices=constants.DELETE_CODE.get_list(), default=constants.DELETE_CODE.NORMAL.code, null=False, db_index=True) remark = models.TextField('备注说明', null=True, blank=True, default='') default_manager = models.Manager() objects = DeletedManager() def __str__(self): if hasattr(self, 'name'): return self.name else: return super(BaseModel, self).__str__() class Meta: abstract = True @classmethod def ex_search_fields(cls): ret = set() for field in cls._meta.fields: if not field.db_index and not field.unique \ and field.name == 'name' and isinstance(field, models.CharField): ret.add(field.name) return ret @classmethod def search_fields(cls): ret = super(BaseModel, cls).search_fields() return ret.union(cls.ex_search_fields()) def delete(self, using=None, keep_parents=False): self.delete_status = constants.DELETE_CODE.DELETED.code return self.save(using=using, force_update=True, update_fields=['delete_status', ]) def save_or_update(self): if self.pk is None: self.save(force_insert=True) else: self.save_changed() class ManyToManyRel(reverse_related.ForeignObjectRel): def __init__(self, field, to, related_name=None, related_query_name=None, limit_choices_to=None, symmetrical=True, through=None, through_fields=None, db_constraint=False): super(ManyToManyRel, self).__init__( field, to, related_name=related_name, related_query_name=related_query_name, limit_choices_to=limit_choices_to, ) self.through = through if through_fields and not through: raise ValueError("Cannot specify through_fields without a through model") self.through_fields = through_fields self.symmetrical = symmetrical self.db_constraint = db_constraint def get_related_field(self): opts = self.through._meta field = None if self.through_fields: field = opts.get_field(self.through_fields[0]) else: for field in opts.fields: rel = getattr(field, 'remote_field', None) if rel and rel.model == self.model: break if field is None: return None else: return field.foreign_related_fields[0] class ManyToManyField(models.ManyToManyField): rel_class = ManyToManyRel def __init__(self, to, related_name=None, related_query_name=None, limit_choices_to=None, symmetrical=None, through=None, through_fields=None, db_constraint=False, db_table=None, swappable=True, **kwargs): super(ManyToManyField, self).__init__(to, related_name, related_query_name, limit_choices_to, symmetrical, through, through_fields, db_constraint, db_table, swappable, **kwargs) class ForeignKey(models.ForeignKey): forward_related_accessor_class = descriptors.ForwardManyToOneCacheDescriptor def __init__(self, to, on_delete=models.DO_NOTHING, related_name=None, related_query_name=None, limit_choices_to=None, parent_link=False, to_field=None, db_constraint=False, **kwargs): super(ForeignKey, self).__init__(to, on_delete, related_name, related_query_name, limit_choices_to, parent_link, to_field, db_constraint, **kwargs) class OneToOneField(models.OneToOneField): forward_related_accessor_class = descriptors.ForwardOneToOneCacheDescriptor def __init__(self, to, on_delete=models.DO_NOTHING, to_field=None, db_constraint=False, **kwargs): super(OneToOneField, self).__init__(to, on_delete, to_field, db_constraint=db_constraint, **kwargs) class ExportMixin(admintools.ExportMixin): def async_export_data(self, func, *args, **kwargs): async_call(func, *args, **kwargs) class ImportExportMixin(admintools.ImportExportMixin): def async_export_data(self, func, *args, **kwargs): async_call(func, *args, **kwargs)