Register the models when using from_celery
[mediagoblin.git] / mediagoblin / app.py
CommitLineData
8e1e744d 1# GNU MediaGoblin -- federated, autonomous media hosting
e5572c60
ML
2# Copyright (C) 2011 Free Software Foundation, Inc
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
31a8ff42
CAW
17import urllib
18
31a8ff42 19import routes
2b4e236a 20import mongokit
b61874b2 21from webob import Request, exc
31a8ff42 22
582c4d5f 23from mediagoblin import routing, util, models, storage, staticdirect
df9809c2 24from mediagoblin.globals import setup_globals
5784c4e9 25from mediagoblin.celery_setup import setup_celery_from_config
31a8ff42
CAW
26
27
28class Error(Exception): pass
29class ImproperlyConfigured(Error): pass
30
31
8e1e744d 32class MediaGoblinApp(object):
31a8ff42
CAW
33 """
34 Really basic wsgi app using routes and WebOb.
35 """
5afdd7a1
CAW
36 def __init__(self, connection, database_path,
37 public_store, queue_store,
582c4d5f 38 staticdirector,
5afdd7a1
CAW
39 user_template_path=None):
40 # Get the template environment
31a8ff42 41 self.template_env = util.get_jinja_env(user_template_path)
5afdd7a1
CAW
42
43 # Set up storage systems
44 self.public_store = public_store
45 self.queue_store = queue_store
46
47 # Set up database
2b4e236a 48 self.connection = connection
65d7374c 49 self.db = connection[database_path]
5afdd7a1
CAW
50 models.register_models(connection)
51
52 # set up routing
0f63a944 53 self.routing = routing.get_mapper()
31a8ff42 54
582c4d5f
CAW
55 # set up staticdirector tool
56 self.staticdirector = staticdirector
2b4e236a 57
df9809c2
CAW
58 # certain properties need to be accessed globally eg from
59 # validators, etc, which might not access to the request
60 # object.
61 setup_globals(
62 db_connection=connection,
63 database=self.db,
64 public_store=self.public_store,
65 queue_store=self.queue_store)
66
31a8ff42
CAW
67 def __call__(self, environ, start_response):
68 request = Request(environ)
69 path_info = request.path_info
582c4d5f
CAW
70
71 ## Routing / controller loading stuff
0f63a944 72 route_match = self.routing.match(path_info)
31a8ff42
CAW
73
74 # No matching page?
75 if route_match is None:
76 # Try to do see if we have a match with a trailing slash
77 # added and if so, redirect
78 if not path_info.endswith('/') \
79 and request.method == 'GET' \
0f63a944 80 and self.routing.match(path_info + '/'):
31a8ff42
CAW
81 new_path_info = path_info + '/'
82 if request.GET:
83 new_path_info = '%s?%s' % (
84 new_path_info, urllib.urlencode(request.GET))
1bb0fdf2 85 redirect = exc.HTTPFound(location=new_path_info)
31a8ff42
CAW
86 return request.get_response(redirect)(environ, start_response)
87
88 # Okay, no matches. 404 time!
89 return exc.HTTPNotFound()(environ, start_response)
90
cb8ea0fe 91 controller = util.import_component(route_match['controller'])
31a8ff42
CAW
92 request.start_response = start_response
93
582c4d5f 94 ## Attach utilities to the request object
31a8ff42 95 request.matchdict = route_match
0f63a944 96 request.urlgen = routes.URLGenerator(self.routing, environ)
7846e406 97 # Do we really want to load this via middleware? Maybe?
14ba9383 98 request.session = request.environ['beaker.session']
0dd65945
CAW
99 # Attach self as request.app
100 # Also attach a few utilities from request.app for convenience?
101 request.app = self
102 request.template_env = self.template_env
103 request.db = self.db
104 request.staticdirect = self.staticdirector
31a8ff42 105
ddff7cce
CAW
106 util.setup_user_in_request(request)
107
31a8ff42
CAW
108 return controller(request)(environ, start_response)
109
110
5784c4e9 111def paste_app_factory(global_config, **app_config):
cb8ea0fe 112 # Get the database connection
2b4e236a 113 connection = mongokit.Connection(
5784c4e9 114 app_config.get('db_host'), app_config.get('db_port'))
73e0dbcc 115
cb8ea0fe 116 # Set up the storage systems.
5afdd7a1 117 public_store = storage.storage_system_from_paste_config(
5784c4e9 118 app_config, 'publicstore')
5afdd7a1 119 queue_store = storage.storage_system_from_paste_config(
5784c4e9 120 app_config, 'queuestore')
5afdd7a1 121
582c4d5f 122 # Set up the staticdirect system
5784c4e9 123 if app_config.has_key('direct_remote_path'):
582c4d5f 124 staticdirector = staticdirect.RemoteStaticDirect(
5784c4e9
CAW
125 app_config['direct_remote_path'].strip())
126 elif app_config.has_key('direct_remote_paths'):
127 direct_remote_path_lines = app_config[
128 'direct_remote_paths'].strip().splitlines()
582c4d5f
CAW
129 staticdirector = staticdirect.MultiRemoteStaticDirect(
130 dict([line.strip().split(' ', 1)
5784c4e9 131 for line in direct_remote_path_lines]))
582c4d5f
CAW
132 else:
133 raise ImproperlyConfigured(
134 "One of direct_remote_path or direct_remote_paths must be provided")
135
5784c4e9
CAW
136 setup_celery_from_config(app_config, global_config)
137
8e1e744d 138 mgoblin_app = MediaGoblinApp(
5784c4e9 139 connection, app_config.get('db_name', 'mediagoblin'),
5afdd7a1 140 public_store=public_store, queue_store=queue_store,
582c4d5f 141 staticdirector=staticdirector,
5784c4e9 142 user_template_path=app_config.get('local_templates'))
b61874b2 143
c4d71564 144 return mgoblin_app