mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Removed django.contrib.databrowse.
RIP -- you served us well.
This commit is contained in:
		| @@ -1,5 +0,0 @@ | ||||
| import warnings | ||||
| from django.contrib.databrowse.sites import DatabrowsePlugin, ModelDatabrowse, DatabrowseSite, site | ||||
|  | ||||
|  | ||||
| warnings.warn("The Databrowse contrib app is deprecated", DeprecationWarning) | ||||
| @@ -1,214 +0,0 @@ | ||||
| """ | ||||
| These classes are light wrappers around Django's database API that provide | ||||
| convenience functionality and permalink functions for the databrowse app. | ||||
| """ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from django.db import models | ||||
| from django.utils import formats | ||||
| from django.utils.text import capfirst | ||||
| from django.utils.encoding import smart_text, force_str, iri_to_uri | ||||
| from django.db.models.query import QuerySet | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
|  | ||||
| EMPTY_VALUE = '(None)' | ||||
| DISPLAY_SIZE = 100 | ||||
|  | ||||
| class EasyModel(object): | ||||
|     def __init__(self, site, model): | ||||
|         self.site = site | ||||
|         self.model = model | ||||
|         self.model_list = list(site.registry.keys()) | ||||
|         self.verbose_name = model._meta.verbose_name | ||||
|         self.verbose_name_plural = model._meta.verbose_name_plural | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return force_str('<EasyModel for %s>' % self.model._meta.object_name) | ||||
|  | ||||
|     def model_databrowse(self): | ||||
|         "Returns the ModelDatabrowse class for this model." | ||||
|         return self.site.registry[self.model] | ||||
|  | ||||
|     def url(self): | ||||
|         return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name) | ||||
|  | ||||
|     def objects(self, **kwargs): | ||||
|         return self.get_query_set().filter(**kwargs) | ||||
|  | ||||
|     def get_query_set(self): | ||||
|         easy_qs = self.model._default_manager.get_query_set()._clone(klass=EasyQuerySet) | ||||
|         easy_qs._easymodel = self | ||||
|         return easy_qs | ||||
|  | ||||
|     def object_by_pk(self, pk): | ||||
|         return EasyInstance(self, self.model._default_manager.get(pk=pk)) | ||||
|  | ||||
|     def sample_objects(self): | ||||
|         for obj in self.model._default_manager.all()[:3]: | ||||
|             yield EasyInstance(self, obj) | ||||
|  | ||||
|     def field(self, name): | ||||
|         try: | ||||
|             f = self.model._meta.get_field(name) | ||||
|         except models.FieldDoesNotExist: | ||||
|             return None | ||||
|         return EasyField(self, f) | ||||
|  | ||||
|     def fields(self): | ||||
|         return [EasyField(self, f) for f in (self.model._meta.fields + self.model._meta.many_to_many)] | ||||
|  | ||||
| class EasyField(object): | ||||
|     def __init__(self, easy_model, field): | ||||
|         self.model, self.field = easy_model, field | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return force_str('<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)) | ||||
|  | ||||
|     def choices(self): | ||||
|         for value, label in self.field.choices: | ||||
|             yield EasyChoice(self.model, self, value, label) | ||||
|  | ||||
|     def url(self): | ||||
|         if self.field.choices: | ||||
|             return '%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name) | ||||
|         elif self.field.rel: | ||||
|             return '%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name) | ||||
|  | ||||
| class EasyChoice(object): | ||||
|     def __init__(self, easy_model, field, value, label): | ||||
|         self.model, self.field = easy_model, field | ||||
|         self.value, self.label = value, label | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return force_str('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name)) | ||||
|  | ||||
|     def url(self): | ||||
|         return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value)) | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class EasyInstance(object): | ||||
|     def __init__(self, easy_model, instance): | ||||
|         self.model, self.instance = easy_model, instance | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return force_str('<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val())) | ||||
|  | ||||
|     def __str__(self): | ||||
|         val = smart_text(self.instance) | ||||
|         if len(val) > DISPLAY_SIZE: | ||||
|             return val[:DISPLAY_SIZE] + '...' | ||||
|         return val | ||||
|  | ||||
|     def pk(self): | ||||
|         return self.instance._get_pk_val() | ||||
|  | ||||
|     def url(self): | ||||
|         return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())) | ||||
|  | ||||
|     def fields(self): | ||||
|         """ | ||||
|         Generator that yields EasyInstanceFields for each field in this | ||||
|         EasyInstance's model. | ||||
|         """ | ||||
|         for f in self.model.model._meta.fields + self.model.model._meta.many_to_many: | ||||
|             yield EasyInstanceField(self.model, self, f) | ||||
|  | ||||
|     def related_objects(self): | ||||
|         """ | ||||
|         Generator that yields dictionaries of all models that have this | ||||
|         EasyInstance's model as a ForeignKey or ManyToManyField, along with | ||||
|         lists of related objects. | ||||
|         """ | ||||
|         for rel_object in self.model.model._meta.get_all_related_objects() + self.model.model._meta.get_all_related_many_to_many_objects(): | ||||
|             if rel_object.model not in self.model.model_list: | ||||
|                 continue # Skip models that aren't in the model_list | ||||
|             em = EasyModel(self.model.site, rel_object.model) | ||||
|             yield { | ||||
|                 'model': em, | ||||
|                 'related_field': rel_object.field.verbose_name, | ||||
|                 'object_list': [EasyInstance(em, i) for i in getattr(self.instance, rel_object.get_accessor_name()).all()], | ||||
|             } | ||||
|  | ||||
| class EasyInstanceField(object): | ||||
|     def __init__(self, easy_model, instance, field): | ||||
|         self.model, self.field, self.instance = easy_model, field, instance | ||||
|         self.raw_value = getattr(instance.instance, field.name) | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return force_str('<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)) | ||||
|  | ||||
|     def values(self): | ||||
|         """ | ||||
|         Returns a list of values for this field for this instance. It's a list | ||||
|         so we can accomodate many-to-many fields. | ||||
|         """ | ||||
|         # This import is deliberately inside the function because it causes | ||||
|         # some settings to be imported, and we don't want to do that at the | ||||
|         # module level. | ||||
|         if self.field.rel: | ||||
|             if isinstance(self.field.rel, models.ManyToOneRel): | ||||
|                 objs = getattr(self.instance.instance, self.field.name) | ||||
|             elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel | ||||
|                 return list(getattr(self.instance.instance, self.field.name).all()) | ||||
|         elif self.field.choices: | ||||
|             objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE) | ||||
|         elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField): | ||||
|             if self.raw_value: | ||||
|                 if isinstance(self.field, models.DateTimeField): | ||||
|                     objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT')) | ||||
|                 elif isinstance(self.field, models.TimeField): | ||||
|                     objs = capfirst(formats.time_format(self.raw_value, 'TIME_FORMAT')) | ||||
|                 else: | ||||
|                     objs = capfirst(formats.date_format(self.raw_value, 'DATE_FORMAT')) | ||||
|             else: | ||||
|                 objs = EMPTY_VALUE | ||||
|         elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField): | ||||
|             objs = {True: 'Yes', False: 'No', None: 'Unknown'}[self.raw_value] | ||||
|         else: | ||||
|             objs = self.raw_value | ||||
|         return [objs] | ||||
|  | ||||
|     def urls(self): | ||||
|         "Returns a list of (value, URL) tuples." | ||||
|         # First, check the urls() method for each plugin. | ||||
|         plugin_urls = [] | ||||
|         for plugin_name, plugin in self.model.model_databrowse().plugins.items(): | ||||
|             urls = plugin.urls(plugin_name, self) | ||||
|             if urls is not None: | ||||
|                 return zip(self.values(), urls) | ||||
|         if self.field.rel: | ||||
|             m = EasyModel(self.model.site, self.field.rel.to) | ||||
|             if self.field.rel.to in self.model.model_list: | ||||
|                 lst = [] | ||||
|                 for value in self.values(): | ||||
|                     if value is None: | ||||
|                         continue | ||||
|                     url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val())) | ||||
|                     lst.append((smart_text(value), url)) | ||||
|             else: | ||||
|                 lst = [(value, None) for value in self.values()] | ||||
|         elif self.field.choices: | ||||
|             lst = [] | ||||
|             for value in self.values(): | ||||
|                 url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value)) | ||||
|                 lst.append((value, url)) | ||||
|         elif isinstance(self.field, models.URLField): | ||||
|             val = list(self.values())[0] | ||||
|             lst = [(val, iri_to_uri(val))] | ||||
|         else: | ||||
|             lst = [(list(self.values())[0], None)] | ||||
|         return lst | ||||
|  | ||||
| class EasyQuerySet(QuerySet): | ||||
|     """ | ||||
|     When creating (or cloning to) an `EasyQuerySet`, make sure to set the | ||||
|     `_easymodel` variable to the related `EasyModel`. | ||||
|     """ | ||||
|     def iterator(self, *args, **kwargs): | ||||
|         for obj in super(EasyQuerySet, self).iterator(*args, **kwargs): | ||||
|             yield EasyInstance(self._easymodel, obj) | ||||
|  | ||||
|     def _clone(self, *args, **kwargs): | ||||
|         c = super(EasyQuerySet, self)._clone(*args, **kwargs) | ||||
|         c._easymodel = self._easymodel | ||||
|         return c | ||||
| @@ -1 +0,0 @@ | ||||
| # Empty models.py to allow for specifying databrowse as a test label. | ||||
| @@ -1,147 +0,0 @@ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from django import http | ||||
| from django.db import models | ||||
| from django.contrib.databrowse.datastructures import EasyModel | ||||
| from django.contrib.databrowse.sites import DatabrowsePlugin | ||||
| from django.shortcuts import render_to_response | ||||
| from django.utils.html import format_html, format_html_join | ||||
| from django.utils.text import capfirst | ||||
| from django.utils.encoding import force_text | ||||
| from django.views.generic import dates | ||||
| from django.utils import datetime_safe | ||||
|  | ||||
|  | ||||
| class DateViewMixin(object): | ||||
|     allow_empty = False | ||||
|     allow_future = True | ||||
|     root_url = None | ||||
|     model = None | ||||
|     field = None | ||||
|  | ||||
|     def get_context_data(self, **kwargs): | ||||
|         context = super(DateViewMixin, self).get_context_data(**kwargs) | ||||
|         context.update({ | ||||
|             'root_url': self.root_url, | ||||
|             'model': self.model, | ||||
|             'field': self.field | ||||
|         }) | ||||
|         return context | ||||
|  | ||||
|  | ||||
| class DayView(DateViewMixin, dates.DayArchiveView): | ||||
|     template_name = 'databrowse/calendar_day.html' | ||||
|  | ||||
|  | ||||
| class MonthView(DateViewMixin, dates.MonthArchiveView): | ||||
|     template_name = 'databrowse/calendar_month.html' | ||||
|  | ||||
|  | ||||
| class YearView(DateViewMixin, dates.YearArchiveView): | ||||
|     template_name = 'databrowse/calendar_year.html' | ||||
|  | ||||
|  | ||||
| class IndexView(DateViewMixin, dates.ArchiveIndexView): | ||||
|     template_name = 'databrowse/calendar_main.html' | ||||
|  | ||||
|  | ||||
| class CalendarPlugin(DatabrowsePlugin): | ||||
|     def __init__(self, field_names=None): | ||||
|         self.field_names = field_names | ||||
|  | ||||
|     def field_dict(self, model): | ||||
|         """ | ||||
|         Helper function that returns a dictionary of all DateFields or | ||||
|         DateTimeFields in the given model. If self.field_names is set, it takes | ||||
|         take that into account when building the dictionary. | ||||
|         """ | ||||
|         if self.field_names is None: | ||||
|             return dict([(f.name, f) for f in model._meta.fields if isinstance(f, models.DateField)]) | ||||
|         else: | ||||
|             return dict([(f.name, f) for f in model._meta.fields if isinstance(f, models.DateField) and f.name in self.field_names]) | ||||
|  | ||||
|     def model_index_html(self, request, model, site): | ||||
|         fields = self.field_dict(model) | ||||
|         if not fields: | ||||
|             return '' | ||||
|         return format_html('<p class="filter"><strong>View calendar by:</strong> {0}</p>', | ||||
|                            format_html_join(', ', '<a href="calendars/{0}/">{1}</a>', | ||||
|                                             ((f.name, force_text(capfirst(f.verbose_name))) for f in fields.values()))) | ||||
|  | ||||
|     def urls(self, plugin_name, easy_instance_field): | ||||
|         if isinstance(easy_instance_field.field, models.DateField): | ||||
|             d = easy_instance_field.raw_value | ||||
|             return ['%s%s/%s/%s/%s/%s/' % ( | ||||
|                 easy_instance_field.model.url(), | ||||
|                 plugin_name, easy_instance_field.field.name, | ||||
|                 str(d.year), | ||||
|                 datetime_safe.new_date(d).strftime('%b').lower(), | ||||
|                 d.day)] | ||||
|  | ||||
|     def model_view(self, request, model_databrowse, url): | ||||
|         self.model, self.site = model_databrowse.model, model_databrowse.site | ||||
|         self.fields = self.field_dict(self.model) | ||||
|  | ||||
|         # If the model has no DateFields, there's no point in going further. | ||||
|         if not self.fields: | ||||
|             raise http.Http404('The requested model has no calendars.') | ||||
|  | ||||
|         if url is None: | ||||
|             return self.homepage_view(request) | ||||
|         url_bits = url.split('/') | ||||
|         if url_bits[0] in self.fields: | ||||
|             return self.calendar_view(request, self.fields[url_bits[0]], *url_bits[1:]) | ||||
|  | ||||
|         raise http.Http404('The requested page does not exist.') | ||||
|  | ||||
|     def homepage_view(self, request): | ||||
|         easy_model = EasyModel(self.site, self.model) | ||||
|         field_list = list(self.fields.values()) | ||||
|         field_list.sort(key=lambda k:k.verbose_name) | ||||
|         return render_to_response('databrowse/calendar_homepage.html', { | ||||
|                 'root_url': self.site.root_url, | ||||
|                 'model': easy_model, | ||||
|                 'field_list': field_list | ||||
|             }) | ||||
|  | ||||
|     def calendar_view(self, request, field, year=None, month=None, day=None): | ||||
|         easy_model = EasyModel(self.site, self.model) | ||||
|         root_url = self.site.root_url | ||||
|  | ||||
|         if day is not None: | ||||
|             return DayView.as_view( | ||||
|                                 year=year, month=month, day=day, | ||||
|                                 date_field=field.name, | ||||
|                                 queryset=easy_model.get_query_set(), | ||||
|                                 root_url=root_url, | ||||
|                                 model=easy_model, | ||||
|                                 field=field | ||||
|                             )(request) | ||||
|         elif month is not None: | ||||
|             return MonthView.as_view( | ||||
|                                 year=year, month=month, | ||||
|                                 date_field=field.name, | ||||
|                                 queryset=easy_model.get_query_set(), | ||||
|                                 root_url=root_url, | ||||
|                                 model=easy_model, | ||||
|                                 field=field | ||||
|                             )(request) | ||||
|         elif year is not None: | ||||
|             return YearView.as_view( | ||||
|                                 year=year, | ||||
|                                 date_field=field.name, | ||||
|                                 queryset=easy_model.get_query_set(), | ||||
|                                 root_url=root_url, | ||||
|                                 model=easy_model, | ||||
|                                 field=field | ||||
|                             )(request) | ||||
|         else: | ||||
|             return IndexView.as_view( | ||||
|                                 date_field=field.name, | ||||
|                                 queryset=easy_model.get_query_set(), | ||||
|                                 root_url=root_url, | ||||
|                                 model=easy_model, | ||||
|                                 field=field | ||||
|                             )(request) | ||||
|  | ||||
|         assert False, ('%s, %s, %s, %s' % (field, year, month, day)) | ||||
| @@ -1,77 +0,0 @@ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from django import http | ||||
| from django.db import models | ||||
| from django.contrib.databrowse.datastructures import EasyModel | ||||
| from django.contrib.databrowse.sites import DatabrowsePlugin | ||||
| from django.shortcuts import render_to_response | ||||
| from django.utils.html import format_html, format_html_join | ||||
| from django.utils.http import urlquote | ||||
| from django.utils.text import capfirst | ||||
| from django.utils.encoding import force_text | ||||
|  | ||||
|  | ||||
| class FieldChoicePlugin(DatabrowsePlugin): | ||||
|     def __init__(self, field_filter=None): | ||||
|         # If field_filter is given, it should be a callable that takes a | ||||
|         # Django database Field instance and returns True if that field should | ||||
|         # be included. If field_filter is None, that all fields will be used. | ||||
|         self.field_filter = field_filter | ||||
|  | ||||
|     def field_dict(self, model): | ||||
|         """ | ||||
|         Helper function that returns a dictionary of all fields in the given | ||||
|         model. If self.field_filter is set, it only includes the fields that | ||||
|         match the filter. | ||||
|         """ | ||||
|         if self.field_filter: | ||||
|             return dict([(f.name, f) for f in model._meta.fields if self.field_filter(f)]) | ||||
|         else: | ||||
|             return dict([(f.name, f) for f in model._meta.fields if not f.rel and not f.primary_key and not f.unique and not isinstance(f, (models.AutoField, models.TextField))]) | ||||
|  | ||||
|     def model_index_html(self, request, model, site): | ||||
|         fields = self.field_dict(model) | ||||
|         if not fields: | ||||
|             return '' | ||||
|         return format_html('<p class="filter"><strong>View by:</strong> {0}</p>', | ||||
|                            format_html_join(', ', '<a href="fields/{0}/">{1}</a>', | ||||
|                                             ((f.name, force_text(capfirst(f.verbose_name))) for f in fields.values()))) | ||||
|  | ||||
|     def urls(self, plugin_name, easy_instance_field): | ||||
|         if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values(): | ||||
|             return ['%s%s/%s/%s/' % ( | ||||
|                 easy_instance_field.model.url(), | ||||
|                 plugin_name, easy_instance_field.field.name, | ||||
|                 urlquote(easy_instance_field.raw_value, safe=''))] | ||||
|  | ||||
|     def model_view(self, request, model_databrowse, url): | ||||
|         self.model, self.site = model_databrowse.model, model_databrowse.site | ||||
|         self.fields = self.field_dict(self.model) | ||||
|  | ||||
|         # If the model has no fields with choices, there's no point in going | ||||
|         # further. | ||||
|         if not self.fields: | ||||
|             raise http.Http404('The requested model has no fields.') | ||||
|  | ||||
|         if url is None: | ||||
|             return self.homepage_view(request) | ||||
|         url_bits = url.split('/', 1) | ||||
|         if url_bits[0] in self.fields: | ||||
|             return self.field_view(request, self.fields[url_bits[0]], *url_bits[1:]) | ||||
|  | ||||
|         raise http.Http404('The requested page does not exist.') | ||||
|  | ||||
|     def homepage_view(self, request): | ||||
|         easy_model = EasyModel(self.site, self.model) | ||||
|         field_list = list(self.fields.values()) | ||||
|         field_list.sort(key=lambda k: k.verbose_name) | ||||
|         return render_to_response('databrowse/fieldchoice_homepage.html', {'root_url': self.site.root_url, 'model': easy_model, 'field_list': field_list}) | ||||
|  | ||||
|     def field_view(self, request, field, value=None): | ||||
|         easy_model = EasyModel(self.site, self.model) | ||||
|         easy_field = easy_model.field(field.name) | ||||
|         if value is not None: | ||||
|             obj_list = easy_model.objects(**{field.name: value}) | ||||
|             return render_to_response('databrowse/fieldchoice_detail.html', {'root_url': self.site.root_url, 'model': easy_model, 'field': easy_field, 'value': value, 'object_list': obj_list}) | ||||
|         obj_list = [v[field.name] for v in self.model._default_manager.distinct().order_by(field.name).values(field.name)] | ||||
|         return render_to_response('databrowse/fieldchoice_list.html', {'root_url': self.site.root_url, 'model': easy_model, 'field': easy_field, 'object_list': obj_list}) | ||||
| @@ -1,18 +0,0 @@ | ||||
| try: | ||||
|     from urllib.parse import urljoin | ||||
| except ImportError:     # Python 2 | ||||
|     from urlparse import urljoin | ||||
|  | ||||
| from django import http | ||||
| from django.contrib.databrowse.datastructures import EasyModel | ||||
| from django.contrib.databrowse.sites import DatabrowsePlugin | ||||
| from django.shortcuts import render_to_response | ||||
|  | ||||
| class ObjectDetailPlugin(DatabrowsePlugin): | ||||
|     def model_view(self, request, model_databrowse, url): | ||||
|         # If the object ID wasn't provided, redirect to the model page, which is one level up. | ||||
|         if url is None: | ||||
|             return http.HttpResponseRedirect(urljoin(request.path, '../')) | ||||
|         easy_model = EasyModel(model_databrowse.site, model_databrowse.model) | ||||
|         obj = easy_model.object_by_pk(url) | ||||
|         return render_to_response('databrowse/object_detail.html', {'object': obj, 'root_url': model_databrowse.site.root_url}) | ||||
| @@ -1,147 +0,0 @@ | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from django import http | ||||
| from django.db import models | ||||
| from django.contrib.databrowse.datastructures import EasyModel | ||||
| from django.shortcuts import render_to_response | ||||
| from django.utils.safestring import mark_safe | ||||
|  | ||||
| class AlreadyRegistered(Exception): | ||||
|     pass | ||||
|  | ||||
| class NotRegistered(Exception): | ||||
|     pass | ||||
|  | ||||
| class DatabrowsePlugin(object): | ||||
|     def urls(self, plugin_name, easy_instance_field): | ||||
|         """ | ||||
|         Given an EasyInstanceField object, returns a list of URLs for this | ||||
|         plugin's views of this object. These URLs should be absolute. | ||||
|  | ||||
|         Returns None if the EasyInstanceField object doesn't get a | ||||
|         list of plugin-specific URLs. | ||||
|         """ | ||||
|         return None | ||||
|  | ||||
|     def model_index_html(self, request, model, site): | ||||
|         """ | ||||
|         Returns a snippet of HTML to include on the model index page. | ||||
|         """ | ||||
|         return '' | ||||
|  | ||||
|     def model_view(self, request, model_databrowse, url): | ||||
|         """ | ||||
|         Handles main URL routing for a plugin's model-specific pages. | ||||
|         """ | ||||
|         raise NotImplementedError | ||||
|  | ||||
| class ModelDatabrowse(object): | ||||
|     plugins = {} | ||||
|  | ||||
|     def __init__(self, model, site): | ||||
|         self.model = model | ||||
|         self.site = site | ||||
|  | ||||
|     def root(self, request, url): | ||||
|         """ | ||||
|         Handles main URL routing for the databrowse app. | ||||
|  | ||||
|         `url` is the remainder of the URL -- e.g. 'objects/3'. | ||||
|         """ | ||||
|         # Delegate to the appropriate method, based on the URL. | ||||
|         if url is None: | ||||
|             return self.main_view(request) | ||||
|         try: | ||||
|             plugin_name, rest_of_url = url.split('/', 1) | ||||
|         except ValueError: # need more than 1 value to unpack | ||||
|             plugin_name, rest_of_url = url, None | ||||
|         try: | ||||
|             plugin = self.plugins[plugin_name] | ||||
|         except KeyError: | ||||
|             raise http.Http404('A plugin with the requested name does not exist.') | ||||
|         return plugin.model_view(request, self, rest_of_url) | ||||
|  | ||||
|     def main_view(self, request): | ||||
|         easy_model = EasyModel(self.site, self.model) | ||||
|         html_snippets = mark_safe('\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()])) | ||||
|         return render_to_response('databrowse/model_detail.html', { | ||||
|             'model': easy_model, | ||||
|             'root_url': self.site.root_url, | ||||
|             'plugin_html': html_snippets, | ||||
|         }) | ||||
|  | ||||
| class DatabrowseSite(object): | ||||
|     def __init__(self): | ||||
|         self.registry = {} # model_class -> databrowse_class | ||||
|         self.root_url = None | ||||
|  | ||||
|     def register(self, *model_list, **options): | ||||
|         """ | ||||
|         Registers the given model(s) with the given databrowse site. | ||||
|  | ||||
|         The model(s) should be Model classes, not instances. | ||||
|  | ||||
|         If a databrowse class isn't given, it will use DefaultModelDatabrowse | ||||
|         (the default databrowse options). | ||||
|  | ||||
|         If a model is already registered, this will raise AlreadyRegistered. | ||||
|         """ | ||||
|         databrowse_class = options.pop('databrowse_class', DefaultModelDatabrowse) | ||||
|         for model in model_list: | ||||
|             if model in self.registry: | ||||
|                 raise AlreadyRegistered('The model %s is already registered' % model.__name__) | ||||
|             self.registry[model] = databrowse_class | ||||
|  | ||||
|     def unregister(self, *model_list): | ||||
|         """ | ||||
|         Unregisters the given model(s). | ||||
|  | ||||
|         If a model isn't already registered, this will raise NotRegistered. | ||||
|         """ | ||||
|         for model in model_list: | ||||
|             if model not in self.registry: | ||||
|                 raise NotRegistered('The model %s is not registered' % model.__name__) | ||||
|             del self.registry[model] | ||||
|  | ||||
|     def root(self, request, url): | ||||
|         """ | ||||
|         Handles main URL routing for the databrowse app. | ||||
|  | ||||
|         `url` is the remainder of the URL -- e.g. 'comments/comment/'. | ||||
|         """ | ||||
|         self.root_url = request.path[:len(request.path) - len(url)] | ||||
|         url = url.rstrip('/') # Trim trailing slash, if it exists. | ||||
|  | ||||
|         if url == '': | ||||
|             return self.index(request) | ||||
|         elif '/' in url: | ||||
|             return self.model_page(request, *url.split('/', 2)) | ||||
|  | ||||
|         raise http.Http404('The requested databrowse page does not exist.') | ||||
|  | ||||
|     def index(self, request): | ||||
|         m_list = [EasyModel(self, m) for m in self.registry.keys()] | ||||
|         return render_to_response('databrowse/homepage.html', {'model_list': m_list, 'root_url': self.root_url}) | ||||
|  | ||||
|     def model_page(self, request, app_label, model_name, rest_of_url=None): | ||||
|         """ | ||||
|         Handles the model-specific functionality of the databrowse site, delegating | ||||
|         to the appropriate ModelDatabrowse class. | ||||
|         """ | ||||
|         model = models.get_model(app_label, model_name) | ||||
|         if model is None: | ||||
|             raise http.Http404("App %r, model %r, not found." % (app_label, model_name)) | ||||
|         try: | ||||
|             databrowse_class = self.registry[model] | ||||
|         except KeyError: | ||||
|             raise http.Http404("This model exists but has not been registered with databrowse.") | ||||
|         return databrowse_class(model, self).root(request, rest_of_url) | ||||
|  | ||||
| site = DatabrowseSite() | ||||
|  | ||||
| from django.contrib.databrowse.plugins.calendars import CalendarPlugin | ||||
| from django.contrib.databrowse.plugins.objects import ObjectDetailPlugin | ||||
| from django.contrib.databrowse.plugins.fieldchoices import FieldChoicePlugin | ||||
|  | ||||
| class DefaultModelDatabrowse(ModelDatabrowse): | ||||
|     plugins = {'objects': ObjectDetailPlugin(), 'calendars': CalendarPlugin(), 'fields': FieldChoicePlugin()} | ||||
| @@ -1,61 +0,0 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}> | ||||
| <head> | ||||
| <title>{% block title %}{% endblock %}</title> | ||||
| {% block style %} | ||||
| <style type="text/css"> | ||||
| * { margin:0; padding:0; } | ||||
| body { background:#eee; color:#333; font:76%/1.6 "Lucida Grande","Bitstream Vera Sans",Verdana,sans-serif; } | ||||
| a { color: #5b80b2; text-decoration:none; } | ||||
| a:hover { text-decoration:underline; } | ||||
| a img { border:none; } | ||||
| h1 { font-size:1.8em; color:#666; margin:0.4em 0 0.2em 0; } | ||||
| h2 { font-size:1.5em; color:#666; margin:1em 0 0.2em 0; } | ||||
| p { margin:0.5em 0 1em 0; } | ||||
| .odd { background-color:#EDF3FE; } | ||||
| .quiet { color:#666; } | ||||
| /* FILTERS */ | ||||
| .filter { color:#999; font-size:0.9em; float:left; margin-bottom:10px; margin-right:20px; } | ||||
| .filter strong { color:#666; } | ||||
| /* OBJECT LISTS */ | ||||
| .objectlist { clear:both; margin:0 -20px; color:#666; } | ||||
| .objectlist li a { display:block; padding:1em 20px; } | ||||
| .objectlist li a:hover { background:#5b80b2; color:#3B5572; color:#fff; text-decoration:none; } | ||||
| .related h2 { font-size: 1em; margin-bottom: 0.6em; } | ||||
| .related .objectlist li a { padding: 0.6em 20px; } | ||||
| .related .objectlist li.odd { background:#eee; } | ||||
| /* OBJECT DETAIL */ | ||||
| .objectinfo { border-collapse:collapse; color:#666; margin:0 -20px; } | ||||
| .objectinfo td, .objectinfo th { padding:1em 20px; vertical-align:top; } | ||||
| .objectinfo td { width:100%; } | ||||
| .objectinfo th { text-align:left; white-space:nowrap; } | ||||
| /* MODEL GROUPS */ | ||||
| .modelgroup { color:#999; font-size:0.9em; margin:0 -20px; } | ||||
| .modelgroup h2 { font-size:1.2em; margin:0; } | ||||
| .modelgroup h2 a { display: block; padding: 0.83em 20px; } | ||||
| .modelgroup h2 a:hover { text-decoration: none; color: #fff; } | ||||
| .modelgroup p { float:left; margin:-2.65em 0 0 14em; position:relative; } | ||||
| .modelgroup p a { white-space:nowrap; } | ||||
| .modelgroup a.more { color:#999; } | ||||
| .modelgroup:hover { background:#5b80b2; color:#becfe5; } | ||||
| .modelgroup:hover p a { color:#becfe5; } | ||||
| .modelgroup:hover a { color:#fff; } | ||||
| .modelgroup:hover a.more { color:#fff; } | ||||
| /* BREADCRUMBS */ | ||||
| #breadcrumbs { padding:10px 0; color:#999; font-size:0.9em; } | ||||
| /* HEADER */ | ||||
| #header a { display:block; background:#eee; color:#676868; padding:10px 20px; font-weight:bold; font-size:1em; text-decoration:none; border-bottom:1px solid #ddd; } | ||||
| #header a:hover { text-decoration:underline; } | ||||
| /* CONTENT */ | ||||
| #content { background:#fff; border-bottom:1px solid #ddd; padding:0 20px; } | ||||
| </style> | ||||
| {% endblock %} | ||||
| {% block extrahead %}{% endblock %} | ||||
| </head> | ||||
| <body id="{% block bodyid %}page{% endblock %}"> | ||||
| <div id="header"><a href="{{ root_url }}">{% block databrowse_title %}Databrowse{% endblock %}</a></div> | ||||
| <div id="content"> | ||||
| {% block content %}{% endblock %} | ||||
| </div> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1 +0,0 @@ | ||||
| {% extends "databrowse/base.html" %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} {{ day|date:"F j, Y" }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../../">Calendars</a> / <a href="../../../">By {{ field.verbose_name }}</a> / <a href="../../">{{ day|date:"Y" }}</a> / <a href="../">{{ day|date:"F" }}</a> / {{ day|date:"d" }}</div> | ||||
|  | ||||
| <h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %} with {{ field.verbose_name }} on {{ day|date:"F j, Y" }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in object_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}Calendars{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / Calendars</div> | ||||
|  | ||||
| <h1>Calendars</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for field in field_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ field.verbose_name|capfirst }} calendar{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../">Calendars</a> / By {{ field.verbose_name }}</div> | ||||
|  | ||||
| <h1>{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for year in date_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ year|date:"Y" }}/">{{ year|date:"Y" }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ month|date:"F Y" }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../">Calendars</a> / <a href="../../">By {{ field.verbose_name }}</a> / <a href="../">{{ month|date:"Y" }}</a> / {{ month|date:"F" }}</div> | ||||
|  | ||||
| <h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %} with {{ field.verbose_name }} on {{ month|date:"F Y" }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in object_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../">Calendars</a> / <a href="../">By {{ field.verbose_name }}</a> / {{ year }}</div> | ||||
|  | ||||
| <h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for month in date_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="{{ field.url }}">By {{ field.field.verbose_name }}</a> / {{ value }}</div> | ||||
|  | ||||
| <h1>{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in object_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / By {{ field.field.verbose_name }}</div> | ||||
|  | ||||
| <h1>{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for choice in field.choices %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ choice.url }}">{{ choice.label }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.field.verbose_name }} {{ value }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../">Fields</a> / <a href="../">By {{ field.field.verbose_name }}</a> / {{ value }}</div> | ||||
|  | ||||
| <h1>{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %} with {{ field.field.verbose_name }} {{ value }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in object_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}Browsable fields in {{ model.verbose_name_plural }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / Fields</div> | ||||
|  | ||||
| <h1>Browsable fields in {{ model.verbose_name_plural }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for field in field_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../">Fields</a> / By {{ field.field.verbose_name }}</div> | ||||
|  | ||||
| <h1>{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}</h1> | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in object_list %} | ||||
| <li class="{% cycle 'odd' 'even' %}"><a href="{{ object|iriencode }}/">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,21 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}Databrowse{% endblock %} | ||||
|  | ||||
| {% block bodyid %}homepage{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| {% for model in model_list %} | ||||
|   <div class="modelgroup {% cycle 'even' 'odd' %}"> | ||||
| 	  <h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2> | ||||
| 		<p> | ||||
| 		{% for object in model.sample_objects %} | ||||
| 			<a href="{{ object.url }}">{{ object }}</a>,  | ||||
| 		{% endfor %} | ||||
| 			<a class="more" href="{{ model.url }}">More →</a> | ||||
| 		</p> | ||||
|   </div> | ||||
| {% endfor %} | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,19 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ model.verbose_name_plural|capfirst }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / {{ model.verbose_name_plural|capfirst }}</div> | ||||
|  | ||||
| <h1>{{ model.objects.count }} {% if model.objects.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %}</h1> | ||||
|  | ||||
| {{ plugin_html }} | ||||
|  | ||||
| <ul class="objectlist"> | ||||
| {% for object in model.objects %} | ||||
|     <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
| {% endfor %} | ||||
| </ul> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,41 +0,0 @@ | ||||
| {% extends "databrowse/base_site.html" %} | ||||
|  | ||||
| {% block title %}{{ object.model.verbose_name|capfirst }}: {{ object }}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
| <div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object }}</div> | ||||
|  | ||||
| <h1>{{ object.model.verbose_name|capfirst }}: {{ object }}</h1> | ||||
|  | ||||
| <table class="objectinfo"> | ||||
| {% for field in object.fields %} | ||||
| <tr class="{% cycle 'odd' 'even' %}"> | ||||
| <th>{{ field.field.verbose_name|capfirst }}</th> | ||||
| <td> | ||||
| {% if field.urls %} | ||||
| {% for value, url in field.urls %} | ||||
| {% if url %}<a href="{{ url }}">{% endif %}{{ value }}{% if url %}</a>{% endif %}{% if not forloop.last %}, {% endif %} | ||||
| {% endfor %} | ||||
| {% else %}None{% endif %} | ||||
| </td> | ||||
| </tr> | ||||
| {% endfor %} | ||||
| </table> | ||||
|  | ||||
| {% for related_object in object.related_objects %} | ||||
|   <div class="related"> | ||||
|   <h2>Appears in "{{ related_object.related_field }}" in the following {{ related_object.model.verbose_name_plural }}:</h2> | ||||
|   {% if related_object.object_list %} | ||||
|   <ul class="objectlist"> | ||||
|     {% for object in related_object.object_list %} | ||||
|     <li class="{% cycle 'odd' 'even' %}"><a href="{{ object.url }}">{{ object }}</a></li> | ||||
|     {% endfor %} | ||||
|   </ul> | ||||
|   {% else %} | ||||
|   <p class="quiet">(None)</p> | ||||
|   {% endif %} | ||||
|   </div> | ||||
| {% endfor %} | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,62 +0,0 @@ | ||||
| from django.contrib import databrowse | ||||
| from django.db import models | ||||
| from django.test import TestCase | ||||
| from django.utils.encoding import python_2_unicode_compatible | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class SomeModel(models.Model): | ||||
|     some_field = models.CharField(max_length=50) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.some_field | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class SomeOtherModel(models.Model): | ||||
|     some_other_field = models.CharField(max_length=50) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.some_other_field | ||||
|  | ||||
|  | ||||
| @python_2_unicode_compatible | ||||
| class YetAnotherModel(models.Model): | ||||
|     yet_another_field = models.CharField(max_length=50) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.yet_another_field | ||||
|  | ||||
|  | ||||
| class DatabrowseTests(TestCase): | ||||
|  | ||||
|     def test_databrowse_register_unregister(self): | ||||
|         databrowse.site.register(SomeModel) | ||||
|         self.assertTrue(SomeModel in databrowse.site.registry) | ||||
|         databrowse.site.register(SomeOtherModel, YetAnotherModel) | ||||
|         self.assertTrue(SomeOtherModel in databrowse.site.registry) | ||||
|         self.assertTrue(YetAnotherModel in databrowse.site.registry) | ||||
|  | ||||
|         self.assertRaisesMessage( | ||||
|             databrowse.sites.AlreadyRegistered, | ||||
|             'The model SomeModel is already registered', | ||||
|             databrowse.site.register, SomeModel, SomeOtherModel | ||||
|         ) | ||||
|  | ||||
|         databrowse.site.unregister(SomeOtherModel) | ||||
|         self.assertFalse(SomeOtherModel in databrowse.site.registry) | ||||
|         databrowse.site.unregister(SomeModel, YetAnotherModel) | ||||
|         self.assertFalse(SomeModel in databrowse.site.registry) | ||||
|         self.assertFalse(YetAnotherModel in databrowse.site.registry) | ||||
|  | ||||
|         self.assertRaisesMessage( | ||||
|             databrowse.sites.NotRegistered, | ||||
|             'The model SomeModel is not registered', | ||||
|             databrowse.site.unregister, SomeModel, SomeOtherModel | ||||
|         ) | ||||
|  | ||||
|         self.assertRaisesMessage( | ||||
|             databrowse.sites.AlreadyRegistered, | ||||
|             'The model SomeModel is already registered', | ||||
|             databrowse.site.register, SomeModel, SomeModel | ||||
|         ) | ||||
| @@ -1,20 +0,0 @@ | ||||
| from django.conf.urls import patterns | ||||
| from django.contrib.databrowse import views | ||||
|  | ||||
| # Note: The views in this URLconf all require a 'models' argument, | ||||
| # which is a list of model classes (*not* instances). | ||||
|  | ||||
| urlpatterns = patterns('', | ||||
|     #(r'^$', views.homepage), | ||||
|     #(r'^([^/]+)/([^/]+)/$', views.model_detail), | ||||
|  | ||||
|     (r'^([^/]+)/([^/]+)/fields/(\w+)/$', views.choice_list), | ||||
|     (r'^([^/]+)/([^/]+)/fields/(\w+)/(.*)/$', views.choice_detail), | ||||
|  | ||||
|     #(r'^([^/]+)/([^/]+)/calendars/(\w+)/$', views.calendar_main), | ||||
|     #(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/$', views.calendar_year), | ||||
|     #(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/(\w{3})/$', views.calendar_month), | ||||
|     #(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/(\w{3})/(\d{1,2})/$', views.calendar_day), | ||||
|  | ||||
|     #(r'^([^/]+)/([^/]+)/objects/(.*)/$', views.object_detail), | ||||
| ) | ||||
| @@ -1,19 +0,0 @@ | ||||
| from django.http import Http404 | ||||
| from django.shortcuts import render_to_response | ||||
|  | ||||
| ########### | ||||
| # CHOICES # | ||||
| ########### | ||||
|  | ||||
| def choice_list(request, app_label, module_name, field_name, models): | ||||
|     m, f = lookup_field(app_label, module_name, field_name, models) | ||||
|     return render_to_response('databrowse/choice_list.html', {'model': m, 'field': f}) | ||||
|  | ||||
| def choice_detail(request, app_label, module_name, field_name, field_val, models): | ||||
|     m, f = lookup_field(app_label, module_name, field_name, models) | ||||
|     try: | ||||
|         label = dict(f.field.choices)[field_val] | ||||
|     except KeyError: | ||||
|         raise Http404('Invalid choice value given') | ||||
|     obj_list = m.objects(**{f.field.name: field_val}) | ||||
|     return render_to_response('databrowse/choice_detail.html', {'model': m, 'field': f, 'value': label, 'object_list': obj_list}) | ||||
		Reference in New Issue
	
	Block a user