Django OR query - django

How would I do:
FinancialStatements.objects.get(statement_id=statement_id)
or SalesStatements.objects.get(statement_id=statement_id)
The result will always yield one result.
I ended up using the try/except route here:
try:
statement_object = FinancialStatements.objects.get(statement_id=statement_id)
except FinancialStatements.DoesNotExist:
statement_object = SalesStatements.objects.get(statement_id=statement_id)

Why not simply do:
result = (FinancialStatements.objects.filter(statement_id=statement_id) or
SalesStatements.objects.filter(statement_id=statement_id))
This should work, because filter returns a list - and an empty list if no entries match. An empty list evaluates to false in python's boolean logic, e.g. try running:
print [] or "hello"
(Just as a check, compare print ["Hi"] or "hello")
So, if the first query returns empty, the second will then be run. However, if the first matches anything, this will be result and the second query will be ignored.
Addendum: result will then be of a list type - you'll need to extract the (one and only) element with result[0].

Related

Python 3.5.2 Regex in List comprehension returns all entries - inconsistent with other example

I am searching a list for a particular entry. The entry is digits followed by oblique (one or many times).
If I put an example into a string and use re.match() I get the result.
If I put the string into a list and loop through I get a result from re.match()
If I try to get the index using list comprehension I get all the list indexes returned.
Using a different list I get the correct result.
Why is the list comprehension for my regex not just returning [2] as the control list does?
Example code:
import re
import sys
from datetime import datetime
rxco = re.compile
rx = {}
#String
s = r'140/154/011/002'
#String in a list
l = ['abc', 'XX123 SHDJ FFFF', s, 'unknown', 'TTL/4/5/6', 'ORD/123']
#Regex to get what I am interested in
rx['ls_pax_split'] = rxco(r'\s?((\d+\/?)*)')
#For loop returns matches and misses
for i in l:
m = re.match(rx['ls_pax_split'], i)
print(m)
#List Comprehension returns ALL entries - NOT EXPECTED
idx = [i for i, item in enumerate(l) if re.match(rx['ls_pax_split'], item)]
print(idx)
#Control Comprehension returns - AS EXPECTED
fruit_list = ['raspberry', 'apple', 'strawberry']
berry_idx = [i for i, item in enumerate(fruit_list) if re.match('rasp', item)]
print(berry_idx)
re.match(rx['ls_pax_split'], item) is returning a match object each time it runs, whereas re.match('rasp', item) is not. Therefore, the result of re.match(rx['ls_pax_split'], item) is always truthy.
Try adding .group(0) to the end of line 22 to get the string that matched the regular expression, or an empty string (i.e. a falsey value) if there was no match.
Like this:
idx = [i for i, item in enumerate(l) if re.match(rx['ls_pax_split'], item).group(0)]
EDIT
While the above will solve this problem, there may be a better way to avoid the hassle of dealing with .group. The regular expression (\d+\/?)* will match (\d+\/?) zero or more times, meaning that it is generating a lot of false positives where it detects exactly zero matches and therefore returns a match. Changing this to (\d+\/?)+ would solve it for this example by looking for one or more (\d+\/?).

Removing a word from a list which appears one after the other

Lets say i have a list of words as shown below,
A=['ab','bc','cd','de','de','ef','bc']
I tried to use sets as seen below,
def remove_similar_words(self,sent):
original_set = set()
result = []
for item in sent:
if item not in original_set:
original_set.add(item)
result.append(item)
return result
sent is list A.
The result of the above method would be
result=['ab','bc','cd','de','ef']
But, i need the result to be,
needed_result=['ab','bc','cd','de','ef','bc']
Question : How can i change my code to cater the requirement of producing the list needed_result?
Also i would like to avoid sets since i need to preserve the order.
def remove_similar_words(sent):
last = ""
result = []
for item in sent:
if item != last:
last=item
result.append(item)
return result
A=['ab','bc','cd','de','de','ef','bc']
print (", ".join(remove_similar_words(A)))
It would seem you just need to check against the prior value in your iterator, not build a complete original_set.

Compare a portion of String value present in 2 Lists

Below code extract a particular value from List srchlist and check for a particular value in List rplzlist. The contents of list srchlist and rplzlist looks like below.
srchlist = ["DD='A'\n", "SOUT='*'\n", 'PGM=FTP\n', 'PGM=EMAIL']
rplzlist = ['A=ZZ.VVMSSB\n', 'SOUT=*\n', 'SALEDB=TEST12']
I am extracting the characters after the '='(equal) sign and within the single quotes using a combination of strip and translate function.
Of the elements in the srchlist only the 'SOUT' matches with the rplzlist.
Do let me know why the below code does not work, also suggest me a better approach to compare a part of string present in the list.
for ele in srchlist:
sYmls = ele.split('=')
vAlue = sYmls[1].translate(None,'\'')
for elem in rplzlist:
rPls = elem.split('=')
if vAlue in rPls:
print("vAlue")
Here is the more pythonic approach for what you wanted to do:
>>> list(set([(i.split('='))[1].translate(None,'\'') for i in srchlist]) & set([j.split('=')[1] for j in rplzlist]))
['*\n']
I used set() and then get the whole output as list, you may use .join().
Inside set(), list comprehension is given which is faster than the normal for loops.
Another Solution Using join(), and replace() in place of translate():
>>> "".join(set([(i.split('='))[1].replace('\'','') for i in srchlist]) & set([j.split('=')[1] for j in rplzlist]))
'*\n'

TypeError during executemany() INSERT statement using a list of strings

I am trying to just do a basic INSERT operation to a PostgreSQL database through Python via the Psycopg2 module. I have read a great many of the questions already posted regarding this subject as well as the documentation but I seem to have done something uniquely wrong and none of the fixes seem to work for my code.
#API CALL + JSON decoding here
x = 0
for item in ulist:
idValue = list['members'][x]['name']
activeUsers.append(str(idValue))
x += 1
dbShell.executemany("""INSERT INTO slickusers (username) VALUES (%s)""", activeUsers
)
The loop creates a list of strings that looks like this when printed:
['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo']
I am just trying to have the code INSERT these strings as 1 row each into the table.
The error specified when running is:
TypeError: not all arguments converted during string formatting
I tried changing the INSERT to:
dbShell.executemany("INSERT INTO slackusers (username) VALUES (%s)", (activeUsers,) )
But that seems like it's merely treating the entire list as a single string as it yields:
psycopg2.DataError: value too long for type character varying(30)
What am I missing?
First in the code you pasted:
x = 0
for item in ulist:
idValue = list['members'][x]['name']
activeUsers.append(str(idValue))
x += 1
Is not the right way to accomplish what you are trying to do.
first list is a reserved word in python and you shouldn't use it as a variable name. I am assuming you meant ulist.
if you really need access to the index of an item in python you can use enumerate:
for x, item in enumerate(ulist):
but, the best way to do what you are trying to do is something like
for item in ulist: # or list['members'] Your example is kinda broken here
activeUsers.append(str(item['name']))
Your first try was:
['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo']
Your second attempt was:
(['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo'], )
What I think you want is:
[['b2ong'], ['dune'], ['drble'], ['drars'], ['feman'], ['got'], ['urbo']]
You could get this many ways:
dbShell.executemany("INSERT INTO slackusers (username) VALUES (%s)", [ [a] for a in activeUsers] )
or event better:
for item in ulist: # or list['members'] Your example is kinda broken here
activeUsers.append([str(item['name'])])
dbShell.executemany("""INSERT INTO slickusers (username) VALUES (%s)""", activeUsers)

Python if statement skipping code even though condition is met

I am trying to check if an entry is already in the database and add the entry if it isn't but the if statement never runs even though the condition is met.
userCurs.execute("SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)", (image,))
exists = userCurs.fetchone()
if exists is None:
addImage(userName,image,'','')
else:
print '--------> image skipped'
print userCurs.fetchone()
I get this output:
--------> image skipped
None
--------> image skipped
None
and no entries are made to the database
The SQL statement:
SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)
will always return a single row. The value of the column in that row will be the result of the EXISTS() function, which will be TRUE if any matches are found, or FALSE otherwise.
Since your original code only tested for the existence of a row in the result, and the full statement will always return exactly one row, you get the behavior you see.
What I think you should do is have your query return a rowset that has zero rows if no matches are found, and one (or more) rows if matches are found:
userCurs.execute("SELECT 1 FROM images WHERE imageLink=?", (image,))
Now your original test should work - if no imageLinks match the query, then there will be no rows in the result, so the first fetchone() will return a null object as you expect.
Of course, as several others have mentioned, you should ony call fetchone() once per row since it moves the cursor.
Solved it by changing the code to
userCurs.execute("SELECT EXISTS(SELECT 1 FROM images WHERE imageLink=?)", (image,))
exists = userCurs.fetchone()
if exists[0] == 0:
addImage(userName,image,'','')
else:
print '--------> image skipped'
print exists
As people have said the calling fetchone() twice gives different results the actual value of exists was (0,)
Don't call cursor.fetchone() again; the next row is always empty. Reuse the variable. You are fetching a (0,) or (1,) tuple; you could use tuple assignment to extract the flag value (note the comma on exits, =):
exists, = userCurs.fetchone()
if not exists:
addImage(userName, image, '', '')
else:
print '--------> image skipped'
print exists
Now exists will be set to 0 or 1, rather than (0,) or (1,) and the if not exists: test will not pass for the 0 case.