---
tags: Django, hack
---
# Django Dynamic URLs
Have you ever considered to create dynamic urls in Django?
Not the url parameters but the ones which are gernerated according to data from a database or a file.
## Concepts
Normally, we create an url path in `urls.py` and map each url to a view function or class:
```python
path('demo', app.demo, related_name="demo")
path('demo_class', app.DemoClass.as_view(), related_name="demo_class")
```
The path function needs a url string, a view function and other parameters.
The point is how do we make the url string and the view function dynamic?
## Dynamic Import
The module `imorptlib` offers you to import module by moudle's name.
```python
module = importlib.import_module('sys')
# <module 'sys' (built-in)>
```
As you can see, the module's name is a string, that means we have more flexibilty to get the modules we want.
Import the views through this method would be like:
```python
view_module = importlib.import_module('%s.views' % app_name)
```
## Get The View
Next step, we need to get the view from the view_module.
A view is an attribute of the view_module, you can see the attribute listed by built-in function `dir()`.
```python
dir(view_module)
```
We use the built-in function `getattr()` to get the view.
```python
view = getattr(view_module, 'myView')
```
## Class Based View or Function Based View
We have to decide the view is a CBV or a FBV. The biggest difference between these two types of view is, CBV needs to call out `as_view()` function.
It means we have to find out wether the class is a class or not:
```python
view_function = view.as_view() if inspect.isclass(view) else view
```
## Return
For the case of Django build-in path method `include`:
```python
include('app.urls')
#(<module 'app.urls' from 'E:\\myproject\\app\\urls.py'>, None, None)
```
Last two parameters are **app_name** and **namesapce**.
That means we should add these two parameters when returning the patterns.
All in all,
```python
def dynamic_urls(programs):
urlpatters = []
for program in programs:
module_name, view_name = program
url = '%s/%s' % (module_name, view_name)
# depends on the rule you use
module = importlib.import_module('%s.views' % module_name)
# dynamic import
view = getattr(module, view_name, None)
if view:
view = view.as_view() if inspect.isclass(view) else view
urlpatterns.append(
path(url, view)
)
return urlpatterns, None, None
dynamic_urls(programs)
# ([<URLPattern 'app/viewa'>, <URLPattern 'app/viewb'>,
# <URLPattern 'common/viewc'>, None, None)
```
Then you can do something like this in your upper level urls.py:
```python
programs = (
('app', 'viewa'),
('app', 'viewb'),
('common', 'viewc'),
)
path('demo/', dynamic_urls(programs))
```
As you see, you can let programs comes from database or other data srouces.
;-)