@@ -863,12 +863,11 @@ class ReferenceField(BaseField):
863863
864864 The options are:
865865
866- * DO_NOTHING - don't do anything (default).
867- * NULLIFY - Updates the reference to null.
868- * CASCADE - Deletes the documents associated with the reference.
869- * DENY - Prevent the deletion of the reference object.
870- * PULL - Pull the reference from a :class:`~mongoengine.fields.ListField`
871- of references
866+ * DO_NOTHING (0) - don't do anything (default).
867+ * NULLIFY (1) - Updates the reference to null.
868+ * CASCADE (2) - Deletes the documents associated with the reference.
869+ * DENY (3) - Prevent the deletion of the reference object.
870+ * PULL (4) - Pull the reference from a :class:`~mongoengine.fields.ListField` of references
872871
873872 Alternative syntax for registering delete rules (useful when implementing
874873 bi-directional delete rules)
@@ -896,6 +895,10 @@ def __init__(self, document_type, dbref=False,
896895 or as the :class:`~pymongo.objectid.ObjectId`.id .
897896 :param reverse_delete_rule: Determines what to do when the referring
898897 object is deleted
898+
899+ .. note ::
900+ A reference to an abstract document type is always stored as a
901+ :class:`~pymongo.dbref.DBRef`, regardless of the value of `dbref`.
899902 """
900903 if not isinstance (document_type , basestring ):
901904 if not issubclass (document_type , (Document , basestring )):
@@ -928,9 +931,14 @@ def __get__(self, instance, owner):
928931 self ._auto_dereference = instance ._fields [self .name ]._auto_dereference
929932 # Dereference DBRefs
930933 if self ._auto_dereference and isinstance (value , DBRef ):
931- value = self .document_type ._get_db ().dereference (value )
934+ if hasattr (value , 'cls' ):
935+ # Dereference using the class type specified in the reference
936+ cls = get_document (value .cls )
937+ else :
938+ cls = self .document_type
939+ value = cls ._get_db ().dereference (value )
932940 if value is not None :
933- instance ._data [self .name ] = self . document_type ._from_son (value )
941+ instance ._data [self .name ] = cls ._from_son (value )
934942
935943 return super (ReferenceField , self ).__get__ (instance , owner )
936944
@@ -940,21 +948,29 @@ def to_mongo(self, document):
940948 return document .id
941949 return document
942950
943- id_field_name = self .document_type ._meta ['id_field' ]
944- id_field = self .document_type ._fields [id_field_name ]
945-
946951 if isinstance (document , Document ):
947952 # We need the id from the saved object to create the DBRef
948953 id_ = document .pk
949954 if id_ is None :
950955 self .error ('You can only reference documents once they have'
951956 ' been saved to the database' )
957+
958+ # Use the attributes from the document instance, so that they
959+ # override the attributes of this field's document type
960+ cls = document
952961 else :
953962 id_ = document
963+ cls = self .document_type
964+
965+ id_field_name = cls ._meta ['id_field' ]
966+ id_field = cls ._fields [id_field_name ]
954967
955968 id_ = id_field .to_mongo (id_ )
956- if self .dbref :
957- collection = self .document_type ._get_collection_name ()
969+ if self .document_type ._meta .get ('abstract' ):
970+ collection = cls ._get_collection_name ()
971+ return DBRef (collection , id_ , cls = cls ._class_name )
972+ elif self .dbref :
973+ collection = cls ._get_collection_name ()
958974 return DBRef (collection , id_ )
959975
960976 return id_
@@ -983,6 +999,14 @@ def validate(self, value):
983999 self .error ('You can only reference documents once they have been '
9841000 'saved to the database' )
9851001
1002+ if self .document_type ._meta .get ('abstract' ) and \
1003+ not isinstance (value , self .document_type ):
1004+ self .error ('%s is not an instance of abstract reference'
1005+ ' type %s' % (value ._class_name ,
1006+ self .document_type ._class_name )
1007+ )
1008+
1009+
9861010 def lookup_member (self , member_name ):
9871011 return self .document_type ._fields .get (member_name )
9881012
0 commit comments