Hi,
I'm new to FastAPI (and web frameworks in general), so I hope one of you can help me.
I've read the docs, but I cant figure out how to create a web form with Jinja.
As my first project I would like to create a simple blog using FastAPI and Jinja.
I tried to this:
from fastapi import FastAPI, Form
from starlette.requests import Request
from starlette.staticfiles import StaticFiles
from starlette.templating import Jinja2Templates
from pydantic import BaseModel
app = FastAPI()
app.mount("/static", StaticFiles(directory="./app/static"), name="static")
templates = Jinja2Templates(directory="./app/templates")
class Username(BaseModel):
username: str
class Login(BaseModel):
username: str = Form(..., title="Your username", max_lengthe=20)
password: str = Form(..., title="Your password")
@app.post("/login/", response_model=Username)
async def login(request: Request, Login):
pass
Not sure if any of this is the correct way of doing it, but I could not figure out what to put in the login function.
Any help is much appreciated :)
You can see how to do this here: https://fastapi.tiangolo.com/tutorial/templates/
Let us know if that doesn't help.
Also, I'm guessing you meant to have the signature of your login function be async def login(request: Request, login: Login); the way it is now, it just has an argument named Login that is not treated as a Login instance.
Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.
Hi @dmontagu,
Thansk for your reply.
I have a flask route that looks like this:
```
from flask import Flask
...
class LoginForm(FlaskForm):
username: str = StringField(
"Username", validators=[DataRequired(), Length(min=3, max=64)]
)
password: str = PasswordField("Passord", validators=[DataRequired(), Length(min=8)])
remember_me: bool = BooleanField("Remember me")
submit = SubmitField("Sign in")
@app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return redirect(url_for("main.index"))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if not user or not user.check_password(form.password.data):
flash("Invalid username or password")
return redirect(url_for("login"))
return redirect(next_page)
return render_template("auth/login.html", title="Sign in", form=form)
...```
How can port something like this to FastAPI?
Can I use the @app.get() and @app.post() decorators for the same function?
@albertfreist you would probably implement it with something like this:
from fastapi import FastAPI, Form, Cookie, Depends
from starlette.responses import RedirectResponse, Response
app = FastAPI()
def get_current_user(session: str = Cookie(None)):
if not session:
return None
else:
data = decrypt(session) # some cryptography decryption
user = query_user(data["user"]) # Query user
return user
@app.get("/")
def main(current_user=Depends(get_current_user)):
if not current_user:
return "Some generic template or a redirection"
return "Some user specific template"
@app.post("/login")
def login(
response: Response,
username: str = Form(..., min_length=3, max_length=64),
password: str = Form(..., min_length=8),
remember_me: bool = Form(False),
):
user = get_user(username) # some DB query here
if not user or not user.check_password(password):
return RedirectResponse("/login?invalid=True", status_code=302)
response.set_cookie("session", "someencrypted session token")
return RedirectResponse("/", status_code=302)
@app.get("/login")
def login(invalid: bool = False, current_user=Depends(get_current_user)):
if current_user.is_authenticated:
return RedirectResponse("/")
return render_template("auth/login.html", title="Sign in", invalid=invalid)
You would probably need to access a database, to implement security to encrypt and decrypt a token or similar, to use dependencies to get a user, to use cookies to set and retrieve a session, etc. All that is in the docs, you can search for each specific subject.
On the other side, have in mind that for modern applications it's a lot more common to not use rendered templates, and instead, have a frontend framework show the information retrieved from an API. FastAPI is optimized to be used for APIs. If all your workflow is based on templates, FastAPI is more or less comparable to any other framework and you probably won't notice a big advantage over others in that scenario, especially if you already have some code in place with a different framework. Maybe FastAPI will be a bit faster and other small benefits, but you probably won't see a huge benefit from it.
On the other side, if your only purpose is to write a blog, I would suggest Dev.to or Medium. If you want to have your own blog and build it, I would suggest you use a JAMStack that builds a static site from code, instead of a full backend with DB and everything. And you could serve it for free on Netlify or other providers. You could use Hugo, Gatsby with markdown, MkDocs or others.
But if your main objective is to learn backend development, I would suggest instead to just follow the FastAPI tutorial, step by step. That would give you some solid foundations to build backends and APIs that can be easily used by other systems and frontend teams.
I know that this issue is closed, but I wanted to add a small follow-up question. Let me know if I should open a new issue instead. Thank you.
I'm currently using FastAPI with forms in the query params. Here's how the app looks like:
@app.post('/context/', response_class=HTMLResponse)
async def query(request: Request, query: Optional[str] = Form(None)):
return templates.TemplateResponse('context.html', {'request': request,
'asins': default_asins})
And here's the HTML
<body>
<form method="post">
<input type="text" name="query" value="{{ query }}"/>
<input type="submit">
</form>
<p>{{ asins }}</p>
</body>
I'm trying to update my app to use Pydantic goodness, but I'm stuck with how to provide the input via Jinja into a Pydantic model. Supposed my Pydantic class is as follows, how should I update my Jinja template?
class Query(BaseModel):
query: str
Most helpful comment
@albertfreist you would probably implement it with something like this:
You would probably need to access a database, to implement security to encrypt and decrypt a token or similar, to use dependencies to get a user, to use cookies to set and retrieve a session, etc. All that is in the docs, you can search for each specific subject.
On the other side, have in mind that for modern applications it's a lot more common to not use rendered templates, and instead, have a frontend framework show the information retrieved from an API. FastAPI is optimized to be used for APIs. If all your workflow is based on templates, FastAPI is more or less comparable to any other framework and you probably won't notice a big advantage over others in that scenario, especially if you already have some code in place with a different framework. Maybe FastAPI will be a bit faster and other small benefits, but you probably won't see a huge benefit from it.
On the other side, if your only purpose is to write a blog, I would suggest Dev.to or Medium. If you want to have your own blog and build it, I would suggest you use a JAMStack that builds a static site from code, instead of a full backend with DB and everything. And you could serve it for free on Netlify or other providers. You could use Hugo, Gatsby with markdown, MkDocs or others.
But if your main objective is to learn backend development, I would suggest instead to just follow the FastAPI tutorial, step by step. That would give you some solid foundations to build backends and APIs that can be easily used by other systems and frontend teams.