HTML flask To accept only integer input - python

I'm trying to accept only integer input using the int() function and the type to number with min set. But I noticed that when I give an input like 5.0 it should treat it as an invalid input and accept only integers.
<input autocomplete="off" class="form-control" min="0" name="shares" id="shares" placeholder="Shares" type="number">
def sell():
"""Sell shares of stock"""
rows = db.execute("SELECT * FROM tracker WHERE id=:id", id = session["user_id"])
if request.method == "GET":
return render_template("sell.html", rows = rows)
else:
symbol = request.form.get("symbol")
shares = request.form.get("shares")
if not shares:
return apology("missing shares",400)
if not symbol:
return apology("missing symbol",400)
lis = db.execute("SELECT * FROM tracker WHERE id=:id AND name=:name", id=session["user_id"], name=symbol)
share = int(shares)
if lis[0]["no"] < share:
return apology("too many shares",400)
price = lookup(symbol)["price"]
cost = price * share;
saving = db.execute("SELECT cash FROM users WHERE id=:id", id=session["user_id"])[0]["cash"]
db.execute("UPDATE users SET cash=:cash WHERE id=:id", cash=cost + saving, id=session["user_id"])
if lis[0]["no"] == share:
db.execute("DELETE FROM tracker WHERE id=:id AND name=:name", id=session["user_id"], name=symbol)
else:
db.execute("UPDATE tracker SET no=:no where id=:id AND name=:name",no=lis[0]["no"] - share,id=session["user_id"], name=symbol)
db.execute("UPDATE users SET cash=:cash WHERE id=:id", cash=saving+cost, id=session["user_id"])
flash("Sold!")
return redirect("/")

I dont' see the error code,however I guess is caused by the html input.
UPDATE
Try this:
<input autocomplete="off" class="form-control" step="0" name="shares" id="shares" placeholder="Shares" type="number">
UPDATED:
Obviously you can instead run the check in Python, by doing something like:
symbol = request.form.get("symbol")
shares = request.form.get("shares")
if not symbol:
return apology("missing symbol",400)
if shares:
try:
shares = int(shares)
except ValueError:
error = 'It must be an integer'
return redirect("/", error=error)
else:
return apology("missing shares",400)
lis = db.execute("SELECT * FROM tracker WHERE id=:id AND name=:name", id=session["user_id"], name=symbol)
if lis[0]["no"] < share:
return apology("too many shares",400)
(For reference i leave the older answer)
Which won't work because shares would be a string
shares = intrequest.form.get("shares")
if isinstance(shares, float)):
error = 'It must be an integer'
return redirect("/", error=error)
This will work because first it checks if is a float or not, if it is then it will redirect , else you turn it a

Related

Display 1 when no data is exist in database

I am trying to generate incremental id whenever I am adding new data in my model. here I am getting the the next number whenever I am adding new data. but If there is no any data in my table its giving me error. 'NoneType' object has no attribute 'tax_id'
Here is my code
views.py
def tax_settings(request):
latest_id = (Tax_Settings.objects.last()).tax_id+1
if request.method == 'POST':
tax_id = latest_id
name = request.POST['tax_name']
tax_percentage = request.POST['tax_percentage']
tax_details=Tax_Settings.objects.create(tax_id=tax_id, name=name, tax_percentage=tax_percentage)
tax_details.save()
next_id = (Tax_Settings.objects.last()).tax_id+1
return render(request,"settings/tax-settings.html",{"latest_id":next_id})
else:
return render(request,"settings/tax-settings.html",{"latest_id":latest_id})
html
<input type="text" class="form-control" placeholder="{{latest_id}}" name="tax_id" disabled>
which condition I can give to my latest_id if data(tax_id) not exists?
You are trying to do too much in too few lines of code. Wherever you use queryset .last() or .first() you must explicitly handle the case where it returns None!
You need code of the form:
o = Tax_Settings.objects.last()
if o is not None:
tax_id = o.tax_id + 1
else:
tax_id = 1 # if that's a sensible default value
or even
o = Tax_Settings.objects.last()
assert o is not None, "This can't happen!" # except obviously, it does in this question.
Either you first create a single record than don't need to handle this or
tax_id = 0
latest_rec = (Tax_Settings.objects.last())
if latest_rec is not None:
latest_id = latest_rec.tax_id+1
You could simply add:
if latest_id is None:
latest_id = 1
If I understand it correctly, you have issues with your first line in the provided function:
latest_id = Tax_Settings.objects.last().tax_id+1
when you have no data, i.e. Tax_Settings.objects.last() is None.
You should define default ID, for instance 0 which would be assigned in case of missing objects:
def tax_settings(request):
if Tax_Settings.objects.last() is not None:
# some data already stored
latest_id = Tax_Settings.objects.last().tax_id
else:
# no data present yet
latest_id = 0
. . .
btw. I am not sure why are you incrementing the latest value in the beginning, but you need to take into account that if your default latest ID is 0 then the ID of the first data unit stored will be 1.
The following code also works:
tax_data=Tax_Settings.objects.all()
if not tax_data:
print("no data found")
latest_id=1
else:
latest_id = (Tax_Settings.objects.last()).tax_id+1

Increment Last Id from String in python Django

I am trying to generate an auto-increment number as an ID with Company Label. Company Labels will be changing for every user. So I cant use slicing here.
My ID is like TES-PRODUCT-01
TES is a company label
PRODUCT is as it is name
But now I wish to change my last number when I am adding new product to TES-PRODUCT-02 and so on
Getting Error **can only concatenate str (not "int") to str**
Here is my code
views.py
def add_new_stock(request):
stock_data=New_Stock_Entry.objects.all()
if not stock_data:
latest_item_code="TES-PRODUCT-001"
else:
latest_item_code = (New_Stock_Entry.objects.last()).item_code+1
get_tax_code=Tax_Settings.objects.values('name', 'tax_percentage','tax_id')
if request.method == 'POST':
item = request.POST['item']
hsn = request.POST['hsn']
item_code=latest_item_code
stock_in_date=request.POST['stock_in_date']
quantity_in_hand=request.POST['quantity_in_hand']
sales_price=request.POST['sales_price']
item_description=request.POST['item_description']
unit=request.POST['unit']
tax_code = request.POST['tax_code']
tax_obj = Tax_Settings.objects.get(tax_id=tax_code)
item_creation_details = New_Stock_Entry.objects.create(item=item, hsn=hsn, item_code=item_code,stock_in_date=stock_in_date,quantity_in_hand=quantity_in_hand,sales_price=sales_price ,item_description=item_description, unit=unit, tax_code=tax_obj)
item_creation_details.save()
print("item_details",item_creation_details)
return render(request,"inventory/add-stock.html")
return render(request,"inventory/add-stock.html",{'get_tax':get_tax_code,'latest_item_code':latest_item_code})
html
<input type="text" class="form-control" placeholder="TES-PRODUCT-{{latest_item_code}}" name="item_code">
How Can I increment my last number from string?
You can simply use "f-strings"
total_stock = New_Stock_Entry.objects.all().count() + 1
latest_item_code=f"TES-PRODUCT-{total_stock}"

in flask, give user a list of options to select from with arbitrary length

i'm new to flask, and python in general so let me know if i'm doing anything wrong...
i'm learning by building a web-app. my current goal is to make playlists on spotify from user input. everything i'm trying to do here i have already made work for myself in pycharm scripts, it's the web-dev and interacting with the user part i'm struggling with atm.
i want to:
take input (artist name) from user (done)
send artist name as search term to spotify and return a list of dictionaries of matching artists. these dictionaries have a bunch of info including 'name' and 'id'. (done)
display the names in the result dicts to the user who will select which to include in their playlist. (please help!)
use the list of ids which match the selected artists to interogate spotify for all the tracks by those artists and create a playlist.
i just need help with #3
i have a functioning flask / bootstrap web-app that allows user to authenticate via spotify and input the artist name and which conducts the search and returns the list of dicts. i'm using flask forms to take the input, and assume i'll use another to display the results as radio-button fields for user to select one/many from but the list is of arbitrary length and i don't know how to pass this dynamically to the html. the dictionary i make from the spotify response has names as keys and ids as values - i only want to pass the names to the user to select from, but i'll need to maintain acces to the dictionaries so i can retrieve the ids for the spotify search later...
i've added the code i use to make and populate the playlists in case anyone likes/wants it/has any comments.
my code:
python
class ArtistTracksForm(FlaskForm):
artist = StringField('Who are you searching for?')
submit = SubmitField('search')
...
#app.route('/artist_playlist', methods=['GET', 'POST'])
def artist_playlist():
# prepare spotify
cache_handler = sp.cache_handler.CacheFileHandler(cache_path=session_cache_path())
auth_manager = sp.oauth2.SpotifyOAuth(cache_handler=cache_handler)
if not auth_manager.validate_token(cache_handler.get_cached_token()):
return redirect('/')
spotify = sp.Spotify(auth_manager=auth_manager)
#get form
form = ArtistTracksForm()
if form.validate_on_submit():
artist = form.artist.data
results = spotify.search(q=artist, type='artist')
items = results['artists']['items']
#make a dictionary of results
names_list = {}
for item in items:
artist_name=item['name']
artist_id = item['id']
names_list.update({artist_name:artist_id})
# temp. make a string of keys (artist names) by unpacking the dict
name_string = ''
for name in [*names_list]:
name_string = name_string + name + ", "
return name_string
#app.route('/handle_data')
def handle_data():
data_handler = request.form['APform']
i don't really know what i'm doing with the 'action=' and handle_data(): parts but can work that out, it's the dynamically sized list of fields and interacting between python and html i'm really perplexed by
html.j2:
{% extends "layout.html.j2" %}
{% block content %}
<div class="content-section">
<form method="POST" action="{{ url_for('handle_data')}}" name=APform>
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Artist Playlists</legend>
<div class="form-group">
{{ form.artist.label(class="form-control-label") }}
{{ form.artist(class="form-control form-control-lg") }}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endblock content %}
any input greatly appreciated, i've been searching google and SO for hours now...
thanks
here's the python code i use to get all the tracks from all the albums that an artist has at least one track on, and make a playlist on my spotify account for each artist.... max tracks is 10k so it makes multiple if that is exceeded... in case that's of interest to anyone who read this far... i've been making sql databases and inserting huge spotify playlists into my account. XD
def get_releases(list_of_artist_dicts, form='dict'):
"""takes list of artist dicts
return list of dicts (form = 'dict)
or list of id strings 'form='list'"""
album_list = []
for artist_dict in list_of_artist_dicts: # iterate artist dicts
artist = artist_dict['artist']
artist_id = artist_dict['artist_id']
results = sp.artist_albums(artist_id) # call spotify for artist_album details
releases = results['items']
while results['next']: # check for more pages
results = sp.next(results)
releases.extend(results['items'])
for release in releases:
album_group = release['album_group']
album_type = release['album_type']
album = release['name']
album_id = release['id']
spotify_album_url = release['external_urls']['spotify']
release_date = release['release_date']
release_date_precision = release['release_date_precision']
release_date = date_stripper(release_date,
release_date_precision) # convert date string to datetime obj, insert spurious 1s if precision < day
album_artist = release['artists'][0]['name'] # get (first) album artist details
album_artist_id = release['artists'][0]['name']
release_dict = {
'artist': artist,
'artist_id': artist_id,
'album_artist': album_artist,
'album_artist_id': album_artist_id,
'album': album,
'album_id': album_id,
'album_group': album_group,
'album_type': album_type,
'release_date': release_date,
'release_date_precision': release_date_precision,
'spotify_album_url': spotify_album_url
}
if form == 'dict':
album_list.append(release_dict)
if form == 'list':
album_list.append(release_dict['album_id'])
return album_list
def get_tracks(list_of_artist_dicts, form=dict):
""" takes list of artist dicts, returns a list of track dicts, or track ids if form=list """
track_dicts_list = []
for artist_dict in list_of_artist_dicts:
album_list = []
artist = artist_dict['artist']
artist_id = artist_dict['artist_id']
artist_dict = [artist_dict]
release_list = get_releases(artist_dict, 'dict')
for release in release_list:
album_id = release['album_id']
album_list.append(album_id)
for offset in range(0, len(album_list), 20):
batch = album_list[offset:offset + 20]
result = sp.albums(batch)
albums_batch = result['albums']
for batched_album in albums_batch:
album = batched_album['name']
album_id = batched_album['id']
# release_date = batched_album['release_date'] tracks dont have release dates?
album_type = batched_album['album_type']
track_count = len(batched_album['tracks']['items'])
for act in batched_album['artists']:
album_artist = act['name']
album_artist_id = act['id']
track_id_list = []
for track in batched_album['tracks']['items']:
track_artist = track['artists'][0]['name']
track_artist_id = track['artists'][0]['id']
title = track['name']
spotify_track_url = track['external_urls']['spotify']
track_id = track['id']
track_id_list.append(track_id)
track_dict = {
'artist': artist,
'artist_id': artist_id,
'album_artist': album_artist,
'album_artist_id': album_artist_id,
'album': album,
'album_id': album_id,
'track_artist': track_artist,
'track_artist_id': track_artist_id,
'title': title,
'track_id': track_id,
'album_type': album_type,
'spotify_track_url': spotify_track_url
}
track_dicts_list.append(track_dict)
if form == 'list':
return track_id_list
return track_dicts_list
def make_playlist(playlist_name='python_play'):
"""creates a playlist on user account, returns playlist_id"""
user = sp.me()['id']
return sp.user_playlist_create(user=user,name=playlist_name)['id']
def add_to_playlist(playlist_id, track_list):
sp.playlist_add_items(items=track_list, playlist_id=playlist_id)
def check_playlist_exists(term):
""" searches current user's playlists for playlist_name = term returns true if exists"""
limit = 50
offset = 0
current_names = []
for step in range (0,1000,50):
current_playlists = sp.current_user_playlists(limit=limit, offset=offset)['items']
for playlist in current_playlists:
current_names.append(playlist['name'])
offset += 50
if term in current_names:
return True
def get_alpha(my_dict):
sorter = my_dict['name']
sortering = sorter.lower()
return sortering
def create_playlist_all_artist_tracks(artist_list):
artist_list.sort(reverse=True, key=get_alpha) # reverse sort list so playlists will be front-sorted in spotify
already = []
making = []
for artist in artist_list:
artist_name = artist['name']
artist_id = artist['id']
playlist_name = f"{artist_name} and friends - all tracks from all releases including features_on- made in python"
if check_playlist_exists(playlist_name):
print (f"ALREADY EXISTS - {playlist_name}")
already.append(playlist_name)
else:
print (f'PLAYLIST NOT FOUND making playlist "{playlist_name}"')
making.append(playlist_name)
artist_tracks = get_track_id_list_artist(artist_id)
if len(artist_tracks) < 10000:
playlist_id = make_playlist(playlist_name)
start = 0
for step in range(start, len(artist_tracks), 100):
batch = artist_tracks[start:start + 100]
add_to_playlist(playlist_id, batch)
start += 100
else:
count = 1
begin = 0
start=0
for section in range(begin, len(artist_tracks), 10000):
playlist_id = make_playlist(f"{playlist_name} number {count}")
chunk = artist_tracks[begin:begin + 10000]
for step in range(start, len(chunk), 100):
batch = artist_tracks[start:start + 100]
add_to_playlist(playlist_id, batch)
start += 100
count+=1
begin += 10000
print ("PLAYLISTS ALREADY MADE:")
pprint (already)
print ("NEW PLAYLISTS CREATED :")
pprint (making)

KEY ERROR on self.cleaned_data.get('file')

I'm getting a key error while I'm trying to validate a simple form in Django:
I've tried accessing the file name using:
all_clean_data['file']
self.cleaned_data.get('file')
self.cleaned_data['file']
To no avail. If i'm accessing as a key, I'm getting key error, if I'm using the get method I get None.
Can you please tell my what I'm doing wrong?
class UploadForm(forms.Form):
url_cell_start = forms.IntegerField()
url_cell_end = forms.IntegerField()
write_cell_start = forms.IntegerField()
write_cell_end = forms.IntegerField()
file = forms.FileField()
def clean(self):
all_clean_data = super(UploadForm, self).clean()
url_c_start = all_clean_data['url_cell_start']
url_c_end = all_clean_data['url_cell_end']
write_c_start = all_clean_data['write_cell_start']
write_c_end = all_clean_data['write_cell_end']
xl_file = all_clean_data["file"]
extension = os.path.splitext(xl_file.name)[1]
VALID_EXTENSION = '.xlsx'
if extension.lowercase != VALID_EXTENSION:
self.add_error('file', 'The file has to be .XLSX')
if (url_c_start is None) or not (url_c_start > 0):
self.add_error('url_cell_start', 'The URL column needs to be a number grater than zero.')
if (url_c_end is None) or not (url_c_start > 0):
self.add_error('url_cell_end', 'The URL column needs to be a number grater than zero.')
else:
if url_c_start is not None:
if url_c_end <= url_c_start:
self.add_error('url_cell_end',
'The URL-End column need to be a number grater or equal than URL Start')
if (write_c_start is None) or not (write_c_start > 0):
self.add_error('write_cell_start', 'The URL column needs to be a number grater than zero.')
else:
if url_c_end is not None:
if url_c_end > write_c_start:
self.add_error('write_cell_start',
'The URL-Write-start column number needs to be a number grater than URL-cell-end')
if (write_c_end is None) or not (write_c_end > 0):
self.add_error('write_cell_end', 'The URL column needs to be a number grater than zero.')
else:
if write_c_start is not None:
if write_c_end <= write_c_start:
self.add_error('write_cell_end',
'The URL-Write-end column number needs'
' to be a number grater or equal than URL-Write-start')
return all_clean_data
Finally, after three hours of intensive google searching I've found the solution.
The reason I wasn't getting the key was that haven't added "enctype="multipart/form-data" to the HTML tag in the template.
Like:
<form method="POST" enctype="multipart/form-data">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" class="btn btn-primary" value="Submit">
</form>

How to get a value from SQLite to convert it?

So I have an issue, I am trying to convert a float value from SQLite Db.
The value represents a price in USD and I want to convert it in BTC, I was installing python-forex but because I do not have experience enough I am stack on this:
b = BtcConverter(force_decimal=True)
p = float(acf1.p1)
pbtc = b.convert_to_btc(10, 'USD')
What I need to do is to exchange "10" with "p", and "p" is a row from my SQlite Db.
I was trying to get acfi.p1 from db table with:
acf1 = KAch.query.order_by(KAch.reg.desc()).all()
As well the html code is:
{{ "%.9f" %pbtc }}
But because I am new is giving me 500 error.
Could you give me a hint?
Update:
#app.route('/adfa', methods=['GET', 'POST'])
def add_foa():
t1=request.form.get('t1')
c1=request.form.get('c1')
p1=request.form.get('p1')
p2=request.form.get('p2')
um1=request.form.get('um1')
ce1=request.form.get('ce1')
dc1=request.form.get('dc1')
mdla1=request.form.get('mdla1')
mdam1=request.form.get('mdam1')
aop=request.form.get('aop')
pz1=request.form.get('pz1')
users_id = request.form.get('users_id')
acf1 = KAch(
t1=t1,
c1=c1,
p1=p1,
p2=p2,
um1=um1,
ce1=ce1,
dc1=dc1,
mdla1=mdla1,
mdam1=mdam1,
aop=aop,
pz1=pz1,
users_id=current_user.id,
reg=datetime.now())
db.session.add(acf1)
db.session.commit()
return redirect(url_for('adfa', users_id=current_user.id, _external=True))
#app.route('/profil/<int:users_id>')
#login_required
def profil(users_id):
ac1 = KAch.query.order_by(KAch.reg.desc()).all()
user = User.query.filter_by(id=users_id).first()
profil1 = KProfil.query.filter_by(id=users_id).one()
b = BtcConverter(force_decimal=True)
#p = float(acf1.p1)
pbtc = b.convert_to_btc(10, 'USD')
if 'out' in current_user.tc:
return redirect(url_for('adpro', users_id=current_user.id, _external=True))
elif 'n' in current_user.tc:
return redirect(url_for('logout', _external=True))
return render_template('front/usr/usr.html', profil1=profil1, user=user, ac1=ac1, pbtc=pbtc)
The Solution I found it is easy and is working!
Server side:
b = BtcConverter(force_decimal=True)
p1btc = b.get_latest_price('USD')
p1btcr = b.get_latest_price('RON')
pbtc = b.convert_to_btc(10, 'USD')
pron = float(Decimal(p1btcr))
HTML side:
{{ acf1.p1 / pron }}

Categories