How to query with many tables - python

from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
#import sqlite3 as sql
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://ahmad:ahmad#192.168.3.103/utama'
db = SQLAlchemy(app)
class ak(db.Model):
__tablename__ = 'ak'
id = db.Column(db.Integer, primary_key=True)
nama = db.Column(db.String)
alamat = db.Column(db.String)
akreditasi = db.Column(db.String)
def __init__(self, id, nama, alamat, akreditasi):
self.id = id
self.city = nama
self.alamat = alamat
self.akreditasi = akreditasi
class av(db.Model):
__tablename__ = 'av'
id = db.Column(db.Integer, primary_key=True)
nama = db.Column(db.String)
alamat = db.Column(db.String)
akreditasi = db.Column(db.String)
def __init__(self, id, nama, alamat, akreditasi):
self.id = id
self.city = nama
self.alamat = alamat
self.akreditasi = akreditasi
id_jurusan = db.Table('id_jurusan',
db.Column('id', db.Integer, db.ForeignKey('ak.id')),
db.Column('id', db.Integer, db.ForeignKey('av.id'))
)
#app.route('/ak')
def jurusan(jurusan):
return render_template('index.html', rows=ak.query.all() )
#app.route('/av')
def Akuntansi():
return render_template('index.html', rows=av.query.all() )
if __name__ == '__main__':
app.run(debug=True, host='1.1.1.1', port=80)
I am a new to learn python, in this case I studied the framework flask and I had trouble on the declaration SQLAlchemy, precisely displays the contents of the table but with the same structure,when executed will be like this.....
[
which one success

You are using the decorator
#app.route('/av')
The method which succeeds Akuntansi() does not require a parameter. So this works. The method which fails expects a parameter jurusan(jurusan) but your decorator #app.route('/ak') does not consider this.
To pass a parameter you need to use the decorator like this:
#app.route("/ak/<jurusan>") and then also pass the parameter in the request.

Related

session.commit not inserting data into database for flask-sqlalchemy

I'm trying to create a sqlite database that takes inputs from a CSV file using flask-sqlalchelmy.
Here is the config file:
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'applicant.db')
app.config['SQLALCHEMY_TRACK _MODIFICATIONS']=False
cors = CORS(app)
db = SQLAlchemy(app)
app.run(debug=True)
Here are the models:
class attributes(db.Model):
__tablename__ = 'attributes'
id = Column(Integer, primary_key=True)
URL = Column(Text)
Gender = Column(String(10))
SAT =Column(Integer)
ACT = Column(Integer)
major =db.relationship('Major',backref = 'attributes')
ecs = db.relationship('Ecs', backref = 'attributes')
Race = db.relationship('Race',backref = 'attributes')
Acceptances = db.relationship('Acceptances', backref = 'attributes')
Rejections = db.relationship('Rejections', backref = 'attributes')
class Ecs(db.Model):
id = Column(Integer, primary_key = True)
listofecs = Column(Text)
Attributeid = Column(Integer, db.ForeignKey('attributes.id'))
def __repr__(self):
return f'<Ecs "{self.title}">'
class Major(db.Model):
id = Column(Integer, primary_key = True)
majorlist = Column(Text)
Attributeid = Column(Integer, db.ForeignKey('attributes.id'))
def __repr__(self):
return f'<major "{self.title}">'
class Race(db.Model):
id = Column(Integer, primary_key = True)
racelist = Column(Text)
Attributeid = Column(Integer, db.ForeignKey('attributes.id'))
def __repr__(self):
return f'<race "{self.title}">'
class Acceptances(db.Model):
id = Column(Integer, primary_key = True)
acceptlist = Column(Text)
Attributeid = Column(Integer, db.ForeignKey('attributes.id'))
def __repr__(self):
return f'<acceptances "{self.title}">'
class Rejections(db.Model):
id = Column(Integer, primary_key = True)
rejectlist = Column(Text)
Attributeid = Column(Integer, db.ForeignKey('attributes.id'))
def __repr__(self):
return f'<rejections "{self.title}">'
They are mostly one-to-many relationships - but i'm not sure if thats the issue.
I'm trying to create the database by using this script:
import pandas as pd
from app import attributes, Major, Ecs, Race, Acceptances,Rejections, db, df
from ast import literal_eval
df = pd.read_csv('..\csvfiles\processeddata.csv')
for i in range(len(df['Gender'])):
applicant = attributes(Gender = df['Gender'].iloc[i],SAT = df['SAT'].iloc[i], ACT = df['ACT'].iloc[i])
db.session.add(applicant)
for racevalues in df['Race'].apply(literal_eval).iloc[i]:
race = Race(racelist = racevalues, Attributeid = i+1)
db.session.add(race)
for majorvalues in df['Major'].apply(literal_eval).iloc[i]:
major = Major(majorlist = majorvalues,Attributeid = i+1 )
db.session.add(major)
for ecvalues in df['Extracurriculars'].apply(literal_eval).iloc[i]:
ecs = Ecs(listofecs = ecvalues , Attributeid = i+1)
db.session.add(ecs)
for valuesacceptances in df["Acceptances"].apply(literal_eval).iloc[i]:
Accepts = Acceptances(acceptlist = valuesacceptances, Attributeid = i+1)
db.session.add(Accepts)
for valuesreject in df["Rejections"].apply(literal_eval).iloc[i]:
Rejects = Rejections(rejectlist = valuesreject, Attributeid = i+1)
db.session.add(Rejects)
db.create_all()
db.session.commit()
df is the data that is taken from the csv file that I want to be inserted into the database. I have confirmed that it is the correct file and has data by printing df. I have also tried to manually create the database using db.create_all() in the command line through the flask shell. This creates the scheme for the database but even after running the script, there is no data inserted into the database. Further, when I try to query the data onto a route the route indeed works but returns an empty array.
The strange thing is that this worked perfectly fine for a few days. It stopped working after my computer crashed and I wonder if that has something to do with it.

How to call an attribute inside the model in FLASK SQLAlchemy

I'm trying to call an attribute inside a model in SQLAlchemy this way
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
class Show(db.Model):
__tablename__ = 'Show'
id = db.Column(db.Integer, primary_key=True)
venue_id = db.Column(
db.Integer, db.ForeignKey('Venue.id'), nullable=True)
class Venue(db.Model):
__tablename__ = 'Venue'
id = db.Column(db.Integer, primary_key=True)
upcoming_shows = Show.query.filter(Show.venue_id == 1).filter(
Show.start_time >= func.current_date()).all()
I want to replace 1 here with the id of the current Venue.. I tried the following:
self.id: returns "Undefined variable: 'self'"
id: returns "Cannot compile Column object until its 'name' is
assigned"
Thanks for help
The simplest solution is to use a hybrid property. A hybrid property is accessible like a normal attribute, but it can run queries to retrieve its value.
from sqlalchemy.ext.hybrid import hybrid_property
class Venue(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
#hybrid_property
def upcoming_shows(self):
upcoming_shows = Show.query.filter(Show.venue_id == self.id).filter(
Show.start_time >= db.func.current_date()).all()
return upcoming_shows
#app.route("/", methods=["GET"])
def index():
venue = Venue.query.first()
shows = venue.upcoming_shows
...

Flask-Admin: Change sort order of inline_models?

In Flask-Admin, is there any way to control the order of the list generated by inline_models? It seems to be coming out in database order, i.e. ordered by the ID primary key.
That is, if I have an Author that has_many Books, and my AuthorModelView class has inline_models = (Books,), the books are always ordered by book_id. Passing column_default_sort to the inline model, to try to sort by (say) title or date_purchased, has no effect. Is there any way to handle this?
Specify the order_by parameter when specifying the relationships, see docs. See note at the end if you want to sort by a specific field at runtime.
Example of model declarations for Author -> Books. Here we are ordering on the book title field ascending - order_by='Book.title.asc()' :
class Author(db.Model):
__tablename__ = 'authors'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Text(length=255), nullable=False)
last_name = db.Column(db.Text(length=255), nullable=False)
books = db.relationship("Book", order_by='Book.title.asc()', cascade="all,delete-orphan", backref=db.backref('author'))
def __str__(self):
return f"ID: {self.id}; First Name: {self.first_name}; Last Name: {self.last_name}"
class Book(db.Model):
__tablename__ = 'books'
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey('authors.id'), nullable=False, index=True)
title = db.Column(db.Text(length=255), nullable=False)
def __str__(self):
return f"ID: {self.id}; Title: {self.title}; Author ID: {self.author_id}"
Single file full example:
from faker import Faker
import click
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin
from flask_admin.contrib import sqla
db = SQLAlchemy()
class Author(db.Model):
__tablename__ = 'authors'
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.Text(length=255), nullable=False)
last_name = db.Column(db.Text(length=255), nullable=False)
books = db.relationship("Book", order_by='Book.title.asc()', cascade="all,delete-orphan", backref=db.backref('author'))
def __str__(self):
return f"ID: {self.id}; First Name: {self.first_name}; Last Name: {self.last_name}"
class Book(db.Model):
__tablename__ = 'books'
id = db.Column(db.Integer, primary_key=True)
author_id = db.Column(db.Integer, db.ForeignKey('authors.id'), nullable=False, index=True)
title = db.Column(db.Text(length=255), nullable=False)
def __str__(self):
return f"ID: {self.id}; Title: {self.title}; Author ID: {self.author_id}"
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
app.config['SQLALCHEMY_ECHO'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sample.sqlite'
db.init_app(app)
#app.cli.command('create-database', short_help='Create Authors database')
#click.option('--count', default=100, help='Number of authors (default 100)')
def create_database(count):
"""
Create database with "count" authors
"""
db.drop_all()
db.create_all()
_faker = Faker()
for _ in range(0, count):
_author = Author(
first_name=_faker.first_name(),
last_name=_faker.last_name(),
)
db.session.add(_author)
for _ in range(0, _faker.pyint(1, 20)):
_book = Book(
title=_faker.sentence(),
author=_author
)
db.session.add(_book)
db.session.commit()
class AuthorView(sqla.ModelView):
# default sort: last_name ascending
column_default_sort = ('last_name', False)
inline_models = (Book,)
# Flask views
#app.route('/')
def index():
return 'Click me to get to Admin!'
admin = Admin(app, template_mode="bootstrap3")
admin.add_view(AuthorView(Author, db.session))
if __name__ == '__main__':
app.run()
Run the following command to initialize an SQLite DB.
flask create-database --count 100
If you want to change the sort field at runtime override the view's get_one() method and use Python to sort the instrumented list directly. For example, sorting by ISBN field instead of title:
class Author2View(sqla.ModelView):
def get_one(self, id):
_author = super().get_one(id)
_author.books = sorted(_author.books, key=lambda book: book.isbn)
return _author
# default sort: last_name ascending
column_default_sort = ('last_name', False)
inline_models = (Book,)
admin.add_view(Author2View(Author, db.session, name="Author 2", endpoint='author-2'))

How to get data from two tables using SQLALCHEMY

Let say I have a model
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Students(db.Model):
__tablename__ = "students"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
description = db.Column(db.String, nullable=False)
class Hobbies(db.Model):
__tablename__ = "hobbies"
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
description = db.Column(db.String)
student_id = db.Column(db.Integer, db.ForeignKey("students.id"), nullable=False)
Now in flask I have following code
import os
from flask import Flask, render_template, request
from models import *
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql://junaid:junaid#localhost:5432/UOB"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
Now I get all the record in the table Hobbies
from sqlalchemy.sql import select
with app.app_context():
a = Hobbies.query.all()
I want to get the result like
Hobby.ID, Hobby.title, Hobby.description, Student.name (The filter is Hobby.student_id = Students.id)
I want to print all the record in the hobbies table with student name in short.
Here is the solution. Sharing if someone else can benefit from this.
hobbies_with_stud = db.session.query(Students, Hobbies).join(Hobbies, Hobbies.student_id == Students.id).all()
for record in hobbies_with_stud:
print(record.Hobbies.title + " is the hobby of "+ record.Students.name)

SQLAlchemy / WTForms - QuerySelectField

I'm using WTForms with the SQLAlchemy extension on a Pyramid application.
My session is:
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
My model is:
class Client(Base):
__tablename__ = 'client'
id = Column(Integer, primary_key=True, nullable=False)
name = Column(Unicode(48))
street = Column(Unicode(48))
city = Column(Unicode(32))
task = relationship("Task", backref="client")
#classmethod
def active(cls):
return DBSession.query(Client).options(load_only("id", "name")).order_by(sa.desc(Client.name)).filter(Client.status == True)
class Task(Base):
__tablename__ = 'task'
id = Column(Integer, primary_key=True, nullable=False)
name = Column(String(48))
status = Column(Boolean)
client_id = Column(Integer, ForeignKey('client.id'))
My form is:
def enabled_client():
return Client.active()
class TaskCreateForm(ModelForm):
name = TextField('Task name', [validators.Length(min=1, max=48)], filters=[strip_filter])
status = BooleanField('Status')
client_id = QuerySelectField('Client', query_factory=enabled_client, get_label='name', allow_blank=False)
My view is:
#view_config(route_name='task_action', match_param='action=create', renderer='arx:templates/task_edit.mako', permission='edit')
def task_create(request):
task = Task()
form = TaskCreateForm(request.POST)
if request.method == 'POST' and form.validate():
form.populate_obj(task)
DBSession.add(task)
return HTTPFound(location=request.route_url('home'))
return {'form':form, 'action':request.matchdict.get('action')}
Form displays select box with proper Client names but the problem emerges when I'm trying to submit form. WTForm should use real ID of Client but it passes SQLAlchemy object eg:
<arx.models.Client object at 0x7fdfb139ddd0>
What am I doing wrong?
My form was too specific (it should be client instead of client_id), so my working code looks like this:
Session:
from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
Model:
class Client(Base):
__tablename__ = 'client'
id = Column(Integer, primary_key=True, nullable=False)
name = Column(Unicode(48))
street = Column(Unicode(48))
city = Column(Unicode(32))
task = relationship("Task", backref="client")
#classmethod
def active(cls):
return DBSession.query(Client).options(load_only("id", "name")).order_by(sa.desc(Client.name)).filter(Client.status == True)
class Task(Base):
__tablename__ = 'task'
id = Column(Integer, primary_key=True, nullable=False)
name = Column(String(48))
status = Column(Boolean)
client_id = Column(Integer, ForeignKey('client.id'))
Form:
def enabled_client():
return Client.active()
class TaskCreateForm(ModelForm):
name = TextField('Task name', [validators.Length(min=1, max=48)], filters=[strip_filter])
status = BooleanField('Status')
client = QuerySelectField('Client', query_factory=enabled_client, get_label='name', allow_blank=False)
View:
#view_config(route_name='task_action', match_param='action=create', renderer='arx:templates/task_edit.mako', permission='edit')
def task_create(request):
task = Task()
form = TaskCreateForm(request.POST)
if request.method == 'POST' and form.validate():
form.populate_obj(task)
DBSession.add(task)
return HTTPFound(location=request.route_url('home'))
return {'form':form, 'action':request.matchdict.get('action')}

Categories