#Convex + Python

1 messages · Page 1 of 1 (latest)

slim imp
#

I'm creating an application with a python (FastAPI) backend and wanted to access data from my convex db with python. I've seen a bunch of conflicting approaches on how to do this online so was looking for some advice/best practices.

elder scarab
#

The convex PyPI package is the best way to do this: https://pypi.org/project/convex/. There are some upgrades coming very soon to it, but the API will be very nearly compatible so it'll be an optional upgrade with instructions about how to change your code in the case that something needs to be changed.

#

@slim imp what are you seeing online, do you have other questions about this? Except for some rare use cases this should be what just about everyone using Python with Convex is using.

slim imp
#

Ah it's working now, not quite sure what went wrong the first time

#

I'm having a little trouble with the auth token though, where exactly can I find that?

elder scarab
#

What kind of auth token do you need, or what are you trying to do? .set_token() is for JWTs, usually obtained in web browsers to identify a specific user. If your FastAPI server is receiving requests from browsers then how to get this token depends in how you authenticate your users.

You may not need an auth token, in which case you could add an argument to your functions fir a secret ket shared with the FastAPI server

slim imp
#

I'm not entirely sure, I was just trying to tets out accessing data from my db in a python notebook like in the picture attached

#

but when that didn't work the error said it was a problem with auth so I tried messing around with the auth token which didn't really get me anywhere either

#

I'm just trying to play around with it to better understand how I can implement it into my fastapi python code

elder scarab
#

Ah cool, what's does the implementation of getSearch look like in documents?

slim imp
#

export const getSearch = query({
handler: async (ctx) => {
const identity = await ctx.auth.getUserIdentity();

if (!identity) {
  throw new Error("Not authenticated");
}

const userId = identity.subject;

const documents = await ctx.db
  .query("documents")
  .withIndex("by_user", (q) => q.eq("userId", userId))
  .filter((q) => q.eq(q.field("isArchived"), false))
  .order("desc")
  .collect();

  
return documents;

}
});

it was one of my simpler queries so I was trying to use that to get a hang of how to better work with convex in python

elder scarab
#

@slim imp the ctx.auth makes more sense for end users, not scripts; you need to have a JWT token (usually obtained through a web browser)

#

Since you're writing a server, you probably want to get this token from browsers? You could send it in in the network requests bound for your FastAPI server.

#

Or you can use your build-in authentication and not use ctx.auth.getUserIdentity() at all; implementing identity using whatever method you already use instead of the JWT-based cx.auth

slim imp
#

I'm sorry I don't quite understand, I'm using convex for auth and was just doing that for error handling which has been working fine in my fully typescript program

#

and the aim is to deal with multiple end users so isn't this the best way to do that?

elder scarab
#

@slim imp sorry I keep back slowly to these! How are you doing authentication in your web app?

#

"Using Convex for auth" sounds like you're using Clerk or Auth0 or similar from the browser?

#

The two options I think of here are:

  1. Write separate endpoints for
    a. public Convex queries, mutations etc. that can be called from the browser (and use ctx.auth) and
    b. queries+mutations that require an extra argument for a secret only the server knows. Then these don't require per-user auth.

It's nice that from your Python server you can do things that wouldn't be safe from the browser because no user should have permissions to do them, e.g. ban a user. These functions are only callable from your Python backend so don't use ctx.auth.

Or
2. Use the same functions everywhere. Send in the JWT in network requests from the browser to your FastAPI server so that that JWT can be used with the Python client.

I'm not sure I'm following what you're trying to do totally, it sounds like option 2?

slim imp
#

For more information, I started with the tutorial for the notion clone that was posted on this server and am trying to extend that with some additional AI capability that I’ve written in python

#

But for those to function as well as possible they’d need to access information from my convex db

slim imp
#

Sorry this is my first full stack application so I’m still trying to figure out the intricacies of it all

elder scarab
#

@slim imp If you do option 2 when you call any of the functions you call from your frontend from Python they should work the same way

slim imp
#

This might be a stupid question but how do exactly can I go about doing that second option?

elder scarab
#

If you're using clerk, these might already be in your request cookies. I'd start with looking at the cookies in the HTTP requests being made to your FastAPI server.

#

If they aren't there, then you need to get the JWT in the browser. That will involve changing the auth code a bit. Clerk has docs on this, generally it's getToken({ template: "convex" }), something like that. Which Clerk library are you using?

slim imp
elder scarab
#

I don't think clerk-reacts adds it since there's nothing server-side going on

#

@slim imp Could you say more about what you're doing, why you want user-authed functions from a Python server?

#

I just want to make sure I'm not pointing you the wrong way for your big picture goals

#

sending in JWTs is totally reasonable, that's how Clerk's e.g. Next.js integration works

slim imp
elder scarab
#

Maybe another question is what kind sof things do you do on your Python server

#

cool!

slim imp
elder scarab
#

so you have endpoints like "I'm this user, go fetch whatever context is relevant for me and do langchain-y stuff"

slim imp
#

yes exactly

elder scarab
#

and you could gather that context from the client side and send it in in the request, but why send data to the browser that the user doens't really need, just request it from the server

#

ok makes sense to me, unfortunately we don't have off-the-shelf demos for grabbing JWTs. Clerk docs should have more, you want to call that getToken function right before making the network request and send it along.

#

Make sure to create new Python http clients for each request, since auth is a stateful thing
client.set_auth("token-from-authetication-flow")

#

after running that line every query, mutation, and action made by this client instance will send in that auth

slim imp
#

So basically I need to figure out how to get the JWTs from Clerk and then use that token to set auth after initializing the ConvexClient and then I should be able to access queries from my db?

elder scarab
#

That's right.

#

Something like

const { isLoaded, isSignedIn, getToken } = useAuth();

async function networkRequest() {
  const token = getToken({ template: "convex" });
  fetch("http://your-fast-api-server/do-rag", {
    body: JSON.stringify({
      token,
      otherData,
    }),
    headers: ...
  });
}
slim imp
#

Okay perfect! This has been really useful, I really appreciate it

#

I’ll try this out and let you know if I come across any difficulties