Django ищет URL в неправильном приложении - PullRequest
0 голосов
/ 09 апреля 2020

Мое приложение в настоящее время использует URL-адреса, предоставленные внешним приложением. Я решил переопределить некоторые из их представлений, однако это привело к проблеме, из-за которой django ищет URL в неправильном каталоге.

Вот мой код, объясняющий проблему:

url.py (не в конфигурации root, но в моем основном приложении)

urlpatterns = [
path('pipeline/<process_pk>/documents/<task_pk>/assign/',    #<---- this is the URL and view that i overrode
    OverrideTaskView.as_view(),
    {'flow_class': Pipeline,
    'flow_task': Pipeline.documents},
    name="pipeline:{}__assign".format(Pipeline.documents.name)),
path('pipeline/', include((pipeline_urls,'pipeline'))),   #<--- this is the app-supplied URLs

просмотров .py

class OverrideTaskView(CoreAssignTaskView,FormView):  #<--- im inheritting the view from the third party app
form_class=AssignForm
action_name = 'assign'

def post(self, request, *args, **kwargs):
    if '_assign' or '_continue' in request.POST:
        self.activation.assign(self.request.user)
        return HttpResponseRedirect(self.get_success_url())  #<---- this is where it calls the faulty code
    else:
        return self.get(request, *args, **kwargs)

def get_success_url(self):                                   #<--- in this get success url the  self.request.resolver is returning the wrong value
    """Continue on task or redirect back to task list."""
    url = self.activation.flow_task.get_task_url(
        self.activation.task, url_type='guess', user=self.request.user,
        namespace=self.request.resolver_match.namespace + ':' + 'pipeline')

    back = self.request.GET.get('back', None)
    if back and not is_safe_url(url=back, allowed_hosts={self.request.get_host()}):
        back = '/'

    if '_continue' in self.request.POST and back:
        url = "{}?back={}".format(url, urlquote(back))
    elif back:
        url = back

    return url

Кусок кода:

url = self.activation.flow_task.get_task_url(
    self.activation.task, url_type='guess', user=self.request.user,
    namespace=self.request.resolver_match.namespace + ':' + 'pipeline')

возвращает неправильное значение:

cash

, которое является пространством имен основного приложения, однако оно вместо этого должно возвращаться:

cash:pipeline

есть ли способ решить эту проблему?

edit

Это полный класс, который я переопределил, он принадлежит пакету с именем viewflow

class AssignTaskView(MessageUserMixin, generic.TemplateView):
    """
    Default assign view for flow task.
    Get confirmation from user, assigns task and redirects to task pages
    """

action_name = 'assign'

def get_template_names(self):
    """List of template names to be used for a process detail page.
    If `template_name` is None, default value is::
        [<app_label>/<flow_label>/<task_name>_assign.html,
         <app_label>/<flow_label>/task_assign.html,
         'viewflow/flow/task_assign.html']
    """
    if self.template_name is None:
        flow_task = self.activation.flow_task
        opts = self.activation.flow_class._meta

        return (
            '{}/{}/{}_assign.html'.format(opts.app_label, opts.flow_label, flow_task.name),
            '{}/{}/task_assign.html'.format(opts.app_label, opts.flow_label),
            'viewflow/flow/task_assign.html')
    else:
        return [self.template_name]

def get_context_data(self, **kwargs):
    """Context for a detail view.
    :keyword activation: the task activation instance
    """
    context = super(AssignTaskView, self).get_context_data(**kwargs)
    context['activation'] = self.activation
    return context

def get_success_url(self):
    """Continue on task or redirect back to task list."""
    url = self.activation.flow_task.get_task_url(
        self.activation.task, url_type='guess', user=self.request.user,
        namespace=self.request.resolver_match.namespace)

    back = self.request.GET.get('back', None)
    if back and not is_safe_url(url=back, allowed_hosts={self.request.get_host()}):
        back = '/'

    if '_continue' in self.request.POST and back:
        url = "{}?back={}".format(url, urlquote(back))
    elif back:
        url = back

    return url

def post(self, request, *args, **kwargs):
    """
    Assign task to the current user.
    Expect that form submitted with `_continue` or `_assign` button::
        <button type="submit" name="_continue">Assign and continue on this process</button>
        <button type="submit" name="_assign">Assign</button>
    """
    if '_assign' or '_continue' in request.POST:
        self.activation.assign(self.request.user)
        self.success(_('Task {task} has been assigned'))
        return HttpResponseRedirect(self.get_success_url())
    else:
        return self.get(request, *args, **kwargs)

@method_decorator(flow_view)
def dispatch(self, request, *args, **kwargs):
    """Check permissions and assign task to the current user."""
    self.activation = request.activation

    if request.user is None or request.user.is_anonymous:
        raise PermissionDenied

    if not self.activation.assign.can_proceed():
        self.error(_('Task {task} cannot be assigned to you'))
        return redirect(self.activation.flow_task.get_task_url(
            self.activation.task, url_type='detail', user=request.user,
            namespace=self.request.resolver_match.namespace))

    if not self.activation.flow_task.can_assign(request.user, self.activation.task):
        raise PermissionDenied

    return super(AssignTaskView, self).dispatch(request, *args, **kwargs)

Приложение генерирует URL на основе абстракции flows.py, с которым оно поставляется, если я не ошибаюсь, вот где оно генерируется:

class FlowViewSet(object):
    """
    Shortcut for a flow urls routing.
    Usage::
        urlpatterns = [
            url(r'/helloworld/', include(FlowViewSet(HelloWorldFlow).urls))
        ]
    """
process_list_view = [
    r'^$',
    ProcessListView.as_view(),
    'index'
]

detail_process_view = [
    r'^(?P<process_pk>\d+)/$',
    DetailProcessView.as_view(),
    'detail'
]

cancel_process_view = [
    r'^action/cancel/(?P<process_pk>\d+)/$',
    CancelProcessView.as_view(),
    'action_cancel'
]

queue_list_view = [
    '^queue/$',
    QueueListView.as_view(),
    'queue',
]

archive_list_view = [
    '^archive/$',
    ArchiveListView.as_view(),
    'archive',
]

inbox_list_view = [
    '^tasks/$',
    TaskListView.as_view(),
    'tasks'
]

def __init__(self, flow_class):  # noqa D102
    self.flow_class = flow_class

def _create_url_entry(self, url_entry):
    regexp, view, name = url_entry
    return url(regexp, view, name=name)

def get_list_urls(self):
    """Collect urls from viewset class."""
    attrs = (getattr(self, attr) for attr in dir(self) if attr.endswith('_view'))
    return [
        self._create_url_entry(value)
        for value in attrs if isinstance(value, (list, tuple))
    ]

@property
def urls(self):
    """Collect the viewset and flow urls."""
    return [
        url('', include(self.get_list_urls()), {'flow_class': self.flow_class}),
        self.flow_class.instance.urls
    ]

и Вот как я генерировал, я назвал генератор URL, так сказать:

pipeline_urls = FlowViewSet(Pipeline).urls

1 Ответ

0 голосов
/ 09 апреля 2020

я отвечаю на свой вопрос, так как обнаружил проблему с ошибкой выше.

При изменении значения

path('pipeline/', include((pipeline_urls,'pipeline')))

на

 path('pipeline/', include(pipeline_urls)),

проблема была решена.

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