def hydrate(self, bundle): value = super(DateTimeField, self).hydrate(bundle) if value and not hasattr(value, 'year'): if isinstance(value, six.string_types): try: # Try to rip a date/datetime out of it. value = make_aware(parse(value)) except (ValueError, TypeError): raise ApiFieldError( "Datetime provided to '%s' field doesn't appear to be a valid datetime string: '%s'" % (self.instance_name, value)) else: raise ApiFieldError( "Datetime provided to '%s' field must be a string: %s" % (self.instance_name, value)) return value
def dehydrate(self, bundle): if not bundle.obj or not bundle.obj.pk: if not self.null: raise ApiFieldError( "The model '%r' does not have a primary key and can not be used in a ToMany context." % bundle.obj) return [] the_m2ms = None if isinstance(self.attribute, basestring): the_m2ms = getattr(bundle.obj, self.attribute) elif callable(self.attribute): the_m2ms = self.attribute(bundle) if not the_m2ms: if not self.null: raise ApiFieldError( "The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (bundle.obj, self.attribute)) return [] self.m2m_resources = [] m2m_dehydrated = [] # TODO: Also model-specific and leaky. Relies on there being a # ``Manager`` there. for m2m in the_m2ms.all(): m2m_resource = self.get_related_resource(m2m) m2m_bundle = Bundle(obj=m2m, request=bundle.request) # add by zzgvh if getattr(bundle, 'related_info', False): m2m_bundle.related_info = bundle_related_data_info_factory( parent_bundle=bundle) # end add self.m2m_resources.append(m2m_resource) m2m_dehydrated.append( self.dehydrate_related(m2m_bundle, m2m_resource)) return m2m_dehydrated
def hydrate_cluster(self, bundle): try: bundle.data['cluster'] = LogicalCluster.objects.get( name=bundle.data['cluster']) except ObjectDoesNotExist: logger.info("[RouteResource.hydrate_cluster()] provided name = %s", bundle.data['cluster']) raise ApiFieldError( "Could not find the provided cluster via resource name '%s'." % bundle.data['cluster']) return bundle
def set_value_on_bundle_obj(self, bundle, value): """ Overrideable hook for writing a value into the object on a bundle. Enables the use of custom setters in your app code if setattr() is too raw for your fancy ORM model. """ try: setattr(bundle.obj, self.attribute, value) except Exception, e: raise ApiFieldError("The '%s' field couldn't set value '%s': %s" % (self.instance_name, value, e))
def dehydrate_related(self, bundle, related_resource, for_list=True): if self.check is not None: if not self.check(bundle): if not self.null: raise ApiFieldError("The field '%s' does not pass \ permission check and does not support null" % (self.attribute)) else: return None return super(CheckToManyField, self).dehydrate_related( bundle, related_resource, for_list)
def resource_from_uri(self, fk_resource, uri, request=None, related_obj=None, related_name=None): """ Given a URI is provided, the related resource is attempted to be loaded based on the identifiers in the URI. """ err_msg = "Could not find the provided %s object via resource URI '%s'." % (fk_resource._meta.resource_name, uri,) if not uri: raise ApiFieldError(err_msg) try: obj = fk_resource.get_via_uri(uri, request=request) bundle = fk_resource.build_bundle( obj=obj, request=request, via_uri=True ) return fk_resource.full_dehydrate(bundle) except ObjectDoesNotExist: raise ApiFieldError(err_msg)
def resource_from_data(self, fk_resource, data, request=None, related_obj=None, related_name=None): """ Given a dictionary-like structure is provided, a fresh related resource is created using that data. """ # Try to hydrate the data provided. data = dict_strip_unicode_keys(data) obj = None if getattr(fk_resource._meta, 'include_resource_uri', True) and 'resource_uri' in data: uri = data['resource_uri'] err_msg = "Could not find the provided %s object via resource URI '%s'." % (fk_resource._meta.resource_name, uri,) try: obj = fk_resource.get_via_uri(uri, request=request) except ObjectDoesNotExist: raise ApiFieldError(err_msg) fk_bundle = fk_resource.build_bundle( data=data, obj=obj, request=request ) if related_obj: fk_bundle.related_obj = related_obj fk_bundle.related_name = related_name unique_keys = { k: v for k, v in data.items() if k == 'pk' or (hasattr(fk_resource, k) and getattr(fk_resource, k).unique) } # If we have no unique keys, we shouldn't go look for some resource that # happens to match other kwargs. In the case of a create, it might be the # completely wrong resource. # We also need to check to see if updates are allowed on the FK resource. if not obj and unique_keys: try: fk_resource.obj_get(fk_bundle, skip_errors=True, **data) except (ObjectDoesNotExist, NotFound, TypeError): try: # Attempt lookup by primary key fk_resource.obj_get(fk_bundle, skip_errors=True, **unique_keys) except (ObjectDoesNotExist, NotFound): pass except MultipleObjectsReturned: pass # If we shouldn't update a resource, or we couldn't find a matching # resource we'll just return a populated bundle instead # of mistakenly updating something that should be read-only. fk_bundle = fk_resource.full_hydrate(fk_bundle) fk_resource.is_valid(fk_bundle) return fk_bundle
def hydrate(self, bundle): value = super(TimedeltaField, self).hydrate(bundle) if value and not hasattr(value, 'seconds'): if isinstance(value, six.string_types): try: match = TIMEDELTA_REGEX.search(value) if match: data = match.groupdict() value = datetime.timedelta(int(data['days']), int(data['hours']), int(data['minutes']), int(data['seconds'])) else: raise ValueError() except (ValueError, TypeError): raise ApiFieldError("Timedelta provided to '%s' field doesn't appear to be a valid datetime string: '%s'" % (self.instance_name, value)) else: raise ApiFieldError("Datetime provided to '%s' field must be a string: %s" % (self.instance_name, value)) return value
def hydrate(self, bundle): location = super(GeoPointField, self).hydrate(bundle) if location is None: return location longitude = location.get('longitude') latitude = location.get('latitude') if longitude is None or latitude is None: raise ApiFieldError( 'Both longitude and latitude properties are required') return Point(longitude, latitude)
def hydrate(self, bundle): value = super(DecimalField, self).hydrate(bundle) if value and not isinstance(value, Decimal): try: value = Decimal(value) except decimal.InvalidOperation: raise ApiFieldError( "Invalid decimal string for '%s' field: '%s'" % (self.instance_name, value)) return value
def dehydrate(self, bundle, for_list=True): foreign_obj = None if callable(self.attribute): previous_obj = bundle.obj foreign_obj = self.attribute(bundle) elif isinstance(self.attribute, six.string_types): foreign_obj = bundle.obj for attr in self._attrs: previous_obj = foreign_obj try: foreign_obj = getattr(foreign_obj, attr, None) except ObjectDoesNotExist: foreign_obj = None if not foreign_obj: if not self.null: if callable(self.attribute): raise ApiFieldError( "The related resource for resource %s could not be found." % (previous_obj)) else: raise ApiFieldError( "The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) return None fk_resource = self.get_related_resource(foreign_obj) selected_fields = None if self.attribute in bundle.selected_fields.keys(): if bundle.selected_fields != {}: selected_fields = bundle.selected_fields[self.attribute] fk_bundle = Bundle(obj=foreign_obj, request=bundle.request, selected_fields=selected_fields) return self.dehydrate_related(fk_bundle, fk_resource, for_list=for_list)
def convert(self, value): if value is None: return None if isinstance(value, six.string_types): try: year, month, day = value[:10].split('-') return datetime_safe.date(int(year), int(month), int(day)) except ValueError: raise ApiFieldError("Date provided to '%s' field doesn't appear to be a valid date string: '%s'" % (self.instance_name, value)) return value
def hydrate_m2m(self, bundle): if bundle.data.get(self.instance_name) is None: if self.null: return [] else: raise ApiFieldError("The '%s' field has no data and doesn't allow a null value." % self.instance_name) m2m_hydrated = [] for value in bundle.data.get(self.instance_name): m2m_hydrated.append(self.build_related_resource(value)) return m2m_hydrated
def convert(self, value): if value is None: return None if isinstance(value, six.string_types): match = TIMEDELTA_REGEX.search(value) if match: data = match.groupdict() return datetime.timedelta(int(data['days']), int(data['hours']), int(data['minutes']), int(data['seconds'])) else: raise ApiFieldError("Timedelta provided to '%s' field doesn't appear to be a valid timedelta string: '%s'" % (self.instance_name, value)) return value
def dehydrate(self, bundle, for_list=True): if self.check is not None: if not self.check(bundle): if not self.null: raise ApiFieldError("The field '%s' does not pass \ permission check and does not support null" % (self.attribute)) else: return None result = super(CheckToManyField, self).dehydrate(bundle, for_list) # avoid returning [[]] if not result or not result[0]: return [] return result
def dehydrate(self, bundle): try: foreign_obj = getattr(bundle.obj, self.attribute) except ObjectDoesNotExist: foreign_obj = None if not foreign_obj: if not self.null: raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (bundle.obj, self.attribute)) return None self.fk_resource = self.get_related_resource(foreign_obj) fk_bundle = Bundle(obj=foreign_obj) return self.dehydrate_related(fk_bundle, self.fk_resource)
def convert(self, value): if value is None: return None if isinstance(value, basestring): match = DATETIME_REGEX.search(value) if match: data = match.groupdict() return datetime_safe.datetime(int(data['year']), int(data['month']), int(data['day']), int(data['hour']), int(data['minute']), int(data['second'])) else: raise ApiFieldError("Datetime provided to '%s' field doesn't appear to be a valid datetime string: '%s'" % (self.instance_name, value)) return value
def resource_from_uri(self, fk_resource, uri, request=None, related_obj=None, related_name=None): try: obj = fk_resource.get_via_uri(uri, request=request) fk_resource = self.get_related_resource(obj) return super(GenericForeignKeyField, self).resource_from_uri(fk_resource, uri, request, related_obj, related_name) except ObjectDoesNotExist: raise ApiFieldError("Could not find the provided object via " "resource URI '%s'." % uri)
def resource_from_uri(self, fk_resource, uri, request=None, related_obj=None, related_name=None): """ Given a URI is provided, the related resource is attempted to be loaded based on the identifiers in the URI. """ try: obj = fk_resource.get_via_uri(uri, request=request) subclassed_obj = obj.__class__.objects.filter(id=obj.id).get_subclass() related_resource = self.get_related_resource(subclassed_obj) bundle = related_resource.build_bundle( obj=subclassed_obj, request=request ) return related_resource.full_dehydrate(bundle) except ObjectDoesNotExist: raise ApiFieldError("Could not find the provided object via resource URI '%s'." % uri)
def hydrate(self, bundle): if self.instance_name not in bundle.data: return None value = bundle.data[self.instance_name] if value is None or len(value) == 0: return None value = str(value).lstrip('[').rstrip(']') try: [int(pk) for pk in value.split(',')] return value except ValueError: raise ApiFieldError('The field %s must be an int array or null' % (self.instance_name))
def hydrate(self, bundle): """ Takes data stored in the bundle for the field and returns it. Used for taking simple data and building a instance object. """ if self.readonly: return None if not bundle.data.has_key(self.instance_name): if getattr(self, 'is_related', False) and not getattr(self, 'is_m2m', False): # We've got an FK (or alike field) & a possible parent object. # Check for it. if bundle.related_obj and bundle.related_name in ( self.attribute, self.instance_name): return bundle.related_obj if getattr(self, 'is_o2o', False) and not getattr(self, 'is_m2m', False): # We've got an FK (or alike field) & a possible parent object. # Check for it. if bundle.related_obj and bundle.related_name in ( self.attribute, self.instance_name): return bundle.related_obj if self.blank: return None elif self.attribute and getattr(bundle.obj, self.attribute, None): return getattr(bundle.obj, self.attribute) elif self.instance_name and hasattr(bundle.obj, self.instance_name): return getattr(bundle.obj, self.instance_name) elif self.has_default(): if callable(self._default): return self._default() return self._default elif self.null: return None else: raise ApiFieldError( "The '%s' field has no data and doesn't allow a default or null value." % self.instance_name) return bundle.data[self.instance_name]
def convert(self, value): if value is None: return None if isinstance(value, str): try: year, month, day = value[:10].split('-') hour, minute, second = value[11:19].split(':') return make_aware( datetime_safe.datetime(int(year), int(month), int(day), int(hour), int(minute), int(second))) except ValueError: raise ApiFieldError( "Datetime provided to '%s' field doesn't appear to be a valid datetime string: '%s'" % (self.instance_name, value)) return value
def hydrate(self, bundle): """ Takes data stored in the bundle for the field and returns it. Used for taking simple data and building a instance object. """ if self.readonly: return None if self.instance_name not in bundle.data: if self.is_related and not self.is_m2m: # We've got an FK (or alike field) & a possible parent object. # Check for it. if bundle.related_obj and bundle.related_name in ( self.attribute, self.instance_name): return bundle.related_obj if self.blank: return None if self.attribute: try: val = getattr(bundle.obj, self.attribute, None) if val is not None: return val except ObjectDoesNotExist: pass if self.instance_name: try: if hasattr(bundle.obj, self.instance_name): return getattr(bundle.obj, self.instance_name) except ObjectDoesNotExist: pass if self.has_default(): if callable(self._default): return self._default() return self._default if self.null: return None raise ApiFieldError( "The '%s' field has no data and doesn't allow a default or null value." % self.instance_name) return bundle.data[self.instance_name]
def dehydrate(self, bundle): attrs = self.attribute.split('__') foreign_obj = bundle.obj for attr in attrs: previous_obj = foreign_obj try: foreign_obj = getattr(foreign_obj, attr, None) except ObjectDoesNotExist: foreign_obj = None if not foreign_obj: if not self.null: raise ApiFieldError("The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (previous_obj, attr)) return None self.fk_resource = self.get_related_resource(foreign_obj) fk_bundle = Bundle(obj=foreign_obj, request=bundle.request) return self.dehydrate_related(fk_bundle, self.fk_resource)
def build_related_resource(self, value, request=None, related_obj=None, related_name=None): """ Returns a bundle of data built by the related resource, usually via ``hydrate`` with the data provided. Accepts either a URI, a data dictionary (or dictionary-like structure) or an object with a ``pk``. """ self.fk_resource = self.to_class() kwargs = { 'request': request, 'related_obj': related_obj, 'related_name': related_name, } if isinstance(value, basestring): # We got a URI. Load the object and assign it. return self.resource_from_uri(self.fk_resource, value, **kwargs) elif isinstance(value, Bundle): # We got a valid bundle object, the RelatedField had full=True return value elif hasattr(value, 'items'): # We've got a data dictionary. # Since this leads to creation, this is the only one of these # methods that might care about "parent" data. return self.resource_from_data(self.fk_resource, value, **kwargs) elif hasattr(value, 'pk'): # We've got an object with a primary key. return self.resource_from_pk(self.fk_resource, value, **kwargs) elif isinstance(value, int): return self.resource_from_id(self.fk_resource, value, **kwargs) # We got a valid pk as int return value else: raise ApiFieldError( "The '%s' field was given data that was not a URI, not a dictionary-alike and does not have a 'pk' attribute: %s." % (self.instance_name, value))
def dehydrate(self, bundle): """ Takes data from the provided object and prepares it for the resource. """ if self.attribute is not None: # Check for `__` in the field for looking through the relation. attrs = self.attribute.split('__') current_object = bundle.obj for attr in attrs: previous_object = current_object current_object = getattr(current_object, attr, None) if current_object is None: if self.has_default(): current_object = self._default # Fall out of the loop, given any further attempts at # accesses will fail miserably. break elif self.null: current_object = None # Fall out of the loop, given any further attempts at # accesses will fail miserably. break else: raise ApiFieldError( "The object '%r' has an empty attribute '%s' and doesn't allow a default or null value." % (previous_object, attr)) if callable(current_object): current_object = current_object() return self.convert(current_object) if self.has_default(): return self.convert(self.default) else: return None
def dehydrate(self, bundle): try: foreign_obj = getattr(bundle.obj, self.attribute) except ObjectDoesNotExist: foreign_obj = None if not foreign_obj: if not self.null: raise ApiFieldError( "The model '%r' has an empty attribute '%s' and doesn't allow a null value." % (bundle.obj, self.attribute)) return None self.fk_resource = self.get_related_resource(foreign_obj) fk_bundle = Bundle(obj=foreign_obj, request=bundle.request) # add by zzgvh if getattr(bundle, 'related_info', False): fk_bundle.related_info = bundle_related_data_info_factory( parent_bundle=bundle) # end add return self.dehydrate_related(fk_bundle, self.fk_resource)
def obj_create(self, bundle, **kwargs): tags = bundle.data.get("tags") user = bundle.request.user if not tags: raise ApiFieldError("标签错误") bundle = super(QuestionResource, self).obj_create(bundle, user=user) #文件 attachments = bundle.data.get("attachment") if attachments: if not isinstance(attachments, list): attachments = [attachments] for attachment in attachments: qa = QuestionAttachment.objects.get_or_create(question=bundle.obj, attachment_id=int(attachment))[0] # 问题标签 tag_objects = self.set_tag(bundle) for t in tag_objects: QuestionTag(question=bundle.obj, tag=t).save() return bundle
def hydrate(self, bundle): """ Takes data stored in the bundle for the field and returns it. Used for taking simple data and building a instance object. """ if self.readonly: return None if not bundle.data.has_key(self.instance_name): if hasattr(bundle.obj, self.instance_name): return getattr(bundle.obj, self.instance_name) elif self.has_default(): if callable(self._default): return self._default() return self._default elif self.null: return None else: raise ApiFieldError("The '%s' field has no data and doesn't allow a default or null value." % self.instance_name) return bundle.data[self.instance_name]
def hydrate_m2m(self, bundle): if self.readonly: return None if bundle.data.get(self.instance_name) is None: if self.blank: return [] if self.null: return [] raise ApiFieldError("The '%s' field has no data and doesn't allow a null value." % self.instance_name) kwargs = { 'request': bundle.request, } if self.related_name: kwargs['related_obj'] = bundle.obj kwargs['related_name'] = self.related_name return [ self.build_related_resource(value, **kwargs) for value in bundle.data.get(self.instance_name) if value is not None ]