I have this code in views.py:
def pins_info(request):
if request.method == "GET":
getpin = request.GET.get('pin', None)
m = ButuanMaps.objects.filter(clandpin=getpin).
values_list('landproperty__ctaxdec')
n = ButuanMaps.objects.filter(clandpin=getpin).
values_list('ssectionid__sbrgyid__cbrgyname')
return HttpResponse(json.dumps({'taxdec': list(m),'brgy': list(n)}),
content_type='application/json')
I works fine, but it is not that effective when I want to get other values. I can access the result in my template like this:
success: function(data) {
taxdec = data['taxdec'];
brgy = data['brgy'];
var inputform = $('#forminput').val();
if( inputform == "Select Land PIN") {
alert('Please Select Land PIN')
}
else{
$('#status').append(
"<p>Tax Declaration: " + taxdec + "<br/>Barangay: " + brgy + "</p>"
);
}
}
How can I simplify my code to make it more effective like:
m = ButuanMaps.objects.filter(clandpin=getpin).
values_list('landproperty__ctaxdec','ssectionid__sbrgyid__cbrgyname')
But how do I pass it to my template?
If we take your m and n queries as:
m = range(5)
n = range(6, 11)
Then your single query of m = ButuanMaps.objects.filter(clandpin=getpin). values_list('landproperty__ctaxdec','ssectionid__sbrgyid__cbrgyname') is equivalent to the structure of:
new = zip(m, n)
#[(0, 6), (1, 7), (2, 8), (3, 9), (4, 10)]
So you can "transpose" that:
zip(*new)
# [(0, 1, 2, 3, 4), (6, 7, 8, 9, 10)]
Then build a dict from that and your keys:
results = dict(zip(['taxdec', 'brgy'], zip(*new))))
# {'brgy': (6, 7, 8, 9, 10), 'taxdec': (0, 1, 2, 3, 4)}
Then json.dumps results.
Or use an OrderedDict for your JSON name and column names values and generalise further:
from collections import OrderedDict
keyvals = OrderedDict([
('taxdec','landproperty__ctaxdec'),
('brgy', 'ssectionid__sbrgyid__cbrgyname')
])
m = ButuanMaps.objects.filter(clandpin=getpin).values_list(*keyvals.values())
result = dict(zip(keyvals, zip(*m)))
That way, you can add/remove columns to be selected and their associated JSON values in one place for the same query.
Related
I am trying to save all function arguments as it is ran, to a container. Container is common for all funcs ran in the script. How to ensure all container's content is NOT saved every time I save function arguments?
Below decorator saves function arguments:
import inspect
from datetime import datetime
import time
def func_logger(method):
def wrapper(*args, **kw):
method_args = inspect.signature(method).bind(*args, **kw).arguments
runtime = str( datetime.now() )
name = method.__name__
module = method.__module__
signature = runtime + ': ' + '.'.join([module, name])
ts = time.time()
result = method(*args, **kw)
te = time.time()
kw['log'][signature] = {}
kw['log'][signature]['time'] = round(te - ts, 2)
kw['log'][signature]['args'] = method_args
return result
return wrapper
And an example function:
#func_logger
def test(a, b=4, c='blah-blah', *args, **kwargs):
return 4**4**8
When I am running the following snippet:
log = {}
output = test(1,4,2,4,1,par=1, log=log)
output = test(1,4,2,4,1,par=1, log=log)
log
I receive this output:
{'2019-05-17 13:48:25.214094: __main__.test': {'time': 0.0,
'args': OrderedDict([('a', 1),
('b', 4),
('c', 2),
('args', (4, 1)),
('kwargs', {'par': 1, 'log': {...}})])},
'2019-05-17 13:48:25.215092: __main__.test': {'time': 0.0,
'args': OrderedDict([('a', 1),
('b', 4),
('c', 2),
('args', (4, 1)),
('kwargs', {'par': 1, 'log': {...}})])}}
I already tried a workaround - a function that removes 'log' entry from the dictionary. However, every next item in this log stores of the log's current content. So when I try this:
list( log.items() )[-1][-1]['args']
The output is this:
OrderedDict([('a', 1),
('b', 4),
('c', 2),
('args', (4, 1)),
('kwargs',
{'par': 1,
'log': {'2019-05-17 13:45:45.748722: __main__.test': {'time': 0.0,
'args': OrderedDict([('a', 1),
('b', 4),
('c', 2),
('args', (4, 1)),
('kwargs', {'par': 1, 'log': {...}})])},
'2019-05-17 13:45:45.749221: __main__.test': {'time': 0.0,
'args': OrderedDict([('a', 1),
('b', 4),
('c', 2),
('args', (4, 1)),
('kwargs', {'par': 1, 'log': {...}})])},
'2019-05-17 13:45:45.750218: __main__.test': {'time': 0.0,
'args': OrderedDict(...)}}})])
So essentially, such a workaround won't work because with time, the memory would get clogged quickly.
Is there any way decorator would not save log entry every time I save function arguments? What I would rather like to avoid is to create a new 'log = {}' container every time I want to dump arguments from a new function.
You could simply store the log parameter if present and remove it from **kw:
def func_logger(method):
def wrapper(*args, **kw):
try:
log = kw['log']
del kw['log']
except KeyError:
log = None
method_args = inspect.signature(method).bind(*args, **kw).arguments
runtime = str( datetime.now() )
name = method.__name__
module = method.__module__
signature = runtime + ': ' + '.'.join([module, name])
ts = time.time()
result = method(*args, **kw)
te = time.time()
if log is not None:
log[signature] = {}
log[signature]['time'] = round(te - ts, 2)
log[signature]['args'] = method_args
return result
return wrapper
use global log in func_logger
log = {}
def func_logger(method):
def wrapper(*args, **kw):
# pass
log[signature] = {...}
return result
return wrapper
then, use output = test(1,4,2,4,1,par=1)
i have done following things
def handle_json(obj):
# i want to make sure control goes here
print(obj)
return obj
def test_json():
data= {datetime.date(2018, 12, 1): 160000.0,
datetime.date(2019, 2, 1): 240000.0,
datetime.date(2020, 9, 1): 1360000.0,
datetime.date(2019, 3, 1): 280000.0}
print(json.dumps(data, default=handle_json))
When i run test_json(), why i am not getting print() from handle_json() on console?
I am trying to modify the fuzzywuzzy library. The module process returns the score and the array element. But I want it to return the index of the element along with the group of score,item,index.
Here is what I tried:
#!/usr/bin/env python
# encoding: utf-8
from fuzzywuzzy import fuzz
from fuzzywuzzy import utils
import heapq
import logging
from functools import partial
default_scorer = fuzz.WRatio
default_processor = utils.full_process
def extractWithoutOrder(query, choices, processor=default_processor, scorer=default_scorer, score_cutoff=0):
def no_process(x):
return x
try:
if choices is None or len(choices) == 0:
raise StopIteration
except TypeError:
pass
if processor is None:
processor = no_process
processed_query = processor(query)
if len(processed_query) == 0:
logging.warning(u"Applied processor reduces input query to empty string, "
"all comparisons will have score 0. "
"[Query: \'{0}\']".format(query))
# Don't run full_process twice
if scorer in [fuzz.WRatio, fuzz.QRatio,
fuzz.token_set_ratio, fuzz.token_sort_ratio,
fuzz.partial_token_set_ratio, fuzz.partial_token_sort_ratio,
fuzz.UWRatio, fuzz.UQRatio] \
and processor == utils.full_process:
processor = no_process
# Only process the query once instead of for every choice
if scorer in [fuzz.UWRatio, fuzz.UQRatio]:
pre_processor = partial(utils.full_process, force_ascii=False)
scorer = partial(scorer, full_process=False)
elif scorer in [fuzz.WRatio, fuzz.QRatio,
fuzz.token_set_ratio, fuzz.token_sort_ratio,
fuzz.partial_token_set_ratio, fuzz.partial_token_sort_ratio]:
pre_processor = partial(utils.full_process, force_ascii=True)
scorer = partial(scorer, full_process=False)
else:
pre_processor = no_process
processed_query = pre_processor(processed_query)
count = -1
try:
# See if choices is a dictionary-like object.
for key, choice in choices.items():
count = count + 1
processed = pre_processor(processor(choice))
score = scorer(processed_query, processed)
if score >= score_cutoff:
yield (choice, score, key,count)
except AttributeError:
# It's a list; just iterate over it.
for choice in choices:
count = count + 1
processed = pre_processor(processor(choice))
score = scorer(processed_query, processed)
if score >= score_cutoff:
yield (choice, score,count)
def extract(query, choices, processor=default_processor, scorer=default_scorer, limit=5):
sl = extractWithoutOrder(query, choices, processor, scorer)
return heapq.nlargest(limit, sl, key=lambda i: i[1]) if limit is not None else \
sorted(sl, key=lambda i: i[1], reverse=True)
When I tried to implement it, the result was what it was previously showing by fuzzywuzzy.
import process as p
box=['ness', 'apple','banana','carrot','duck','eagle','fish','gate','hitler']
p.extract('b',box)
[('banana', 90), ('apple', 0), ('carrot', 0), ('duck', 0), ('eagle', 0)]
But what I am expecting it to return is:
[('banana', 90, 2), ('apple', 0, 1), ('carrot', 0, 3), ('duck', 0, 4), ('eagle', 0, 5)]
Kindly let me know the suggestion.
As an alternative to FuzzyWuzzy you could use RapidFuzz (I am the author) which will return the index as well:
from rapidfuzz import process
box=['ness', 'apple','banana','carrot','duck','eagle','fish','gate','hitler']
p.extract('b',box)
which returns
[('banana', 90, 2), ('apple', 0, 1), ('carrot', 0, 3), ('duck', 0, 4), ('eagle', 0, 5)]
For those looking for the answer, can pass a dictionary to the process.
from fuzzywuzzy import fuzz
from fuzzywuzzy import process
box = ['apple','banana','carrot','duck','eagle']
box_dict = {i: val for i, val in enumerate(box)}
process.extract("b", box_dict, scorer=fuzz.WRatio)
# O/P -> [("banana", 90, 1), ('apple', 0, 0), ('carrot', 0, 2), ('duck', 0, 3), ('eagle', 0, 4)]
I have a list of tuples like
list_of_tuples = [(number, name, id, parent_id),
(number, name, id, parent_id),
]
I am trying to sort it into an ordered structure like:
{
parent: [(id, name), (id, name)],
parent: {parent: [(id, name)]
{
So, any node could have a parent and/or children
I tried with:
tree = defaultdict(lambda: [None, ()])
ancestors = set([item[3] for item in list_of_tuples])
for items in list_of_tuples:
children_root = {}
descendants = []
number, name, id, parent = items
if parent is None:
tree[id] = [(id, name)]
elif parent:
if parent not in tree.keys():
node = tree.get(parent)
node.append((id, name))
children = (id, name)
tree[parent].append(children)
But I'm losing deep hierarchy when a node has both a parent and children
How do I make the ordering work correctly?
I propose to represent the tree nodes as tuples ((id, name), dict_of_children).
list_of_tuples = [(1, 'name1', 1, None),
(2, 'name2', 2, 1),
(3, 'name3', 3, 1),
(4, 'name4', 4, 2),
(5, 'name5', 5, 2),
(6, 'name5', 6, None),
(7, 'name5', 7, 6),
]
def build_tree(list_of_tuples):
"""
>>> import pprint
>>> pprint.pprint(build_tree(list_of_tuples))
{1: ((1, 'name1'),
{2: ((2, 'name2'), {4: ((4, 'name4'), {}), 5: ((5, 'name5'), {})}),
3: ((3, 'name3'), {})}),
6: ((6, 'name5'), {7: ((7, 'name5'), {})})}
"""
all_nodes = {n[2]:((n[2], n[1]), {}) for n in list_of_tuples}
root = {}
for item in list_of_tuples:
number, name, id, parent = item
if parent is not None:
all_nodes[parent][1][id] = all_nodes[id]
else:
root[id] = all_nodes[id]
return root
I am using the following code to extract the geolocation of an image taken with an iPhone:
from PIL import Image
from PIL.ExifTags import TAGS
def get_exif(fn):
ret = {}
i = Image.open(fn)
info = i._getexif()
for tag, value in info.items():
decoded = TAGS.get(tag, tag)
ret[decoded] = value
return ret
a = get_exif('photo2.jpg')
print a
This is the result that I am returned:
{
'YResolution': (4718592, 65536),
41986: 0,
41987: 0,
41990: 0,
'Make': 'Apple',
'Flash': 32,
'ResolutionUnit': 2,
'GPSInfo': {
1: 'N',
2: ((32, 1), (4571, 100), (0, 1)),
3: 'W',
4: ((117, 1), (878, 100), (0, 1)),
7: ((21, 1), (47, 1), (3712, 100))
},
'MeteringMode': 1,
'XResolution': (4718592, 65536),
'ExposureProgram': 2,
'ColorSpace': 1,
'ExifImageWidth': 1600,
'DateTimeDigitized': '2011:03:01 13:47:39',
'ApertureValue': (4281, 1441),
316: 'Mac OS X 10.6.6',
'SensingMethod': 2,
'FNumber': (14, 5),
'DateTimeOriginal': '2011:03:01 13:47:39',
'ComponentsConfiguration': '\x01\x02\x03\x00',
'ExifOffset': 254,
'ExifImageHeight': 1200,
'Model': 'iPhone 3G',
'DateTime': '2011:03:03 10:37:32',
'Software': 'QuickTime 7.6.6',
'Orientation': 1,
'FlashPixVersion': '0100',
'YCbCrPositioning': 1,
'ExifVersion': '0220'
}
So, I am wondering how I convert the GPSInfo values (DMS) to Decimal Degrees for actual coordinates? Also, there seems to be two Wests listed . . . ?
Here's a way to do it, adapted for a script I wrote some months ago using pyexiv2:
a = get_exif('photo2.jpg')
lat = [float(x)/float(y) for x, y in a['GPSInfo'][2]]
latref = a['GPSInfo'][1]
lon = [float(x)/float(y) for x, y in a['GPSInfo'][4]]
lonref = a['GPSInfo'][3]
lat = lat[0] + lat[1]/60 + lat[2]/3600
lon = lon[0] + lon[1]/60 + lon[2]/3600
if latref == 'S':
lat = -lat
if lonref == 'W':
lon = -lon
This gives me the following latitude and longitude for your picture: 32.7618333, -117.146333 (same results as Lance Lee).
The last entry of GPSInfo may be the heading of the picture. You could check this using a tool that gives proper names to the different EXIF values such as exiv2 or exiftools.
http://www.exiv2.org/tags.html
find the string 'Exif.GPSInfo.GPSLatitude' in that page.
It appears that you get 3 pairs (representing rationals) and the second number in the pair is the denominator.
I would expect the thing after Longitude to be altitude, however it is a better fit for GPS timestamp.
In this example:
32/1 + (4571 / 100)/60 + (0 / 1)/3600 = 32.761833 N
117/1 + (878 / 100)/60 + (0 / 1)/3600 = 117.146333 W
Was this picture taken near 4646 Park Blvd, San Diego, CA 92116? If not then ignore this answer.