我们从Python开源项目中,提取了以下23个代码示例,用于说明如何使用django.contrib.contenttypes.fields.GenericForeignKey()。
def _get_remote_field_name(field): reverse_field = True if isinstance(field, ( models.ManyToManyRel, models.ManyToOneRel, models.OneToOneRel, GenericRelation)) else False return str('{model}.{field}'.format( model=get_model_string(field.model), field=(field.related_name or '%s_set' % field.name if not isinstance(field, (models.OneToOneRel, GenericRelation)) else field.name)) if reverse_field else field.remote_field.field if not isinstance(field, GenericForeignKey) else str(field)).lower()
def get_cardinality_for_field(field): """ Returns the cardinality for ``field``. """ cardinalities = { models.ForeignKey: ZeroOrOne, models.ManyToOneRel: ZeroOrMore, models.OneToOneField: ZeroOrOne, models.OneToOneRel: ZeroOrOne, models.ManyToManyField: ZeroOrMore, models.ManyToManyRel: ZeroOrMore, GenericForeignKey: ZeroOrOne, GenericRelation: ZeroOrMore } return cardinalities[field.__class__]
def get_forward_relation_fields(cls): return [ field for field in cls.Meta.model._meta.get_fields() if field.is_relation and ( not field.auto_created or field.concrete or field.one_to_one or (field.many_to_one and field.related_model) or isinstance(field, GenericForeignKey) ) ]
def get_related_node_property_for_field(cls, field, meta_node=False): """ Get the relationship definition for the related node based on field. :param field: Field to inspect :param meta_node: If True, return the meta node for the related model, else return the model node. :returns: A ``RelationshipDefinition`` instance. """ from chemtrails.neoutils import ( __meta_cache__, __node_cache__, get_node_class_for_model, get_meta_node_class_for_model ) reverse_field = True if isinstance(field, ( models.ManyToManyRel, models.ManyToOneRel, models.OneToOneRel, GenericRelation)) else False class DynamicRelation(StructuredRel): type = StringProperty(default=field.__class__.__name__) is_meta = BooleanProperty(default=meta_node) remote_field = StringProperty(default=cls._get_remote_field_name(field)) target_field = StringProperty(default=str(getattr(field, 'target_field', '')).lower()) # NOTE: Workaround for #27 prop = cls.get_property_class_for_field(field.__class__) relationship_type = cls.get_relationship_type(field) related_model = field.model if isinstance(field, GenericForeignKey) else field.related_model if meta_node: klass = (__meta_cache__[related_model] if related_model in __meta_cache__ else get_meta_node_class_for_model(related_model)) return (prop(cls_name=klass, rel_type=relationship_type, model=DynamicRelation) # FIXME: Support cardinality for MetaNodes if not klass._is_ignored else None) else: klass = (__node_cache__[related_model] if reverse_field and related_model in __node_cache__ else get_node_class_for_model(related_model)) return (prop(cls_name=klass, rel_type=relationship_type, model=DynamicRelation, cardinality=cls.get_cardinality_for_field(field)) if not klass._is_ignored else None)
def test_content_object(self): field = ServeLog._meta.get_field('content_object') self.assertEqual(field.__class__, GenericForeignKey) self.assertEqual(field.ct_field, 'content_type') self.assertEqual(field.fk_field, 'object_id')
def test_form_field(self): """ The model should have a form field """ field = OmniField.form self.assertIsInstance(field, GenericForeignKey)
def test_form(self): """ The model should have a 'form' field """ field = OmniFormHandler.form self.assertIsInstance(field, GenericForeignKey)
def get_model_fields(self): """ Method to get all model fields for the content type associated with the forms specified content type :return: List of model field instances """ def is_valid_field(field): if isinstance(field, (models.AutoField, ForeignObjectRel, GenericRelation, GenericForeignKey)): return False else: return True return list(filter(is_valid_field, self.content_type.model_class()._meta.get_fields()))
def _check_relation(self, obj, parent_model): # There's no FK, but we do need to confirm that the ct_field and ct_fk_field are valid, # and that they are part of a GenericForeignKey. gfks = [ f for f in obj.model._meta.private_fields if isinstance(f, GenericForeignKey) ] if len(gfks) == 0: return [ checks.Error( "'%s.%s' has no GenericForeignKey." % ( obj.model._meta.app_label, obj.model._meta.object_name ), obj=obj.__class__, id='admin.E301' ) ] else: # Check that the ct_field and ct_fk_fields exist try: obj.model._meta.get_field(obj.ct_field) except FieldDoesNotExist: return [ checks.Error( "'ct_field' references '%s', which is not a field on '%s.%s'." % ( obj.ct_field, obj.model._meta.app_label, obj.model._meta.object_name ), obj=obj.__class__, id='admin.E302' ) ] try: obj.model._meta.get_field(obj.ct_fk_field) except FieldDoesNotExist: return [ checks.Error( "'ct_fk_field' references '%s', which is not a field on '%s.%s'." % ( obj.ct_fk_field, obj.model._meta.app_label, obj.model._meta.object_name ), obj=obj.__class__, id='admin.E303' ) ] # There's one or more GenericForeignKeys; make sure that one of them # uses the right ct_field and ct_fk_field. for gfk in gfks: if gfk.ct_field == obj.ct_field and gfk.fk_field == obj.ct_fk_field: return [] return [ checks.Error( "'%s.%s' has no GenericForeignKey using content type field '%s' and object ID field '%s'." % ( obj.model._meta.app_label, obj.model._meta.object_name, obj.ct_field, obj.ct_fk_field ), obj=obj.__class__, id='admin.E304' ) ]
def restore_object(self, attrs, instance=None): """ Restore the model instance. """ m2m_data = {} related_data = {} nested_forward_relations = {} # noinspection PyProtectedMember meta = self.opts.model._meta # Reverse fk or one-to-one relations for (obj, model) in meta.get_all_related_objects_with_model(): field_name = obj.get_accessor_name() if field_name in attrs: related_data[field_name] = attrs.pop(field_name) # Reverse m2m relations for (obj, model) in meta.get_all_related_m2m_objects_with_model(): field_name = obj.get_accessor_name() if field_name in attrs: m2m_data[field_name] = attrs.pop(field_name) # Forward m2m relations if issubclass(meta.many_to_many.__class__, tuple): temp_m2m = list(meta.many_to_many) else: temp_m2m = meta.many_to_many for field in temp_m2m + meta.virtual_fields: if isinstance(field, GenericForeignKey): continue if field.name in attrs: m2m_data[field.name] = attrs.pop(field.name) # Nested forward relations - These need to be marked so we can save # them before saving the parent model instance. for field_name in attrs.keys(): if isinstance(self.fields.get(field_name, None), Serializer): nested_forward_relations[field_name] = attrs[field_name] # Create an empty instance of the model if instance is None: instance = self.opts.model() for key, val in attrs.items(): try: setattr(instance, key, val) except ValueError: self._errors[key] = [self.error_messages['required']] # Any relations that cannot be set until we've # saved the model get hidden away on these # private attributes, so we can deal with them # at the point of save. instance._related_data = related_data instance._m2m_data = m2m_data instance._nested_forward_relations = nested_forward_relations return instance
def __init__(self, instance=None, bind=False, *args, **kwargs): self._instance = instance self.__recursion_depth__ = 0 defaults = {key: getattr(self._instance, key, kwargs.get(key, None)) for key, _ in self.__all_properties__} kwargs.update(defaults) super(ModelNodeMixinBase, self).__init__(self, *args, **kwargs) # Never try to bind ignore nodes if bind and self._is_ignored: bind = False # Query the database for an existing node and set the id if found. # This will make this a "bound" node. if bind and not hasattr(self, 'id'): required = {key: prop for key, prop in self.defined_properties(aliases=False, rels=False).items() if prop.required or prop.unique_index} if all(getattr(self, attr) for attr in required.keys()): node_id = self._get_id_from_database(self.deflate(self.__properties__)) if node_id: self.id = node_id if not self._instance and self.pk: self._instance = self.get_object(self.pk) if self._instance: # For GenericForeignKey fields, we have no way of knowing what kind of # object it is related to during class creation, thus the relationship # definition is set to refer itself. # When initializing we have access to the underlying django object instance and # can inspect it, so we need to switch out the relationship definition # node class in order to connect to the correct node. from chemtrails.neoutils import get_node_class_for_model generic_fks = filter(lambda f: isinstance(f, GenericForeignKey), self.get_forward_relation_fields()) for field in generic_fks: relationship = self.defined_properties(aliases=False, properties=False).get(field.name, None) if isinstance(getattr(self._instance, field.name, None), models.Model) and relationship: node_class = get_node_class_for_model(getattr(self._instance, field.name)) model = relationship.definition['model'] model.target_field.default = str(node_class._pk_field).lower() # defensively set the definition dictionary to a dict like class # which will protect the safeguarded keys against being copied over # by neomodel relationship.definition = DefinitionDict(relationship.definition) relationship.definition._safeguard('node_class', node_class) relationship.definition._safeguard('model', model)