What is the meaning of 'q' in request.GET var? - python

Following to this question: How to Check if request.GET var is None?
I have this function in view.py:
def search(request):
error = False
if 'q' in request.GET:
q = request.GET['q']
if not q:
error = True
else:
.....
it takes a string and search for it.... I don't understand the 'q' part.
I'm assuming its part of the URL pattern of the query: /search/?q=....
but I don't see where I set up this exact pattern.
Why it has to be 'q'? what is the meaning of it?

It is the param given in url:
...com/?q=variable
So in view you have a dict request.GET and q is the key and variable is the value:
{'q': 'variable'}
If you want to change it in url, like this:
...com/?b=...
You will need to change in your view:
def search(request):
error = False
if 'b' in request.GET:
b = request.GET['b']
if not b:
error = True
else:
.....
As you can see, just replace q by b or whatever you want to be the name of your param.

Related

Remove a specific letter from form input

Within clean(), I am attempting to check if the User included "#" in the SearchHashtagForm and, if so, remove it.
For example, assume that User enters "#foo" on the SearchHashtagForm:
EXPECTED 'search_text': "foo"
ACTUAL 'search_text': "#foo"
I suspect that the line: form_input = form_input[1:] doesn't work, but I'm not sure what else to use?
Views.py
class HashtagSearch(FormView):
""" FormView for user to enter hashtag search query """
def form_valid(self, form):
form.clean()
return super().form_valid(form)
Forms.py
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean(self):
cleaned_data = self.cleaned_data
form_input = cleaned_data.get('search_text')
if form_input.startswith('#'): # if input starts with '#', remove it.
form_input = form_input[1:]
cleaned_data['search_text'] = form_input
return cleaned_data
SOLVED
In the interests of being succinct, I omitted the line: self.get_tweets(form) from form_valid() from the original query. I have provided by a more complete copy of the code, along with the solution, below:
As the solution, I removed clean() and instead included lstrip("#") (as suggested by below) in both get_success_url and get_tweets().
def get_success_url(self):
return '{}?search_text={}'.format(
reverse('mapping_twitter:results'),
self.request.POST.get('search_text').lower().lstrip("#"),
)
def form_valid(self, form):
self.get_tweets(form)
return super().form_valid(form)
def get_tweets(self, form):
...
search_filter = self.request.POST.get('search_text').lower().lstrip("#")
...
tweet_object, created = Hashtag.objects.get_or_create(search_text=search_filter)
...
You may use lstrip(), to remove the unwanted characters from the starting of your string as:
>>> tag = "#foo"
>>> tag.lstrip("#")
>>> "foo"
>>> tag = "foo"
>>> tag.lstrip("#")
>>> "foo"
>>> tag = "#foo#bar"
>>> tag.lstrip("#")
>>> "foo#bar"
This will also save you the extra method calls to check if the string starts with "#" or not, it implicitly handles it and does nothing if the tag does not start with the desired "#".
if form_input = form_input[1:] and form_input.startswith('#') don't throw errors,
Maybe you've got a normal string (else Idk why slicing and .startswith('#') should work) that starts with n invisible trailing characters before the # you see.
if thats the case, just try :
form_input = form_input[2:]
form_input = form_input[3:]
form_input = form_input[4:]
...
and see if you get reasonable results.
(print form_input and see what comes out)
if this does not work, you most likely have some werid datatype in form input.
obtain type and value of form input and add those to your question.
You can try this too:
''.join(filter(lambda x: x != '#', '#foo'))
# foo
You can use regular expression for this
import re
class SearchHashtagForm(ModelForm):
""" ModelForm for user to search by hashtag """
def clean(self):
cleaned_data = self.cleaned_data
form_input = cleaned_data.get('search_text')
re.sub('[#]','', form_input)
cleaned_data['search_text'] = form_input
return cleaned_data
This will replace all the characters in the string matching '#'. This solution is more robust since you can check for more characters like "%". for instance
re.sub('[#%]','', form_input)

Python: string manipulation not working inside a function

Here's the code:
def url_is_image(url):
if url[-4:] in ['.jpg', '.png']:
return True
elif 'imgur' in url:
url += '.jpg'
return True
else:
return False
u1 = 'http://i.imgur.com/jtboy'
url_is_image(u1)
print u1
Output is 'http://i.imgur.com/jtboy' without the .jpg extension. Any ideas for why my function (line 5) fails to add .jpg to the string? Thanks
The scope of the argument url is local to the call to the function. Assignment to it does not affect any variable or value outside the function.
The variable u1 was assigned to once. The function call does not affect it. Then it is printed.
Since you didn't test the truthiness of the function's return value, you could rewrite it this way:
def url_is_image(url):
if url[-4:] in ['.jpg', '.png']:
return url
elif 'imgur' in url:
return url + '.jpg'
else:
return url
u1 = 'http://i.imgur.com/jtboy'
u1 = url_is_image(u1)
print u1
However, the function name is misleading in this case. Since I don't know how you expect to really use the function it is hard to suggest a better solution. Maybe you want to return a 2-tuple containing the boolean and the modified string.
Addendum: based on the purpose you outlined in your comment here I would consider a function that returns only the interesting URLs. For example:
def consider_url(url):
if url[-4:] in ['.jpg', '.png']:
return url
elif 'imgur' in url:
return url + '.jpg'
else:
return None
Then you can use this to both transform the interesting URLs and ignore the uninteresting ones.
for url in some_list:
url = consider_url(url)
if url is None:
continue
print(url)
Another approach is to write a generator that provides you only the interesting urls:
def interesting_urls(iter):
for url in iter:
if url[-4:] in ['.jpg', '.png']:
yield url
elif 'imgur' in url:
yield url + '.jpg'
Then you can process your urls even more succinctly:
for url in interesting_urls(some_list):
print(url)
These examples assume that somehow you have already retrieved the URLs in a list or other iterable object. You can try it with a simple list such as the following. Although most of the strings in the list are not valid URLs, they do exercise the logic of the functions above.
some_list = [
"foo", "bar.jpg", "something/imgur/baz", "uninteresting", 'http://i.imgur.com/jtboy'
]
try this:
def url_is_image(url):
status = False
ret = url
if url[-4:] in ['.jpg', '.png']:
status = True
elif 'imgur' in url:
ret = url + '.jpg'
status = True
return status, ret
u1 = 'http://i.imgur.com/jtboy'
stat, u1 = url_is_image(u1)
print stat, u1
You have to add the "global" keyword to your function. Just add a line "global url" to the very top of it. Also remove the parameter.
What you try to do is a "side-effect". The function modifies a variable outside of its scope. This can cause headaches to readers, especially when you name the function "url_is_image", where a reader would expect only a check and not a modification.
I'd suggest to move the side-effect to a separate function "fix_imgur_jpg_url", that takes the url as a parameter and returns the fixed url.
Because when you pass url to url_is_image, it is creating a new url object. Modify your return statement. Don't use a global variable
def url_is_image(url):
if url[-4:] in ['.jpg', '.png']:
return url
elif 'imgur' in url:
return url + '.jpg'
else:
return False
u1 = 'http://i.imgur.com/jtboy'
url_is_image(u1)
print u1
Or you can replace return False with return None, depending on what happens next.
You must return what you have changed inside your function to take effect.
EDIT: following programming practices to not return different types, the previous code has been modified.
def url_is_image(url):
exit_code = 1
if url.endswith(('.jpg', '.png')):
pass #exit_code still 1.
elif 'imgur' in url:
url += '.jpg' #exit_code still 1.
else:
exit_code = 0 #url does not match requirements
return url, exit_code
u1 = 'http://i.imgur.com/jtboy'
u1, stat = url_is_image(u1)
if stat: #url has been modified or has required extension
print (u1)

Form validator in web.py, help find the mistake

I seem to have a mistake in my validator. Even when I enter -1 in my form I still get my value returned instead of blaat. Perchance someone sees my mistake?
class test:
def __init__(self):
self.render = web.template.render('templates/')
self.myForm = web.form.Form(
web.form.Textbox('minutes', id='minutes'),
validators = [form.Validator("Minutes not correct",
lambda i: i.minutes > 0)]
)
def GET(self):
return self.render.addLog(self.myForm)
def POST(self):
webinput = web.input()
if self.myForm.validates():
return webinput.date1+webinput.minutes
else:
return "blaat"
i.minutes won't be converted to int automatically, and strings compare greater than integers:
>>> '-1' > 0
True
Use int(i.munites)
By the way, form-wide validators are used to compare form fields between each other, e.g. to check that the entered passwords match. To check if any given field is correct, use one-field validators:
self.myForm = web.form.Form(
web.form.Textbox('minutes',
web.form.Validator("Minutes not correct", lambda x: int(x) > 0)),
)

Python return function error

While running this function to validate captcha key and value i am not able to return
it show error like this
"AttributeError: 'bool' object has no attribute 'status_code'"
def validate(request):
id=request.GET.get('id','')
key=request.GET.get('key','')
captchavalue = mc.get(str(id))
if captchavalue == key:
return True
else:
return False
By reading the code and the error, I assume that validate is a view. A view must always return a HttpResponse. So if you want to return a response indicating a boolean value, indicating if captchavalue == key, do:
from django.http import HttpResponse
def validate(request):
id=request.GET.get('id','')
key=request.GET.get('key','')
captchavalue = mc.get(str(id))
return HttpResponse(captchavalue == key)
I'm not 100% sure about the import line, but it's something very similar.
I don't know much Django, but it seems it expects you to return a response object instead of a bool value (True / False).
Maybe your code should like more like this:
if captchvalue == key:
return HttpResponse('HTML Page saying OK')
else:
return HttpResponse('HTML Page saying Error')

Context processors, passing a session which doesn't exist

Hay All, I've got a simple context processor which looks within a session and if a 'user' key exists. If it does i want to return it to the template.
Here's my context Processor
def get_user_details(request):
user = request.session['user']
data = {
'user':user
}
return data
and here is a sample view
def render_home(request):
return render_to_response("home", context_instance=RequestContext(request))
If the session['user'] doesn't exists, i want it to silently fail, or return False or Null.
Because the key doesnt exist within the session, i get a KeyError.
Any idea's how to fix this?
You can get a default value like None this way: request.session.get('user', None). Just like in normal Python dicts.
user = request.session.get('user', None)
or,
user = None
if 'user' in request.session:
user = request.session['user']
def get_user_details(request):
try:
user = request.session['user']
except KeyError:
return
data = {
'user':user
}
return data
Or if you want to catch it further away, do this instead:
def render_home(request):
try:
return render_to_response("home", context_instance=RequestContext(request))
except KeyError:
return

Categories