python3 wx.TreeCtrl - how to iterate through several levels - python-3.x

I have a treectrl structure which is populated from an external search of an open data set hosted by our municipal government. The data pertains to business licenses and is requested using Pandas and Sodapy. The tree is populated as follows:
for index, row in results_df.iterrows():
tradename = row['tradename']
address = row['address']
licTypes = row['licencetypes']
comm = row['comdistnm']
jobSts = row['jobstatusdesc']
jobCrt = row['jobcreated']
lng = row['longitude']
lng = str(lng)
lat = row['latitude']
lat = str(lat)
# Populate Tree Controls with DataFrame values
trdName = self.thrTree.AppendItem(root, tradename)
self.thrTree.AppendItem(trdName, address)
self.thrTree.AppendItem(trdName, licTypes)
self.thrTree.AppendItem(trdName, comm)
self.thrTree.AppendItem(trdName, jobSts)
self.thrTree.AppendItem(trdName, jobCrt)
self.thrTree.AppendItem(trdName, lng)
self.thrTree.AppendItem(trdName, lat)
This will result in a final structure of root, then node 1 with business name, and when expanded, contains all the information listed above, so I'm assuming root level, then child node 1, then child.child of node 1? Not even sure how the second second indented nodes are called. (I've heard the term leaf for the third level used before) But I digress; what I am interested in is grabbing the Latitude and Longitude of where the business is located, then allowing the user to map the location if they choose. I bind a wx.EVT_TREE_ITEM_ACTIVATED so that when the user double clicks on a business name to get the details, I want to grab the items displayed. This is how I am currently trying to iterate through the child nodes.
item = self.thrTree.GetSelection()
while self.thrTree.GetItemParent(item):
piece = self.thrTree.GetItemText(item)
tmpHldr.insert(0, piece)
item = self.thrTree.GetItemParent(item)
Looking at item, it appears to be collecting all the business names under root, and ignoring the third level items of interest.
What do I need to do to go deeper within the tree to grab the details under the business clicked on, and not just the list of business names under the root item, which is called 'Search Results'?
Thanks!

#YYC_Code,
Did you look here?
This has GetFirstChild()/GetNextChild() pair functions that you can use to iterate. It also has ItemHasChildren() function which you can use to verify if the item has any children and use the pair mentioned above if it does.
EDIT:
[quote]
For this enumeration function you must pass in a ‘cookie’ parameter which is opaque for the application but is necessary for the library to make these functions reentrant (i.e. allow more than one enumeration on one and the same object simultaneously). The cookie passed to GetFirstChild and GetNextChild should be the same variable.
[/quote]
You need to make sure that the cookie parameter is the same during the iteration.
You should also do this:
[quote]
Returns an invalid tree item (i.e. wx.TreeItemId.IsOk returns False) if there are no further children.
[/quote]

Related

Is this efficient way to use Nim ref data structure?

I'm keeping in memory huge list of companies, and need to do lots of operations of getting individual company.
Like getting individual company "Microsoft" by its symbol "MSFT".
Would the data structure below be a proper way to model that? There should be no copy-by-value of the whole list or map.
It is ok if the individual company would be copied by value.
import tables
type
Company = object
name: string
symbol: string
description: string
CompaniesRef = ref object
list: seq[Company]
map: Table[string, Company]
# Cached data structure to keep thousands of different companies
var cached_companies: CompaniesRef
proc companies(): CompaniesRef =
if cached_companies == nil:
# Here will be a proper code of loading companies into the
# CompaniesRef data structure
cached_companies = CompaniesRef()
cached_companies
# Lots of operations of getting a specific company from the list
# or from the map by its symbol
for i in 1..1000:
# it's ok if individual company will be copied by value,
# but the whole list should be passed by reference
let company1 = companies().list[0].name
# it's ok if individual company will be copied by value
# but the whole map should be passed by reference
let company2 = companies().map["MSFT"]
That global structure should be fine as it is, an object reference is just a memory managed pointer, so passing its reference around only copies the memory address. Unless you are going to do something with that pointer, why not create it as a global? Hiding it behind a proc call reeks of the I'm-afraid-of-globals-but-can't-live-without-them-singleton pattern.
let companies = CompaniesRef()
With regards to the contents of the structure, you are storing twice each Company object, you might want to store a reference to the Company in the Table or simply use an OrderedTable if you need to keep the order of the inserted keys.

ArangoDB - Get edge information while using traversals

I'm interested in using traversals to quickly find all the documents linked to an initial document. For this I'd use:
let id = 'documents/18787898'
for d in documents
filter d._id == id
for i in 1..1 any d edges
return i
This generally provides me with all the documents related to the initial ones. However, say that in these edges I have more information than just the standard _from and _to. Say it also contains order, in which I indicate the order in which something is to be displayed. Is there a way to also grab that information at the same time as making the traversal? Or do I now have to make a completely separate query for that information?
You are very close, but your graph traversal is slightly incorrect.
The way I read the documentation, it shows that you can return vertex, edge, and path objects in a traversal:
FOR vertex[, edge[, path]]
IN [min[..max]]
OUTBOUND|INBOUND|ANY startVertex
edgeCollection1, ..., edgeCollectionN
I suggest adding the edge variable e to your FOR statement, and you do not need to find document/vertex matches first (given than id is a single string), so the FOR/FILTER pair can be eliminated:
LET id = 'documents/18787898'
FOR v, e IN 1 ANY id edges
RETURN e

Insert values into API request dynamically?

I have an API request I'm writing to query OpenWeatherMap's API to get weather data. I am using a city_id number to submit a request for a unique place in the world. A successful API query looks like this:
r = requests.get('http://api.openweathermap.org/data/2.5/group?APPID=333de4e909a5ffe9bfa46f0f89cad105&id=4456703&units=imperial')
The key part of this is 4456703, which is a unique city_ID
I want the user to choose a few cities, which then I'll look through a JSON file for the city_ID, then supply the city_ID to the API request.
I can add multiple city_ID's by hard coding. I can also add city_IDs as variables. But what I can't figure out is if users choose a random number of cities (could be up to 20), how can I insert this into the API request. I've tried adding lists and tuples via several iterations of something like...
#assume the user already chose 3 cities, city_ids are below
city_ids = [763942, 539671, 334596]
r = requests.get(f'http://api.openweathermap.org/data/2.5/groupAPPID=333de4e909a5ffe9bfa46f0f89cad105&id={city_ids}&units=imperial')
Maybe a list is not the right data type to use?
Successful code would look something like...
r = requests.get(f'http://api.openweathermap.org/data/2.5/group?APPID=333de4e909a5ffe9bfa46f0f89cad105&id={city_id1},{city_id2},{city_id3}&units=imperial')
Except, as I stated previously, the user could choose 3 cities or 10 so that part would have to be updated dynamically.
you can use some string methods and list comprehensions to append all the variables of a list to single string and format that to the API string as following:
city_ids_list = [763942, 539671, 334596]
city_ids_string = ','.join([str(city) for city in city_ids_list]) # Would output "763942,539671,334596"
r = requests.get('http://api.openweathermap.org/data/2.5/group?APPID=333de4e909a5ffe9bfa46f0f89cad105&id={city_ids}&units=imperial'.format(city_ids=city_ids_string))
hope it helps,
good luck

How to get many to many values and store in an array or list in python +django

Ok
i have this class in my model :
i want to get the agencys value which is a many to many on this class and store them in a list or array . Agency which store agency_id with the id of my class on a seprate table.
Agency has it's own tabel as well
class GPSpecial(BaseModel):
hotel = models.ForeignKey('Hotel')
rooms = models.ManyToManyField('Room')
agencys = models.ManyToManyField('Agency')
You can make it a bit more compact by using the flat=True parameter:
agencys_spe = list(GPSpecial.objects.values_list('agencys', flat=True))
The list(..) part is not necessary: without it, you have a QuerySet that contains the ids, and the query is postponed. By using list(..) we force the data into a list (and the query is executed).
It is possible that multiple GPSpecial objects have a common Agency, in that case it will be repeated. We can use the .distinct() function to prevent that:
agencys_spe = list(GPSpecial.objects.values_list('agencys', flat=True).distinct())
If you are however interested in the Agency objects, for example of GPSpecials that satisfy a certain predicate, you better query the Agency objects directly, like for example:
agencies = Agency.objects.filter(gpspecial__is_active=True).distinct()
will produce all Agency objects for which a GPSpecial object exists where is_active is set to True.
I think i found the answer to my question:
agencys_sp = GPSpecial.objects.filter(agencys=32,is_active=True).values_list('agencys')
agencys_spe = [i[0] for i in agencys_sp]

Filtering Haystack (SOLR) results by django_id

With Django/Haystack/SOLR, I'd like to be able to restrict the result of a search to those records within a particular range of django_ids. Getting these IDs is not a problem, but trying to filter by them produces some unexpected effects. The code looks like this (extraneous code trimmed for clarity):
def view_results(request,arg):
# django_ids list is first calculated using arg...
sqs = SearchQuerySet().facet('example_facet') # STEP_1
sqs = sqs.filter(django_id__in=django_ids) # STEP_2
view = search_view_factory(
view_class=SearchView,
template='search/search-results.html',
searchqueryset=sqs,
form_class=FacetedSearchForm
)
return view(request)
At the point marked STEP_1 I get all the database records. At STEP_2 the records are successfully narrowed down to the number I'd expect for that list of django_ids. The problem comes when the search results are displayed in cases where the user has specified a search term in the form. Rather than returning all records from STEP_2 which match the term, I get all records from STEP_2 plus all from STEP_1 which match the term.
Presumably, therefore, I need to override one/some of the methods in for SearchView in haystack/views.py, but what? Can anyone suggest a means of achieving what is required here?
After a bit more thought, I found a way around this. In the code above, the problem was occurring in the view = search_view_factory... line, so I needed to create my own SearchView class and override the get_results(self) method in order to apply the filtering after the search has been run with the user's search terms. The result is code along these lines:
class MySearchView(SearchView):
def get_results(self):
search = self.form.search()
# The ID I need for the database search is at the end of the URL,
# but this may have some search parameters on and need cleaning up.
view_id = self.request.path.split("/")[-1]
view_query = MyView.objects.filter(id=view_id.split("&")[0])
# At this point the django_ids of the required objects can be found.
if len(view_query) > 0:
view_item = view_query.__getitem__(0)
django_ids = []
for thing in view_item.things.all():
django_ids.append(thing.id)
search = search.filter_and(django_id__in=django_ids)
return search
Using search.filter_and rather than search.filter at the end was another thing which turned out to be essential, but which didn't do what I needed when the filtering was being performed before getting to the SearchView.

Resources