2006-05-02 09:31:56 +08:00
from django import template , templatetags
from django . template import RequestContext
2005-07-13 09:25:57 +08:00
from django . conf import settings
2005-10-18 13:12:45 +08:00
from django . contrib . admin . views . decorators import staff_member_required
2006-05-02 09:31:56 +08:00
from django . db import models
from django . shortcuts import render_to_response
from django . core . exceptions import ImproperlyConfigured , ViewDoesNotExist
2008-07-22 11:24:09 +08:00
from django . http import Http404
2006-05-02 09:31:56 +08:00
from django . core import urlresolvers
2008-07-19 07:54:34 +08:00
from django . contrib . admindocs import utils
2006-05-02 09:31:56 +08:00
from django . contrib . sites . models import Site
Merged Unicode branch into trunk (r4952:5608). This should be fully
backwards compatible for all practical purposes.
Fixed #2391, #2489, #2996, #3322, #3344, #3370, #3406, #3432, #3454, #3492, #3582, #3690, #3878, #3891, #3937, #4039, #4141, #4227, #4286, #4291, #4300, #4452, #4702
git-svn-id: http://code.djangoproject.com/svn/django/trunk@5609 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2007-07-04 20:11:04 +08:00
from django . utils . translation import ugettext as _
2007-11-14 20:58:53 +08:00
from django . utils . safestring import mark_safe
2005-07-27 00:11:43 +08:00
import inspect , os , re
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
# Exclude methods starting with these strings from documentation
MODEL_METHODS_EXCLUDE = ( ' _ ' , ' add_ ' , ' delete ' , ' save ' , ' set_ ' )
2006-06-27 07:01:46 +08:00
class GenericSite ( object ) :
domain = ' example.com '
name = ' my site '
2008-08-30 03:29:16 +08:00
def get_root_path ( ) :
from django . contrib import admin
try :
return urlresolvers . reverse ( admin . site . root , args = [ ' ' ] )
except urlresolvers . NoReverseMatch :
return getattr ( settings , " ADMIN_SITE_ROOT_URL " , " /admin/ " )
2005-07-13 09:25:57 +08:00
def doc_index ( request ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2008-07-19 07:54:34 +08:00
return render_to_response ( ' admin_doc/index.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2008-07-19 07:54:34 +08:00
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
doc_index = staff_member_required ( doc_index )
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
def bookmarklets ( request ) :
2008-08-30 03:29:16 +08:00
admin_root = get_root_path ( )
2006-05-02 09:31:56 +08:00
return render_to_response ( ' admin_doc/bookmarklets.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : admin_root ,
2007-11-14 20:58:53 +08:00
' admin_url ' : mark_safe ( " %s :// %s %s " % ( request . is_secure ( ) and ' https ' or ' http ' , request . get_host ( ) , admin_root ) ) ,
2006-05-02 09:31:56 +08:00
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
bookmarklets = staff_member_required ( bookmarklets )
2005-07-13 09:25:57 +08:00
def template_tag_index ( request ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
load_all_installed_template_libraries ( )
tags = [ ]
2005-11-28 01:14:11 +08:00
for module_name , library in template . libraries . items ( ) :
for tag_name , tag_func in library . tags . items ( ) :
2005-11-28 01:20:43 +08:00
title , body , metadata = utils . parse_docstring ( tag_func . __doc__ )
2005-11-28 01:14:11 +08:00
if title :
2006-08-11 13:07:07 +08:00
title = utils . parse_rst ( title , ' tag ' , _ ( ' tag: ' ) + tag_name )
2005-11-28 01:14:11 +08:00
if body :
2006-08-11 13:07:07 +08:00
body = utils . parse_rst ( body , ' tag ' , _ ( ' tag: ' ) + tag_name )
2005-11-28 01:14:11 +08:00
for key in metadata :
2006-08-11 13:07:07 +08:00
metadata [ key ] = utils . parse_rst ( metadata [ key ] , ' tag ' , _ ( ' tag: ' ) + tag_name )
2005-11-28 01:14:11 +08:00
if library in template . builtins :
tag_library = None
else :
tag_library = module_name . split ( ' . ' ) [ - 1 ]
tags . append ( {
' name ' : tag_name ,
' title ' : title ,
' body ' : body ,
' meta ' : metadata ,
' library ' : tag_library ,
} )
2008-07-19 07:54:34 +08:00
return render_to_response ( ' admin_doc/template_tag_index.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2008-07-19 07:54:34 +08:00
' tags ' : tags
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
template_tag_index = staff_member_required ( template_tag_index )
2005-07-13 09:25:57 +08:00
def template_filter_index ( request ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
load_all_installed_template_libraries ( )
filters = [ ]
2005-11-28 01:14:11 +08:00
for module_name , library in template . libraries . items ( ) :
for filter_name , filter_func in library . filters . items ( ) :
2005-11-28 01:20:43 +08:00
title , body , metadata = utils . parse_docstring ( filter_func . __doc__ )
2005-11-28 01:14:11 +08:00
if title :
2006-08-11 13:07:07 +08:00
title = utils . parse_rst ( title , ' filter ' , _ ( ' filter: ' ) + filter_name )
2005-11-28 01:14:11 +08:00
if body :
2006-08-11 13:07:07 +08:00
body = utils . parse_rst ( body , ' filter ' , _ ( ' filter: ' ) + filter_name )
2005-11-28 01:14:11 +08:00
for key in metadata :
2006-08-11 13:07:07 +08:00
metadata [ key ] = utils . parse_rst ( metadata [ key ] , ' filter ' , _ ( ' filter: ' ) + filter_name )
2005-11-28 01:14:11 +08:00
if library in template . builtins :
tag_library = None
else :
tag_library = module_name . split ( ' . ' ) [ - 1 ]
filters . append ( {
' name ' : filter_name ,
' title ' : title ,
' body ' : body ,
' meta ' : metadata ,
' library ' : tag_library ,
} )
2008-07-19 07:54:34 +08:00
return render_to_response ( ' admin_doc/template_filter_index.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2008-07-19 07:54:34 +08:00
' filters ' : filters
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
template_filter_index = staff_member_required ( template_filter_index )
2005-07-13 09:25:57 +08:00
def view_index ( request ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2006-05-02 09:31:56 +08:00
if settings . ADMIN_FOR :
2006-10-31 04:50:27 +08:00
settings_modules = [ __import__ ( m , { } , { } , [ ' ' ] ) for m in settings . ADMIN_FOR ]
2006-05-02 09:31:56 +08:00
else :
settings_modules = [ settings ]
2005-07-13 09:25:57 +08:00
views = [ ]
2006-05-02 09:31:56 +08:00
for settings_mod in settings_modules :
2006-10-31 04:50:27 +08:00
urlconf = __import__ ( settings_mod . ROOT_URLCONF , { } , { } , [ ' ' ] )
2005-07-13 09:25:57 +08:00
view_functions = extract_views_from_urlpatterns ( urlconf . urlpatterns )
2006-06-27 07:01:46 +08:00
if Site . _meta . installed :
site_obj = Site . objects . get ( pk = settings_mod . SITE_ID )
else :
site_obj = GenericSite ( )
2005-07-13 09:25:57 +08:00
for ( func , regex ) in view_functions :
views . append ( {
2005-11-28 01:14:11 +08:00
' name ' : func . __name__ ,
' module ' : func . __module__ ,
2005-07-13 09:25:57 +08:00
' site_id ' : settings_mod . SITE_ID ,
2006-06-27 07:01:46 +08:00
' site ' : site_obj ,
2005-11-28 01:14:11 +08:00
' url ' : simplify_regex ( regex ) ,
2005-07-13 09:25:57 +08:00
} )
2008-07-19 07:54:34 +08:00
return render_to_response ( ' admin_doc/view_index.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2008-07-19 07:54:34 +08:00
' views ' : views
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
view_index = staff_member_required ( view_index )
2005-07-13 09:25:57 +08:00
def view_detail ( request , view ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
mod , func = urlresolvers . get_mod_func ( view )
try :
2006-10-31 04:50:27 +08:00
view_func = getattr ( __import__ ( mod , { } , { } , [ ' ' ] ) , func )
2005-07-13 09:25:57 +08:00
except ( ImportError , AttributeError ) :
raise Http404
2005-11-28 01:20:43 +08:00
title , body , metadata = utils . parse_docstring ( view_func . __doc__ )
2005-07-13 09:25:57 +08:00
if title :
2006-08-11 13:07:07 +08:00
title = utils . parse_rst ( title , ' view ' , _ ( ' view: ' ) + view )
2005-07-13 09:25:57 +08:00
if body :
2006-08-11 13:07:07 +08:00
body = utils . parse_rst ( body , ' view ' , _ ( ' view: ' ) + view )
2005-07-13 09:25:57 +08:00
for key in metadata :
2006-08-11 13:07:07 +08:00
metadata [ key ] = utils . parse_rst ( metadata [ key ] , ' model ' , _ ( ' view: ' ) + view )
2006-05-02 09:31:56 +08:00
return render_to_response ( ' admin_doc/view_detail.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2005-09-22 13:23:41 +08:00
' name ' : view ,
' summary ' : title ,
' body ' : body ,
' meta ' : metadata ,
2006-05-02 09:31:56 +08:00
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
view_detail = staff_member_required ( view_detail )
2005-07-13 09:25:57 +08:00
def model_index ( request ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2006-05-02 09:31:56 +08:00
m_list = [ m . _meta for m in models . get_models ( ) ]
2008-07-19 07:54:34 +08:00
return render_to_response ( ' admin_doc/model_index.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2008-07-19 07:54:34 +08:00
' models ' : m_list
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
model_index = staff_member_required ( model_index )
2005-07-13 09:25:57 +08:00
2006-05-02 09:31:56 +08:00
def model_detail ( request , app_label , model_name ) :
2005-11-28 01:20:43 +08:00
if not utils . docutils_is_available :
2005-07-13 09:25:57 +08:00
return missing_docutils_page ( request )
2008-07-19 07:54:34 +08:00
2006-05-02 09:31:56 +08:00
# Get the model class.
2005-07-13 09:25:57 +08:00
try :
2006-05-02 09:31:56 +08:00
app_mod = models . get_app ( app_label )
except ImproperlyConfigured :
2006-08-11 13:07:07 +08:00
raise Http404 , _ ( " App %r not found " ) % app_label
2006-05-02 09:31:56 +08:00
model = None
for m in models . get_models ( app_mod ) :
if m . _meta . object_name . lower ( ) == model_name :
model = m
break
if model is None :
2008-07-19 07:54:34 +08:00
raise Http404 , _ ( " Model %(model_name)r not found in app %(app_label)r " ) % { ' model_name ' : model_name , ' app_label ' : app_label }
2005-07-16 01:09:01 +08:00
2006-05-02 09:31:56 +08:00
opts = model . _meta
# Gather fields/field descriptions.
2005-07-13 09:25:57 +08:00
fields = [ ]
for field in opts . fields :
2006-05-02 09:31:56 +08:00
# ForeignKey is a special case since the field will actually be a
# descriptor that returns the other object
if isinstance ( field , models . ForeignKey ) :
data_type = related_object_name = field . rel . to . __name__
app_label = field . rel . to . _meta . app_label
2008-07-19 07:54:34 +08:00
verbose = utils . parse_rst ( ( _ ( " the related ` %(app_label)s . %(data_type)s ` object " ) % { ' app_label ' : app_label , ' data_type ' : data_type } ) , ' model ' , _ ( ' model: ' ) + data_type )
2006-05-02 09:31:56 +08:00
else :
data_type = get_readable_field_data_type ( field )
verbose = field . verbose_name
2005-07-13 09:25:57 +08:00
fields . append ( {
2005-11-28 01:14:11 +08:00
' name ' : field . name ,
2006-05-02 09:31:56 +08:00
' data_type ' : data_type ,
' verbose ' : verbose ,
2006-07-07 12:00:44 +08:00
' help_text ' : field . help_text ,
2005-07-13 09:25:57 +08:00
} )
2006-05-02 09:31:56 +08:00
# Gather model methods.
for func_name , func in model . __dict__ . items ( ) :
if ( inspect . isfunction ( func ) and len ( inspect . getargspec ( func ) [ 0 ] ) == 1 ) :
2005-07-13 09:25:57 +08:00
try :
for exclude in MODEL_METHODS_EXCLUDE :
if func_name . startswith ( exclude ) :
raise StopIteration
except StopIteration :
continue
verbose = func . __doc__
if verbose :
2006-08-11 13:07:07 +08:00
verbose = utils . parse_rst ( utils . trim_docstring ( verbose ) , ' model ' , _ ( ' model: ' ) + opts . module_name )
2005-07-13 09:25:57 +08:00
fields . append ( {
2005-11-28 01:14:11 +08:00
' name ' : func_name ,
' data_type ' : get_return_data_type ( func_name ) ,
' verbose ' : verbose ,
2005-07-13 09:25:57 +08:00
} )
2006-05-02 09:31:56 +08:00
# Gather related objects
for rel in opts . get_all_related_objects ( ) :
2008-07-19 07:54:34 +08:00
verbose = _ ( " related ` %(app_label)s . %(object_name)s ` objects " ) % { ' app_label ' : rel . opts . app_label , ' object_name ' : rel . opts . object_name }
2006-05-02 09:31:56 +08:00
accessor = rel . get_accessor_name ( )
fields . append ( {
2006-05-18 23:17:42 +08:00
' name ' : " %s .all " % accessor ,
' data_type ' : ' List ' ,
2006-08-11 13:07:07 +08:00
' verbose ' : utils . parse_rst ( _ ( " all %s " ) % verbose , ' model ' , _ ( ' model: ' ) + opts . module_name ) ,
2006-05-02 09:31:56 +08:00
} )
fields . append ( {
2006-05-18 23:17:42 +08:00
' name ' : " %s .count " % accessor ,
' data_type ' : ' Integer ' ,
2006-08-11 13:07:07 +08:00
' verbose ' : utils . parse_rst ( _ ( " number of %s " ) % verbose , ' model ' , _ ( ' model: ' ) + opts . module_name ) ,
2006-05-02 09:31:56 +08:00
} )
return render_to_response ( ' admin_doc/model_detail.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2006-05-02 09:31:56 +08:00
' name ' : ' %s . %s ' % ( opts . app_label , opts . object_name ) ,
2006-08-18 11:37:01 +08:00
' summary ' : _ ( " Fields on %s objects " ) % opts . object_name ,
2006-02-28 05:37:11 +08:00
' description ' : model . __doc__ ,
2005-09-22 13:23:41 +08:00
' fields ' : fields ,
2006-05-02 09:31:56 +08:00
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
model_detail = staff_member_required ( model_detail )
2005-07-13 09:25:57 +08:00
2005-08-03 04:29:27 +08:00
def template_detail ( request , template ) :
templates = [ ]
for site_settings_module in settings . ADMIN_FOR :
2006-10-31 04:50:27 +08:00
settings_mod = __import__ ( site_settings_module , { } , { } , [ ' ' ] )
2006-06-27 07:01:46 +08:00
if Site . _meta . installed :
site_obj = Site . objects . get ( pk = settings_mod . SITE_ID )
else :
site_obj = GenericSite ( )
2005-08-03 04:29:27 +08:00
for dir in settings_mod . TEMPLATE_DIRS :
template_file = os . path . join ( dir , " %s .html " % template )
templates . append ( {
2005-11-28 01:14:11 +08:00
' file ' : template_file ,
' exists ' : os . path . exists ( template_file ) ,
' contents ' : lambda : os . path . exists ( template_file ) and open ( template_file ) . read ( ) or ' ' ,
' site_id ' : settings_mod . SITE_ID ,
2006-06-27 07:01:46 +08:00
' site ' : site_obj ,
2005-11-28 01:14:11 +08:00
' order ' : list ( settings_mod . TEMPLATE_DIRS ) . index ( dir ) ,
2005-08-03 04:29:27 +08:00
} )
2006-05-02 09:31:56 +08:00
return render_to_response ( ' admin_doc/template_detail.html ' , {
2008-08-30 03:29:16 +08:00
' root_path ' : get_root_path ( ) ,
2005-09-22 13:23:41 +08:00
' name ' : template ,
' templates ' : templates ,
2006-05-02 09:31:56 +08:00
} , context_instance = RequestContext ( request ) )
2005-10-18 13:12:45 +08:00
template_detail = staff_member_required ( template_detail )
2005-08-06 05:24:24 +08:00
2005-07-13 09:25:57 +08:00
####################
# Helper functions #
####################
def missing_docutils_page ( request ) :
""" Display an error message for people without docutils """
2006-05-02 09:31:56 +08:00
return render_to_response ( ' admin_doc/missing_docutils.html ' )
2005-07-13 09:25:57 +08:00
def load_all_installed_template_libraries ( ) :
2005-11-28 01:14:11 +08:00
# Load/register all template tag libraries from installed apps.
2005-07-13 09:25:57 +08:00
for e in templatetags . __path__ :
libraries = [ os . path . splitext ( p ) [ 0 ] for p in os . listdir ( e ) if p . endswith ( ' .py ' ) and p [ 0 ] . isalpha ( ) ]
2005-11-28 01:14:11 +08:00
for library_name in libraries :
2005-07-13 09:25:57 +08:00
try :
2005-11-28 01:14:11 +08:00
lib = template . get_library ( " django.templatetags. %s " % library_name . split ( ' . ' ) [ - 1 ] )
except template . InvalidTemplateLibrary :
2005-07-13 09:25:57 +08:00
pass
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
def get_return_data_type ( func_name ) :
""" Return a somewhat-helpful data type given a function name """
if func_name . startswith ( ' get_ ' ) :
if func_name . endswith ( ' _list ' ) :
return ' List '
elif func_name . endswith ( ' _count ' ) :
return ' Integer '
return ' '
# Maps Field objects to their human-readable data types, as strings.
# Column-type strings can contain format strings; they'll be interpolated
# against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPE_MAPPING = {
2005-11-24 01:02:38 +08:00
' AutoField ' : _ ( ' Integer ' ) ,
' BooleanField ' : _ ( ' Boolean (Either True or False) ' ) ,
2007-08-05 13:14:46 +08:00
' CharField ' : _ ( ' String (up to %(max_length)s ) ' ) ,
2005-11-24 01:02:38 +08:00
' CommaSeparatedIntegerField ' : _ ( ' Comma-separated integers ' ) ,
' DateField ' : _ ( ' Date (without time) ' ) ,
' DateTimeField ' : _ ( ' Date (with time) ' ) ,
2007-05-21 09:29:58 +08:00
' DecimalField ' : _ ( ' Decimal number ' ) ,
2005-11-24 01:02:38 +08:00
' EmailField ' : _ ( ' E-mail address ' ) ,
' FileField ' : _ ( ' File path ' ) ,
2006-05-22 12:47:14 +08:00
' FilePathField ' : _ ( ' File path ' ) ,
2007-05-21 09:29:58 +08:00
' FloatField ' : _ ( ' Floating point number ' ) ,
2005-11-24 01:02:38 +08:00
' ForeignKey ' : _ ( ' Integer ' ) ,
' ImageField ' : _ ( ' File path ' ) ,
' IntegerField ' : _ ( ' Integer ' ) ,
' IPAddressField ' : _ ( ' IP address ' ) ,
2005-07-13 09:25:57 +08:00
' ManyToManyField ' : ' ' ,
2005-11-24 01:02:38 +08:00
' NullBooleanField ' : _ ( ' Boolean (Either True, False or None) ' ) ,
2005-11-28 07:43:35 +08:00
' OneToOneField ' : _ ( ' Relation to parent model ' ) ,
2005-11-24 01:02:38 +08:00
' PhoneNumberField ' : _ ( ' Phone number ' ) ,
' PositiveIntegerField ' : _ ( ' Integer ' ) ,
' PositiveSmallIntegerField ' : _ ( ' Integer ' ) ,
2007-08-05 13:14:46 +08:00
' SlugField ' : _ ( ' String (up to %(max_length)s ) ' ) ,
2005-11-24 01:02:38 +08:00
' SmallIntegerField ' : _ ( ' Integer ' ) ,
' TextField ' : _ ( ' Text ' ) ,
' TimeField ' : _ ( ' Time ' ) ,
' URLField ' : _ ( ' URL ' ) ,
' USStateField ' : _ ( ' U.S. state (two uppercase letters) ' ) ,
' XMLField ' : _ ( ' XML text ' ) ,
2005-07-13 09:25:57 +08:00
}
2005-07-16 01:09:01 +08:00
def get_readable_field_data_type ( field ) :
2005-10-28 11:48:33 +08:00
return DATA_TYPE_MAPPING [ field . get_internal_type ( ) ] % field . __dict__
2005-07-13 09:25:57 +08:00
def extract_views_from_urlpatterns ( urlpatterns , base = ' ' ) :
"""
Return a list of views from a list of urlpatterns .
2005-07-16 01:09:01 +08:00
2005-07-13 09:25:57 +08:00
Each object in the returned list is a two - tuple : ( view_func , regex )
"""
views = [ ]
for p in urlpatterns :
2006-09-01 05:32:50 +08:00
if hasattr ( p , ' _get_callback ' ) :
2005-07-13 09:25:57 +08:00
try :
2006-09-01 05:32:50 +08:00
views . append ( ( p . _get_callback ( ) , base + p . regex . pattern ) )
2005-07-13 09:25:57 +08:00
except ViewDoesNotExist :
continue
2005-08-06 05:24:24 +08:00
elif hasattr ( p , ' _get_url_patterns ' ) :
2006-09-01 05:35:36 +08:00
try :
patterns = p . url_patterns
except ImportError :
continue
views . extend ( extract_views_from_urlpatterns ( patterns , base + p . regex . pattern ) )
2005-07-13 09:25:57 +08:00
else :
2006-08-11 13:07:07 +08:00
raise TypeError , _ ( " %s does not appear to be a urlpattern object " ) % p
2005-07-13 09:25:57 +08:00
return views
named_group_matcher = re . compile ( r ' \ ( \ ?P(< \ w+>).+? \ ) ' )
2006-05-02 09:31:56 +08:00
non_named_group_matcher = re . compile ( r ' \ (.*? \ ) ' )
2005-07-13 09:25:57 +08:00
def simplify_regex ( pattern ) :
2006-05-02 09:31:56 +08:00
"""
Clean up urlpattern regexes into something somewhat readable by Mere Humans :
turns something like " ^(?P<sport_slug> \ w+)/athletes/(?P<athlete_slug> \ w+)/$ "
into " <sport_slug>/athletes/<athlete_slug>/ "
"""
# handle named groups first
2005-07-13 09:25:57 +08:00
pattern = named_group_matcher . sub ( lambda m : m . group ( 1 ) , pattern )
2006-05-02 09:31:56 +08:00
# handle non-named groups
pattern = non_named_group_matcher . sub ( " <var> " , pattern )
# clean up any outstanding regex-y characters.
pattern = pattern . replace ( ' ^ ' , ' ' ) . replace ( ' $ ' , ' ' ) . replace ( ' ? ' , ' ' ) . replace ( ' // ' , ' / ' ) . replace ( ' \\ ' , ' ' )
2005-07-13 09:25:57 +08:00
if not pattern . startswith ( ' / ' ) :
pattern = ' / ' + pattern
2005-07-19 04:35:51 +08:00
return pattern