Мое приложение в настоящее время использует 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