summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in1
-rw-r--r--django/contrib/databrowse/__init__.py5
-rw-r--r--django/contrib/databrowse/datastructures.py214
-rw-r--r--django/contrib/databrowse/models.py1
-rw-r--r--django/contrib/databrowse/plugins/__init__.py0
-rw-r--r--django/contrib/databrowse/plugins/calendars.py147
-rw-r--r--django/contrib/databrowse/plugins/fieldchoices.py77
-rw-r--r--django/contrib/databrowse/plugins/objects.py18
-rw-r--r--django/contrib/databrowse/sites.py147
-rw-r--r--django/contrib/databrowse/templates/databrowse/base.html61
-rw-r--r--django/contrib/databrowse/templates/databrowse/base_site.html1
-rw-r--r--django/contrib/databrowse/templates/databrowse/calendar_day.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/calendar_homepage.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/calendar_main.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/calendar_month.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/calendar_year.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/choice_detail.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/choice_list.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/fieldchoice_list.html17
-rw-r--r--django/contrib/databrowse/templates/databrowse/homepage.html21
-rw-r--r--django/contrib/databrowse/templates/databrowse/model_detail.html19
-rw-r--r--django/contrib/databrowse/templates/databrowse/object_detail.html41
-rw-r--r--django/contrib/databrowse/tests.py62
-rw-r--r--django/contrib/databrowse/urls.py20
-rw-r--r--django/contrib/databrowse/views.py19
-rw-r--r--docs/index.txt1
-rw-r--r--docs/ref/contrib/databrowse.txt89
-rw-r--r--docs/ref/contrib/index.txt1
-rwxr-xr-xtests/runtests.py5
31 files changed, 0 insertions, 1120 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index fbda541d22..0e0aba1268 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -19,7 +19,6 @@ recursive-include django/contrib/auth/fixtures *
recursive-include django/contrib/auth/templates *
recursive-include django/contrib/auth/tests/templates *
recursive-include django/contrib/comments/templates *
-recursive-include django/contrib/databrowse/templates *
recursive-include django/contrib/formtools/templates *
recursive-include django/contrib/formtools/tests/templates *
recursive-include django/contrib/flatpages/fixtures *
diff --git a/django/contrib/databrowse/__init__.py b/django/contrib/databrowse/__init__.py
deleted file mode 100644
index acb7626c8d..0000000000
--- a/django/contrib/databrowse/__init__.py
+++ /dev/null
@@ -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)
diff --git a/django/contrib/databrowse/datastructures.py b/django/contrib/databrowse/datastructures.py
deleted file mode 100644
index 5f5f46f0d1..0000000000
--- a/django/contrib/databrowse/datastructures.py
+++ /dev/null
@@ -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
diff --git a/django/contrib/databrowse/models.py b/django/contrib/databrowse/models.py
deleted file mode 100644
index 2e283e0995..0000000000
--- a/django/contrib/databrowse/models.py
+++ /dev/null
@@ -1 +0,0 @@
-# Empty models.py to allow for specifying databrowse as a test label.
diff --git a/django/contrib/databrowse/plugins/__init__.py b/django/contrib/databrowse/plugins/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
--- a/django/contrib/databrowse/plugins/__init__.py
+++ /dev/null
diff --git a/django/contrib/databrowse/plugins/calendars.py b/django/contrib/databrowse/plugins/calendars.py
deleted file mode 100644
index a548c33c8f..0000000000
--- a/django/contrib/databrowse/plugins/calendars.py
+++ /dev/null
@@ -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))
diff --git a/django/contrib/databrowse/plugins/fieldchoices.py b/django/contrib/databrowse/plugins/fieldchoices.py
deleted file mode 100644
index dc5e9aef14..0000000000
--- a/django/contrib/databrowse/plugins/fieldchoices.py
+++ /dev/null
@@ -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})
diff --git a/django/contrib/databrowse/plugins/objects.py b/django/contrib/databrowse/plugins/objects.py
deleted file mode 100644
index e956f4ea67..0000000000
--- a/django/contrib/databrowse/plugins/objects.py
+++ /dev/null
@@ -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})
diff --git a/django/contrib/databrowse/sites.py b/django/contrib/databrowse/sites.py
deleted file mode 100644
index b5cb2639d6..0000000000
--- a/django/contrib/databrowse/sites.py
+++ /dev/null
@@ -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()}
diff --git a/django/contrib/databrowse/templates/databrowse/base.html b/django/contrib/databrowse/templates/databrowse/base.html
deleted file mode 100644
index 56464e0614..0000000000
--- a/django/contrib/databrowse/templates/databrowse/base.html
+++ /dev/null
@@ -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>
diff --git a/django/contrib/databrowse/templates/databrowse/base_site.html b/django/contrib/databrowse/templates/databrowse/base_site.html
deleted file mode 100644
index b577ab8427..0000000000
--- a/django/contrib/databrowse/templates/databrowse/base_site.html
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "databrowse/base.html" %}
diff --git a/django/contrib/databrowse/templates/databrowse/calendar_day.html b/django/contrib/databrowse/templates/databrowse/calendar_day.html
deleted file mode 100644
index c009a94c66..0000000000
--- a/django/contrib/databrowse/templates/databrowse/calendar_day.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html b/django/contrib/databrowse/templates/databrowse/calendar_homepage.html
deleted file mode 100644
index 85eb8af9eb..0000000000
--- a/django/contrib/databrowse/templates/databrowse/calendar_homepage.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/calendar_main.html b/django/contrib/databrowse/templates/databrowse/calendar_main.html
deleted file mode 100644
index 7cb59042df..0000000000
--- a/django/contrib/databrowse/templates/databrowse/calendar_main.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/calendar_month.html b/django/contrib/databrowse/templates/databrowse/calendar_month.html
deleted file mode 100644
index ad189f441c..0000000000
--- a/django/contrib/databrowse/templates/databrowse/calendar_month.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/calendar_year.html b/django/contrib/databrowse/templates/databrowse/calendar_year.html
deleted file mode 100644
index a6e6f53ba3..0000000000
--- a/django/contrib/databrowse/templates/databrowse/calendar_year.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/choice_detail.html b/django/contrib/databrowse/templates/databrowse/choice_detail.html
deleted file mode 100644
index 0abc536515..0000000000
--- a/django/contrib/databrowse/templates/databrowse/choice_detail.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/choice_list.html b/django/contrib/databrowse/templates/databrowse/choice_list.html
deleted file mode 100644
index 58675e82bf..0000000000
--- a/django/contrib/databrowse/templates/databrowse/choice_list.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html
deleted file mode 100644
index 2dd55d48ac..0000000000
--- a/django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html
deleted file mode 100644
index b82c22d5b4..0000000000
--- a/django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html b/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html
deleted file mode 100644
index bb60a0e871..0000000000
--- a/django/contrib/databrowse/templates/databrowse/fieldchoice_list.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/homepage.html b/django/contrib/databrowse/templates/databrowse/homepage.html
deleted file mode 100644
index 0f6708f5fd..0000000000
--- a/django/contrib/databrowse/templates/databrowse/homepage.html
+++ /dev/null
@@ -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 &rarr;</a>
- </p>
- </div>
-{% endfor %}
-
-{% endblock %}
diff --git a/django/contrib/databrowse/templates/databrowse/model_detail.html b/django/contrib/databrowse/templates/databrowse/model_detail.html
deleted file mode 100644
index 11c6808f14..0000000000
--- a/django/contrib/databrowse/templates/databrowse/model_detail.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/templates/databrowse/object_detail.html b/django/contrib/databrowse/templates/databrowse/object_detail.html
deleted file mode 100644
index 81c37f7736..0000000000
--- a/django/contrib/databrowse/templates/databrowse/object_detail.html
+++ /dev/null
@@ -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 %}
diff --git a/django/contrib/databrowse/tests.py b/django/contrib/databrowse/tests.py
deleted file mode 100644
index d649b4af67..0000000000
--- a/django/contrib/databrowse/tests.py
+++ /dev/null
@@ -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
- )
diff --git a/django/contrib/databrowse/urls.py b/django/contrib/databrowse/urls.py
deleted file mode 100644
index 5c431deb21..0000000000
--- a/django/contrib/databrowse/urls.py
+++ /dev/null
@@ -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),
-)
diff --git a/django/contrib/databrowse/views.py b/django/contrib/databrowse/views.py
deleted file mode 100644
index 4543e95780..0000000000
--- a/django/contrib/databrowse/views.py
+++ /dev/null
@@ -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})
diff --git a/docs/index.txt b/docs/index.txt
index 971c2ff479..3d1765f399 100644
--- a/docs/index.txt
+++ b/docs/index.txt
@@ -267,7 +267,6 @@ Learn about some other core functionalities of the Django framework:
* :doc:`Conditional content processing <topics/conditional-view-processing>`
* :doc:`Content types and generic relations <ref/contrib/contenttypes>`
-* :doc:`Databrowse <ref/contrib/databrowse>`
* :doc:`Flatpages <ref/contrib/flatpages>`
* :doc:`Redirects <ref/contrib/redirects>`
* :doc:`Signals <topics/signals>`
diff --git a/docs/ref/contrib/databrowse.txt b/docs/ref/contrib/databrowse.txt
deleted file mode 100644
index 3d411bb7b4..0000000000
--- a/docs/ref/contrib/databrowse.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-==========
-Databrowse
-==========
-
-.. module:: django.contrib.databrowse
- :synopsis: Databrowse is a Django application that lets you browse your data.
-
-.. deprecated:: 1.4
- This module has been deprecated.
-
-Databrowse is a Django application that lets you browse your data.
-
-As the Django admin dynamically creates an admin interface by introspecting
-your models, Databrowse dynamically creates a rich, browsable Web site by
-introspecting your models.
-
-How to use Databrowse
-=====================
-
-1. Point Django at the default Databrowse templates. There are two ways to
- do this:
-
- * Add ``'django.contrib.databrowse'`` to your :setting:`INSTALLED_APPS`
- setting. This will work if your :setting:`TEMPLATE_LOADERS` setting
- includes the ``app_directories`` template loader (which is the case by
- default). See the :ref:`template loader docs <template-loaders>` for
- more.
-
- * Otherwise, determine the full filesystem path to the
- :file:`django/contrib/databrowse/templates` directory, and add that
- directory to your :setting:`TEMPLATE_DIRS` setting.
-
-2. Register a number of models with the Databrowse site::
-
- from django.contrib import databrowse
- from myapp.models import SomeModel, SomeOtherModel, YetAnotherModel
-
- databrowse.site.register(SomeModel)
- databrowse.site.register(SomeOtherModel, YetAnotherModel)
-
- Note that you should register the model *classes*, not instances.
-
- .. versionchanged:: 1.4
-
- Since Django 1.4, it is possible to register several models in the same
- call to :func:`~databrowse.site.register`.
-
- It doesn't matter where you put this, as long as it gets executed at some
- point. A good place for it is in your :doc:`URLconf file
- </topics/http/urls>` (``urls.py``).
-
-3. Change your URLconf to import the :mod:`~django.contrib.databrowse` module::
-
- from django.contrib import databrowse
-
- ...and add the following line to your URLconf::
-
- (r'^databrowse/(.*)', databrowse.site.root),
-
- The prefix doesn't matter -- you can use ``databrowse/`` or ``db/`` or
- whatever you'd like.
-
-4. Run the Django server and visit ``/databrowse/`` in your browser.
-
-Requiring user login
-====================
-
-You can restrict access to logged-in users with only a few extra lines of
-code. Simply add the following import to your URLconf::
-
- from django.contrib.auth.decorators import login_required
-
-Then modify the :doc:`URLconf </topics/http/urls>` so that the
-:func:`databrowse.site.root` view is decorated with
-:func:`django.contrib.auth.decorators.login_required`::
-
- (r'^databrowse/(.*)', login_required(databrowse.site.root)),
-
-If you haven't already added support for user logins to your :doc:`URLconf
-</topics/http/urls>`, as described in the :doc:`user authentication docs
-</ref/contrib/auth>`, then you will need to do so now with the following
-mapping::
-
- (r'^accounts/login/$', 'django.contrib.auth.views.login'),
-
-The final step is to create the login form required by
-:func:`django.contrib.auth.views.login`. The
-:doc:`user authentication docs </ref/contrib/auth>` provide full details and a
-sample template that can be used for this purpose.
diff --git a/docs/ref/contrib/index.txt b/docs/ref/contrib/index.txt
index 3bf5288ee4..d014cf36a3 100644
--- a/docs/ref/contrib/index.txt
+++ b/docs/ref/contrib/index.txt
@@ -27,7 +27,6 @@ those packages have.
comments/index
contenttypes
csrf
- databrowse
flatpages
formtools/index
gis/index
diff --git a/tests/runtests.py b/tests/runtests.py
index 8c56e273b5..c23737ed14 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -10,10 +10,6 @@ from django import contrib
from django.utils._os import upath
from django.utils import six
-# databrowse is deprecated, but we still want to run its tests
-warnings.filterwarnings('ignore', "The Databrowse contrib app is deprecated",
- DeprecationWarning, 'django.contrib.databrowse')
-
CONTRIB_DIR_NAME = 'django.contrib'
MODEL_TESTS_DIR_NAME = 'modeltests'
REGRESSION_TESTS_DIR_NAME = 'regressiontests'
@@ -40,7 +36,6 @@ ALWAYS_INSTALLED_APPS = [
'django.contrib.comments',
'django.contrib.admin',
'django.contrib.admindocs',
- 'django.contrib.databrowse',
'django.contrib.staticfiles',
'django.contrib.humanize',
'regressiontests.staticfiles_tests',