From 052271168bc8f46c64451340d39682d5efdef9b6 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Mon, 24 Dec 2012 22:46:34 +0100 Subject: [PATCH] Removed django.contrib.databrowse. RIP -- you served us well. --- MANIFEST.in | 1 - django/contrib/databrowse/__init__.py | 5 - django/contrib/databrowse/datastructures.py | 214 ------------------ django/contrib/databrowse/models.py | 1 - django/contrib/databrowse/plugins/__init__.py | 0 .../contrib/databrowse/plugins/calendars.py | 147 ------------ .../databrowse/plugins/fieldchoices.py | 77 ------- django/contrib/databrowse/plugins/objects.py | 18 -- django/contrib/databrowse/sites.py | 147 ------------ .../databrowse/templates/databrowse/base.html | 61 ----- .../templates/databrowse/base_site.html | 1 - .../templates/databrowse/calendar_day.html | 17 -- .../databrowse/calendar_homepage.html | 17 -- .../templates/databrowse/calendar_main.html | 17 -- .../templates/databrowse/calendar_month.html | 17 -- .../templates/databrowse/calendar_year.html | 17 -- .../templates/databrowse/choice_detail.html | 17 -- .../templates/databrowse/choice_list.html | 17 -- .../databrowse/fieldchoice_detail.html | 17 -- .../databrowse/fieldchoice_homepage.html | 17 -- .../databrowse/fieldchoice_list.html | 17 -- .../templates/databrowse/homepage.html | 21 -- .../templates/databrowse/model_detail.html | 19 -- .../templates/databrowse/object_detail.html | 41 ---- django/contrib/databrowse/tests.py | 62 ----- django/contrib/databrowse/urls.py | 20 -- django/contrib/databrowse/views.py | 19 -- docs/index.txt | 1 - docs/ref/contrib/databrowse.txt | 89 -------- docs/ref/contrib/index.txt | 1 - tests/runtests.py | 5 - 31 files changed, 1120 deletions(-) delete mode 100644 django/contrib/databrowse/__init__.py delete mode 100644 django/contrib/databrowse/datastructures.py delete mode 100644 django/contrib/databrowse/models.py delete mode 100644 django/contrib/databrowse/plugins/__init__.py delete mode 100644 django/contrib/databrowse/plugins/calendars.py delete mode 100644 django/contrib/databrowse/plugins/fieldchoices.py delete mode 100644 django/contrib/databrowse/plugins/objects.py delete mode 100644 django/contrib/databrowse/sites.py delete mode 100644 django/contrib/databrowse/templates/databrowse/base.html delete mode 100644 django/contrib/databrowse/templates/databrowse/base_site.html delete mode 100644 django/contrib/databrowse/templates/databrowse/calendar_day.html delete mode 100644 django/contrib/databrowse/templates/databrowse/calendar_homepage.html delete mode 100644 django/contrib/databrowse/templates/databrowse/calendar_main.html delete mode 100644 django/contrib/databrowse/templates/databrowse/calendar_month.html delete mode 100644 django/contrib/databrowse/templates/databrowse/calendar_year.html delete mode 100644 django/contrib/databrowse/templates/databrowse/choice_detail.html delete mode 100644 django/contrib/databrowse/templates/databrowse/choice_list.html delete mode 100644 django/contrib/databrowse/templates/databrowse/fieldchoice_detail.html delete mode 100644 django/contrib/databrowse/templates/databrowse/fieldchoice_homepage.html delete mode 100644 django/contrib/databrowse/templates/databrowse/fieldchoice_list.html delete mode 100644 django/contrib/databrowse/templates/databrowse/homepage.html delete mode 100644 django/contrib/databrowse/templates/databrowse/model_detail.html delete mode 100644 django/contrib/databrowse/templates/databrowse/object_detail.html delete mode 100644 django/contrib/databrowse/tests.py delete mode 100644 django/contrib/databrowse/urls.py delete mode 100644 django/contrib/databrowse/views.py delete mode 100644 docs/ref/contrib/databrowse.txt diff --git a/MANIFEST.in b/MANIFEST.in index fbda541d22c..0e0aba12680 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 acb7626c8db..00000000000 --- 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 5f5f46f0d1b..00000000000 --- 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('' % 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('' % (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('' % (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('' % (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('' % (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 2e283e09953..00000000000 --- 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 e69de29bb2d..00000000000 diff --git a/django/contrib/databrowse/plugins/calendars.py b/django/contrib/databrowse/plugins/calendars.py deleted file mode 100644 index a548c33c8fb..00000000000 --- 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('

View calendar by: {0}

', - format_html_join(', ', '{1}', - ((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 dc5e9aef14b..00000000000 --- 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('

View by: {0}

', - format_html_join(', ', '{1}', - ((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 e956f4ea677..00000000000 --- 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 b5cb2639d63..00000000000 --- 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 56464e06148..00000000000 --- a/django/contrib/databrowse/templates/databrowse/base.html +++ /dev/null @@ -1,61 +0,0 @@ - - - -{% block title %}{% endblock %} -{% block style %} - -{% endblock %} -{% block extrahead %}{% endblock %} - - - -
-{% block content %}{% endblock %} -
- - 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 b577ab84272..00000000000 --- 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 c009a94c66b..00000000000 --- 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 %} - - - -

{{ 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" }}

- -
    -{% for object in object_list %} -
  • {{ object }}
  • -{% endfor %} -
- -{% 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 85eb8af9eb0..00000000000 --- 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 %} - - - -

Calendars

- - - -{% 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 7cb59042df8..00000000000 --- 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 %} - - - -

{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}

- - - -{% 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 ad189f441c9..00000000000 --- 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 %} - - - -

{{ 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" }}

- -
    -{% for object in object_list %} -
  • {{ object }}
  • -{% endfor %} -
- -{% 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 a6e6f53ba3f..00000000000 --- 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 %} - - - -

{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}

- - - -{% 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 0abc5365154..00000000000 --- 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 %} - - - -

{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value }}

- -
    -{% for object in object_list %} -
  • {{ object }}
  • -{% endfor %} -
- -{% 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 58675e82bf7..00000000000 --- 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 %} - - - -

{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}

- - - -{% 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 2dd55d48ac6..00000000000 --- 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 %} - - - -

{{ object_list.count }} {% if object_list.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %} with {{ field.field.verbose_name }} {{ value }}

- -
    -{% for object in object_list %} -
  • {{ object }}
  • -{% endfor %} -
- -{% 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 b82c22d5b40..00000000000 --- 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 %} - - - -

Browsable fields in {{ model.verbose_name_plural }}

- - - -{% 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 bb60a0e8717..00000000000 --- 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 %} - - - -

{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}

- -
    -{% for object in object_list %} -
  • {{ object }}
  • -{% endfor %} -
- -{% endblock %} diff --git a/django/contrib/databrowse/templates/databrowse/homepage.html b/django/contrib/databrowse/templates/databrowse/homepage.html deleted file mode 100644 index 0f6708f5fde..00000000000 --- 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 %} -
-

{{ model.verbose_name_plural|capfirst }}

-

- {% for object in model.sample_objects %} - {{ object }}, - {% endfor %} - More → -

-
-{% 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 11c6808f149..00000000000 --- 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 %} - - - -

{{ model.objects.count }} {% if model.objects.count|pluralize %}{{ model.verbose_name_plural }}{% else %}{{ model.verbose_name }}{% endif %}

- -{{ plugin_html }} - -
    -{% for object in model.objects %} -
  • {{ object }}
  • -{% endfor %} -
- -{% 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 81c37f7736e..00000000000 --- 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 %} - - - -

{{ object.model.verbose_name|capfirst }}: {{ object }}

- - -{% for field in object.fields %} - - - - -{% endfor %} -
{{ field.field.verbose_name|capfirst }} -{% if field.urls %} -{% for value, url in field.urls %} -{% if url %}{% endif %}{{ value }}{% if url %}{% endif %}{% if not forloop.last %}, {% endif %} -{% endfor %} -{% else %}None{% endif %} -
- -{% for related_object in object.related_objects %} - -{% endfor %} - -{% endblock %} diff --git a/django/contrib/databrowse/tests.py b/django/contrib/databrowse/tests.py deleted file mode 100644 index d649b4af679..00000000000 --- 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 5c431deb210..00000000000 --- 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 4543e95780b..00000000000 --- 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 971c2ff4797..3d1765f3993 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 ` * :doc:`Content types and generic relations ` -* :doc:`Databrowse ` * :doc:`Flatpages ` * :doc:`Redirects ` * :doc:`Signals ` diff --git a/docs/ref/contrib/databrowse.txt b/docs/ref/contrib/databrowse.txt deleted file mode 100644 index 3d411bb7b4d..00000000000 --- 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 ` 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 - ` (``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 ` 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 -`, as described in the :doc:`user authentication docs -`, 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 ` 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 3bf5288ee4f..d014cf36a35 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 8c56e273b57..c23737ed140 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',