django-viewflow - getting task URL without request

624 Views Asked by At

Knowing task instance is there a way to get the url of it? For example in the cookbook: https://github.com/viewflow/cookbook/blob/master/helloworld/demo/helloworld/flows.py - how do I get the url of assign task of approve flow_task?

I know there is flow_task.get_task_url(task, url_type='guess', namespace='', **kwargs), but the point is that from what I can see the namespace is usually fetched from self.request.resolver_match.namespace. That's not ideal - what if we are in other part of the app and we simply want to provide links to the tasks directly?

3

There are 3 best solutions below

5
On BEST ANSWER

Same as with django reverse you need to pass a namespace to get an URL. In case of build-in viewflow frontend the namespace is viewflow:[app_label]:[flow_label] ex: "viewflow:helloworld:helloworld"

0
On

If you have the task object in a template, you can extract the url as follows:

<a href="/workflow/formworkflow/{{ task.process.flow_class.flow_name }}/{{ task.process.flow_class.process_name }}/{{ task.process.pk }}/{{task.flow_task.name}}/{{task.id}}">Task Link</a>

This could be added as a template filter if used often.

This is a dirty hack untill I understand how the namespaces work.

1
On

To get the url of a task all you need is the app_name(app_namespace), flow_namespace and flow_label. The most challenging item here is the flow_namespace (if you have not used the frontend urls). To resolve this, you could use a map borrowing from FlowListMixin's ns_map. Defining the flow_namespace for every flow in your project. You then determine the flows namespace and url_name from the above.

ns_map = {'MyFlow':'flow_namespace', 'AnotherFlow':'flow_namespace2'}

# flow_namespace as defined in the urls.py
# e.g if you defined your flow urls as
# flow_urls = FlowViewSet(MyFlow).urls
# flow_urls2 = FLowViewSet(MyFlow2).urls
# urlpatterns = [url(r'flow_path/', include(flow_urls, name=flow_namespace)),
# url(r'flow_path2/', include(flow_urls2, name=flow_namespace2)),
# ]
# With this is included in the root_url as
# urlpatterns = [
#     url(r'app/' include(app_urls, namespace='app_namespace')
#]

What you need is to reverse the flow like this reverse('app_name:flow_namespace:flow_label', kwargs={'process_pk':ppk, 'task_pk':tpk})

flow_class_name = task.process.flow_class.__name__
flow_namespace = ns_map.get(flow_class_name)
app_name = task.process.flow_class.__module__.split('.')[0]
flow_label = task.flow_task.name
url_name = "{}:{}:{}".format(app_name, flow_label, url_name)

Then you can reverse your task url

url = reverse(url_name, kwargs={"task_pk", task.pk, "process_pk":task.flow_process.pk}

# If you know where you are you could use resolver match to determine
# the app namespace. Be Sure of this, see more of that [here][1]

NOTE: I am assuming that you namespaced your apps as app_name If it is different you have to find alternatives to finding the app_names namespace but that should not be too difficult.