def setup_generic_relations(model_class): """ Set up GenericRelations for actionable models. """ Action = apps.get_model('actstream', 'action') if Action is None: raise RegistrationError( 'Unable get actstream.Action. Potential circular imports ' 'in initialisation. Try moving actstream app to come after the ' 'apps which have models to register in the INSTALLED_APPS setting.' ) related_attr_name = 'related_query_name' related_attr_value = 'actions_with_%s' % label(model_class) relations = {} for field in ('actor', 'target', 'action_object'): attr = '%s_actions' % field attr_value = '%s_as_%s' % (related_attr_value, field) kwargs = { 'content_type_field': '%s_content_type' % field, 'object_id_field': '%s_object_id' % field, related_attr_name: attr_value } rel = GenericRelation('actstream.Action', **kwargs) rel.contribute_to_class(model_class, attr) relations[field] = rel # @@@ I'm not entirely sure why this works setattr(Action, attr_value, None) return relations
def post_through_setup(self, cls): if RelatedObject is not None: # Django < 1.8 self.related = RelatedObject(cls, self.model, self) self.use_gfk = (self.through is None or issubclass( self.through, CommonGenericTaggedItemBase)) # rel.to renamed to remote_field.model in Django 1.9 if VERSION >= (1, 9): if not self.remote_field.model: self.remote_field.model = self.through._meta.get_field( "tag").remote_field.model else: if not self.rel.to: self.rel.to = self.through._meta.get_field("tag").rel.to if RelatedObject is not None: # Django < 1.8 self.related = RelatedObject(self.through, cls, self) if self.use_gfk: tagged_items = GenericRelation(self.through) tagged_items.contribute_to_class(cls, 'tagged_items') for rel in cls._meta.local_many_to_many: if rel == self or not isinstance(rel, TaggableManager): continue if rel.through == self.through: raise ValueError( 'You can\'t have two TaggableManagers with the' ' same through model.')
def setup_generic_relations(model_class): """ Set up GenericRelations for actionable models. """ Action = apps.get_model('actstream', 'action') if Action is None: raise RegistrationError( 'Unable get actstream.Action. Potential circular imports ' 'in initialisation. Try moving actstream app to come after the ' 'apps which have models to register in the INSTALLED_APPS setting.' ) related_attr_name = 'related_query_name' related_attr_value = 'actions_with_%s' % label(model_class) relations = {} for field in ('actor', 'target', 'action_object'): attr = '%s_actions' % field attr_value = '{}_as_{}'.format(related_attr_value, field) kwargs = { 'content_type_field': '%s_content_type' % field, 'object_id_field': '%s_object_id' % field, related_attr_name: attr_value } rel = GenericRelation('actstream.Action', **kwargs) rel.contribute_to_class(model_class, attr) relations[field] = rel # @@@ I'm not entirely sure why this works setattr(Action, attr_value, None) return relations
def post_through_setup(self, cls): if RelatedObject is not None: # Django < 1.8 self.related = RelatedObject(cls, self.model, self) self.use_gfk = ( self.through is None or issubclass(self.through, CommonGenericTaggedItemBase) ) # rel.to renamed to remote_field.model in Django 1.9 if VERSION >= (1, 9): if not self.remote_field.model: self.remote_field.model = self.through._meta.get_field("tag").remote_field.model else: if not self.rel.to: self.rel.to = self.through._meta.get_field("tag").rel.to if RelatedObject is not None: # Django < 1.8 self.related = RelatedObject(self.through, cls, self) if self.use_gfk: tagged_items = GenericRelation(self.through) tagged_items.contribute_to_class(cls, 'tagged_items') for rel in cls._meta.local_many_to_many: if rel == self or not isinstance(rel, TaggableManager): continue if rel.through == self.through: raise ValueError('You can\'t have two TaggableManagers with the' ' same through model.')
def create_link(linkable_model, linked_model, linkable_link_name=None, verbose_name=None, verbose_name_plural=None): class LinkedModel(object): def __init__(self, model, link_name=None, verbose_name=None, verbose_name_plural=None, reverse_link_name=None): self.model = model self.link_name = link_name self.reverse_link_name = reverse_link_name self.verbose_name = verbose_name self.verbose_name_plural = verbose_name_plural if issubclass(linkable_model, ManyLinkableModel): get_link_name = get_plural elif issubclass(linkable_model, OneLinkableModel): get_link_name = get_singular if linkable_link_name is None: linkable_link_name = get_link_name(linked_model) if verbose_name is None: verbose_name = linked_model._meta.verbose_name if verbose_name_plural is None: verbose_name_plural = linked_model._meta.verbose_name_plural linked_link_name = get_plural(linkable_model) if issubclass(linkable_model, ManyLinkableModel): field = models.ManyToManyField(linkable_model, related_name=linkable_link_name) setattr(linked_model, linked_link_name, field) field.contribute_to_class(linked_model, linked_link_name) elif issubclass(linkable_model, OneLinkableModel): linked_link_name = get_singular(linkable_model) + "_set" field = GenericRelation(linkable_model, related_query_name=linkable_link_name) setattr(linked_model, linked_link_name, field) field.contribute_to_class(linked_model, linked_link_name) setattr( linkable_model, linkable_link_name, property(fget=lambda x: linkable_model.get_related(x), fset=lambda x, y: linkable_model.set_related(x, y))) if not hasattr(linkable_model, "_LINKS") or linkable_model._LINKS is None: setattr(linkable_model, "_LINKS", dict()) linkable_model._LINKS[linkable_link_name] = LinkedModel( linked_model, link_name=linkable_link_name, verbose_name=verbose_name, verbose_name_plural=verbose_name_plural, reverse_link_name=linked_link_name) return linkable_model
def post_through_setup(self, cls): self.use_gfk = ( self.through is None ) self.rel.to = self.through._meta.get_field("group").rel.to if RelatedObject is not None: self.related = RelatedObject(self.through, cls, self) if self.use_gfk: groups = GenericRelation(self.through) groups.contribute_to_class(cls, "groups")
def contribute_to_class(model): """ Adds a 'maat_ranking' attribute to each instance of model. The attribute is a generic relation to MaatRanking, used by the handler to retrieve the ordered queryset. """ try: generic_relation = GenericRelation(MaatRanking) except TypeError: # Django < 1.7 generic_relation = GenericRelation(MaatRanking) generic_relation.contribute_to_class(model, 'maat_ranking')
def _attach_generic_relation(self): ''' Set up the generic relation for the entity ''' rel_name = self.config_cls.generic_relation_related_name or \ 'entity' gr_name = self.config_cls.generic_relation_attr.lower() generic_relation = GenericRelation(Value, object_id_field='entity_id', content_type_field='entity_ct', related_query_name=rel_name) generic_relation.contribute_to_class(self.model_cls, gr_name)
def _attach_generic_relation(self): ''' Set up the generic relation for the entity ''' rel_name = self.config_cls.generic_relation_related_name or \ self.model_cls.__name__ gr_name = self.config_cls.generic_relation_attr.lower() generic_relation = GenericRelation(Value, object_id_field='entity_id', content_type_field='entity_ct', related_query_name=rel_name) generic_relation.contribute_to_class(self.model_cls, gr_name)
def _inject_generic_relation(qs_or_model): if isinstance(qs_or_model, models.Model): model = qs_or_model elif isinstance(qs_or_model, models.QuerySet): model = qs_or_model.model else: raise TypeError('Can`t inject generic relation') try: model._meta.get_field(MODEL_ATTR_FIELD_NAME) except FieldDoesNotExist: generic_relation = GenericRelation( Attribute, related_query_name=MODEL_ATTR_FIELD_NAME) generic_relation.contribute_to_class(model, MODEL_ATTR_FIELD_NAME)
def register_models(): """ Load model strings specified in settings.HISTORY_MODELS. """ from django.contrib.contenttypes.fields import GenericRelation for model_name in settings.HISTORY_MODELS: model = apps.get_model(model_name) if model not in history_models: history_models.add(model) relation = GenericRelation('history.History', related_query_name='{}_{}' \ .format( model._meta.app_label, model._meta.model_name)) field_name = getattr(settings, 'HISTORY_FIELD_NAME', '_history') relation.contribute_to_class(model, field_name)
def post_through_setup(self, cls): self.related = RelatedObject(cls, self.model, self) self.use_gfk = (self.through is None or issubclass(self.through, GenericTaggedItemBase)) self.rel.to = self.through._meta.get_field("tag").rel.to self.related = RelatedObject(self.through, cls, self) if self.use_gfk: tagged_items = GenericRelation(self.through) tagged_items.contribute_to_class(cls, 'tagged_items') for rel in cls._meta.local_many_to_many: if rel == self or not isinstance(rel, TaggableManager): continue if rel.through == self.through: raise ValueError( 'You can\'t have two TaggableManagers with the' ' same through model.')
def post_through_setup(self, cls): self.related = RelatedObject(cls, self.model, self) self.use_gfk = ( self.through is None or issubclass(self.through, GenericTaggedItemBase) ) self.rel.to = self.through._meta.get_field("tag").rel.to self.related = RelatedObject(self.through, cls, self) if self.use_gfk: tagged_items = GenericRelation(self.through) tagged_items.contribute_to_class(cls, 'tagged_items') for rel in cls._meta.local_many_to_many: if rel == self or not isinstance(rel, TaggableManager): continue if rel.through == self.through: raise ValueError('You can\'t have two TaggableManagers with the' ' same through model.')
def create_link(linkable_model, linked_model, linkable_link_name=None, verbose_name=None, verbose_name_plural=None): class LinkedModel(object): def __init__(self, model, link_name=None, verbose_name=None, verbose_name_plural=None, reverse_link_name=None): self.model = model self.link_name = link_name self.reverse_link_name = reverse_link_name self.verbose_name = verbose_name self.verbose_name_plural = verbose_name_plural if issubclass(linkable_model, ManyLinkableModel): get_link_name = get_plural elif issubclass(linkable_model, OneLinkableModel): get_link_name = get_singular if linkable_link_name is None: linkable_link_name = get_link_name(linked_model) if verbose_name is None: verbose_name = linked_model._meta.verbose_name if verbose_name_plural is None: verbose_name_plural = linked_model._meta.verbose_name_plural linked_link_name = get_plural(linkable_model) if issubclass(linkable_model, ManyLinkableModel): field = models.ManyToManyField(linkable_model, related_name=linkable_link_name) setattr(linked_model, linked_link_name, field) field.contribute_to_class(linked_model, linked_link_name) elif issubclass(linkable_model, OneLinkableModel): linked_link_name = get_singular(linkable_model)+"_set" field = GenericRelation(linkable_model, related_query_name=linkable_link_name) setattr(linked_model, linked_link_name, field) field.contribute_to_class(linked_model, linked_link_name) setattr(linkable_model, linkable_link_name, property( fget=lambda x: linkable_model.get_related(x), fset=lambda x, y: linkable_model.set_related(x, y))) if not hasattr(linkable_model, "_LINKS") or linkable_model._LINKS is None: setattr(linkable_model, "_LINKS", dict()) linkable_model._LINKS[linkable_link_name] = LinkedModel( linked_model, link_name=linkable_link_name, verbose_name=verbose_name, verbose_name_plural=verbose_name_plural, reverse_link_name=linked_link_name) return linkable_model
def post_through_setup(self, cls): self.use_gfk = self.through is None or issubclass( self.through, CommonGenericTaggedItemBase) if not self.remote_field.model: self.remote_field.model = self.through._meta.get_field( "tag").remote_field.model if self.use_gfk: tagged_items = GenericRelation(self.through) tagged_items.contribute_to_class(cls, "tagged_items") for rel in cls._meta.local_many_to_many: if rel == self or not isinstance(rel, TaggableManager): continue if rel.through == self.through: raise ValueError("You can't have two TaggableManagers with the" " same through model.")
def setup_generic_relations(model_class): """ 注册过的model_class实例可以如此操作: instance.actor_actions.filter(...) instance.target_actions.filter(...) instance.relative_actions.filter(...) """ from qevent.models import Action related_attr_value = 'actions_with_%s' % label(model_class) # relations = {} for field in ('actor', 'target', 'relative'): attr_value = '%s_as_%s' % (related_attr_value, field) rel = GenericRelation(Action, content_type_field='%s_type' % field, object_id_field='%s_object_id' % field, related_query_name=attr_value, ) rel.contribute_to_class(model_class, '%s_actions' % field) relations[field] = rel # setattr(Action, attr_value, None) return relations
def setup_generic_relations(model_actor, relation_methods): """ 注册过的 actor_model_class 实例可以如此操作: actor.METHOD(target) # 建立 target 的特定 RELATION actor.dont_METHOD(target) # 或 no_METHOD 取消 target 的特定 RELATION # actor.actor_relations.filter(...) actor.METHOD_relations(...) # AS actor 的特定 RELATION filter actor.has_METHOD(target) # 与 target 是否存在特定 RELATION target_model_instance 可以有如下操作: target.target_relations.filter(...) target.METHOD_related(...) # AS target 的特定 RELATION filter target.was_METHOD(actor) # 与 actor 是否存在特定 RELATION owner_model_instance 可以有如下操作: owner.owner_relations.filter(...) owner.METHOD_related(...) # AS owner 的特定 RELATION filter """ from qrelation import models # rel = GenericRelation(models.Relation, content_type_field='actor_type', object_id_field='actor_id', related_query_name='relations_with_%s_as_%s' % (label(model_actor), 'actor')) rel.contribute_to_class(model_actor, 'actor_relations') # actor_type = get_contenttype(model_actor) for method, kwargs in relation_methods.items(): # 'follow': { # 'relation': models.REL_USER_FOLLOW, # 'target': 'quser.User', # } model_target = validate(kwargs.pop('target')) if not hasattr(model_target, 'target_relations'): rel = GenericRelation(models.Relation, content_type_field='target_type', object_id_field='target_id', related_query_name='relations_with_%s_as_%s' % (label(model_target), 'target')) rel.contribute_to_class(model_target, 'target_relations') model_owner = kwargs.pop('owner', None) if model_owner: model_owner = validate(model_owner) owner_type = get_contenttype(model_owner) if model_owner and not hasattr(model_owner, 'owner_relations'): rel = GenericRelation(models.Relation, content_type_field='owner_type', object_id_field='owner_id', related_query_name='relations_with_%s_as_%s' % (label(model_owner), 'owner')) rel.contribute_to_class(model_owner, 'owner_relations') # target_type = get_contenttype(model_target) relation, owner_field = kwargs.pop('relation'), kwargs.pop('owner_field', None) # 建立 relation setattr(model_actor, method, functools.partialmethod( relate, relation=relation, target_type=target_type, model_target=model_target, actor_type=actor_type, owner_field=owner_field)) cancel_method = functools.partialmethod( relate, relation=relation, target_type=target_type, model_target=model_target, actor_type=actor_type, deleted=True) # 取消 relation setattr(model_actor, 'dont_%s' % method, cancel_method) setattr(model_actor, 'no_%s' % method, cancel_method) # 给 actor_model 增加类方法 METHOD_relations setattr(model_actor, '%s_relations' % method, functools.partialmethod( filter_relations, relation=relation)) # 给 actor_model 增加类方法 has_METHOD setattr(model_actor, 'has_%s' % method, functools.partialmethod( check_relation, relation=relation, target_type=target_type, model_target=model_target)) # 给 target_model 增加类方法 METHOD_related setattr(model_target, '%s_related' % method, functools.partialmethod( filter_related, relation=relation)) # 给 target_model 增加类方法 was_METHOD setattr(model_target, 'was_%s' % method, functools.partialmethod( check_related, relation=relation, actor_type=actor_type, model_actor=model_actor)) if not model_owner: continue # 给 owner_model 增加类方法 setattr(model_owner, '%s_related' % method, functools.partialmethod( filter_owner, relation=relation))
def get_objects_resource(self, table_pk): try: md = ModelDefinition.objects.get(pk=table_pk) except ModelDefinition.DoesNotExist: return http.HttpNotFound() Model = md.model_class() GeomModelField = Model._meta.get_field_by_name( DEFAULT_MD_GEOMETRY_FIELD_NAME)[0] gr = GenericRelation(AttachedFile) gr.contribute_to_class(Model, 'files') proxy = self class AttachedFilesInlineResource(ModelResource): class Meta: queryset = AttachedFile.objects.all() def get_resource_uri(self, bundle): kwargs = dict(table_pk=md.pk, object_pk=bundle.obj.object_id, file_pk=bundle.obj.pk) return proxy.uri_for_file_detail(**kwargs) class R(ModelResource): logger = logging.getLogger('userlayers.api.data') class Meta: queryset = Model.objects.all() authorization = get_table_data_auth(md)() serializer = GeoJsonSerializer() max_limit = None validation = FormValidation(form_class=modelform_factory( md.model_class(), exclude=('id', ))) def dispatch(self, *args, **kwargs): response = super(R, self).dispatch(*args, **kwargs) ct = response.get('Content-Type') if ct and ct.startswith('application/zip'): response[ 'Content-Disposition'] = 'attachment; filename=%s.zip' % md.name return response def get_model_definition(self): return md def get_resource_uri(self, bundle_or_obj=None, **kwargs): url = proxy.uri_for_table(table_pk) if bundle_or_obj: kw = self.resource_uri_kwargs(bundle_or_obj) url += '%s%s' % (kw['pk'], trailing_slash()) return url def error_response(self, request, errors, response_class=None): if isinstance(self._meta.serializer, GeoJsonSerializer): self._meta.serializer = Serializer() return super(R, self).error_response(request, errors, response_class=None) def serialize(self, request, data, format, options=None): options = options or {} options['geometry_field'] = DEFAULT_MD_GEOMETRY_FIELD_NAME return super(R, self).serialize(request, data, format, options) def full_hydrate(self, bundle): bundle = super(R, self).full_hydrate(bundle) try: bundle.data['geometry'] = bundle.obj.geometry except GDALException: raise ImmediateHttpResponse(response=self.error_response( bundle.request, {'geometry': 'invalid geometry'})) if bundle.obj.geometry and GeomModelField.dim == 3 and not bundle.obj.geometry.hasz: geom_3d = bundle.obj.geometry.ogr geom_3d._set_coord_dim(3) bundle.data['geometry'] = geom_3d.geos return bundle def obj_create(self, bundle, **kwargs): bundle = super(R, self).obj_create(bundle, **kwargs) self.logger.info( '"%s" created table data, table "%s", object pk "%s"' % (bundle.request.user, md.db_table, bundle.obj.pk)) return bundle def obj_update(self, bundle, **kwargs): bundle = super(R, self).obj_update(bundle, **kwargs) self.logger.info( '"%s" updated table data, table "%s", object pk "%s"' % (bundle.request.user, md.db_table, bundle.obj.pk)) return bundle def obj_delete(self, bundle, **kwargs): super(R, self).obj_delete(bundle, **kwargs) self.logger.info( '"%s" deleted table data, table "%s", object pk "%s"' % (bundle.request.user, md.db_table, bundle.obj.pk)) def dehydrate(self, bundle): bundle.data['files_uri'] = proxy.uri_for_file_list( table_pk, bundle.obj.pk) return bundle return R
def contribute_to_class(self, cls, name): relation = GenericRelation(self.model, related_query_name=cls._meta.model_name) relation.contribute_to_class(cls, name)