miguelgrinberg / microblog-api Goto Github PK
View Code? Open in Web Editor NEWA modern (as of 2024) Flask API back end.
License: MIT License
A modern (as of 2024) Flask API back end.
License: MIT License
Hello,
Thank you for all you tutorials! They have been extremely helpful in learning about Flask and React, and web development in general. I'm attempting to understand the api, and was confused with marshmallow. I was exposed to this only on examination of this api, since you haven't yet used this in your Flask Mega-Tutorial. While I think I understand how marshmallow is working, I'm confused on where this specific package is used? When I examined the generated pip-compile requirements, marshmallow_sqlalchemy is not a dependency for any other package. Furthermore, most of the features used in this package are already implemented in flask-marshmallow, which you already use.
I think I'm getting confused with all the integrations that are happening with sqlalchemy, flask, etc. Please let me know if I am missing something?
Thank you
Hi Miguel -
I have been hacking away at this for awhile and I can't seem to get this to work properly. Ultimately I am trying to have an after commit handler on one of my models:
# Define the create_job_after_commit function outside of the create_job_when_accepted function
@event.listens_for(db.session, 'after_commit')
def create_job_after_commit(session):
with app.app_context():
for target in session.new:
if isinstance(target, Estimate) and target.status == 'Accepted':
est = session.query(Estimate).get(target.id)
# Extract the vendor_id from the loaded Estimate instance
vendor_id = est.vendor_id
job = Job(name=est.name, status='Upcoming', vendor_id=vendor_id, user_id=est.user_id)
db.session.add(job)
The problem is I am getting an error: RuntimeError: Working outside of application context.
I've tried a bunch of different things to import the current app but to no success.
Initially I tried to do an event on the status field of my model, but this didn't give me access to the vendor_id or user_id fields... Oddly it did give me access to the name fields. I am 100% confident these fields are set when I initialize an estimate record:
@event.listens_for(Estimate.status, 'set')
def create_job_when_accepted(target, value, old_value, initiator):
if value == 'Accepted' and old_value != 'Accepted':
# Create a new Job instance
job = Job(name=target.name, status='Upcoming', vendor_id=target.vendor_id, user_id=target.user_id)
db.session.add(job)
Any help is appreciated.
Hi Miguel. Thanks for open sourcing the microblog-api project. By any chance do you have a tutorial for it? If not I am trying to get rid of the "data" entry along with the object format on top. I can't figure out how to do this. Do you have any suggestions?
Format wanted:
[
{
"banners": [],
"created_at": "2022-10-03T00:20:16.691223",
"icon": "FruitsVegetable",
"id": 1,
"images": [],
"language": "en",
"name": "Grocery",
"promotional_sliders": [],
"settings": {
"isHome": true,
"layoutType": "classic",
"productCard": "neon"
},
"slug": "grocery",
"translated_languages": [
"es",
"fr",
"de"
],
"updated_at": "2022-10-03T00:20:16.691223"
},
{
"banners": [],
"created_at": "2022-10-03T00:20:16.693224",
"icon": "Bakery",
"id": 2,
"images": [],
"name": "Bakery",
"promotional_sliders": [],
"settings": {
"isHome": false,
"layoutType": "standard",
"productCard": "argon"
},
"slug": "bakery",
"translated_languages": [],
"updated_at": "2022-10-03T00:20:16.693224"
},
]
Using the paginated decorator you made I get this:
{
"data": [
{
"banners": [],
"created_at": "2022-10-03T00:20:16.691223",
"icon": "FruitsVegetable",
"id": 1,
"images": [],
"language": "en",
"name": "Grocery",
"promotional_sliders": [],
"settings": {
"isHome": true,
"layoutType": "classic",
"productCard": "neon"
},
"slug": "grocery",
"translated_languages": [
"es",
"fr",
"de"
],
"updated_at": "2022-10-03T00:20:16.691223"
},
{
"banners": [],
"created_at": "2022-10-03T00:20:16.693224",
"icon": "Bakery",
"id": 2,
"images": [],
"name": "Bakery",
"promotional_sliders": [],
"settings": {
"isHome": false,
"layoutType": "standard",
"productCard": "argon"
},
"slug": "bakery",
"translated_languages": [],
"updated_at": "2022-10-03T00:20:16.693224"
},
]
}
Hi, big thanks to Miguel for this awesome repo & blog post (https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xv-a-better-application-structure)
I've cloned your repo, made a new model & added a new route, I would now like to write tests from them.
I'm trying to run the existing tests in the tests folder, but think I'm doing something wrong. In the blog post it mentions tests.py but this file does not exist any longer, tad confused.
How do you actually run the tests please? Is there a Flash command to run, eg: Flask run tests?
Thank you
Sharry
Hi, I noticed problems with my pagination. After I digged into it, I noticed that for my app the pagination does not work if the posts were all created in the same second, even though they differ in the microseconds and the microseconds are correctly stored in the database.
Is this maybe a marshmallow bug or in the code or on my end?
Hi Miguel,
I am testing the api application and I found that Revoke an access token endpoint return an 500 error in HTML format to API (in webUI Documentation and also with httpie in console)
it looks that one schema auth argument and/or 500 error handle is missing.
Saludos desde Guatemala.
Best Regards,
DH
Hey Miguel,
Thank you for the project. I realized your GitHub actions workflow does not seem to catch an error with the password reset function, however mine does. I am not sure yet why, but when I tried to test it manually, it also did not work. It could be because I ran:
pytest -cov tests/
But I am not entirely sure. I modified the .yaml
in my repo. Please check it for any suggestions on how to fix it.
Best,
Manuel
Mac M1... I create the venv and I get this error.
/api/app.py", line 3, in <module>
from flask_migrate import Migrate
ModuleNotFoundError: No module named 'flask_migrate'
Of course this is in my venv, requirements:
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
#
alchemical==0.5.1
# via -r requirements.in
alembic==1.7.7
# via flask-migrate
apifairy==0.9.1
# via -r requirements.in
apispec==5.1.1
# via apifairy
blinker==1.4
# via flask-mail
click==8.1.0
# via flask
faker==13.3.4
# via -r requirements.in
flask==2.1.0
# via
# -r requirements.in
# apifairy
# flask-cors
# flask-httpauth
# flask-mail
# flask-marshmallow
# flask-migrate
# flask-sqlalchemy
flask-cors==3.0.10
# via -r requirements.in
flask-httpauth==4.5.0
# via
# -r requirements.in
# apifairy
flask-mail==0.9.1
# via -r requirements.in
flask-marshmallow==0.14.0
# via
# -r requirements.in
# apifairy
flask-migrate==3.1.0
# via -r requirements.in
flask-sqlalchemy==2.5.1
# via flask-migrate
greenlet==1.1.2
# via sqlalchemy
gunicorn==20.1.0
# via -r requirements.in
itsdangerous==2.1.2
# via flask
jinja2==3.1.1
# via flask
mako==1.2.0
# via alembic
markupsafe==2.1.1
# via
# jinja2
# mako
marshmallow==3.15.0
# via
# flask-marshmallow
# marshmallow-sqlalchemy
# webargs
marshmallow-sqlalchemy==0.28.0
# via -r requirements.in
packaging==21.3
# via
# marshmallow
# webargs
pyjwt==2.3.0
# via -r requirements.in
pyparsing==3.0.7
# via packaging
python-dateutil==2.8.2
# via faker
python-dotenv==0.20.0
# via -r requirements.in
six==1.16.0
# via
# flask-cors
# flask-marshmallow
# python-dateutil
sqlalchemy==1.4.32
# via
# alchemical
# alembic
# flask-sqlalchemy
# marshmallow-sqlalchemy
webargs==8.1.0
# via apifairy
werkzeug==2.1.0
# via flask
# The following packages are considered to be unsafe in a requirements file:
# setuptools
Hi Miguel,
I'm puzzled with the token refresh procedure. If I understand correctly, to get a fresh access token, one can give the expired access token along with corresponding valid refresh token with a PUT request on /tokens endpoint.
From reading the code, both are verified with User.verify_refresh_token(refresh_token, access_token_jwt)
which in turn triggers Token.from_jwt(access_token_jwt)
.
In the from_jwt
method, you call jwt.decode()
However, the access token is expired, so jwt.decode
should fail.
This means that you no longer can get a fresh access token as soon as your previous access token is expired.
Am I right?
Wouldn't it be better to call jwt.decode()
with verify_exp=False
in this case?
Pierre
Hi Miguel, thanks for your contributions to the Flask community.
I was going through the code, and noticed that on this line, we ping the user, but not commit the change. This may be by design, I'm not sure, but since verify_access_token
commits the last_seen
, I just thought I'll point it out.
Thanks
User
in Token
is indexed, while the ones in followers
table aren't?db.session.scalars(User.select().where(User.id == self.id, User.following.contains(user))).one_or_none() is not None
over something like db.session.scalar(User.select().where(User.id == self.id, User.following.contains(user))) is not None
?Thanks!
Hi thanks for the great book. Many other books are confusing, yours is great. When I try to deploy the app to Heroku, I get the following error:
Create app
App creation failed. Please ensure you have valid values in the above form fields.
Configure environment
There was an issue setting up your app environment.
invalid app.json
The heroku-postgresql:hobby-dev plan is no longer available. Choose a different plan. See all available plans in the Elements Marketplace at elements.heroku.com.
(see attached screenshots)
Heroku stopped the free plans last year. I have a 'Eco Dynos Plan' and 'Heroku Postgres Mini' plan activated, but it seems the app.json file is choosing a plan that no longer exists, and the error happens. I don't seem to have any option to change the plan
Hi, I am running this project and trying to learn some new things. I love how you wrote this project.
So, I tried to run this project and changed APIFAIRY_UI
to swagger_ui
so that I can test the endpoints locally.
After basic registration with /api/users
endpoint, I went and clicked ###Authorize "icon" in swagger ui and entered my basic_auth credentials. I then went to /api/tokens
with a POST
request to get the tokens for authentication. I went back to Authorize icon in swagger ui to enter token_auth
credentials given for /api/tokens
endpoint.
I then went back to Users where I tried to access the endpoints that require token based authentication.
But every time I am getting Unauthorized error from flask backend. I could be missing something and I would like to get some help to get HTTP 200
response code.
Much thanks
Hi Miguel -
How would you recommend going about google oauth flow using the flask http auth library?
I'm building an app where you'll be able to upload an image to the api which will then process the image. The api will reply with an accepted or error message.
I'm curious how I would add an image to the schemas so the documentation shows the api can accept images (.png/.jpg) to the endpoint?
Thanks.
I cloned the application and run:
$ flask db upgrade
Which results in a module not found error:
from alchemical.flask import Alchemical
ModuleNotFoundError: No module named 'alchemical'
I'm struggling with this part, I will work out a way. I have tired to make a custom validator for marshmallow but still no luck.
But the server replies with this
body = Object {code: 400, description: "UNIQUE constraint failed: users.email", message: "Database integrity error"}
Instead of the correctly formatted errors object.
How would I add order by the the decorator?
For example:
@posts.route('/posts', methods=['GET'])
@authenticate(token_auth)
@paginated_response(posts_schema, order_by=Post.timestamp,
order_direction='desc',
pagination_schema=DateTimePaginationSchema)
def all():
"""Retrieve all posts"""
return Post.select()
However, I want the client to pass in a field name for the order by. If this happens, the client is really only passing in a string so the decorator errors because there is no desc attribute on a string:
order_by = pagination.get('order_by')
order_direction = pagination.get('order_direction')
if order_by is not None:
o = order_by.desc() if order_direction == 'desc' else order_by
I am certainly new to flask and python generally, so I apologize if this solution is obvious. Ultimately I want an elegant solution that will allow this paginated response to be flexible across many different tables.
Thanks again!
After test and use the api, Token table data is increasing. Should the table should overwrite new token?
When you create a new token, is it just my code or something wrong with codebase that the refresh token returns as a null value?
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.........",
"refresh_token": null
}
And when revoking the access_token, I always get this error:
return _unicodify_header_value(self.environ[f"HTTP_{key}"])
KeyError: 'HTTP_AUTHORIZATION'
Can't seem to find where it's originating from.
The shell context script only filters the models defined with Model
, but not sa.Table
, can we modify to access them as well?
https://github.com/miguelgrinberg/microblog-api/blob/main/api/app.py#L42-L50
I am currently getting ./boot.sh: Permission denied Exited with code 126 in docker on my mac pro with M1. Any thoughts on this?
/bin/sh: 1: ./boot.sh: Permission denied
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.