# -*- coding: UTF-8 -*- import functools from django.conf import settings from gm_rpcd.all import context, bind from gm_rpcd.internals.dynamic_scopes import DynamicVariableUnboundError from helios.rpc import create_default_invoker from utils.rpc import logging_exception, gen from gm_types.error import ERROR as CODES rpc_invoker = create_default_invoker(debug=settings.DEBUG) def get_current_rpc_invoker(): try: return context.rpc except DynamicVariableUnboundError: return rpc_invoker class RPCMixin(object): @classmethod def call_rpc(cls, api_endpoint, **kwargs): """call rpc. get rpc invoker from current ctx, this method only support call rpc sequentially. """ r = get_current_rpc_invoker() result = r[api_endpoint](**kwargs) return result.unwrap() def get_objects_from_queryset_and_pk_list(queryset, pk_list): qs_objects = queryset.filter(pk__in=pk_list) obj_map = {o.pk: o for o in qs_objects} return [ obj_map[pk] for pk in pk_list if pk in obj_map ] def bind_context(endpoint, **kwargs): def _wrap(func): @functools.wraps(func) def _wrapper(*args, **kwargs): return func(context, *args, **kwargs) return bind(endpoint)(_wrapper) return _wrap def to_dict(obj, fields=None, excludes=None, expands=None): ret = {} model_fields = [] for field in obj._meta.get_fields(): field_name = field.name model_fields.append(field_name) if (excludes is not None and field_name in excludes) or \ (fields is not None and field_name not in fields): # skip field that in the excludes or not in ther fields continue try: fval = getattr(obj, field_name, None) except: fval = None if not isinstance(field, models.fields.related.RelatedField) or not fval: # Basic Field, get value directly ret[field_name] = _get_val(fval) else: if expands is None or field_name not in expands.keys(): if isinstance(field, models.ForeignKey): ret[field_name] = fval.id if fval else None else: # ManyToManyField ret[field_name] = list(fval.values_list('id', flat=True)) else: # need expand related object related_fields = expands[field_name] if isinstance(field, models.ForeignKey): ret[field_name] = _fetch_related(fval, related_fields) else: # ManyToManyField ret[field_name] = [ _fetch_related(o, related_fields) for o in fval.all() ] # access the field not a Model's Field if fields: for field_name in set(fields) - set(model_fields): field_list = field_name.split('__') if len(field_list) > 1: fval = obj for i in field_list: if fval is None: break try: fval = getattr(fval, i, None) except: break else: fval = get_non_model_field_value(obj, field_name) ret[field_name] = _get_val(fval) return ret