1 from django
import http
2 from django
.db
import models
3 from django
.contrib
.databrowse
.datastructures
import EasyModel
, EasyChoice
4 from django
.shortcuts
import render_to_response
5 from django
.utils
.safestring
import mark_safe
7 class AlreadyRegistered(Exception):
10 class NotRegistered(Exception):
13 class DatabrowsePlugin(object):
14 def urls(self
, plugin_name
, easy_instance_field
):
16 Given an EasyInstanceField object, returns a list of URLs for this
17 plugin's views of this object. These URLs should be absolute.
19 Returns None if the EasyInstanceField object doesn't get a
20 list of plugin-specific URLs.
24 def model_index_html(self
, request
, model
, site
):
26 Returns a snippet of HTML to include on the model index page.
30 def model_view(self
, request
, model_databrowse
, url
):
32 Handles main URL routing for a plugin's model-specific pages.
34 raise NotImplementedError
36 class ModelDatabrowse(object):
39 def __init__(self
, model
, site
):
43 def root(self
, request
, url
):
45 Handles main URL routing for the databrowse app.
47 `url` is the remainder of the URL -- e.g. 'objects/3'.
49 # Delegate to the appropriate method, based on the URL.
51 return self
.main_view(request
)
53 plugin_name
, rest_of_url
= url
.split('/', 1)
54 except ValueError: # need more than 1 value to unpack
55 plugin_name
, rest_of_url
= url
, None
57 plugin
= self
.plugins
[plugin_name
]
59 raise http
.Http404('A plugin with the requested name does not exist.')
60 return plugin
.model_view(request
, self
, rest_of_url
)
62 def main_view(self
, request
):
63 easy_model
= EasyModel(self
.site
, self
.model
)
64 html_snippets
= mark_safe(u
'\n'.join([p
.model_index_html(request
, self
.model
, self
.site
) for p
in self
.plugins
.values()]))
65 return render_to_response('databrowse/model_detail.html', {
67 'root_url': self
.site
.root_url
,
68 'plugin_html': html_snippets
,
71 class DatabrowseSite(object):
73 self
.registry
= {} # model_class -> databrowse_class
76 def register(self
, model_or_iterable
, databrowse_class
=None, **options
):
78 Registers the given model(s) with the given databrowse site.
80 The model(s) should be Model classes, not instances.
82 If a databrowse class isn't given, it will use DefaultModelDatabrowse
83 (the default databrowse options).
85 If a model is already registered, this will raise AlreadyRegistered.
87 databrowse_class
= databrowse_class
or DefaultModelDatabrowse
88 if issubclass(model_or_iterable
, models
.Model
):
89 model_or_iterable
= [model_or_iterable
]
90 for model
in model_or_iterable
:
91 if model
in self
.registry
:
92 raise AlreadyRegistered('The model %s is already registered' % model
.__class
__.__name
__)
93 self
.registry
[model
] = databrowse_class
95 def unregister(self
, model_or_iterable
):
97 Unregisters the given model(s).
99 If a model isn't already registered, this will raise NotRegistered.
101 if issubclass(model_or_iterable
, models
.Model
):
102 model_or_iterable
= [model_or_iterable
]
103 for model
in model_or_iterable
:
104 if model
not in self
.registry
:
105 raise NotRegistered('The model %s is not registered' % model
.__class
__.__name
__)
106 del self
.registry
[model
]
108 def root(self
, request
, url
):
110 Handles main URL routing for the databrowse app.
112 `url` is the remainder of the URL -- e.g. 'comments/comment/'.
114 self
.root_url
= request
.path
[:len(request
.path
) - len(url
)]
115 url
= url
.rstrip('/') # Trim trailing slash, if it exists.
118 return self
.index(request
)
120 return self
.model_page(request
, *url
.split('/', 2))
122 raise http
.Http404('The requested databrowse page does not exist.')
124 def index(self
, request
):
125 m_list
= [EasyModel(self
, m
) for m
in self
.registry
.keys()]
126 return render_to_response('databrowse/homepage.html', {'model_list': m_list
, 'root_url': self
.root_url
})
128 def model_page(self
, request
, app_label
, model_name
, rest_of_url
=None):
130 Handles the model-specific functionality of the databrowse site, delegating
131 to the appropriate ModelDatabrowse class.
133 model
= models
.get_model(app_label
, model_name
)
135 raise http
.Http404("App %r, model %r, not found." % (app_label
, model_name
))
137 databrowse_class
= self
.registry
[model
]
139 raise http
.Http404("This model exists but has not been registered with databrowse.")
140 return databrowse_class(model
, self
).root(request
, rest_of_url
)
142 site
= DatabrowseSite()
144 from django
.contrib
.databrowse
.plugins
.calendars
import CalendarPlugin
145 from django
.contrib
.databrowse
.plugins
.objects
import ObjectDetailPlugin
146 from django
.contrib
.databrowse
.plugins
.fieldchoices
import FieldChoicePlugin
148 class DefaultModelDatabrowse(ModelDatabrowse
):
149 plugins
= {'objects': ObjectDetailPlugin(), 'calendars': CalendarPlugin(), 'fields': FieldChoicePlugin()}