I'm writing the following to generate URLs for my urls.py:
urls = {
'overview': {
r'^$': [ 'Index' ],
r'^/account$': [ 'Account' ],
},
'content': {
r'^/content$': [ 'Index' ]
r'^/content/upload$': [ 'Uploader', 'Default' ]
}
}
urlpatterns = patterns('')
for module, spec in urls.iteritems():
urlpatterns += patterns('views.'+ module,
[
url(regex, (getattr(module.capitalize() , 'as_view'))(), action=view[0])
if len(view) == 1 else
url(regex, (getattr(view[0], 'as_view'))(), action=view[1])
for regex, view in spec.iteritems()
]
)
I have modules overview
and content
, with classes Overview
, and Content
and Uploader
, respectively.
If the view
array (e.g., [ 'Index' ]
contains a single element, I use the capitalized form of the module (e.g., overview
becomes Overview
) to generate the route:
url(r'^$', Overview.as_view(), action='Index')
whereas if it contains two elements, (e.g., [ 'Uploader', 'Default' ]
), the first element specifies the class name and the second the method:
url(r'^$', Uploader.as_view(), action='Default')
As you may have noticed, the issue is with my use of getattr()
, whose first argument requires a class reference. So, my question is whether there is any way to get the class object from a string that contains the identifier of said class object, e.g., the Uploader
class from 'Uploader'
.
As a disclaimer these are not my exact routes, just an example. And of course further comments are welcome with respect to my overall design here as well.
I'd say there are two common ways of doing it. Consider example below:
from random import choice
class A(object):
def __init__(self):
self.name = 'in A'
class B(object):
def __init__(self):
self.name = 'in B'
class C(object):
def __init__(self):
self.name = 'in C'
if __name__ == "__main__":
classes = ['A', 'B', 'C']
class_name = choice(classes)
print class_name
# 1st way
obj = globals()[class_name]()
print obj.name
# 2nd way
import sys
obj = getattr(sys.modules['__main__'], class_name)()
print obj.name
# 3rd way - not recommended
obj = eval(class_name)()
print obj.name