【问题标题】:Django is searching the URL in the wrong applicationDjango 在错误的应用程序中搜索 URL
【发布时间】:2020-07-21 22:28:17
【问题描述】:

我的应用程序当前正在使用外部应用程序提供的 URL。我决定覆盖他们的一些观点,但这导致了 django 在错误目录中搜索 URL 的问题。

这是我的一些代码来解释这个问题:

url.py(不是根配置,但它在我的主应用程序中)

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

views.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

有没有办法解决这个问题?

编辑

这是我覆盖的完整类,它属于一个名为 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)

应用程序根据它附带的 flow.py 抽象生成 URL,如果我没有错,这里是它的生成位置:

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

【问题讨论】:

  • 有趣。您能否提供pipeline_urls 文件和实际的TaskView 代码,它也没有被覆盖? (它可能有帮助,也可能没有!但最好把它们放在这里)
  • @aasmpro 嘿!我已经更新了上面的帖子,我认为 URL 是动态生成的,如上所示

标签: python django url view namespaces


【解决方案1】:

我正在回答我自己的问题,因为我发现了上述错误的问题。

通过改变

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

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

问题已解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2017-05-19
    • 2017-02-28
    相关资源
    最近更新 更多