99from debug_toolbar .utils import get_stack_trace , get_template_info
1010
1111try :
12- from psycopg2 ._json import Json as PostgresJson
13- from psycopg2 .extensions import STATUS_IN_TRANSACTION
12+ import psycopg
13+
14+ PostgresJson = psycopg .types .json .Jsonb
15+ STATUS_IN_TRANSACTION = psycopg .pq .TransactionStatus .INTRANS
1416except ImportError :
15- PostgresJson = None
16- STATUS_IN_TRANSACTION = None
17+ try :
18+ from psycopg2 ._json import Json as PostgresJson
19+ from psycopg2 .extensions import STATUS_IN_TRANSACTION
20+ except ImportError :
21+ PostgresJson = None
22+ STATUS_IN_TRANSACTION = None
1723
1824# Prevents SQL queries from being sent to the DB. It's used
1925# by the TemplatePanel to prevent the toolbar from issuing
@@ -126,7 +132,13 @@ def _quote_params(self, params):
126132
127133 def _decode (self , param ):
128134 if PostgresJson and isinstance (param , PostgresJson ):
129- return param .dumps (param .adapted )
135+ # psycopg3
136+ if hasattr (param , "obj" ):
137+ return param .dumps (param .obj )
138+ # psycopg2
139+ if hasattr (param , "adapted" ):
140+ return param .dumps (param .adapted )
141+
130142 # If a sequence type, decode each element separately
131143 if isinstance (param , (tuple , list )):
132144 return [self ._decode (element ) for element in param ]
@@ -149,7 +161,7 @@ def _record(self, method, sql, params):
149161 if vendor == "postgresql" :
150162 # The underlying DB connection (as opposed to Django's wrapper)
151163 conn = self .db .connection
152- initial_conn_status = conn .status
164+ initial_conn_status = conn .info . transaction_status
153165
154166 start_time = time ()
155167 try :
@@ -166,7 +178,10 @@ def _record(self, method, sql, params):
166178
167179 # Sql might be an object (such as psycopg Composed).
168180 # For logging purposes, make sure it's str.
169- sql = str (sql )
181+ if vendor == "postgresql" and not isinstance (sql , str ):
182+ sql = sql .as_string (conn )
183+ else :
184+ sql = str (sql )
170185
171186 params = {
172187 "vendor" : vendor ,
@@ -205,7 +220,7 @@ def _record(self, method, sql, params):
205220 # case where Django can start a transaction before the first query
206221 # executes, so in that case logger.current_transaction_id() will
207222 # generate a new transaction ID since one does not already exist.
208- final_conn_status = conn .status
223+ final_conn_status = conn .info . transaction_status
209224 if final_conn_status == STATUS_IN_TRANSACTION :
210225 if initial_conn_status == STATUS_IN_TRANSACTION :
211226 trans_id = self .logger .current_transaction_id (alias )
@@ -217,7 +232,7 @@ def _record(self, method, sql, params):
217232 params .update (
218233 {
219234 "trans_id" : trans_id ,
220- "trans_status" : conn .get_transaction_status () ,
235+ "trans_status" : conn .info . transaction_status ,
221236 "iso_level" : iso_level ,
222237 }
223238 )
0 commit comments