I’m struggling to figure out how to pass list of integer as arguments for Django’s raw SQL without using f-string method.
I have tried a simple method of
def raw_query(self) -> str:
return """select * from table where some_id in %s"""
and call with (where ids are list of integer that I already wrap them as tuple)
tupled_ids = tuple(ids)
with connection.cursor() as cursor:
cursor.execute(self.raw_query(), [ids])
Apparently, this wraps the argument with single quote, making them ‘(1,2,3)’ instead of (1,2,3). Thus, syntax error.
django.db.utils.ProgrammingError: syntax error at or near "'(1,2,3)'"
I’ve also tried
def raw_query(self) -> str:
return """select * from table where some_id = any(%s)"""
also give me similar error
django.db.utils.DataError: malformed array literal: "(1,2,3,4,5)"
LINE 2: ...om table where some_id = any('(1,2,3...`
I’ve also tried with named params
def raw_query(self) -> str:
return """select * from table where some_id in %(ids)s"""
with connection.cursor() as cursor:
cursor.execute(sql=self.raw_query(),
params={
"ids": tuple(ids)
})
Still produce syntax error.
Looks like django keep wrapping my list with quote. I feel like there must have been an obvious mistake but I can’t really figure it out.
There are other solutions that suggest to generate a place holder and use f-string to format the raw SQL statement, such as.
def raw_query(self, ids: list[int]) -> str:
placeholder = ','.join(['%s'] * len(ids))
return f"""select * from table where some_id in ({placeholders})"""
^ This works
Still, I am wondering if there’s a better solution as I don’t want to string format my SQL statement.
Any help is gladly appreciated.