Flask passing variables through routes - python

So i have an issue where I am using the flask route to edit a existing tab in a project of mine. What should happen is that my project store two things user and tabs. I have several tabs that are in my database and i want to create edit functionality to it. So i am creating and edit route that will pass the users id and tab id that is being editied. What should happen is that the tabs amount and description that is being edited will appear in the input box for me to edit. it should then change that tab in the database and return to the page that shows all of the tables with the edit.
What is happening is that no matter what tab i click on it shows the first tabs information in the input box and when i submit to edit add and commit the change to the database, it is added a new tab and giving it the values that changed. I will insert 3 peices of code.
** i do have all of the correct sqlalchemy informaiton imported
the first piece of code is the database
class Users(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key = True)
username = Column(String(16), nullable = False, unique = True, index = True)
class Tab_Event(Base):
__tablename__ = 'tab_event'
id = Column(Integer, primary_key = True)
description = Column(String(200))
amount = Column(String(10))#may be changed to a float or decimal value later on during development
user_id = Column(Integer(10), ForeignKey('users.id'))
users = relationship(Users)
The following section of code is the routes that are being used
#app.route('/user/<int:user_id>')
def DisplayUsers(user_id):
user = session.query(Users).filter_by(id = user_id).one()
items = session.query(Tab_Event).filter_by(user_id = user.id)
return render_template('viewTabs.html', user = user, items = items)
#app.route('/newtab/<int:user_id>', methods = ['GET', 'POST'])
def AddNewTab(user_id):
if request.method == 'POST':
newTab = Tab_Event(amount = request.form['amount'], description = request.form['description'], user_id = user_id)
session.add(newTab)
session.commit()
return redirect(url_for('DisplayUsers', user_id = user_id))
return render_template('createTab.html', user_id = user_id)
#app.route('/edit/<int:user_id>/<int:tab_id>', methods = ['GET', 'POST'])
def EditTabEvent(user_id, tab_id):
editTab = session.query(Tab_Event).filter_by(id = user_id).one()
if request.method == 'POST':
if request.form['name']:
editTab.name = request.form['amount']
if request.form['description']:
editTab.description = request.form['description']
session.add(editTab)
session.commit()
return redirect(url_for('DisplayUsers', user_id = user_id))
else:
return render_template('editTab.html', user_id = user_id, tab_id = tab_id, item = editTab)
The last piece of code is the html document that i am using to edit
<html>
<body>
<h1>This page is where new users are made</h1>
<form action="{{url_for('AddNewTab', user_id = user_id, tab_id = item.id)}}" method="POST">
<table>
<tr>
<td>Username</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>Amount</td>
<td><input type="text" name="amount", value="{{item.amount}}"></td>
</tr>
<tr>
<td>Description</td>
<td><input type="text" name="description", value="{{item.description}}"></td>
</tr>
<tr>
<td><input type="Radio">Personal</td>
<td><input type="Radio">Business</td>
</tr>
<tr>
<td><input type="submit" value="Edit Tab"></td>
</tr>
</table>
</form>
</body>
</html>
the repository that has these files is below:
vagrant >> PayUp >> all of the files for this project to run on local machine
https://github.com/omar-jandali/Udacity-Tournament/tree/master/vagrant/PayUp

Related

An Unexpected Error while trying to delete data

I am doing CRUD using serializers and foreign key as tasked,the problem is that when I am trying to delete a data,an error which is completely unexpected has come.
this error should not be coming as I am not missing the id in the below functions and html code
NOTE : I am doing soft delete hence the parameter 'isactive' is there
delete function
def delete(request,id):
deleteclothes = Products.objects.all(id=id)
delclothes = {}
delclothes['isactive']=False
form = POLLSerializer(deleteclothes,data=delclothes)
if form.is_valid():
print("error of form when valid:",form.errors)
form.save()
return redirect('polls:show')
else:
print("error of form when not valid:",form.errors)
return redirect('polls:show')
html code of product_list
<td>
<a href="/delete/{{result.id}}/" onclick="return confirm('Are You Sure you want to delete?')">
<button class="btn btn-danger">
Delete
</button>
</a>
</td>
models
class Products(models.Model):
categories = models.ForeignKey(Categories,on_delete=models.CASCADE)
sub_categories = models.ForeignKey(SUBCategories,on_delete=models.CASCADE)
color = models.ForeignKey(Colors,on_delete=models.CASCADE)
size = models.ForeignKey(Size,on_delete=models.CASCADE)
# image = models.ImageField(upload_to = 'media/',width_field=None,height_field=None,null=True)
title = models.CharField(max_length=50)
price = models.CharField(max_length=10)
sku_number = models.CharField(max_length=10)
product_details = models.CharField(max_length=300)
quantity = models.IntegerField(default=0)
isactive = models.BooleanField(default=True)
where am I going wrong in the code?
You can't do deleteclothes = Products.objects.all(id=id), whether you retrieve all Products by doing :
deleteclothes = Products.objects.all()
Or you retrieve the one with the id you want (which is what you need here) with :
deleteclothes = Products.objects.get(id=id)

Trying to load data into databse through web browser: save() prohibited to prevent data loss due to unsaved related object 'ship'

I'm at a total loss as to why I get this error. When I run similar code in the python shell I never get this error but when I try to do this through the web browser I get this error. Any idea why this happens? FYI, I'm a total beginner.
Models:
from django.contrib.auth.models import User
class Hull (models.Model):
hull = models.CharField(max_length = 33, )
def __str__(self):
return self.hull
class Hull_Spec(models.Model):
ship = models.ForeignKey(Hull, on_delete=models.CASCADE)
speed = models.FloatField()
depth = models.FloatField()
remarks = models.CharField(max_length =300)
def __str__(self):
return self.remarks
views
def new_ship (response):
x = Hull
x.objects.create(hull = response.POST.get('ship'))
Z = Hull(hull = response.POST.get('ship'))
Z.hull_spec_set.create(speed = response.POST.get('speed'), depth = response.POST.get('depth'), remarks = response.POST.get('remarks')).save()
return HttpResponse('Success')
html user interface
<div>
<form action = '/new_ship/' method = 'POST'>
{% csrf_token %}
<table>
<col>
<tr>
<td><input type = 'text' name = 'ship'>Hull</input></td>
<td><input type = 'text' name = 'speed'>Speed</input></td>
</tr>
<tr>
<td><input type = 'text' name = 'depth'>Depth</input></td>
<td><input type = 'text' name = 'remarks'>Remarks</input></td>
</tr>
<tr>
<td><input type="submit" value="Submit Fields" id = 'button_1'></td>
</tr>
</col>
</table>
</form>
</div>
Your instannce of Hull (Z) has not been saved to the database (with .save() ). This is the cause of the error.
You need to first create your Hull instance (instances are normally lower (snake) case):
hull = Hull.objects.create(hull = response.POST.get('ship'))
Then you can use that to create a Hull_Spec instance:
hull_spec = Hull_spec.objects.create(
hull=hull,
speed = response.POST.get('speed'),
depth = response.POST.get('depth'),
remarks = response.POST.get('remarks')
)
So your view would become:
def new_ship (response):
hull = Hull.objects.create(hull = response.POST.get('ship'))
hull_spec = Hull_spec.objects.create(
hull=hull,
speed = response.POST.get('speed'),
depth = response.POST.get('depth'),
remarks = response.POST.get('remarks')
)
return HttpResponse('Success')
Note also, it would be convention to name your model HullSpec not Hull_Spec.
In general the two ways of saving a model instance to the db would be:
hull = Hull(hull="something") # creates the instance
hull.save() # saves it to the database
# or
hull = Hull.objects.create(hull="something") # does it all in one go

Reading through joined query Sqlalchemy Jinja

I am trying to display a doctors first name from another table that is linked by foreign key. I can get the doctor_id to display but cannot get his name to display.
I looked at this solution
reading from joined query in flask-sqlalchemy
but it is slightly different as I am querying from the other side and cannot use the backref value as a reference. I have removed the irrelevant code.
class Appointment(db.Model):
id = db.Column(db.Integer, primary_key=True)
patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'),
nullable=False)
doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id'),
nullable=False)
class Doctor(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(30), unique=False, nullable=False)
appointments = db.relationship('Appointment', backref =
db.backref('doctor',lazy=True))
and the query
all_appmts = db.session.query(Appointment)
.filter_by(patient_id=id)
.join(Doctor)
result =appointments_schema.dump(all_appmts)
return render_template('patient.html', all_appointments=result.data)
and this is what i tried
{% for a in all_appointments %}
<td>{{ a.doctor_id.first_name }}</td>
{% endfor %}
The doctor name displayed should be based on the the doctor id for that appointment.
Here is the marshmallow part.
class AppointmentSchema(ma.Schema):
class Meta:
# Fields to expose
fields = ('id','start_datetime', 'end_datetime', 'title',
'patient_id', 'doctor_id')
appointments_schema = AppointmentSchema(many=True)
You are trying to access doctor_id.first_name. But the name of the relationship is doctor. If you are converting the result of the query to a list of dicts, then you should serialize the appointment.doctor relationship also, so that the dict looks like
{
id: 12,
doctor: {
id: 34
}
}
Then you can access it like this
<td>{{ a.doctor.first_name }}</td>
But if you are just planning to use it in jinja template, then what is the need to serialize the objects? Instead you can just pass the result of the query.all() to the template. Jinja can directly access the python objects and show the data. So instead of result =appointments_schema.dump(all_appmts), try doing this
all_appmts = db.session.query(Appointment)
.filter_by(patient_id=id)
.join(Doctor)
return render_template('patient.html', all_appointments=all_aptmts.all())
And then keep the jinja template as the same
{% for a in all_appointments %}
<td>{{ a.doctor.first_name }}</td>
{% endfor %}
It will work

Flask - Python WTForms, Populate form with <li> list, <a> anchor data

I am using flask, sqlalchemy, jinja2 and python and I am struggling after getting data from the database and displaying them in my html while they are inside a list and in an anchor to post them with anchor click inside a form to submit them afterwords in another database table.
Here is what I have so far.
My html
<div class="container-fluid">
<div id="training_list">
<h1>List of Exercises</h1>
{% for exercises in exlist %}
<li id="li_ex_list">{{ exercises.name }} | Reputations:
{{ exercises.reps }}</li>
{% endfor %}
</div>
<div id="training_content">
<h1>My Workout Plan</h1>
<form method="POST" action="/my_workouts">
</form>
</br>
<button type="submit" class="btn btn-info">Save my plan</button>
</div>
</div>
My flask-python
class Exercises(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(40), unique=True, nullable=False)
reps = db.Column(db.Integer(), nullable=False)
complete = db.Column(db.Boolean, default=False)
def __init__(self, name, reps, complete):
self.name = name
self.reps = reps
self.complete = complete
def __repr__(self):
return '<Exercises %r>' % self.name
class Traningplan(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
ex_id = db.Column(db.Integer, db.ForeignKey('exercises.id'), nullable=False)
ex_name = db.Column(db.String(40), db.ForeignKey('exercises.name'), nullable=False)
class Usertrainingplan(FlaskForm):
user_id = IntegerField('Userid', render_kw={'readonly': True})
ex_id = IntegerField('Exerciseid', render_kw={'readonly': True})
ex_name = StringField('Exercisename', render_kw={'readonly': True})
#app.route('/my_workouts', methods=['GET', 'POST'])
#login_required
def my_workouts():
exlist = Exercises.query.all()
form = Usertrainingplan()
return render_template('My_Training_Programs.html', exlist=exlist, form=form)
I have tried filtering for complete True/False and passing 2 variables for complete and incomplete(also added them with jinja2 template in my html) but I can't make it work.
---- This part was inside "def_myworkouts():"-----
incomplete = Exercises.query.filter_by(complete=False).all()
complete = Exercises.query.filter_by(complete=True).all()
#app.route('/complete/<id>')
def complete(id):
exercises = Exercises.query.filter_by(id=int(id)).first()
exercises.complete = True
db.session.commit()
return redirect(url_for('my_workouts'))
Additional Information:
Current page looks like this:
current page
So what I want to do is:
Once the user clicks on the links on the left side, I want the text of the links (e.g. Landmine) to be added in the right side of the page where "My workout plan" is, and create a list with all the selected items.
Additionaly I want to be able to place them inside a form and the submit(POST) the form inside a table in my database, with the columns: user_id, ex_id, ex_name as foreign keys. user_id(foreign key) should be the current logged in users id(primary key), ex_id(foreign key) should be the id of the exercise and finally ex_name(foreign key) should be the name of the exercise. The primary keys ofcourse are already commited in the database in the required tables and sames goes with exercises names.
Thanks for your time in advance. Any help highly appriceated.
Stackoverflow you are my only savior

Multiple join in SQLalchemy

I've got some objects that look like below. I've got some property units, which contain one or more tenants, and the tenant object has a one-to-one relationship with users
class User(Base):
"""
Application's user model.
"""
__tablename__ = 'usr_users'
usr_user_id = Column(Integer, primary_key=True)
usr_email = Column(Unicode(50))
_usr_password = Column('password', Unicode(64))
usr_groups = Column(Unicode(256))
usr_activated = Column(Boolean)
tenant = relationship("Tenant", uselist=False, backref="usr_users")
class Tenant(Base):
__tablename__ = 'ten_tenants'
ten_tenant_id = Column(Integer, primary_key=True)
ten_ptu_property_unit_id = Column(Integer, ForeignKey('ptu_property_units.ptu_property_unit_id'))
ten_usr_user_id = Column(Integer, ForeignKey('usr_users.usr_user_id'))
class PropertyUnit(Base):
__tablename__ = 'ptu_property_units'
ptu_property_unit_id = Column(Integer, primary_key=True)
ptu_pty_property_id = Column(Integer, ForeignKey('pty_propertys.pty_property_id'))
tenants = relationship("Tenant")
I'm attempting to pull all of the units for a property, including the tenant information and the email from the user table.
I managed to get one join pretty easy:
rows = DBSession.query(PropertyUnit).join(Tenant).filter(PropertyUnit.ptu_pty_property_id==request.GET['property_id']).order_by(PropertyUnit.ptu_number)
units = rows.all()
And I'm displaying in the template like this:
% for unit in units:
<%
tenants = unit.tenants
%>
<tr>
<td>${unit.ptu_number}</td>
<td>
% for tenant in tenants:
${tenant.ten_usr_user_id},
% endfor
</td>
</tr>
% endfor
So far so good. Now I need to pull the user information from the tenant foreign key, so I thought I could just tack on another join:
rows = DBSession.query(PropertyUnit).join(Tenant).join(User).filter(PropertyUnit.ptu_pty_property_id==request.GET['property_id']).order_by(PropertyUnit.ptu_number)
units = rows.all()
This appears to work in the SQL logs, as it generates the right SQL, but I'm unable to get to the data in the same way that I did the first time. This fails:
% for unit in units:
<%
tenants = unit.tenants
%>
<tr>
<td>${unit.ptu_number}</td>
<td>
% for tenant in tenants:
<%
user = tenant.User
%>
${tenant.ten_usr_user_id},
% endfor
</td>
</tr>
% endfor
So, the above code throws a "'Tenant' object has no attribute 'User'" error.
How do I get to that user join?
There's no attribute User on Tenant because you didn't define one. You called it usr_users in the backref, so you should access it as tenant.usr_users.

Categories