class Power(BaseModel): name = models.CharField(_('权限名'), max_length=64) permissions = models.TextField(_('权限列表'), editable=False) # 操作权限的集合 def __unicode__(self): return u'%s' % self.name class Meta: verbose_name = _('权限') verbose_name_plural = _('权限') ordering = ['ordering', 'id'] app_label = 'user'
class MoneyStats(BaseModel): """ money stats """ title = models.CharField(_('标题'), max_length=64) money = models.CharField(_('金额'), max_length=64) date = models.DateField(_('日期'), default=timezone.now) def __unicode__(self): return u'%s' % self.title class Meta: verbose_name = _('金额统计') verbose_name_plural = _('金额统计') ordering = ['ordering', 'id'] app_label = 'stats'
class BaseModel(models.Model): ordering = models.IntegerField(_('排序权值'), default=0, db_index=True, editable=False) created = models.DateTimeField(_('创建时间'), auto_now_add=True) date = models.DateField(_('创建日期'), default=timezone.now) # titimezone 是系统设置时区 updated = models.DateTimeField(_('修改时间'), auto_now=True) class Meta: abstract = True ordering = ['-ordering', '-id'] @cached_property def base_fields(self): """ 基本字段list(BaseModel的字段 + id) :return: """ return [item.attname for item in BaseModel()._meta.concrete_fields] def get_fields(self, not_add_fields=True): """ 返回模型字典名称的list(不会返回id和基本字段,需要则手动添加) :param not_add_fields: 决定是否添加模型的add_fields属性里面的字段 :return: """ fields = [item.attname for item in self._meta.concrete_fields if item.attname not in self.base_fields] if getattr(self, 'add_fields', None) and not not_add_fields: add_fields = getattr(self, 'add_fields', []) fields += add_fields return fields def get_dict(self, not_add_fields=True, other_fields=[]): """ 返回模型实例的字典 :return: """ _dict = {} _field = self.get_fields(not_add_fields) _field += other_fields for item in _field: _dict[item] = getattr(self, item, '') return _dict
class UserGroup(BaseModel): name = models.CharField(_('组名'), max_length=64) power = models.ManyToManyField(to='user.Power') def __unicode__(self): return u'%s' % self.name class Meta: verbose_name = _('用户组') verbose_name_plural = _('用户组') ordering = ['ordering', 'id'] app_label = 'user'
class DataDic(BaseModel): objects = StatusManager() raw_objects = models.Manager() status = models.IntegerField(_('状态'), default=StatusManager.STATUS_NORMAL, choices=StatusManager.STATUS_CHOICES, editable=False) type = bfield.NameField(_('类型')) value = bfield.NameField(_('数据')) json = bfield.JsonField(_('附加'), default={}) def __unicode__(self): return u'%s: %s' % (self.type, self.value) def to_json(self): return {'id': self.id, 'value': self.value} class Meta: verbose_name = _('数据字典') verbose_name_plural = _('数据字典') ordering = ['ordering'] app_label = 'base'
class Meta: verbose_name = _('用户组') verbose_name_plural = _('用户组') ordering = ['ordering', 'id'] app_label = 'user'
class User(BaseModel): last_name = models.CharField(_('用户名'), max_length=128, null=True, blank=True) first_name = models.CharField(_('用户姓'), max_length=64, null=True, blank=True) name = models.CharField(_('姓名'), max_length=192, db_index=True, null=True, blank=True) code = models.CharField(_('编号'), max_length=64, db_index=True, null=True, blank=True) email = models.EmailField(_('邮件'), max_length=256, null=True, blank=True) username = models.CharField(_('登录帐号'), max_length=32, db_index=True, null=False, unique=True) password = models.CharField(_('加密密码'), max_length=32, null=False) icon = models.CharField(_('头像'), max_length=128, null=True, blank=True) level = models.SmallIntegerField(_('等级'), default=1) role = models.ForeignKey(to='user.Role', verbose_name=_('角色'), null=True, blank=True, on_delete=models.SET_NULL, related_name="%(app_label)s_%(class)s_related") group = models.ForeignKey(to='user.UserGroup', verbose_name=_('用户组'), null=True, blank=True, on_delete=models.SET_NULL, related_name="%(app_label)s_%(class)s_related") @staticmethod def make_password_for_hash(value): """ 通过框架加密工具加密密码 :param value: :return: """ return make_password(value) def check_password(self, password): """ 密码解密验证 :return: """ return check_password(password, self.password) def __unicode__(self): return u'%s' % self.name class Meta: verbose_name = _('用户') verbose_name_plural = _('用户') ordering = ['ordering', 'id'] app_label = 'user'
class BaseModel(models.Model): ordering = models.IntegerField(_('排序权值'), default=0, db_index=True, editable=False) created = models.DateTimeField(_('创建时间'), auto_now_add=True) updated = models.DateTimeField(_('修改时间'), auto_now=True) class Meta: abstract = True ordering = ['-ordering', '-id'] @classmethod def get_fields(clz): return clz._meta.fields @classmethod def get_allfields(clz): return [f.name for f in clz.get_fields()] @classmethod def get_editfields(clz): return [ f.name for f in clz.get_fields() if f.editable and not f.primary_key ] @classmethod def get_dictfields(cls, full=False): arr = [] for f in cls.get_fields(): if f.editable and not f.primary_key: fd = { 'name': f.name + "_id" if hasattr(f, 'rel') and hasattr(f.rel, 'to') else f.name, 'editable': f.editable and not f.primary_key, 'value': f.get_default(), 'type': f.__class__.__name__, 'max_length': f.max_length, 'required': not (f.blank or f.null), 'verbose_name': f.verbose_name, 'choices': f.choices, 'relmodel': (f.rel.to.__name__ if hasattr( f.rel.to, '__name__') else f.rel.to) if hasattr(f, 'rel') and hasattr(f.rel, 'to') else None } if full: fd['field'] = f arr.append(fd) return arr @classmethod def get_field(cls, name): rs = [f for f in cls.get_fields() if f.name == name] return rs[0] if rs else None def save(self, force_insert=False, force_update=False, using=None, update_fields=None): if not self.ordering: orderingby = getattr(self._meta, 'ordering', []) if orderingby and orderingby[0] == 'ordering': import time self.ordering = int(time.time()) if self.id: from base.utils import del_cached_obj del_cached_obj(self) if update_fields: default_fields = ["updated"] update_fields = default_fields + update_fields return models.Model.save(self, force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields) def to_json(self): return {'id': self.id}
class Meta: verbose_name = _('数据字典') verbose_name_plural = _('数据字典') ordering = ['ordering'] app_label = 'base'
class KeyValue(BaseModel): key = models.CharField(_('健'), max_length=255, db_index=True, unique=True) type = models.CharField(_('类型'), max_length=255, null=True, blank=True, default="text") name = models.CharField(_('名称'), max_length=255, null=True, blank=True) value = models.TextField(_('值'), max_length=65535, null=True, blank=True) other = models.CharField(_('附加'), max_length=255, null=True, blank=True) @property def depends(self): return self.other.split(';')[0] if self.other else None @property def attachs(self): rs = self.other.split(';') if self.other else [] return rs[1] if len(rs) > 1 else None @property def attachssetting(self): attachs = self.attachs if attachs: import re return dict(re.findall('([^=^\s]+)\s*=\s*([^=^\s]*)', attachs)) else: return {} @classmethod def listjson(cls, v): if type(v) != list: try: v = json.loads(v) except: v = [] return v @classmethod def trystr(cls, v): try: return str(v) except: pass return unicode(v) @classmethod def safefloat(cls, v): try: return float(v) except: pass return 0 @classmethod def safejson(cls, v): if isinstance(v, basestring): try: v = json.loads(v) except: v = {} return v @classmethod def trydatetime(cls, v): from base.utils import parse_datetime return parse_datetime(v) TYPE_MAP = { 'text': lambda s: KeyValue.trystr(s) if s else "", 'largetext': lambda s: KeyValue.trystr(s) if s else "", 'int': lambda s: int(s) if s else 0, 'float': lambda s: float(s) if s else 0.0, 'bool': lambda s: s and s.upper() == "TRUE", 'imagelinks': lambda s: KeyValue.listjson(s), 'texts': lambda s: [v.strip() for v in s.split(';') if v.strip()], 'ints': lambda s: [int(v.strip()) for v in s.split(';') if v.strip().isdigit()], 'floats': lambda s: [KeyValue.safefloat(v) for v in s.split(';') if v.strip()], 'fixfloats': lambda s: [KeyValue.safefloat(v) for v in s.split(';')], 'keyvals': lambda s: KeyValue.listjson(s), 'timesegs': lambda s: KeyValue.listjson(s), 'time': lambda s: KeyValue.trystr(s), 'json': lambda s: KeyValue.safejson(s), 'datetime': lambda s: KeyValue.trydatetime(s), 'date': lambda s: KeyValue.trystr(s), } def __unicode__(self): return u'%s(%s)' % (self.name, self.key) class Meta: verbose_name = _('设置') verbose_name_plural = _('设置') ordering = ['ordering'] app_label = 'base' @property def pyvalue(self): return KeyValue.TYPE_MAP[self.type]( self.value) if self.type in KeyValue.TYPE_MAP else None @classmethod def gen_setting(cls, dft=None, ckord=False, autodel=False): '''def=[(key,type,name,value,other)]''' kvs = dict((v[0], v) for v in dft) if dft else None ks = [v[0] for v in dft] if dft else None if autodel: KeyValue.objects.filter().exclude(key__in=ks).delete() query = KeyValue.objects if ks: query = query.filter(key__in=ks) res = {} items = [i for i in query] for i in items: if ks and i.key in ks: ks.remove(i.key) res[i.key] = i.pyvalue if ks: arr = [] for k in ks: v = kvs[k] kv = KeyValue(key=k, type=v[1], name=v[2], value=v[3], other=v[4]) arr.append(kv) res[k] = kv.pyvalue KeyValue.objects.bulk_create(arr) if ckord and dft: ks = [v[0] for v in dft] idic = dict([(i.key, i) for i in KeyValue.objects.filter(key__in=ks)]) for ordering, di in enumerate(dft): key = di[0] if key in idic: item = idic[key] other = di[4] name = di[2] stype = di[1] nordering = ordering + 1 if item.ordering != nordering or item.other != other or item.name != name or item.type != stype: item.ordering = nordering item.other = other item.name = name item.type = stype item.save() return res
class Meta: verbose_name = _('文章分类') verbose_name_plural = _('文章分类') ordering = ['ordering', 'id'] # ordering = ['?'] 随机排序 app_label = 'vadmin'
class Meta: verbose_name = _('文章') verbose_name_plural = _('文章') ordering = ['ordering', 'id'] app_label = 'vadmin'
class Article(BaseModel): """ 文章模型 """ title = models.CharField(_('标题'), max_length=16) author = models.CharField(_('作者'), max_length=16) abstract = models.TextField(_('摘要')) cover = models.CharField(_('封面img对应url'), max_length=256) content = models.TextField(_('内容')) times = models.SmallIntegerField(_('浏览次数')) guid = models.CharField(_('GUID'), max_length=32) articleclassify = models.CharField(_('所属分类的GUID'), max_length=32) def __unicode__(self): return u'%s-%s' % (self.title, self.author) class Meta: verbose_name = _('文章') verbose_name_plural = _('文章') ordering = ['ordering', 'id'] app_label = 'vadmin' @staticmethod def refresh_ordering(): """ 刷新排序 :return: """ query = Article.objects.all() for key, item in enumerate(query): item.ordering = key item.save() return query.count() @property def lastArticle(self): """ 上一篇文章 :return: """ a = Article.objects.filter(ordering=(self.ordering - 1)).first() return a and {'guid': a.guid, 'title': a.title} or {'guid': self.guid, 'title': '没有更多'} @property def nextArticle(self): """ 下一篇文章 :return: """ a = Article.objects.filter(ordering=(self.ordering + 1)).first() return a and {'guid': a.guid, 'title': a.title} or {'guid': self.guid, 'title': '没有更多'} @property def return_article_classify_name(self): # article_classify_name 名字不能用,和框架冲突了 ac = ArticleClassify.objects.get(guid=self.articleclassify) return ac and ac.name or '' @property def article_to_article_classify(self): return ArticleClassify.objects.filter(guid=self.articleclassify).first() @property def return_classify_parents(self): """ 返回文章所属分类的层级信息 :return: """ return self.article_to_article_classify.return_parents def update_times(self): """ 更新浏览次数 :return: """ self.times = self.times + 1 self.save() # 由通用方法处理的模型,通过定义add_fields实现字段扩展 add_fields = ['return_article_classify_name', 'return_classify_parents', 'lastArticle', 'nextArticle'] # 通用方法获取数据列表,由该方法来做过滤处理,方法名称必须为filter_handler @staticmethod def filter_handler(params, query): """ 数据筛选处理方法,返回筛选后的结果 :return: """ classify_guid = params.get('classify_guid') if classify_guid: article_classify = ArticleClassify.objects.filter(guid=classify_guid).first() if not article_classify: return query classify_list = article_classify.return_all_children_to_list id_list = [item.guid for item in classify_list if item and item.guid or None] query = query.filter(articleclassify__in=id_list) return query else: return query
class ArticleClassify(BaseModel): """ 文章分类模型 """ name = models.CharField(_('分类名称'), max_length=32) parent = models.CharField(_('所属分类'), max_length=32) # 存储分类上级的GUID guid = models.CharField(_('GUID'), max_length=32) level = models.SmallIntegerField(_('级别'), default=1) # 最大到三级(没有做限制) def __unicode__(self): return u'%s' % self.name def __repr__(self): return u'%s' % self.name class Meta: verbose_name = _('文章分类') verbose_name_plural = _('文章分类') ordering = ['ordering', 'id'] # ordering = ['?'] 随机排序 app_label = 'vadmin' @property def return_children(self): """ 返回属于这个分类的子项(只返回子项,不返回子项的子项) :return: """ query = ArticleClassify.objects.filter(parent=self.guid) return query @staticmethod def get_children(guid): """ 获取parent为guid的子项 :param guid: :return: guid list """ return ArticleClassify.objects.filter(parent=guid).values_list('guid', flat=True) @property def return_all_children_count(self): """ 返回该分类下有多少文章 :return: """ query_list = self.return_all_children_to_list id_list = [item.guid for item in query_list if item and item.guid or None] count = Article.objects.filter(articleclassify__in=id_list).count() return count or 0 @property def isLeaf(self): """ 判断是否为子节点的(前端使用,根据当前分类有没有子分类来决定) :return: """ query = ArticleClassify.objects.filter(parent=self.guid).first() return False if query else True @staticmethod def return_tree_data(): """ 返回树形结构数据 :return: """ # 查出顶级对象 top_data = ArticleClassify.objects.filter(level=1) data = [] for item in top_data: hander = lambda x: object_to_dict(['name', 'guid', 'isLeaf', 'return_all_children_count'], x) res = hander(item) res['children_list'] = item.get_true_children(item.guid, hander) data.append(res) return data def get_true_children(self, guid, hander): """ 树形数据中计算子项 :param guid: :param hander: :return: """ hander = hander query = ArticleClassify.objects.filter(parent=guid) children_list = [hander(i) for i in query] for i in children_list: if not i['isLeaf']: self_query = ArticleClassify.objects.filter(guid=i.get('guid')).first() i['children_list'] = self_query.get_true_children(i.get('guid'), hander) return children_list @property def return_all_children_to_list(self): """ 返回所有的子项,包含自身(利用N叉树遍历方法, 结果包含在一个列表中) :return: """ root = self if not root: return [] que = [] # 保存节点的队列 res = [] # 保存结果的列表 que.append(root) # while len(que): # 判断队列不为空 length = len(que) for i in range(length): current = que.pop(0) # 出队列的当前节点 res.append(current) # 直接把节点加到结果里面 for child in current.return_children: # 所有子结点入队列 que.append(child) return res def return_all_children_to_layer(self): """ 返回所有的子项(N叉树层序遍历) :return: """ root = self if not root: return [] que = [] # 保存节点的队列 res = [] # 保存结果的列表 que.append(root) # while len(que): # 判断队列不为空 length = len(que) sub = [] # 保存每层的节点的值 for i in range(length): current = que.pop(0) # 出队列的当前节点 print(current) sub.append(current) for child in current.return_children: # 所有子结点入队列 que.append(child) res.append(sub) # 把每层的节点的值加入结果列表 return res @property def return_parents(self): """ 返回当前分类的父级信息 :return: """ parent = ArticleClassify.objects.filter(guid=self.parent).first() loop = 5 # 做限制,最多迭代5次 res = [] if parent: res.append({'name': parent.name}) while parent and loop: parent = ArticleClassify.objects.filter(guid=parent.parent).first() if parent: res.append({'name': parent.name}) loop -= 1 return res
class Meta: verbose_name = _('金额统计') verbose_name_plural = _('金额统计') ordering = ['ordering', 'id'] app_label = 'stats'