How to Check if request.GET var is None? - python

I'm getting into django and this is getting me a headache. I'm trying to get a simple GET variable. URL is site.com/search/?q=search-term
My view is:
def search(request):
if request.method == 'GET' and 'q' in request.GET:
q = request.GET.get('q', None)
if q is not None:
results = Task.objects.filter(
Q(title__contains=q)
|
Q(description__contains=q),
)
...return...
else:
...
else:
...
Search queries like mysite.com/search/? (without q) get through the first if correctly.
The problem is in queries like mysite.com/search/?q=. They don't get caught by if q is not None:
So, the short answer would be How can I check q == None? (I've already tried '', None, etc, to no avail.)

First, check if the request.GET dict contains a parameter named q. You're doing this properly already:
if request.method == 'GET' and 'q' in request.GET:
Next, check if the value of q is either None or the empty string. To do that, you can write this:
q = request.GET['q']
if q is not None and q != '':
# Do processing here
Notice that it is not necessary to write request.GET.get('q', None). We've already checked to make sure there is a 'q' key inside the request.GET dict, so we can grab the value directly. The only time you should use the get method is if you're not sure a dict has a certain key and want to avoid raising a KeyError exception.
However, there is an even better solution based on the following facts:
The value None evaluates to False
The empty string '' also evaluates to False
Any non-empty string evaluates to True.
So now you can write:
q = request.GET['q']
if q:
# Do processing here
See these other resources for more details:
Python: Truth Value Testing
Python: dict.get

Thanks for the clarification by #Ned.
Found a complete explanation here.
Basically:
'==' can be thought of as "value equality", that is, if two things look
the same, == should return a true value. (For those with a Java
background, Python's == is actually doing something akin to an equals()
method.)
'is' can be thought of as 'object
identity', that is, if the two things
actually are the same object.

Related

Easier flag to filter nothing in sqlalchemy?

I have two tables T1 and T2. T1 contains a column "name" while T2 does not.
I want to call
def get(T, query_name):
return session.query(T).filter(T.name == query_name).all()
The only calls for this function will be either:
get(T1, "some name") or get(T2, NULL) - for the second case I want the filter to just be ignored
A solution is:
def get(T, query_name):
if query_name != NULL:
return session.query(T).filter(T.name == query_name).all()
else:
return session.query(T).all()
The above code isn't too bad but I repeat this code a LOT (everytime I query) and was wondering if there's any other concise way.
Set a default argument. There is no NULL in python, you need None. You can build queries up sequentially, so maybe this is a better pattern, where you provide a default argument for query_name:
def get(T, query_name=None):
data = session.query(T)
if query_name is not None:
data = data.filter(T.name == query_name)
return data.all()
It makes no real difference with this example, but it will if you have a lot of optional arguments.

Converting GET request parameter to int ... if it is numeric

lets say i'm showing some data to user , i want user to be able to perform some sort of filtering on a numeric field in the database using a GET form so i have something like this
code = request.GET.get('code')
condition = {}
if( code is not None and int(code) > 0 ):
condition['code'] = int(code)
Somemodel.objects.filter(**condition)
but this works only if i code contains a number otherwise i get this error
invalid literal for int() with base 10: ''
so what is the pythonic way to handle this problem ? should i use try/except block? i perfer to handle this in the same if statement considering i might add other filters
isnumeric could check if code can be cast to int and also check that code is positive (when converted to an integer) thus replacing int(code) > 0:
if code is not None and code.isnumeric():
condition['code'] = int(code)
You should use a Django form with one or more IntegerFields; they do this conversion for you, then you can get the result from cleaned_data.
This function convert GET params to python numeric/bool accordingly:
def convert_params_to_int_or_bool(params):
for k, v in params.items():
if v.isnumeric():
params[k] = int(v)
if v == 'false':
params[k] = False
if v == 'true':
params[k] = True
The reason you are getting this error because int() expects the value in number it can be in the form string but it should be a number like "22","33" etc are valid .
But in your case you are passing empty that's why its raising an error. You can achieve your desired output using type(), it helps you in checking the type of number
So the modified code is
code = request.GET.get('code')
condition = {}
if( code is not None and type(code) == int ):
condition['code'] = int(code)
Somemodel.objects.filter(**condition)
Hope it helps :)

Python "if" statement - if xpath is true

im trying to code in python (very new to it) and need to check if an xpath is there then variable = the xpath but if not variable = string.
An example is below
if tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()') = true
$value = tree.xpath('//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()')
else
$value = ''
You should really start by doing the whole official tutorial before anything else, as it will anwser your question.
First point : Python objects all have a 'truth' value in a boolean context, which is defined by the object's type and actual value. For builtin types, all empty containers (lists, dicts, sets etc), the empty string, all numerical zeros and the None object are false, everything else is true. For non builtin types you'll have to check the package's documentation.
The builtin type bool will also tell you the boolean value of a given object, so all of the below tests are equivalent:
if myobj:
xxx
if bool(myobj):
xxx
if bool(myobj) == True:
xxx
BUT keep in mind that it doesn't imply that bool(myobj) is the same as myobj - the first one is the boolean value of your object, so the following is NOT equivalent (unless myobj is one of True, 1 or 1.0):
if myobj == True:
xxx
Now wrt/ your actual code snippet: it's not valid Python (bad indentation, invalid identifier $value, invalid use of the assignment operator =, missing : after the if and else statements, wrong capitalization for True...)
Assuming you meant:
# let's make this at least readable:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
if tree.xpath(path) == True:
value = tree.xpath(path)
else:
value = ''
The obvious error is the explicit test against True (tree.xpath() doesn't return a boolean). You either have to explicitely cast the return of tree.xpath() to a boolean (which is quite verbose, totally useless and definitly unpythonic) or just let Python do the right thing by removing the == True part of your test.
As a side note: calling tree.xpath twice in a row with the same argument is a waste of processor cycle (both calls will return the same value), so use a variable instead - it will also make your code much more readable and maintainable. The Pythonic version of your code would look something like:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
found = tree.xpath(path)
value = found if found else ''
or even more simply:
path = '//*#id="page"]/div[1]/div/main/div/article/div/div[1]/section[2]/p[1]/span/text()'
value = tree.xpath(path) or ''
since the or operator will not yield a boolean value but either the first of it's operand that has a true value or the last operand if none has a true value.
#No need to test == if value is bool. and you not check, you assign value with one =
if anything:
#Then do this
else:
#Do this

what is the meaning of this (redundant?) python expression?

str='test'
example={'test':'value',}
return str in example and example[str] or None
why the seemingly redundant extra test for key str in example?
In this specific example, the check is to first make sure that 'test' is actually a valid key in the example dict, otherwise you would get a KeyError exception. Then the logic proceeds to check the key and either return it, or a None if the value of example[str] evals to False
It would be a lot easier if this example simply did:
str='test'
example={'test':'value',}
return example.get(str, None) or None
Update
Even simpler, since the extra param to get() is not needed:
return example.get(str) or None
Update 2: Breaking down the truth tests and boolean operations from the OP (based on comments)
example = {
'test' : 'value',
'test2': 0,
'test3': [],
}
test = lambda k: k in example and example[k] or None
print test('test')
# value
print test('test2')
# None
print test('test3')
# None
For starters, the behaviour is different for the case where you're looking up a non-existent key (the extra test would prevent a KeyError exception being thrown).
However, it goes further than that because example[str] can be false in a boolean context. e.g., it could be an empty string.
>>> str='test'
>>> example={'test':[],}
>>> str in example and example[str] or None
>>> str in example or None
True
So it is not quite redundant. str in example checks for the existence of the key, whereas and example[str] is also checking the truthiness of the value.
Since Python evaluates Booleans lazily, you can safely omit parentheses in simple tests. This might make it easier to read:
(str in example and example[str]) or None
In plain English:
"Make sure the dictionary example has the key str and that the key also has a non-False value. If so, return the value of the key example[str]. Otherwise return None"
Graceful failure. If the key doesn't exist, the lookup 'example[str]' will fail at runtime. You'll get a fault, terminate your app and get a traceback. By checking for the key first you get the None value back instead and your application will go on on its merry way.
Another, more general approach would be to catch the exception and return None as a result of that.
def testfun():
str='test2'
example={'test':'value',}
try:
return example[str]
except KeyError:
return None
If the key doesn't exist it will get KeyError exception
#!/usr/bin/python
str='test'
example={'test':'value',}
if str in example and example[str]:
print example[str]
else:
print False
str in example is a boolean test to see if str is a key in example, while example[str] yields the actual value associated with that key.

Pythonic get element of array or default if it doesn't exist

We have
matches = re.findall(r'somewhat', 'somewhere')
Can we simplify this
if len(matches) > index:
return matches[index]
else:
return 'default'
or
return matches[index] if len(mathes) > index else 'default'
to something similar to JS's
return matches[index] || 'default'
that we can simply use
return 'somewhere'.match(/somewhat/)[index] || 'default'
Something like this might help:
>>> reg = re.compile('-\d+-')
>>> reg.findall('a-23-b-12-c') or ['default']
['-23-', '-12-']
>>> reg.findall('a-b-c') or ['default']
['default']
Edit
Ugly one-liner
(reg.findall('a-b-c')[index:] or ['default'])[0]
I'd be tempted to use a try except block. You'd be required to consider when index was negative though. Is this an error or an acceptable input?
But the following would work:
try:
return re.findall(r'somewhat', 'somewhere')[index]
except IndexError:
return 'default'
This is meant to be the preferred way if you're concerned about efficiency as it avoids checking the bounds of the array twice (once when you manually do it and and second when python does its internal check as well).
edit: I've never particularly liked this way as it hides any IndexErrors thrown by sub calls and would return the default (which I doubt would be the desired behaviour and a possible source of bugs).
Not really, because running mathes[x] with an invalid index will throw an IndexError, which does not return False.

Categories

Resources