Flask ressults filter box - python

I'm new in Flask , SQLALchemy
i have 1 page that retuern a list of companies , each company has City, Address , and belong to specific industrial sector, and has multiple products
what the best way to Filter results
for example based on City , or CITY AND Sector
MY models here
lass Sector (db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), unique=True, nullable=False)
companies=db.relationship('Company',backref='sector')
class Company(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), unique=True, nullable=False)
address = db.Column(db.String(),nullable=False)
city_id=db.Column(db.Integer,db.ForeignKey('city.id'))
sector_id=db.Column(db.Integer,db.ForeignKey('sector.id'))
products=db.relationship('Product',backref='company')
class Certificate(db.Model):
id = db.Column(db.Integer, primary_key=True)
type = db.Column(db.String())
products=db.relationship('Product',backref='certificate')
class Product (db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
company_id=db.Column(db.Integer,db.ForeignKey('company.id'))
certificate_id=db.Column(db.Integer,db.ForeignKey('certificate.id'))
and view page here
{%extends "layout.html"%}
{%block content%}
{%for company in companies%}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="#">{{ company.name }}</a>
<small class="text-muted">{{ company.sector.name}}</small>
</div>
<ul>
{%for product in company.products%}
<li>{{product.name}}</li>
{%endfor%}
</ul>
<p class="article-content">{{ company.city.name }}</p>
</div>
</article>
{%endif%}
{%endfor%}
{%endblock%}

Instead of having Company.query.order_by(Company.name) to query all of your data, you could
Company.query.filter(city_id=city_id_value, sector_id=sector_id_value)
The city_id_value and sector_id_value may be provided in the route like
sector_id_value = request.args.get('sector', type = int)
city_id_value = request.args.get('city', type = int)
Flask supports named parameters in urls. See this post for a detailed explaination.
If you access the url /?sector=10&city=5, then city_id_value will be 5 and sector_id_value will be 10.

Related

How can I display a nested list of tasks in a Flask application?

I would like to generate output in this format:
<h1>2023-01-16 #task.week_start_date</h1>
<h2>Build a house #task.project.name</h2>
<h3>Buy a a blueprint #task.name</h3>
<h3>Buy some wood #task.name</h3>
<h2>Plan a vacation #task.project.name</h2>
<h3>Ask family where they would like to go #task.name</h3>
<h1>2023-01-23 #task.week_start_date</h1>
<h2>Build a house #task.project.name</h2>
<h3>Build the frame #task.name</h3>
<h2>Plan a vacation #task.project.name</h2>
<h3>Pick a week when all the family can go #task.name</h3>
<h3>Check on plane ticket prices #task.name</h3>
Here is the Flask app:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db = SQLAlchemy(app)
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
tasks = db.relationship('Task', backref='project', lazy=True)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
week_start_date = db.Column(db.String)
project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
#app.route('/')
def home():
tasks = Task.query.order_by(Task.week_start_date,Task.project_id).all()
return render_template('home.html', tasks=tasks)
How should I code home() and home.html to achieve the above output?
I tried this in home.html:
{% for task in tasks %}
{% if loop.changed(task.week_start_date) %}
<h1>{{ task.week_start_date }}</h1>
{% endif %}
{% if loop.changed(task.project.id) %}
<h2>{{ task.project.name }}</h2>
{% endif %}
<h3>{{ task.name }}</h3>
{% endfor %}
However, it would create a new H1 for every task, even if the following task had the same start week.

Data is not stored in flask sqlAlchemy

Im creating a flask app and the data is not stored when i click register after adding all the information. when I click the register button there are no any errors showing.
heres my routes.py
#app.route('/register', methods=['GET', 'POST'])
def register_page():
form = RegisterForm()
if form.validate_on_submit():
user_to_create = User(username=form.username.data,email=form.email.data,password_hash=form.password1.data)
db.session.add(user_to_create)
db.session.commit()
flash(f'Account created Successfully...! you are now logged in as {{ user_to_create.username }}',
category='success')
return redirect(url_for('topup_page'))
if form.errors != {}:
for error in form.errors.values():
flash(f'There was an error with creating the user{error}', category='danger')
return render_template('register.html', form=form)
here is my register.html file
<div class="col-6">
<div class="container">
<form method="POST" class="form-register">
<h2>Please Create Your Account</h2>
{{ form.hidden_tag() }}
<br>
{{ form.username.label()}}
{{ form.username(class="form-control", placeholder="User Name")}}
<br>
{{ form.email.label()}}
{{ form.email(class="form-control", placeholder="Email Address")}}
<br>
{{ form.password1.label()}}
{{ form.password1(class="form-control", placeholder="Password")}}
<br>
{{ form.password2.label()}}
{{ form.password2(class="form-control", placeholder="Confirm Password")}}
<br>
{{ form.submit(class="btn btn-lg btn-block btn-primary disabled") }}
<div class="checkbox mb-3">
<h6> Already have an account? Sign In
</h6>
</div>
</form>
</div>
here is my models.py file
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer(), nullable=False, primary_key=True)
username = db.Column(db.String(20), nullable=False, unique=True)
email = db.Column(db.String(30), nullable=False, unique=True)
password = db.Column(db.String(60), nullable=False)
credit = db.relationship('Credit', backref='owner')
i think you need to add a name attribute to the inputs. Sorry if this is a wrong answer.I have not used flask in a long time.
I will show you sample code:
Template:
<form action="{{ url_for('app.update_view') }}" method="post"
enctype="multipart/form-data">
<input name="name1" placeholder='abc'>
<input name="name2" placeholder='xyz'>
<input name="name3" placeholder='123'>
<button type="submit" class="btn btn-primary">Register</button>
</form>
View:
#app.route('/path', methods=['POST', 'GET'])
#roles_required('admin,member') # doenst matter
def update_view():
try:
if request.method == 'POST':
name1 = request.form.get('name1')
name2 = request.form.get('name2')
name3 = request.form.get('name3')
if name1 is not None and name2 is not None:
YourModelNAme.create_classmethod(name1, name2, name3)
return render_template("directory_name/your_html.html")
except Exception as e:
return create_json_response(
{'message': 'Error->' + e.__str__()}, False, 201), 201
Model:
class YourModelNAme(db.Model, UserMixin):
name1 = db.Column(db.Integer(), nullable=False, primary_key=True)
name2 = db.Column(db.String(20), nullable=False, unique=True)
name3 = db.Column(db.String(60), nullable=False)
#classmethod
def create_classmethod(cls,name1,name2,name3):
your_model = YourModelNAme()
your_model.name1 = name1
...
db.session.add(your_model)
db.session.commit()
return your_model

If condition doesn't work with object's attribute

im trying to write app similiar to Tinder.
I created models:
class User(db.Model, UserMixin):
id = db.Column('id', db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True, nullable=False)
name = db.Column(db.String(20), nullable=False)
age = db.Column(db.Integer, nullable=False)
description = db.Column(db.String(200), default='')
gender = db.Column(db.String(6), nullable=False)
image = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
likes = db.relationship('Like', backref='liked_by', lazy=True)
def __repr__(self):
return f'User({self.name}, {self.gender}, {self.age}, {self.image})'
class Like(db.Model):
id = db.Column('id', db.Integer, primary_key=True)
like_to = db.Column(db.Integer)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
I want to current_user wont be able to see user on the home page if he already liked him. And here is my problem to create appropriate if condition. Now it looks like this and doesn't work:
{% block content %}
{% for user in users %}
{% if current_user.gender != user.gender %}
{% **if user.id not in current_user.likes** %}
<form action="{{ url_for('like_profile', user_id=user.id) }}" method="POST">
{{ form.hidden_tag() }}
<p>{{ user.name }}</p>
<p>{{ user.gender }}</p>
<p>{{ user.age }}</p>
<p>User id: {{ user.id }}</p>
<p>User likes: {{ user.likes }}</p>
<p>{{ form.submit }}</p>
</form>
{% endif %}
{% endif %}
{% endfor %}
{% endblock %}
This line: if user.id not in current_user.likes - how should i do this?
The function which creates like:
#app.route('/profile/<int:user_id>', methods=['POST'])
def like_profile(user_id):
user = User.query.get_or_404(user_id)
like = Like(like_to=user.id, liked_by=current_user)
db.session.add(like)
db.session.commit()
flash(f'Like has been given to {user} from {current_user}. {type(current_user.likes)}')
return redirect(url_for('home'))
Ok guys, maybe someone will be interested. I found some resolution.
First:
current_user.likes was giving Like objects like Ilja said.
I changed from lazy=True to lazy='dynamic' in relationship, now it looks like this:
class User(db.Model, UserMixin):
id = db.Column('id', db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True, nullable=False)
name = db.Column(db.String(20), nullable=False)
age = db.Column(db.Integer, nullable=False)
description = db.Column(db.String(200), default='')
gender = db.Column(db.String(6), nullable=False)
image = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
likes = db.relationship('Like', backref='liked_by', lazy='dynamic')
def __repr__(self):
return f'User({self.name}, {self.gender}, {self.age}, {self.image})'
class Like(db.Model):
id = db.Column('id', db.Integer, primary_key=True)
like_to = db.Column(db.Integer)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __repr__(self):
return f"Like id: {self.id}, user id: {self.user_id}, like to: {self.like_to}, like from: {self.liked_by}"
And it gave me new functionality, i can: current_user.likes.filter_by(like_to=user.id).first().like_to
what finnaly returns liked user's ID.
And my home template now looks like this:
{% block content %}
{% for user in users %}
{% if current_user.gender != user.gender %}
{% if user.id != current_user.likes.filter_by(like_to=user.id).first().like_to %}
<form action="{{ url_for('like_profile', user_id=user.id) }}" method="POST">
{{ form.hidden_tag() }}
<p>{{ user.name }}</p>
<p>{{ user.gender }}</p>
<p>{{ user.age }}</p>
<p>User id: {{ user.id }}</p>
<p>User likes: {{ user.likes }}</p>
<p>{{ form.submit }}</p>
</form>
{% endif %}
{% endif %}
{% endfor %}
{% endblock %}
Thanks for trying to help me.

How can I query categories for blog posts with flask-sqlalchemy?

I would like to show the categories of blog posts (many-to-many-relationship). How can I query them correctly with SQL-Alchemy and show them with Jinja2 in a HTML-Template?
models.py
category_post = db.Table('category_post',
db.Column('posts_id', db.Integer, db.ForeignKey('posts.id')),
db.Column('categories_id', db.Integer, db.ForeignKey('categories.id'))
)
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
author_id = db.Column(db.Integer, db.ForeignKey('users.id'))
active = db.Column(db.Boolean, default="0")
categories = db.relationship('Category',
secondary=category_post,
backref=db.backref('posts', lazy='dynamic'),
lazy='dynamic')
comments = db.relationship('Comment', backref='post', lazy='dynamic')
en_title = db.Column(db.String(128))
de_title = db.Column(db.String(128))
en_subtitle = db.Column(db.String(128))
de_subtitle = db.Column(db.String(128))
en_description = db.Column(db.String(256))
de_description = db.Column(db.String(256))
en_body = db.Column(db.Text)
de_body = db.Column(db.Text)
en_url = db.Column(db.String(128))
de_url = db.Column(db.String(128))
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key=True)
en_name = db.Column(db.String(128))
en_url = db.Column(db.String(128))
de_name = db.Column(db.String(128))
de_url = db.Column(db.String(128))
views.py
#main.route('/')
def index():
posts = Post.query.filter_by(active="1").order_by(Post.timestamp.desc())
return render_template('index.html', posts=posts)
Template
<div class="ui items">
{% for post in posts %}
<div class="item">
<div class="image">
<div class="ui placeholder">
<div class="square image"></div>
</div>
</div>
<div class="middle aligned content">
<a class="header" href="{{ _(post.en_url) }}">{{ _(post.en_title) }}</a>
<div class="meta">
<span>{{ _(post.en_subtitle) }}</span>
</div>
<div class="description">
<p>
{{ _(post.en_description) }}
</p>
</div>
{% for category in categories %}
<a class="ui grey label"> <i class="fas fa-globe"></i> {{ _(categories.en_name) }} </a>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
It should provide the names of the categories, but I get no result, just empty space, where they should appear. Thanks in advance for your help.
You may want to use the categories attribute you created on the Post model:
{% for category in post.categories %}

Flask sqlalchemy InterfaceError

I'm not sure whats going wrong here...I get this error:
InterfaceError: (InterfaceError) Error binding parameter 0 - probably unsupported type. u'SELECT contact.id AS contact_id, contact.surname AS contact_surname, contact.firstname AS contact_firstname, contact.email AS contact_email, contact.mobile AS contact_mobile, contact.work_location AS contact_work_location \nFROM contact \nWHERE contact.id = ?' ([1],)
My method:
#app.route('/contacts/<int:contact_id>', methods=['GET'])
def contact_detail(contact_id):
if request.method == 'GET':
db.session.query(Contact).filter_by(id=[contact_id]).all()
return render_template('modcontact.html', title = 'Contact Detail')
My models:
class Contact(db.Model):
id = db.Column(db.Integer, primary_key = True)
surname = db.Column(db.String(100))
firstname = db.Column(db.String(100))
email = db.Column(db.String(100))
mobile = db.Column(db.String(20))
work_location = db.Column(db.String(100))
#user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Contact %r>' % (self.surname)
template:
{% extends "base.html" %}
{% block content %}
<h1>List of contacts</h1>
<ul class=contacts>
{% for contacts in contacts %}
<li><h3>
<a href="{{ url_for('contact_detail',contact_id=contacts.id)}}">
{{ contacts.surname }}, {{ contacts.firstname }}
</a>
</h3></li>
{% else %}
<li><em>No contacts available</em></li>
{% endfor %}
</ul>
Add a new contact
{% endblock %}
You pass a list in your query filter. So the parameter in the query is a list therefore the 'Error binding parameter 0'.
Try this instead: db.session.query(Contact).filter_by(id=contact_id).all()

Categories