Refs #27656 -- Updated django.views docstring verbs according to PEP 257.

This commit is contained in:
Anton Samarchyan 2017-01-24 15:36:07 -05:00 committed by Tim Graham
parent b23d264046
commit 711123e1cd
11 changed files with 164 additions and 343 deletions

View File

@ -24,10 +24,11 @@ CLEANSED_SUBSTITUTE = '********************'
class CallableSettingWrapper: class CallableSettingWrapper:
""" Object to wrap callable appearing in settings """
Object to wrap callable appearing in settings.
* Not to call in the debug page (#21345). * Not to call in the debug page (#21345).
* Not to break the debug page if the callable forbidding to set attributes (#23070). * Not to break the debug page if the callable forbidding to set attributes
(#23070).
""" """
def __init__(self, callable_setting): def __init__(self, callable_setting):
self._wrapped = callable_setting self._wrapped = callable_setting
@ -37,10 +38,9 @@ class CallableSettingWrapper:
def cleanse_setting(key, value): def cleanse_setting(key, value):
"""Cleanse an individual setting key/value of sensitive content. """
Cleanse an individual setting key/value of sensitive content. If the value
If the value is a dictionary, recursively cleanse the keys in is a dictionary, recursively cleanse the keys in that dictionary.
that dictionary.
""" """
try: try:
if HIDDEN_SETTINGS.search(key): if HIDDEN_SETTINGS.search(key):
@ -62,7 +62,10 @@ def cleanse_setting(key, value):
def get_safe_settings(): def get_safe_settings():
"Returns a dictionary of the settings module, with sensitive settings blurred out." """
Return a dictionary of the settings module with values of sensitive
settings replaced with stars (*********).
"""
settings_dict = {} settings_dict = {}
for k in dir(settings): for k in dir(settings):
if k.isupper(): if k.isupper():
@ -128,7 +131,7 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter):
def get_cleansed_multivaluedict(self, request, multivaluedict): def get_cleansed_multivaluedict(self, request, multivaluedict):
""" """
Replaces the keys in a MultiValueDict marked as sensitive with stars. Replace the keys in a MultiValueDict marked as sensitive with stars.
This mitigates leaking sensitive POST parameters if something like This mitigates leaking sensitive POST parameters if something like
request.POST['nonexistent_key'] throws an exception (#21098). request.POST['nonexistent_key'] throws an exception (#21098).
""" """
@ -142,7 +145,7 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter):
def get_post_parameters(self, request): def get_post_parameters(self, request):
""" """
Replaces the values of POST parameters marked as sensitive with Replace the values of POST parameters marked as sensitive with
stars (*********). stars (*********).
""" """
if request is None: if request is None:
@ -181,7 +184,7 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter):
def get_traceback_frame_variables(self, request, tb_frame): def get_traceback_frame_variables(self, request, tb_frame):
""" """
Replaces the values of variables marked as sensitive with Replace the values of variables marked as sensitive with
stars (*********). stars (*********).
""" """
# Loop through the frame's callers to see if the sensitive_variables # Loop through the frame's callers to see if the sensitive_variables
@ -231,9 +234,7 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter):
class ExceptionReporter: class ExceptionReporter:
""" """Organize and coordinate reporting on exceptions."""
A class to organize and coordinate reporting on exceptions.
"""
def __init__(self, request, exc_type, exc_value, tb, is_email=False): def __init__(self, request, exc_type, exc_value, tb, is_email=False):
self.request = request self.request = request
self.filter = get_exception_reporter_filter(self.request) self.filter = get_exception_reporter_filter(self.request)
@ -318,21 +319,21 @@ class ExceptionReporter:
return c return c
def get_traceback_html(self): def get_traceback_html(self):
"Return HTML version of debug 500 HTTP error page." """Return HTML version of debug 500 HTTP error page."""
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE) t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE)
c = Context(self.get_traceback_data(), use_l10n=False) c = Context(self.get_traceback_data(), use_l10n=False)
return t.render(c) return t.render(c)
def get_traceback_text(self): def get_traceback_text(self):
"Return plain text version of debug 500 HTTP error page." """Return plain text version of debug 500 HTTP error page."""
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE) t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE)
c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False) c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
return t.render(c) return t.render(c)
def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None): def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None):
""" """
Returns context_lines before and after lineno from file. Return context_lines before and after lineno from file.
Returns (pre_context_lineno, pre_context, context_line, post_context). Return (pre_context_lineno, pre_context, context_line, post_context).
""" """
source = None source = None
if loader is not None and hasattr(loader, "get_source"): if loader is not None and hasattr(loader, "get_source"):
@ -439,7 +440,7 @@ class ExceptionReporter:
def technical_404_response(request, exception): def technical_404_response(request, exception):
"Create a technical 404 error response. The exception should be the Http404." """Create a technical 404 error response. `exception` is the Http404."""
try: try:
error_url = exception.args[0]['path'] error_url = exception.args[0]['path']
except (IndexError, TypeError, KeyError): except (IndexError, TypeError, KeyError):
@ -494,7 +495,7 @@ def technical_404_response(request, exception):
def default_urlconf(request): def default_urlconf(request):
"Create an empty URLconf 404 error response." """Create an empty URLconf 404 error response."""
t = DEBUG_ENGINE.from_string(DEFAULT_URLCONF_TEMPLATE) t = DEBUG_ENGINE.from_string(DEFAULT_URLCONF_TEMPLATE)
c = Context({ c = Context({
"title": _("Welcome to Django"), "title": _("Welcome to Django"),

View File

@ -37,8 +37,7 @@ def cache_control(**kwargs):
def never_cache(view_func): def never_cache(view_func):
""" """
Decorator that adds headers to a response so that it will Decorator that adds headers to a response so that it will never be cached.
never be cached.
""" """
@wraps(view_func) @wraps(view_func)
def _wrapped_view_func(request, *args, **kwargs): def _wrapped_view_func(request, *args, **kwargs):

View File

@ -3,11 +3,9 @@ from functools import wraps
def xframe_options_deny(view_func): def xframe_options_deny(view_func):
""" """
Modifies a view function so its response has the X-Frame-Options HTTP Modify a view function so its response has the X-Frame-Options HTTP
header set to 'DENY' as long as the response doesn't already have that header set to 'DENY' as long as the response doesn't already have that
header set. header set. Usage:
e.g.
@xframe_options_deny @xframe_options_deny
def some_view(request): def some_view(request):
@ -23,11 +21,9 @@ def xframe_options_deny(view_func):
def xframe_options_sameorigin(view_func): def xframe_options_sameorigin(view_func):
""" """
Modifies a view function so its response has the X-Frame-Options HTTP Modify a view function so its response has the X-Frame-Options HTTP
header set to 'SAMEORIGIN' as long as the response doesn't already have header set to 'SAMEORIGIN' as long as the response doesn't already have
that header set. that header set. Usage:
e.g.
@xframe_options_sameorigin @xframe_options_sameorigin
def some_view(request): def some_view(request):
@ -43,10 +39,8 @@ def xframe_options_sameorigin(view_func):
def xframe_options_exempt(view_func): def xframe_options_exempt(view_func):
""" """
Modifies a view function by setting a response variable that instructs Modify a view function by setting a response variable that instructs
XFrameOptionsMiddleware to NOT set the X-Frame-Options HTTP header. XFrameOptionsMiddleware to NOT set the X-Frame-Options HTTP header. Usage:
e.g.
@xframe_options_exempt @xframe_options_exempt
def some_view(request): def some_view(request):

View File

@ -13,8 +13,7 @@ using the decorator multiple times, is harmless and efficient.
class _EnsureCsrfToken(CsrfViewMiddleware): class _EnsureCsrfToken(CsrfViewMiddleware):
# We need this to behave just like the CsrfViewMiddleware, but not reject # Behave like CsrfViewMiddleware but don't reject requests or log warnings.
# requests or log warnings.
def _reject(self, request, reason): def _reject(self, request, reason):
return None return None
@ -34,7 +33,7 @@ class _EnsureCsrfCookie(CsrfViewMiddleware):
def process_view(self, request, callback, callback_args, callback_kwargs): def process_view(self, request, callback, callback_args, callback_kwargs):
retval = super().process_view(request, callback, callback_args, callback_kwargs) retval = super().process_view(request, callback, callback_args, callback_kwargs)
# Forces process_response to send the cookie # Force process_response to send the cookie
get_token(request) get_token(request)
return retval return retval
@ -48,12 +47,9 @@ uses the csrf_token template tag, or the CsrfViewMiddleware is used.
def csrf_exempt(view_func): def csrf_exempt(view_func):
""" """Mark a view function as being exempt from the CSRF view protection."""
Marks a view function as being exempt from the CSRF view protection. # view_func.csrf_exempt = True would also work, but decorators are nicer
""" # if they don't have side effects, so return a new function.
# We could just do view_func.csrf_exempt = True, but decorators
# are nicer if they don't have side-effects, so we return a new
# function.
def wrapped_view(*args, **kwargs): def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs) return view_func(*args, **kwargs)
wrapped_view.csrf_exempt = True wrapped_view.csrf_exempt = True

View File

@ -5,11 +5,11 @@ from django.http import HttpRequest
def sensitive_variables(*variables): def sensitive_variables(*variables):
""" """
Indicates which variables used in the decorated function are sensitive, so Indicate which variables used in the decorated function are sensitive so
that those variables can later be treated in a special way, for example that those variables can later be treated in a special way, for example
by hiding them when logging unhandled exceptions. by hiding them when logging unhandled exceptions.
Two forms are accepted: Accept two forms:
* with specified variable names: * with specified variable names:
@ -19,8 +19,8 @@ def sensitive_variables(*variables):
credit_card = user.credit_card_number credit_card = user.credit_card_number
... ...
* without any specified variable names, in which case it is assumed that * without any specified variable names, in which case consider all
all variables are considered sensitive: variables are sensitive:
@sensitive_variables() @sensitive_variables()
def my_function() def my_function()
@ -40,11 +40,11 @@ def sensitive_variables(*variables):
def sensitive_post_parameters(*parameters): def sensitive_post_parameters(*parameters):
""" """
Indicates which POST parameters used in the decorated view are sensitive, Indicate which POST parameters used in the decorated view are sensitive,
so that those parameters can later be treated in a special way, for example so that those parameters can later be treated in a special way, for example
by hiding them when logging unhandled exceptions. by hiding them when logging unhandled exceptions.
Two forms are accepted: Accept two forms:
* with specified parameters: * with specified parameters:
@ -54,8 +54,8 @@ def sensitive_post_parameters(*parameters):
cc = request.POST['credit_card'] cc = request.POST['credit_card']
... ...
* without any specified parameters, in which case it is assumed that * without any specified parameters, in which case consider all
all parameters are considered sensitive: variables are sensitive:
@sensitive_post_parameters() @sensitive_post_parameters()
def my_view(request) def my_view(request)

View File

@ -16,7 +16,7 @@ logger = logging.getLogger('django.request')
class ContextMixin: class ContextMixin:
""" """
A default context mixin that passes the keyword arguments received by A default context mixin that passes the keyword arguments received by
get_context_data as the template context. get_context_data() as the template context.
""" """
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -45,9 +45,7 @@ class View:
@classonlymethod @classonlymethod
def as_view(cls, **initkwargs): def as_view(cls, **initkwargs):
""" """Main entry point for a request-response process."""
Main entry point for a request-response process.
"""
for key in initkwargs: for key in initkwargs:
if key in cls.http_method_names: if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a " raise TypeError("You tried to pass in the %s method name as a "
@ -95,9 +93,7 @@ class View:
return HttpResponseNotAllowed(self._allowed_methods()) return HttpResponseNotAllowed(self._allowed_methods())
def options(self, request, *args, **kwargs): def options(self, request, *args, **kwargs):
""" """Handle responding to requests for the OPTIONS HTTP verb."""
Handles responding to requests for the OPTIONS HTTP verb.
"""
response = HttpResponse() response = HttpResponse()
response['Allow'] = ', '.join(self._allowed_methods()) response['Allow'] = ', '.join(self._allowed_methods())
response['Content-Length'] = '0' response['Content-Length'] = '0'
@ -108,9 +104,7 @@ class View:
class TemplateResponseMixin: class TemplateResponseMixin:
""" """A mixin that can be used to render a template."""
A mixin that can be used to render a template.
"""
template_name = None template_name = None
template_engine = None template_engine = None
response_class = TemplateResponse response_class = TemplateResponse
@ -118,11 +112,10 @@ class TemplateResponseMixin:
def render_to_response(self, context, **response_kwargs): def render_to_response(self, context, **response_kwargs):
""" """
Returns a response, using the `response_class` for this Return a response, using the `response_class` for this view, with a
view, with a template rendered with the given context. template rendered with the given context.
If any keyword arguments are provided, they will be Pass response_kwargs to the constructor of the response class.
passed to the constructor of the response class.
""" """
response_kwargs.setdefault('content_type', self.content_type) response_kwargs.setdefault('content_type', self.content_type)
return self.response_class( return self.response_class(
@ -135,8 +128,8 @@ class TemplateResponseMixin:
def get_template_names(self): def get_template_names(self):
""" """
Returns a list of template names to be used for the request. Must return Return a list of template names to be used for the request. Must return
a list. May not be called if render_to_response is overridden. a list. May not be called if render_to_response() is overridden.
""" """
if self.template_name is None: if self.template_name is None:
raise ImproperlyConfigured( raise ImproperlyConfigured(
@ -148,8 +141,7 @@ class TemplateResponseMixin:
class TemplateView(TemplateResponseMixin, ContextMixin, View): class TemplateView(TemplateResponseMixin, ContextMixin, View):
""" """
A view that renders a template. This view will also pass into the context Render a template. Pass keyword arguments from the URLconf to the context.
any keyword arguments passed by the URLconf.
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs) context = self.get_context_data(**kwargs)
@ -157,9 +149,7 @@ class TemplateView(TemplateResponseMixin, ContextMixin, View):
class RedirectView(View): class RedirectView(View):
""" """Provide a redirect on any GET request."""
A view that provides a redirect on any GET request.
"""
permanent = False permanent = False
url = None url = None
pattern_name = None pattern_name = None
@ -167,9 +157,9 @@ class RedirectView(View):
def get_redirect_url(self, *args, **kwargs): def get_redirect_url(self, *args, **kwargs):
""" """
Return the URL redirect to. Keyword arguments from the Return the URL redirect to. Keyword arguments from the URL pattern
URL pattern match generating the redirect request match generating the redirect request are provided as kwargs to this
are provided as kwargs to this method. method.
""" """
if self.url: if self.url:
url = self.url % kwargs url = self.url % kwargs

View File

@ -18,9 +18,7 @@ from django.views.generic.list import (
class YearMixin: class YearMixin:
""" """Mixin for views manipulating year-based data."""
Mixin for views manipulating year-based data.
"""
year_format = '%Y' year_format = '%Y'
year = None year = None
@ -32,9 +30,7 @@ class YearMixin:
return self.year_format return self.year_format
def get_year(self): def get_year(self):
""" """Return the year for which this view should display data."""
Return the year for which this view should display data.
"""
year = self.year year = self.year
if year is None: if year is None:
try: try:
@ -47,15 +43,11 @@ class YearMixin:
return year return year
def get_next_year(self, date): def get_next_year(self, date):
""" """Get the next valid year."""
Get the next valid year.
"""
return _get_next_prev(self, date, is_previous=False, period='year') return _get_next_prev(self, date, is_previous=False, period='year')
def get_previous_year(self, date): def get_previous_year(self, date):
""" """Get the previous valid year."""
Get the previous valid year.
"""
return _get_next_prev(self, date, is_previous=True, period='year') return _get_next_prev(self, date, is_previous=True, period='year')
def _get_next_year(self, date): def _get_next_year(self, date):
@ -67,16 +59,12 @@ class YearMixin:
return date.replace(year=date.year + 1, month=1, day=1) return date.replace(year=date.year + 1, month=1, day=1)
def _get_current_year(self, date): def _get_current_year(self, date):
""" """Return the start date of the current interval."""
Return the start date of the current interval.
"""
return date.replace(month=1, day=1) return date.replace(month=1, day=1)
class MonthMixin: class MonthMixin:
""" """Mixin for views manipulating month-based data."""
Mixin for views manipulating month-based data.
"""
month_format = '%b' month_format = '%b'
month = None month = None
@ -88,9 +76,7 @@ class MonthMixin:
return self.month_format return self.month_format
def get_month(self): def get_month(self):
""" """Return the month for which this view should display data."""
Return the month for which this view should display data.
"""
month = self.month month = self.month
if month is None: if month is None:
try: try:
@ -103,15 +89,11 @@ class MonthMixin:
return month return month
def get_next_month(self, date): def get_next_month(self, date):
""" """Get the next valid month."""
Get the next valid month.
"""
return _get_next_prev(self, date, is_previous=False, period='month') return _get_next_prev(self, date, is_previous=False, period='month')
def get_previous_month(self, date): def get_previous_month(self, date):
""" """Get the previous valid month."""
Get the previous valid month.
"""
return _get_next_prev(self, date, is_previous=True, period='month') return _get_next_prev(self, date, is_previous=True, period='month')
def _get_next_month(self, date): def _get_next_month(self, date):
@ -126,16 +108,12 @@ class MonthMixin:
return date.replace(month=date.month + 1, day=1) return date.replace(month=date.month + 1, day=1)
def _get_current_month(self, date): def _get_current_month(self, date):
""" """Return the start date of the previous interval."""
Return the start date of the previous interval.
"""
return date.replace(day=1) return date.replace(day=1)
class DayMixin: class DayMixin:
""" """Mixin for views manipulating day-based data."""
Mixin for views manipulating day-based data.
"""
day_format = '%d' day_format = '%d'
day = None day = None
@ -147,9 +125,7 @@ class DayMixin:
return self.day_format return self.day_format
def get_day(self): def get_day(self):
""" """Return the day for which this view should display data."""
Return the day for which this view should display data.
"""
day = self.day day = self.day
if day is None: if day is None:
try: try:
@ -162,15 +138,11 @@ class DayMixin:
return day return day
def get_next_day(self, date): def get_next_day(self, date):
""" """Get the next valid day."""
Get the next valid day.
"""
return _get_next_prev(self, date, is_previous=False, period='day') return _get_next_prev(self, date, is_previous=False, period='day')
def get_previous_day(self, date): def get_previous_day(self, date):
""" """Get the previous valid day."""
Get the previous valid day.
"""
return _get_next_prev(self, date, is_previous=True, period='day') return _get_next_prev(self, date, is_previous=True, period='day')
def _get_next_day(self, date): def _get_next_day(self, date):
@ -182,16 +154,12 @@ class DayMixin:
return date + datetime.timedelta(days=1) return date + datetime.timedelta(days=1)
def _get_current_day(self, date): def _get_current_day(self, date):
""" """Return the start date of the current interval."""
Return the start date of the current interval.
"""
return date return date
class WeekMixin: class WeekMixin:
""" """Mixin for views manipulating week-based data."""
Mixin for views manipulating week-based data.
"""
week_format = '%U' week_format = '%U'
week = None week = None
@ -203,9 +171,7 @@ class WeekMixin:
return self.week_format return self.week_format
def get_week(self): def get_week(self):
""" """Return the week for which this view should display data."""
Return the week for which this view should display data
"""
week = self.week week = self.week
if week is None: if week is None:
try: try:
@ -218,15 +184,11 @@ class WeekMixin:
return week return week
def get_next_week(self, date): def get_next_week(self, date):
""" """Get the next valid week."""
Get the next valid week.
"""
return _get_next_prev(self, date, is_previous=False, period='week') return _get_next_prev(self, date, is_previous=False, period='week')
def get_previous_week(self, date): def get_previous_week(self, date):
""" """Get the previous valid week."""
Get the previous valid week.
"""
return _get_next_prev(self, date, is_previous=True, period='week') return _get_next_prev(self, date, is_previous=True, period='week')
def _get_next_week(self, date): def _get_next_week(self, date):
@ -238,9 +200,7 @@ class WeekMixin:
return date + datetime.timedelta(days=7 - self._get_weekday(date)) return date + datetime.timedelta(days=7 - self._get_weekday(date))
def _get_current_week(self, date): def _get_current_week(self, date):
""" """Return the start date of the current interval."""
Return the start date of the current interval.
"""
return date - datetime.timedelta(self._get_weekday(date)) return date - datetime.timedelta(self._get_weekday(date))
def _get_weekday(self, date): def _get_weekday(self, date):
@ -259,23 +219,19 @@ class WeekMixin:
class DateMixin: class DateMixin:
""" """Mixin class for views manipulating date-based data."""
Mixin class for views manipulating date-based data.
"""
date_field = None date_field = None
allow_future = False allow_future = False
def get_date_field(self): def get_date_field(self):
""" """Get the name of the date field to be used to filter by."""
Get the name of the date field to be used to filter by.
"""
if self.date_field is None: if self.date_field is None:
raise ImproperlyConfigured("%s.date_field is required." % self.__class__.__name__) raise ImproperlyConfigured("%s.date_field is required." % self.__class__.__name__)
return self.date_field return self.date_field
def get_allow_future(self): def get_allow_future(self):
""" """
Returns `True` if the view should be allowed to display objects from Return `True` if the view should be allowed to display objects from
the future. the future.
""" """
return self.allow_future return self.allow_future
@ -327,9 +283,7 @@ class DateMixin:
class BaseDateListView(MultipleObjectMixin, DateMixin, View): class BaseDateListView(MultipleObjectMixin, DateMixin, View):
""" """Abstract base class for date-based views displaying a list of objects."""
Abstract base class for date-based views displaying a list of objects.
"""
allow_empty = False allow_empty = False
date_list_period = 'year' date_list_period = 'year'
@ -341,14 +295,12 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View):
return self.render_to_response(context) return self.render_to_response(context)
def get_dated_items(self): def get_dated_items(self):
""" """Obtain the list of dates and items."""
Obtain the list of dates and items.
"""
raise NotImplementedError('A DateView must provide an implementation of get_dated_items()') raise NotImplementedError('A DateView must provide an implementation of get_dated_items()')
def get_ordering(self): def get_ordering(self):
""" """
Returns the field or fields to use for ordering the queryset; uses the Return the field or fields to use for ordering the queryset; use the
date field by default. date field by default.
""" """
return '-%s' % self.get_date_field() if self.ordering is None else self.ordering return '-%s' % self.get_date_field() if self.ordering is None else self.ordering
@ -381,7 +333,8 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View):
def get_date_list_period(self): def get_date_list_period(self):
""" """
Get the aggregation period for the list of dates: 'year', 'month', or 'day'. Get the aggregation period for the list of dates: 'year', 'month', or
'day'.
""" """
return self.date_list_period return self.date_list_period
@ -409,16 +362,12 @@ class BaseDateListView(MultipleObjectMixin, DateMixin, View):
class BaseArchiveIndexView(BaseDateListView): class BaseArchiveIndexView(BaseDateListView):
""" """
Base class for archives of date-based items. Base class for archives of date-based items. Requires a response mixin.
Requires a response mixin.
""" """
context_object_name = 'latest' context_object_name = 'latest'
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
qs = self.get_dated_queryset() qs = self.get_dated_queryset()
date_list = self.get_date_list(qs, ordering='DESC') date_list = self.get_date_list(qs, ordering='DESC')
@ -429,23 +378,17 @@ class BaseArchiveIndexView(BaseDateListView):
class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView): class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
""" """Top-level archive of date-based items."""
Top-level archive of date-based items.
"""
template_name_suffix = '_archive' template_name_suffix = '_archive'
class BaseYearArchiveView(YearMixin, BaseDateListView): class BaseYearArchiveView(YearMixin, BaseDateListView):
""" """List of objects published in a given year."""
List of objects published in a given year.
"""
date_list_period = 'month' date_list_period = 'month'
make_object_list = False make_object_list = False
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year() year = self.get_year()
date_field = self.get_date_field() date_field = self.get_date_field()
@ -481,22 +424,16 @@ class BaseYearArchiveView(YearMixin, BaseDateListView):
class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView): class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView):
""" """List of objects published in a given year."""
List of objects published in a given year.
"""
template_name_suffix = '_archive_year' template_name_suffix = '_archive_year'
class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView): class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView):
""" """List of objects published in a given month."""
List of objects published in a given month.
"""
date_list_period = 'day' date_list_period = 'day'
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year() year = self.get_year()
month = self.get_month() month = self.get_month()
@ -522,21 +459,15 @@ class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView):
class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView): class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView):
""" """List of objects published in a given month."""
List of objects published in a given month.
"""
template_name_suffix = '_archive_month' template_name_suffix = '_archive_month'
class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView): class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
""" """List of objects published in a given week."""
List of objects published in a given week.
"""
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year() year = self.get_year()
week = self.get_week() week = self.get_week()
@ -567,20 +498,14 @@ class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView): class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
""" """List of objects published in a given week."""
List of objects published in a given week.
"""
template_name_suffix = '_archive_week' template_name_suffix = '_archive_week'
class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView): class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
""" """List of objects published on a given day."""
List of objects published on a given day.
"""
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
year = self.get_year() year = self.get_year()
month = self.get_month() month = self.get_month()
day = self.get_day() day = self.get_day()
@ -609,28 +534,20 @@ class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView): class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView):
""" """List of objects published on a given day."""
List of objects published on a given day.
"""
template_name_suffix = "_archive_day" template_name_suffix = "_archive_day"
class BaseTodayArchiveView(BaseDayArchiveView): class BaseTodayArchiveView(BaseDayArchiveView):
""" """List of objects published today."""
List of objects published today.
"""
def get_dated_items(self): def get_dated_items(self):
""" """Return (date_list, items, extra_context) for this request."""
Return (date_list, items, extra_context) for this request.
"""
return self._get_dated_items(datetime.date.today()) return self._get_dated_items(datetime.date.today())
class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView): class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView):
""" """List of objects published today."""
List of objects published today.
"""
template_name_suffix = "_archive_day" template_name_suffix = "_archive_day"
@ -640,9 +557,7 @@ class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailV
standard DetailView by accepting a year/month/day in the URL. standard DetailView by accepting a year/month/day in the URL.
""" """
def get_object(self, queryset=None): def get_object(self, queryset=None):
""" """Get the object this request displays."""
Get the object this request displays.
"""
year = self.get_year() year = self.get_year()
month = self.get_month() month = self.get_month()
day = self.get_day() day = self.get_day()
@ -681,8 +596,8 @@ class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView):
def _date_from_string(year, year_format, month='', month_format='', day='', day_format='', delim='__'): def _date_from_string(year, year_format, month='', month_format='', day='', day_format='', delim='__'):
""" """
Helper: get a datetime.date object given a format string and a year, Get a datetime.date object given a format string and a year, month, and day
month, and day (only year is mandatory). Raise a 404 for an invalid date. (only year is mandatory). Raise a 404 for an invalid date.
""" """
format = delim.join((year_format, month_format, day_format)) format = delim.join((year_format, month_format, day_format))
datestr = delim.join((year, month, day)) datestr = delim.join((year, month, day))
@ -697,9 +612,9 @@ def _date_from_string(year, year_format, month='', month_format='', day='', day_
def _get_next_prev(generic_view, date, is_previous, period): def _get_next_prev(generic_view, date, is_previous, period):
""" """
Helper: Get the next or the previous valid date. The idea is to allow Get the next or the previous valid date. The idea is to allow links on
links on month/day views to never be 404s by never providing a date month/day views to never be 404s by never providing a date that'll be
that'll be invalid for the given view. invalid for the given view.
This is a bit complicated since it handles different intervals of time, This is a bit complicated since it handles different intervals of time,
hence the coupling to generic_view. hence the coupling to generic_view.
@ -786,9 +701,7 @@ def _get_next_prev(generic_view, date, is_previous, period):
def timezone_today(): def timezone_today():
""" """Return the current date in the current time zone."""
Return the current date in the current time zone.
"""
if settings.USE_TZ: if settings.USE_TZ:
return timezone.localdate() return timezone.localdate()
else: else:

View File

@ -7,7 +7,7 @@ from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
class SingleObjectMixin(ContextMixin): class SingleObjectMixin(ContextMixin):
""" """
Provides the ability to retrieve a single object for further manipulation. Provide the ability to retrieve a single object for further manipulation.
""" """
model = None model = None
queryset = None queryset = None
@ -19,10 +19,10 @@ class SingleObjectMixin(ContextMixin):
def get_object(self, queryset=None): def get_object(self, queryset=None):
""" """
Returns the object the view is displaying. Return the object the view is displaying.
By default this requires `self.queryset` and a `pk` or `slug` argument Require `self.queryset` and a `pk` or `slug` argument in the URLconf.
in the URLconf, but subclasses can override this to return any object. Subclasses can override this to return any object.
""" """
# Use a custom queryset if provided; this is required for subclasses # Use a custom queryset if provided; this is required for subclasses
# like DateDetailView # like DateDetailView
@ -58,8 +58,8 @@ class SingleObjectMixin(ContextMixin):
""" """
Return the `QuerySet` that will be used to look up the object. Return the `QuerySet` that will be used to look up the object.
Note that this method is called by the default implementation of This method is called by the default implementation of get_object() and
`get_object` and may not be called if `get_object` is overridden. may not be called if get_object() is overridden.
""" """
if self.queryset is None: if self.queryset is None:
if self.model: if self.model:
@ -75,15 +75,11 @@ class SingleObjectMixin(ContextMixin):
return self.queryset.all() return self.queryset.all()
def get_slug_field(self): def get_slug_field(self):
""" """Get the name of a slug field to be used to look up by slug."""
Get the name of a slug field to be used to look up by slug.
"""
return self.slug_field return self.slug_field
def get_context_object_name(self, obj): def get_context_object_name(self, obj):
""" """Get the name to use for the object."""
Get the name to use for the object.
"""
if self.context_object_name: if self.context_object_name:
return self.context_object_name return self.context_object_name
elif isinstance(obj, models.Model): elif isinstance(obj, models.Model):
@ -92,9 +88,7 @@ class SingleObjectMixin(ContextMixin):
return None return None
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
""" """Insert the single object into the context dict."""
Insert the single object into the context dict.
"""
context = {} context = {}
if self.object: if self.object:
context['object'] = self.object context['object'] = self.object
@ -106,9 +100,7 @@ class SingleObjectMixin(ContextMixin):
class BaseDetailView(SingleObjectMixin, View): class BaseDetailView(SingleObjectMixin, View):
""" """A base view for displaying a single object."""
A base view for displaying a single object
"""
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
context = self.get_context_data(object=self.object) context = self.get_context_data(object=self.object)
@ -122,7 +114,7 @@ class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
def get_template_names(self): def get_template_names(self):
""" """
Return a list of template names to be used for the request. May not be Return a list of template names to be used for the request. May not be
called if render_to_response is overridden. Returns the following list: called if render_to_response() is overridden. Return the following list:
* the value of ``template_name`` on the view (if provided) * the value of ``template_name`` on the view (if provided)
* the contents of the ``template_name_field`` field on the * the contents of the ``template_name_field`` field on the

View File

@ -9,45 +9,32 @@ from django.views.generic.detail import (
class FormMixin(ContextMixin): class FormMixin(ContextMixin):
""" """Provide a way to show and handle a form in a request."""
A mixin that provides a way to show and handle a form in a request.
"""
initial = {} initial = {}
form_class = None form_class = None
success_url = None success_url = None
prefix = None prefix = None
def get_initial(self): def get_initial(self):
""" """Return the initial data to use for forms on this view."""
Returns the initial data to use for forms on this view.
"""
return self.initial.copy() return self.initial.copy()
def get_prefix(self): def get_prefix(self):
""" """Return the prefix to use for forms."""
Returns the prefix to use for forms on this view
"""
return self.prefix return self.prefix
def get_form_class(self): def get_form_class(self):
""" """Return the form class to use."""
Returns the form class to use in this view
"""
return self.form_class return self.form_class
def get_form(self, form_class=None): def get_form(self, form_class=None):
""" """Return an instance of the form to be used in this view."""
Returns an instance of the form to be used in this view.
"""
if form_class is None: if form_class is None:
form_class = self.get_form_class() form_class = self.get_form_class()
return form_class(**self.get_form_kwargs()) return form_class(**self.get_form_kwargs())
def get_form_kwargs(self): def get_form_kwargs(self):
""" """Return the keyword arguments for instantiating the form."""
Returns the keyword arguments for instantiating the form.
"""
kwargs = { kwargs = {
'initial': self.get_initial(), 'initial': self.get_initial(),
'prefix': self.get_prefix(), 'prefix': self.get_prefix(),
@ -61,9 +48,7 @@ class FormMixin(ContextMixin):
return kwargs return kwargs
def get_success_url(self): def get_success_url(self):
""" """Return the URL to redirect to after processing a valid form."""
Returns the supplied success URL.
"""
if self.success_url: if self.success_url:
# Forcing possible reverse_lazy evaluation # Forcing possible reverse_lazy evaluation
url = force_text(self.success_url) url = force_text(self.success_url)
@ -73,37 +58,26 @@ class FormMixin(ContextMixin):
return url return url
def form_valid(self, form): def form_valid(self, form):
""" """If the form is valid, redirect to the supplied URL."""
If the form is valid, redirect to the supplied URL.
"""
return HttpResponseRedirect(self.get_success_url()) return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form): def form_invalid(self, form):
""" """If the form is invalid, render the invalid form."""
If the form is invalid, re-render the context data with the
data-filled form and errors.
"""
return self.render_to_response(self.get_context_data(form=form)) return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
""" """Insert the form into the context dict."""
Insert the form into the context dict.
"""
if 'form' not in kwargs: if 'form' not in kwargs:
kwargs['form'] = self.get_form() kwargs['form'] = self.get_form()
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
class ModelFormMixin(FormMixin, SingleObjectMixin): class ModelFormMixin(FormMixin, SingleObjectMixin):
""" """Provide a way to show and handle a ModelForm in a request."""
A mixin that provides a way to show and handle a modelform in a request.
"""
fields = None fields = None
def get_form_class(self): def get_form_class(self):
""" """Return the form class to use in this view."""
Returns the form class to use in this view.
"""
if self.fields is not None and self.form_class: if self.fields is not None and self.form_class:
raise ImproperlyConfigured( raise ImproperlyConfigured(
"Specifying both 'fields' and 'form_class' is not permitted." "Specifying both 'fields' and 'form_class' is not permitted."
@ -132,18 +106,14 @@ class ModelFormMixin(FormMixin, SingleObjectMixin):
return model_forms.modelform_factory(model, fields=self.fields) return model_forms.modelform_factory(model, fields=self.fields)
def get_form_kwargs(self): def get_form_kwargs(self):
""" """Return the keyword arguments for instantiating the form."""
Returns the keyword arguments for instantiating the form.
"""
kwargs = super().get_form_kwargs() kwargs = super().get_form_kwargs()
if hasattr(self, 'object'): if hasattr(self, 'object'):
kwargs.update({'instance': self.object}) kwargs.update({'instance': self.object})
return kwargs return kwargs
def get_success_url(self): def get_success_url(self):
""" """Return the URL to redirect to after processing a valid form."""
Returns the supplied URL.
"""
if self.success_url: if self.success_url:
url = self.success_url.format(**self.object.__dict__) url = self.success_url.format(**self.object.__dict__)
else: else:
@ -156,27 +126,21 @@ class ModelFormMixin(FormMixin, SingleObjectMixin):
return url return url
def form_valid(self, form): def form_valid(self, form):
""" """If the form is valid, save the associated model."""
If the form is valid, save the associated model.
"""
self.object = form.save() self.object = form.save()
return super().form_valid(form) return super().form_valid(form)
class ProcessFormView(View): class ProcessFormView(View):
""" """Render a form on GET and processes it on POST."""
A mixin that renders a form on GET and processes it on POST.
"""
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
""" """Handle GET requests: instantiate a blank version of the form."""
Handles GET requests and instantiates a blank version of the form.
"""
return self.render_to_response(self.get_context_data()) return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
""" """
Handles POST requests, instantiating a form instance with the passed Handle POST requests: instantiate a form instance with the passed
POST variables and then checked for validity. POST variables and then check if it's valid.
""" """
form = self.get_form() form = self.get_form()
if form.is_valid(): if form.is_valid():
@ -191,15 +155,11 @@ class ProcessFormView(View):
class BaseFormView(FormMixin, ProcessFormView): class BaseFormView(FormMixin, ProcessFormView):
""" """A base view for displaying a form."""
A base view for displaying a form.
"""
class FormView(TemplateResponseMixin, BaseFormView): class FormView(TemplateResponseMixin, BaseFormView):
""" """A view for displaying a form and rendering a template response."""
A view for displaying a form, and rendering a template response.
"""
class BaseCreateView(ModelFormMixin, ProcessFormView): class BaseCreateView(ModelFormMixin, ProcessFormView):
@ -219,8 +179,7 @@ class BaseCreateView(ModelFormMixin, ProcessFormView):
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView): class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
""" """
View for creating a new object instance, View for creating a new object, with a response rendered by a template.
with a response rendered by template.
""" """
template_name_suffix = '_form' template_name_suffix = '_form'
@ -241,23 +200,18 @@ class BaseUpdateView(ModelFormMixin, ProcessFormView):
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView): class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
""" """View for updating an object, with a response rendered by a template."""
View for updating an object,
with a response rendered by template.
"""
template_name_suffix = '_form' template_name_suffix = '_form'
class DeletionMixin: class DeletionMixin:
""" """Provide the ability to delete objects."""
A mixin providing the ability to delete objects
"""
success_url = None success_url = None
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
""" """
Calls the delete() method on the fetched object and then Call the delete() method on the fetched object and then redirect to the
redirects to the success URL. success URL.
""" """
self.object = self.get_object() self.object = self.get_object()
success_url = self.get_success_url() success_url = self.get_success_url()
@ -286,7 +240,7 @@ class BaseDeleteView(DeletionMixin, BaseDetailView):
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView): class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
""" """
View for deleting an object retrieved with `self.get_object()`, View for deleting an object retrieved with self.get_object(), with a
with a response rendered by template. response rendered by a template.
""" """
template_name_suffix = '_confirm_delete' template_name_suffix = '_confirm_delete'

View File

@ -7,9 +7,7 @@ from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
class MultipleObjectMixin(ContextMixin): class MultipleObjectMixin(ContextMixin):
""" """A mixin for views manipulating multiple objects."""
A mixin for views manipulating multiple objects.
"""
allow_empty = True allow_empty = True
queryset = None queryset = None
model = None model = None
@ -50,15 +48,11 @@ class MultipleObjectMixin(ContextMixin):
return queryset return queryset
def get_ordering(self): def get_ordering(self):
""" """Return the field or fields to use for ordering the queryset."""
Return the field or fields to use for ordering the queryset.
"""
return self.ordering return self.ordering
def paginate_queryset(self, queryset, page_size): def paginate_queryset(self, queryset, page_size):
""" """Paginate the queryset, if needed."""
Paginate the queryset, if needed.
"""
paginator = self.get_paginator( paginator = self.get_paginator(
queryset, page_size, orphans=self.get_paginate_orphans(), queryset, page_size, orphans=self.get_paginate_orphans(),
allow_empty_first_page=self.get_allow_empty()) allow_empty_first_page=self.get_allow_empty())
@ -88,31 +82,27 @@ class MultipleObjectMixin(ContextMixin):
def get_paginator(self, queryset, per_page, orphans=0, def get_paginator(self, queryset, per_page, orphans=0,
allow_empty_first_page=True, **kwargs): allow_empty_first_page=True, **kwargs):
""" """Return an instance of the paginator for this view."""
Return an instance of the paginator for this view.
"""
return self.paginator_class( return self.paginator_class(
queryset, per_page, orphans=orphans, queryset, per_page, orphans=orphans,
allow_empty_first_page=allow_empty_first_page, **kwargs) allow_empty_first_page=allow_empty_first_page, **kwargs)
def get_paginate_orphans(self): def get_paginate_orphans(self):
""" """
Returns the maximum number of orphans extend the last page by when Return the maximum number of orphans extend the last page by when
paginating. paginating.
""" """
return self.paginate_orphans return self.paginate_orphans
def get_allow_empty(self): def get_allow_empty(self):
""" """
Returns ``True`` if the view should display empty lists, and ``False`` Return ``True`` if the view should display empty lists and ``False``
if a 404 should be raised instead. if a 404 should be raised instead.
""" """
return self.allow_empty return self.allow_empty
def get_context_object_name(self, object_list): def get_context_object_name(self, object_list):
""" """Get the name of the item to be used in the context."""
Get the name of the item to be used in the context.
"""
if self.context_object_name: if self.context_object_name:
return self.context_object_name return self.context_object_name
elif hasattr(object_list, 'model'): elif hasattr(object_list, 'model'):
@ -121,9 +111,7 @@ class MultipleObjectMixin(ContextMixin):
return None return None
def get_context_data(self, *, object_list=None, **kwargs): def get_context_data(self, *, object_list=None, **kwargs):
""" """Get the context for this view."""
Get the context for this view.
"""
queryset = object_list if object_list is not None else self.object_list queryset = object_list if object_list is not None else self.object_list
page_size = self.get_paginate_by(queryset) page_size = self.get_paginate_by(queryset)
context_object_name = self.get_context_object_name(queryset) context_object_name = self.get_context_object_name(queryset)
@ -149,9 +137,7 @@ class MultipleObjectMixin(ContextMixin):
class BaseListView(MultipleObjectMixin, View): class BaseListView(MultipleObjectMixin, View):
""" """A base view for displaying a list of objects."""
A base view for displaying a list of objects.
"""
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset() self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty() allow_empty = self.get_allow_empty()
@ -173,9 +159,7 @@ class BaseListView(MultipleObjectMixin, View):
class MultipleObjectTemplateResponseMixin(TemplateResponseMixin): class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
""" """Mixin for responding with a template and list of objects."""
Mixin for responding with a template and list of objects.
"""
template_name_suffix = '_list' template_name_suffix = '_list'
def get_template_names(self): def get_template_names(self):

View File

@ -22,9 +22,9 @@ LANGUAGE_QUERY_PARAMETER = 'language'
def set_language(request): def set_language(request):
""" """
Redirect to a given url while setting the chosen language in the Redirect to a given URL while setting the chosen language in the session or
session or cookie. The url and the language code need to be cookie. The URL and the language code need to be specified in the request
specified in the request parameters. parameters.
Since this view changes how the user will see the rest of the site, it must Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will only be accessed as a POST request. If called as a GET request, it will
@ -60,9 +60,7 @@ def set_language(request):
def get_formats(): def get_formats():
""" """Return all formats strings required for i18n to work."""
Returns all formats strings required for i18n to work
"""
FORMAT_SETTINGS = ( FORMAT_SETTINGS = (
'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT', 'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT',
'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT', 'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT',
@ -207,7 +205,7 @@ def render_javascript_catalog(catalog=None, plural=None):
def null_javascript_catalog(request, domain=None, packages=None): def null_javascript_catalog(request, domain=None, packages=None):
""" """
Returns "identity" versions of the JavaScript i18n functions -- i.e., Return "identity" versions of the JavaScript i18n functions -- i.e.,
versions that don't actually do anything. versions that don't actually do anything.
""" """
return render_javascript_catalog() return render_javascript_catalog()
@ -217,7 +215,7 @@ class JavaScriptCatalog(View):
""" """
Return the selected language catalog as a JavaScript library. Return the selected language catalog as a JavaScript library.
Receives the list of packages to check for translations in the `packages` Receive the list of packages to check for translations in the `packages`
kwarg either from the extra dictionary passed to the url() function or as a kwarg either from the extra dictionary passed to the url() function or as a
plus-sign delimited string from the request. Default is 'django.conf'. plus-sign delimited string from the request. Default is 'django.conf'.
@ -305,7 +303,7 @@ class JSONCatalog(JavaScriptCatalog):
""" """
Return the selected language catalog as a JSON object. Return the selected language catalog as a JSON object.
Receives the same parameters as JavaScriptCatalog and returns a response Receive the same parameters as JavaScriptCatalog and return a response
with a JSON object of the following format: with a JSON object of the following format:
{ {