00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """Tools for manipulating DBRefs (references to MongoDB documents)."""
00016
00017 from bson.son import SON
00018 from copy import deepcopy
00019
00020
00021 class DBRef(object):
00022 """A reference to a document stored in MongoDB.
00023 """
00024
00025 def __init__(self, collection, id, database=None, _extra={}, **kwargs):
00026 """Initialize a new :class:`DBRef`.
00027
00028 Raises :class:`TypeError` if `collection` or `database` is not
00029 an instance of :class:`basestring`. `database` is optional and
00030 allows references to documents to work across databases. Any
00031 additional keyword arguments will create additional fields in
00032 the resultant embedded document.
00033
00034 :Parameters:
00035 - `collection`: name of the collection the document is stored in
00036 - `id`: the value of the document's ``"_id"`` field
00037 - `database` (optional): name of the database to reference
00038 - `**kwargs` (optional): additional keyword arguments will
00039 create additional, custom fields
00040
00041 .. versionchanged:: 1.8
00042 Now takes keyword arguments to specify additional fields.
00043 .. versionadded:: 1.1.1
00044 The `database` parameter.
00045
00046 .. mongodoc:: dbrefs
00047 """
00048 if not isinstance(collection, basestring):
00049 raise TypeError("collection must be an instance of basestring")
00050 if database is not None and not isinstance(database, basestring):
00051 raise TypeError("database must be an instance of basestring")
00052
00053 self.__collection = collection
00054 self.__id = id
00055 self.__database = database
00056 kwargs.update(_extra)
00057 self.__kwargs = kwargs
00058
00059 @property
00060 def collection(self):
00061 """Get the name of this DBRef's collection as unicode.
00062 """
00063 return self.__collection
00064
00065 @property
00066 def id(self):
00067 """Get this DBRef's _id.
00068 """
00069 return self.__id
00070
00071 @property
00072 def database(self):
00073 """Get the name of this DBRef's database.
00074
00075 Returns None if this DBRef doesn't specify a database.
00076
00077 .. versionadded:: 1.1.1
00078 """
00079 return self.__database
00080
00081 def __getattr__(self, key):
00082 return self.__kwargs[key]
00083
00084 def as_doc(self):
00085 """Get the SON document representation of this DBRef.
00086
00087 Generally not needed by application developers
00088 """
00089 doc = SON([("$ref", self.collection),
00090 ("$id", self.id)])
00091 if self.database is not None:
00092 doc["$db"] = self.database
00093 doc.update(self.__kwargs)
00094 return doc
00095
00096 def __repr__(self):
00097 extra = "".join([", %s=%r" % (k, v)
00098 for k, v in self.__kwargs.iteritems()])
00099 if self.database is None:
00100 return "DBRef(%r, %r%s)" % (self.collection, self.id, extra)
00101 return "DBRef(%r, %r, %r%s)" % (self.collection, self.id,
00102 self.database, extra)
00103
00104 def __cmp__(self, other):
00105 if isinstance(other, DBRef):
00106 return cmp([self.__database, self.__collection,
00107 self.__id, self.__kwargs],
00108 [other.__database, other.__collection,
00109 other.__id, other.__kwargs])
00110 return NotImplemented
00111
00112 def __hash__(self):
00113 """Get a hash value for this :class:`DBRef`.
00114
00115 .. versionadded:: 1.1
00116 """
00117 return hash((self.__collection, self.__id,
00118 self.__database, self.__kwargs))
00119
00120 def __deepcopy__(self, memo):
00121 """Support function for `copy.deepcopy()`.
00122
00123 .. versionadded:: 1.10
00124 """
00125 return DBRef(deepcopy(self.__collection, memo),
00126 deepcopy(self.__id, memo),
00127 deepcopy(self.__database, memo),
00128 deepcopy(self.__kwargs, memo))