Как превратить переменную в модуль с хаком sys.modules? - PullRequest
0 голосов
/ 05 июня 2019
import os
from glob import glob
from importlib import import_module

from django.urls import re_path as _re_path, path as _path


def _glob_init(name):
    name = name.replace('.', os.sep)
    path = os.sep + '**'
    modules = []
    for module in glob(name + path, recursive=True):
        importable = os.path.splitext(module)[0].replace(os.sep, '.')
        if '__' in importable:
            continue
        try:
            module = import_module(importable)
        except ModuleNotFoundError:
            module = import_module(importable[:-1])
        modules.append(module)
    return modules


class UrlManager:
    def __init__(self, views_root):
        self.views_root = views_root
        self._url_patterns = []

    def _path(self, route, kwargs=None, name=None, is_re=None):
        func = _re_path if is_re else _path

        def decorator(view):
            _view = view  # keep the original view
            if isinstance(view, type):
                view = view.as_view()
            self._url_patterns.append(
                func(route, view, kwargs=kwargs, name=name or view.__name__)
            )
            return _view

        return decorator

    def path(self, route, kwargs=None, name=None):
        return self._path(route, kwargs=kwargs, name=name, is_re=False)

    def re_path(self, route, kwargs=None, name=None):
        return self._path(route, kwargs=kwargs, name=name, is_re=True)

    @property
    def url_patterns(self):
        if isinstance(self.views_root, str):
            _glob_init(self.views_root)
        else:
            for root in self.views_root:
                _glob_init(root)
        return self._url_patterns

Основное использование:

# app.urls.py 

app_urls = UrlManager('app.views')

# app.views.py

from models import SomeModel
from urls import app_urls

@app_urls.path('foo/', name='foo')
def view(request):
    return response

# project.urls.py

from django.urls import include
from app.urls import app_urls

urlpatterns = [
    path('', include(app_urls.urlpatterns))
]

Хорошо, теперь:

Все работает, когда миграции уже запущены и работают, но когда вы хотите создать новую миграцию; из-за того, что этот поток кода выглядит примерно так:

- проект urls.py импортирует app.urls

- app.urls импортирует представления

- просмотр импортируемых моделей

- модели еще не существуют, потому что это команда миграции, запускаемая

- ошибка

Мне нужно как-то либо создать модуль с именем instance, чтобы я мог использовать include('module.urls'), либо каким-либо другим способом отложить импорт.

Репо на https://github.com/isik-kaplan/django_urls, если кто-то хочет открыть пр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...