django-viewflow - getting task URL without request - django-viewflow

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?

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"

If you have the task object in a template, you can extract the url as follows:
Task Link
This could be added as a template filter if used often.
This is a dirty hack untill I understand how the namespaces work.

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.

Related

Get AWS SSM Parameters Tags without Get Parameter

I am trying to list of all Parameters along with all their tags, I am trying to do so without listing the value of the parameters.
My initial approach was to do a describe_parameters and then loop through the Key Names and then perform list_tags, while doing so I found out that the ARNs are needed to perform list_tags which are not returned in the describe parameters.
Is there a way to get the parameters along with their tags without actually getting the parameters?
You can do this with the resource groups tagging api IF THEY ARE ALREADY TAGGED. Here's a basic example below without pagination.
import boto3
profile = "your_profile_name"
region = "us-east-1"
session = boto3.session.Session(profile_name=profile, region_name=region)
client = session.client('resourcegroupstaggingapi')
response = client.get_resources(
ResourceTypeFilters=[
'ssm',
],
)
print(response)
If you're wanting to discover untagged parameters, this won't work. Better would be to setup config rules to highlight these issues without you having to manage searching for them.

django-viewflow, multiple flows within the same app causes url not unique via #rest.register

Say I have an app called 'MRT`, inside the app I have 2 flow definitions.
Flow_A and Flow_B
both registered via #rest.register as below:
#frontend.register
#rest.register
class Flow_A(Flow):
....
#frontend.register
#rest.register
class Flow_B(Flow):
....
When I runserver, it raises warning: ?: (urls.W005) URL namespace 'viewflow_rest:mrt' isn't unique. You may not be able to reverse all URLs in this namespace
The consequences of this is that causing tasks of one of the flow(depends on which one registered last) cannot be url reversed. eg. Reverse for 'check_size__detail' not found. 'check_size__detail' is not a valid view function or pattern name.
Issue has been rectified in v1.5.11
see github ticket

Navigating from Location to Workorder

I need to :
1. Create a single page location application
2. Display all the asset present in the selected location in a table
3. Provide a button from which user can navigate to WOTRACK to view all the workorder(s) created on selected location and its asset(s).
I am facing difficulty in the 3rd one. I have tried Launch in Context and it is working fine except am not able to pass sql query like 'location={location} and assetnum in ({asset.assetnum})'. I need to filter workorders with particular location and all its assets.
I tried to save all the assets in the location to a Non-persistant attribute and passing the values of the attribute in the Launch in context url, Its working as expected but to do so I have written a script on 'Initialize value' which is causing performance issues.
script goes like this:
from psdi.server import MXServer;
from psdi.mbo import MboConstants;
if app == "LOCATION1" :
if mbo.getString("LOCATION") is not None:
Locsite = mbo.getString("SITEID")
desc = mbo.getString("DESCRIPTION")
MaxuserSet = MXServer.getMXServer().getMboSet("MAXUSER", mbo.getUserInfo())
MaxuserSet.setWhere(" userid='"+user+"' ")
MaxuserSet.reset()
UserSite = MaxuserSet.getMbo(0).getString("DEFSITE")
if Locsite == UserSite:
AssetSet = mbo.getMboSet("ASSET")
AssetSet.setFlag(MboConstants.DISCARDABLE, True);
if not AssetSet.isEmpty():
AssetList = ""
AssetMbo = AssetSet.moveFirst()
while AssetMbo is not None:
AssetList = AssetList + str(AssetMbo.getString("ASSETNUM")) + "%2C"
AssetMbo = AssetSet.moveNext()
mbo.setValue("non-persitant",str(AssetList),11L)
and in the LIC url i have given : 'http://xx.x.x.xx/maximo/ui/?event=loadapp&value=wotrack&tabid=List&additionalevent=useqbe&additionaleventvalue=location={LOCATION}|assetnum={non-persistant}'
Is there any other feasible solution to the requirement?
Thanks in Advance
Launch In Context is better used for sending the user to an outside-of-Maximo application and passing along some data from inside-Maximo to provide context in that external app.
What you are doing sounds like a good place to use a workflow process with an Interaction node. The developer tells the Interaction node which app to take the user to and which Relationship to use to find the data the user should work with there.
Why don't you add a table control inside the table details (expanded table row) and show a list of the work orders there. From the WONUM in that table, you could have an app link to take them to WOTRACK, if they want more details about a particular work order. No customization (automation scripting) needed. No workflow needed. Nice and simple.

Any examples of using multilogicadapter in chatterbot?

I am trying to combine multiple logic adapters in Python chatterbot. I cannot seem to get it right. I tried this:
english_bot = ChatBot("English Bot",
storage_adapter="chatterbot.storage.SQLStorageAdapter",
multi_logic_adapter = [
"chatterbot.logic.MathematicalEvaluation",
"chatterbot.logic.TimeLogicAdapter",
"chatterbot.logic.BestMatch"]
)
Only BestMatch seems to be active
And I tried this:
english_bot = ChatBot("English Bot",
storage_adapter="chatterbot.storage.SQLStorageAdapter",
logic_adapter = [
"chatterbot.logic.multi_adapter.MultiLogicAdapter",
"chatterbot.logic.MathematicalEvaluation",
"chatterbot.logic.TimeLogicAdapter",
"chatterbot.logic.BestMatch"]
)
But I get this error: AttributeError: 'NoneType' object has no attribute 'confidence' and none of the logic_adapters seems to be active.
Thanks,
Herb
BestMatch
Adapter is the default adapter for chatterbot, You don't need explicitly specify that. More information http://chatterbot.readthedocs.io/en/stable/logic/index.html#best-match-adapter
And you code should like this
# -*- coding: utf-8 -*-
from chatterbot import ChatBot
bot = ChatBot(
"English Bot",
logic_adapters=[
"chatterbot.logic.MathematicalEvaluation",
"chatterbot.logic.TimeLogicAdapter"
]
)
# Print an example of getting one math based response
response = bot.get_response("What is 4 + 9?")
print(response)
# Print an example of getting one time based response
response = bot.get_response("What time is it?")
print(response)
Every logic adapter in logic_adapters=[] is automatically processed by MultiLogicAdapter. You might need to tweak the confidence levels though.
More info about the MultiLogicAdapter here:
http://chatterbot.readthedocs.io/en/stable/logic/multi-logic-adapter.html
Multi Logic adapter is an inbuilt class and is not explicitly defined in the code.You can see this statement in the introduction part:"ChatterBot internally uses a special logic adapter that allows it to choose the best response generated by any number of other logic adapters" This is the link - http://chatterbot.readthedocs.io/en/stable/logic/multi-logic-adapter.html
Also, similar query is already available on stackover flow. Refer this as well.
Error while using chatterbot
The MultiLogicAdapter typically doesn't get used directly in this way.
Each logic adapter that you add to the logic_adapters=[] will get processed by the MultiLogicAdapter internally by ChatterBot, no need to explicitly specify it.

Codeigniter routing URL with product name to product id

I need to redirect the URLs like this http://mysite.com/store/store-name to http://mysite.com/stores/products/store-id. Note that i need to get the store id from the database. So is it possible to do db operations in routes.php?
And in documentation the syntax is give as $route['store/:any']. How to get the value of second parameter here which is mentioned as :any.
There's not really any good nor simple way of running database queries through the routes. You can however have in the beginning of the controller function a validation.
I asume your store-name is some sort of slug for the product? Basicly you can validate if value is numeric or not, and if not find by slug and then redirect.
config/routes.php
$route["store/(.*)"] = 'stores/products/$1';
/* () and $1 together passes the values */
controllers/stores.php
/* Class etc. */
function products($mix) {
if (is_numeric($mix))
$int_id = $mix;
else {
$row = $this->get_where('products', array('slug' => $mix))->row();
$this->load->helper('url');
redirect("stores/products/{$row->id}");
}
/* Do stuff with the $int_id */
}
This asumes that you have:
A table named products
A column named id that's your products id
A column named slug that that's based on your store-name
I may be a little late to the party, but I may have an alternative suggestion.
I use the following for my routes:
http://mysite.com/store/1/store-name
Reason being... Based on your method, if you create
http://mysite.com/store/store-name
but then after a period of time (of which no doubt Google has indexed your page) you decide for what ever reason you have to change the name of the store to "Wonderful store name", you would naturally change your link to
http://mysite.com/store/wonderful-store-name
Which kills your SEO and any index links.
My solution of using http://mysite.com/store/1/store-name means that you can change store-name to anything you want, but it will always reference 1 meaning the user will still see the related page.
Anything is possible with CodeIgniter routes. Its all in the way you code it. Routing in CI is really flexible. You can use regular expressions besides the standard CI wildcards (:any)(:num). You can even add prefixes or suffixes to the path variables if you have to like:
$route['store/(:any)'] = "redircontroller/redirfunction/$1";
// for instance the namelookup method of the mystores controller
$route['stores/products/(:any)'] = "mystores/namelookup/$1";
You get the second parameter(and third and so on) by defining the variables in your route value which get passed to the controller method you define. If 'products' in you new url is also a variant you should start your wildcard expression there instead. You could also pull parameters out of the url using the URI class ($this->uri->segment(n)).
You don't, however, do database operations in routes.php. You do your database operations in the controller where you route to. My guess is that you'll have to match the store id using whatever is used in the url in a query.
In any case the path that you are using the routes file for is the path the user will see. To do the redirect you have to accept the original path and then redirect the user to the new path like so:
// in some controller that's attached to the original url
public function redirfunct($var){
$this->load->helper('url');
redirect(base_url('stores/products/' . $var));
}
I hope this helps you.
Yes that is easy, you only need to show the ID instead of the name,
you must be doing like storeName> Click to view details
Make it as
storeId> Click to view details
and when you are passing the parameter to the database, change the check of mysql, change it to id instead of name , that can be some like
" select yourRequiredColumn from table_name where id=".parameter."
Thanks

Resources