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)
Related
The problem is that I am trying to call a function from my views.py and print the result in my template through a context variable. The function prints in the terminal and does not work in the template. I posted a question a few days ago regarding doing this with subprocess, but I still could not figure it out.
How can I print "This is a test function for AAPL" in my template instead of in the terminal?
Views.py
from django.shortcuts import render
from backtests.scripts import Backtests
def index(request):
if 'symbol' in request.GET:
symbol = request.GET.get('symbol','Invalid Symbol')
request.session['symbol'] = symbol
else:
symbol = request.session['symbol']
earnings_object = Backtests("AAPL")
test = earnings_object.print_discrep()
return render(request, 'backtests/earnings.html', {'symbol':symbol, 'test':test})
scripts.py
class Backtests:
def __init__(self, symbol):
self.symbol = symbol
def print_discrep(self):
print('This is a test function for the graph ' + self.symbol)
It is returning None in my template.
You're calling the function in the view. To call it in the template, assign the function object, not the result of the function call:
test = earnings_object.print_discrep # no ()
Update:
print prints to the command line, not into your template.
The template displays the return value of functions you call. Your print_discrep doesn't have a return value, defaulting to None.
If you want to display data in the template, return that data in your function:
def get_discrep(self):
return 'This is a test function for the graph ' + self.symbol
Then you can call the function either in the view or in the template.
How do I get otherImages to return the string in it so that I can replace a word within it when called from 'narrow' method?
def otherImages(self):
self.wfile.write(bytes("<div id='menu_button'><a href='/narrow'><img src='../images/menu_button.png'></a></div>", "utf8"))
#^word I want to replace
def contentList(self, skip_name=''): # All content methods in list
methods = [self.title, self.containerDIV, self.heading, self.stopSection, self.offlineSection, self.onlineSection, self.endDIV, self.otherImages]
for m in methods:
if m.__name__ != skip_name:
m()
def narrow(self):
try:
self.reply()
self.contentList('onlineSection') # removed onlineSection
for words in self.otherImages():
words.replace("narrow", "index")
self.otherImages doesn't return anything! When a function does not return an explicit value in python, it returns None. You cannot iterate over None.
Here are the changes I made which solves my problem. It allows me to edit the string when called from the 'narrow' method.
def otherImages(self):
return["<div id='menu_button'><a href='/narrow'><img src='../images/menu_button.png'></a></div>"]
def narrow(self):
try:
self.reply()
self.contentList('onlineSection') # removed onlineSectionv
for words in self.otherImages():
words = words.replace("/narrow", "/")
self.wfile.write(bytes(words, "utf8"))
return
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.
I have numerous regular expressions, such as:
quantity_validation = re.compile("""^-?[0-9]+$""", re.I)
I use these regex in functions like:
def validate_quantity(self, value):
if value != self.context.quantity:
# while not self.quantity_validation.match(value):
# return 0, "Value is not a number"
if not self.quantity_validation.match(value):
return 0, "Value is not a number"
return 1, ""
and the validation method:
#view_config(name="validate", renderer='json')
def validate(self, full={}):
def do_validation(field, value):
message = ""
valid = 1
if getattr(self, 'validate_%s' % field, False):
valid, message = getattr(self, 'validate_%s' % field)(value)
out = dict(message=message, valid=valid, value=value)
return out
if not full:
field = self.request.params.get('field')
if not field:
return "INVALID"
return do_validation(field, self.request.params.get('value'))
else:
return dict(((field, do_validation(field, value)) for field, value in full.items()))
On the HTML form I have a modal with a quantity field on which I do ajax validation(I use jqBootstrapValidation to validate my forms)
The regex validation works fine until I type a + then the validation stop working until I refresh the page.
Why does the validation stop working?
Is it perhaps a bug in jqBootstrapValidation?
or is it a bug in the re module?
You are not encoding your URLs/inputs correctly. The '+' gets parsed into a ' ' when you pass it via the parameter string. Try '%2B' instead which should be decoded into a '+' through the form library.
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)),
)