def insert_user_info(data, model, user_id, action): if not isinstance(data, dict): return None, None creator_field = get_gmeta_config_by_key(model, gmeta.GMETA_CREATOR_FIELD) updater_field = get_gmeta_config_by_key( model, gmeta.GMETA_UPDATER_FIELD) or getattr( model, admin.BSM_AUTH_FILTER_FIELD, None) if updater_field: data[updater_field] = user_id if action == "create" and creator_field and creator_field != updater_field: data[creator_field] = user_id return creator_field, updater_field
def get_queryset(self): """动态的计算结果集 - 如果是展开字段,这里做好是否关联查询 """ managers = get_gmeta_config_by_key(self.model, gmeta.GMETA_MANAGERS) if managers and "client_api" in managers: objects = getattr(self.model, managers["client_api"], self.model.objects) else: objects = self.model.objects queryset = objects.all() expand_fields = self.expand_fields if expand_fields: expand_fields = self.translate_expand_fields(expand_fields) field_list = [item.replace(".", "__") for item in expand_fields] queryset = queryset.prefetch_related(*field_list) filter_fields = set() def add_filter_fields(cons): for con in cons: if "field" in con: filter_fields.add(con["field"]) if "children" in con: add_filter_fields(con["children"]) add_filter_fields(self.request.data.get(const.FILTER_CONDITIONS, [])) queryset = queryset_utils.annotate( queryset, filter_fields, context={"user": self.request.user} ) return self._get_queryset(queryset)
def get_export_config_by_key(model, key, export_config=None): """ 获取指定键的导出配置数据 """ value = None if isinstance(export_config, dict): value = export_config.get(key) if not value: value = get_gmeta_config_by_key(model, key) return value
def check_permissions(self, request): """校验权限""" if not hasattr(self, "model"): return False action_skip = get_gmeta_config_by_key( self.model, gmeta.GMETA_CLIENT_API_PERMISSION_SKIP ) if isinstance(action_skip, (tuple, list)) and self.action in action_skip: return True super().check_permissions(request)
def get_queryset_by_filter_user(self, queryset): """通过用户过滤对应的数据集 - 如果用户是超级用户,则不做任何过滤 - 如果用户是普通用户,则客户端筛选的模型有引用到了用户模型,则过滤对应的数据集 """ user = self.request.user if user and user.is_staff and user.is_superuser: return queryset # 检测模型中是否有字段引用了用户模型 has_user_field = meta.get_related_model_field(self.model, get_user_model()) if has_user_field: # 如果有,则读取模型中 GMeta 中的配置 # FIXME: 注意,这里和管理端的处理逻辑暂时是不同的 user_field_name = get_gmeta_config_by_key( self.model, gmeta.GMETA_CLIENT_USER_FIELD ) filter_by_login_user = get_gmeta_config_by_key( self.model, gmeta.GMETA_CLIENT_FILTER_BY_LOGIN_USER ) if user_field_name and filter_by_login_user: return queryset.filter(**{user_field_name: user}) return queryset
def create_form_class(model, exclude_fields=None, **kwargs): """构建序列化类""" def __init__(self, *args, **kwargs): """ 重置导出的字段映射,因为类似 BooleanField 字段,显示为中文会比较友好 """ self.serializer_field_mapping[JSONField] = drf_field.JSONField self.serializer_field_mapping[OriginJSONField] = DrfJSONField super(serializers.ModelSerializer, self).__init__(*args, **kwargs) def update(self, instance, validated_data): raise_errors_on_nested_writes("update", self, validated_data) info = model_meta.get_field_info(instance) for attr, value in validated_data.items(): if attr in info.relations and info.relations[attr].to_many: field = getattr(instance, attr) if rfu_modes.append and attr in rfu_modes.append: field.add(value) else: field.set(value) else: setattr(instance, attr, value) instance.save() return instance attrs = { "Meta": create_meta_class(model, exclude_fields=None), "__init__": __init__, "update": update, } attrs.update(kwargs) class_name = f"{model}ModelSerializer" # 创建表单级的校验方法 validators = get_gmeta_config_by_key(model, gmeta.GMETA_OBJECT_VALIDATORS) if validators: attrs["validate"] = get_validate(validators) # MethodType(get_validate(validators), cls) return type(class_name, (serializers.ModelSerializer, ), attrs)
def insert_user_to_data(model, user, data): """插入用户到数据中""" # 第一部分,先检测模型中的字段是否有引用用户模型,如果有,则注入用户数据 auth_user_field = None # 检测模型中是否有字段引用了用户模型 has_user_field = meta.get_related_model_field(model, get_user_model()) if has_user_field: field_name = get_gmeta_config_by_key(model, gmeta.GMETA_CLIENT_USER_FIELD) if field_name: auth_user_field = field_name # 如果用户数据中没有传递用户的数据,则进行插入 if field_name not in data: data[field_name] = user.id relation_fields = meta.get_all_relation_fields(model) if relation_fields: for item in relation_fields: if item.name not in data or item.name == auth_user_field: # 如果字段没有在 data 中或者字段名称和 auth_user_field 相同,则不做任何处理 continue value = data[item.name] if meta.check_field_is_reverse(item): # FIXME: 当前反向字段使用的是列表数据结构 if not value or not isinstance(value, list): continue has_user_field = meta.get_related_model_field( item.related_model, get_user_model()) if has_user_field: field_name = get_gmeta_config_by_key( item.related_model, gmeta.GMETA_CLIENT_USER_FIELD) if field_name: for reverse_item in value: if isinstance(reverse_item, dict): # 如果用户数据中没有传递用户的数据,则进行插入 if field_name not in reverse_item: reverse_item[field_name] = user.id else: # 这里说明是正向字段 if item.many_to_many: # 说明是多对多字段 if not value or not isinstance(value, list): continue has_user_field = meta.get_related_model_field( item.related_model, get_user_model()) if has_user_field: field_name = get_gmeta_config_by_key( item.related_model, gmeta.GMETA_CLIENT_USER_FIELD) if field_name: for child_item in value: if isinstance(child_item, dict): # 如果用户数据中没有传递用户的数据,则进行插入 if field_name not in child_item: child_item[field_name] = user.id else: # 使用字典数据结构 if isinstance(value, dict): has_user_field = meta.get_related_model_field( item.related_model, get_user_model()) if has_user_field: field_name = get_gmeta_config_by_key( item.related_model, gmeta.GMETA_CLIENT_USER_FIELD) if field_name: # 如果用户数据中没有传递用户的数据,则进行插入 if field_name not in value: value[field_name] = user
def create_serializer_class( model, exclude_fields=None, tree_structure=None, action=None, end_slug=None, attrs=None, display_fields=None, allow_one_to_one=False, ): """构建序列化类 Params: tree_structure 元组 admin 中做对应配置 """ if attrs is None: attrs = {} def __init__(self, *args, **kwargs): """ 重置导出的字段映射,因为类似 BooleanField 字段,显示为中文会比较友好 """ self.serializer_field_mapping[JSONField] = drf_field.JSONField self.serializer_field_mapping[OriginJSONField] = DrfJSONField if self.action == "export_file": self.serializer_field_mapping[ models.BooleanField] = drf_field.ExportBooleanField self.serializer_field_mapping[ models.DateTimeField] = drf_field.ExportDateTimeField self.serializer_choice_field = drf_field.ExportChoiceField else: # 恢复为原来的字段类型映射,因为上面改了类的变量属性值 self.serializer_field_mapping[ models.BooleanField] = fields.BooleanField self.serializer_field_mapping[ models.DateTimeField] = fields.DateTimeField self.serializer_choice_field = fields.ChoiceField super(CustomModelSerializer, self).__init__(*args, **kwargs) extra_fields = list(attrs.keys()) new_attr = {} # 动态构建树形结构的字段 if tree_structure: extra_fields.append(tree_structure[1]) new_attr[tree_structure[1]] = RecursiveSerializer(many=True) # 构建计算属性字段 computed_fields = get_gmeta_config_by_key(model, gmeta.GMETA_COMPUTED_FIELDS) if computed_fields: extra_fields += [f["name"] for f in computed_fields] for field in computed_fields: name = field["name"] field_type = field["type"] # 如果是导出,则使用导出的字段序列化类 if (action == EXPORT_FILE_ACTION and field_type in ExportFieldTypeSerializerMap): new_attr[name] = ExportFieldTypeSerializerMap[field_type]( read_only=True) else: new_attr[name] = ComputedFieldTypeSerializerMap[field_type]( read_only=True) # 构建annotate算属性字段 annotated_fields = get_attr_in_gmeta_class(model, gmeta.GMETA_ANNOTATED_FIELDS, {}) if annotated_fields: extra_fields += annotated_fields.keys() for name, field in annotated_fields.items(): new_attr[name] = ComputedFieldTypeSerializerMap[field["type"]]( read_only=True) class_name = f"{model.__name__}ModelSerializer" return type( class_name, (BaseModelSerializerMixin, CustomModelSerializer), { "Meta": create_meta_class( model, exclude_fields=exclude_fields, extra_fields=extra_fields, display_fields=display_fields, action=action, allow_one_to_one=allow_one_to_one, ), "action": action, "basebone_model": model, "basebone_end_slug": end_slug, "__init__": __init__, **new_attr, **attrs, }, )