Sebastian Spaeth 5c2b84869f Move DBModel._id -> DBModel.id
We were refering to model._id in most of the code base as this is
what Mongo uses. However, each use of _id required a) fixup of queries:
e.g. what we did in our find() and find_one() functions moving all
'_id' to 'id'. It also required using AliasFields to make the ._id
attribute available. This all means lots of superfluous fixing and
transitioning in a SQL world.

It will also not work in the long run. Much newer code already refers
to the objects by model.id (e.g. in the oauth plugin), which will break
with Mongo. So let's be honest, rip out the _id mongoism and live with
.id as the one canonical way to address objects.

This commit modifies all users and providers of model._id to use
model.id instead. This patch works with or without Mongo removed first,
but will break Mongo usage (even more than before)

I have not bothered to fixup db.mongo.* and db.sql.convert
(which converts from Mongo to SQL)

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-12-21 00:30:48 +01:00

101 lines
3.0 KiB
Python

# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker, object_session
from sqlalchemy.orm.query import Query
from sqlalchemy.sql.expression import desc
from mediagoblin.db.sql.fake import DESCENDING
def _get_query_model(query):
cols = query.column_descriptions
assert len(cols) == 1, "These functions work only on simple queries"
return cols[0]["type"]
class GMGQuery(Query):
def sort(self, key, direction):
key_col = getattr(_get_query_model(self), key)
if direction is DESCENDING:
key_col = desc(key_col)
return self.order_by(key_col)
def skip(self, amount):
return self.offset(amount)
Session = scoped_session(sessionmaker(query_cls=GMGQuery))
class GMGTableBase(object):
query = Session.query_property()
@classmethod
def find(cls, query_dict):
return cls.query.filter_by(**query_dict)
@classmethod
def find_one(cls, query_dict):
return cls.query.filter_by(**query_dict).first()
@classmethod
def one(cls, query_dict):
return cls.find(query_dict).one()
def get(self, key):
return getattr(self, key)
def setdefault(self, key, defaultvalue):
# The key *has* to exist on sql.
return getattr(self, key)
def save(self, validate=True):
assert validate
sess = object_session(self)
if sess is None:
sess = Session()
sess.add(self)
sess.commit()
def delete(self, commit=True):
"""Delete the object and commit the change immediately by default"""
sess = object_session(self)
assert sess is not None, "Not going to delete detached %r" % self
sess.delete(self)
if commit:
sess.commit()
Base = declarative_base(cls=GMGTableBase)
class DictReadAttrProxy(object):
"""
Maps read accesses to obj['key'] to obj.key
and hides all the rest of the obj
"""
def __init__(self, proxied_obj):
self.proxied_obj = proxied_obj
def __getitem__(self, key):
try:
return getattr(self.proxied_obj, key)
except AttributeError:
raise KeyError("%r is not an attribute on %r"
% (key, self.proxied_obj))