88
99
1010class Command (DCommand ):
11- db_module = "clickhouse_backend"
12-
1311 def handle_inspection (self , options ):
1412 connection = connections [options ["database" ]]
13+ if connection .vendor != "clickhouse" :
14+ return super ().handle_inspection (options )
1515 # 'table_name_filter' is a stealth option
1616 table_name_filter = options .get ("table_name_filter" )
1717
@@ -31,7 +31,7 @@ def table2model(table_name):
3131 "# Feel free to rename the models, but don't rename db_table values or "
3232 "field names."
3333 )
34- yield "from %s import models" % self . db_module
34+ yield "from clickhouse_backend import models"
3535 known_models = []
3636 # Determine types of tables and/or views to be introspected.
3737 types = {"t" }
@@ -45,24 +45,18 @@ def table2model(table_name):
4545 if not table_name_filter (table_name ):
4646 continue
4747 try :
48- try :
49- constraints = connection .introspection .get_constraints (
50- cursor , table_name
51- )
52- except NotImplementedError :
53- constraints = {}
5448 table_description = connection .introspection .get_table_description (
5549 cursor , table_name
5650 )
5751 except Exception as e :
58- yield "# Unable to inspect table '%s'" % table_name
59- yield "# The error was: %s" % e
52+ yield f "# Unable to inspect table '{ table_name } '"
53+ yield f "# The error was: { e } "
6054 continue
6155
6256 model_name = table2model (table_name )
6357 yield ""
6458 yield ""
65- yield "class %s (models.ClickhouseModel):" % model_name
59+ yield f "class { model_name } (models.ClickhouseModel):"
6660 known_models .append (model_name )
6761 used_column_names = [] # Holds column names used in the table so far
6862 column_to_field_name = {} # Maps column names to names of model fields
@@ -88,9 +82,7 @@ def table2model(table_name):
8882 extra_params ["db_comment" ] = row .comment
8983
9084 if extra_params :
91- param = ", " .join (
92- "%s=%r" % (k , v ) for k , v in extra_params .items ()
93- )
85+ param = ", " .join (f"{ k } ={ v !r} " for k , v in extra_params .items ())
9486 else :
9587 param = ""
9688
@@ -100,46 +92,45 @@ def table2model(table_name):
10092 field_desc = f"{ att_name } = { field_define } "
10193 if comment_notes :
10294 field_desc += " # " + " " .join (comment_notes )
103- yield " %s" % field_desc
95+ yield f" { field_desc } "
96+
10497 comment = None
98+ managed_comment = ""
10599 if info := table_info .get (table_name ):
106- is_view = info .type == "v"
100+ if info .type == "v" :
101+ managed_comment = " # Created from a view. Don't remove."
107102 if connection .features .supports_comments :
108103 comment = info .comment
109- else :
110- is_view = False
111- yield from self .get_meta (
112- table_name ,
113- constraints ,
114- column_to_field_name ,
115- is_view ,
116- False ,
117- comment ,
118- )
104+
105+ yield ""
106+ yield " class Meta:"
107+ yield f" managed = False{ managed_comment } "
108+ yield f" db_table = { table_name !r} "
109+ if compat .dj_ge42 and comment :
110+ yield f" db_table_comment = { comment !r} "
119111
120112 def inspect_field_type (self , column_type , param = "" ):
121113 column_type = ensure_str (column_type )
122-
123- if column_type .startswith ("LowCardinality" ): # LowCardinality(Int16)
114+ # LowCardinality(Int16)
115+ if column_type .startswith ("LowCardinality" ):
124116 param = self .merge_params (param , "low_cardinality=True" )
125117 remain = yield from self .inspect_field_type (column_type [15 :], param )
126118 return remain [1 :]
127- elif column_type .startswith ("Nullable" ): # Nullable(Int16)
119+ # Nullable(Int16)
120+ elif column_type .startswith ("Nullable" ):
128121 param = self .merge_params (param , "null=True" , "blank=True" )
129- remain = yield from self .inspect_field_type (
130- column_type [9 :], param
131- ) # Nullable(Int16)
122+ remain = yield from self .inspect_field_type (column_type [9 :], param )
132123 return remain [1 :]
133- elif column_type .startswith ("FixedString" ): # FixedString(20)
124+ # FixedString(20)
125+ elif column_type .startswith ("FixedString" ):
134126 i = 12
135127 while column_type [i ].isdigit ():
136128 i += 1
137129 param = self .merge_params (param , f"max_bytes={ column_type [12 :i ]} " )
138130 yield f"models.FixedStringField({ param } )"
139131 return column_type [i + 1 :]
140- elif column_type .startswith (
141- "DateTime64"
142- ): # DateTime64(6, 'UTC') or DateTime64(9)
132+ # DateTime64(6, 'UTC') or DateTime64(9)
133+ elif column_type .startswith ("DateTime64" ):
143134 if int (column_type [11 ]) != models .DateTime64Field .DEFAULT_PRECISION :
144135 param = self .merge_params (param , f"precision={ column_type [11 ]} " )
145136 yield f"models.DateTime64Field({ param } )"
@@ -150,15 +141,17 @@ def inspect_field_type(self, column_type, param=""):
150141 i += 1
151142 return column_type [i + 2 :]
152143 return column_type [13 :]
153- elif column_type .startswith ("DateTime" ): # DateTime('UTC') or DateTime
144+ # DateTime('UTC') or DateTime
145+ elif column_type .startswith ("DateTime" ):
154146 yield f"models.DateTimeField({ param } )"
155147 if len (column_type ) > 8 and column_type [8 ] == "(" :
156148 i = 10
157149 while column_type [i ] != "'" :
158150 i += 1
159151 return column_type [i + 2 :]
160152 return column_type [8 :]
161- elif column_type .startswith ("Decimal" ): # Decimal(9, 3)
153+ # Decimal(9, 3)
154+ elif column_type .startswith ("Decimal" ):
162155 i = 8
163156 while column_type [i ].isdigit ():
164157 i += 1
@@ -171,7 +164,8 @@ def inspect_field_type(self, column_type, param=""):
171164 param = self .merge_params (param , max_digits , decimal_places )
172165 yield f"models.DecimalField({ param } )"
173166 return column_type [i + 1 :]
174- elif column_type .startswith ("Enum" ): # Enum8('a' = 1, 'b' = 2)
167+ # Enum8('a' = 1, 'b' = 2)
168+ elif column_type .startswith ("Enum" ):
175169 i = 4
176170 while column_type [i ].isdigit ():
177171 i += 1
@@ -185,16 +179,16 @@ def inspect_field_type(self, column_type, param=""):
185179 param = self .merge_params (param , f"choices=[{ ', ' .join (choices )} ]" )
186180 yield f"models.{ typ } Field({ param } )"
187181 return remain [1 :]
188- elif column_type .startswith (
189- "Array"
190- ): # Array(Tuple(String, Enum8('a' = 1, 'b' = 2)))
182+ # Array(Tuple(String, Enum8('a' = 1, 'b' = 2)))
183+ elif column_type .startswith ("Array" ):
191184 yield "models.ArrayField("
192185 remain = yield from self .inspect_field_type (column_type [6 :])
193186 if param :
194187 yield f", { param } "
195188 yield ")"
196189 return remain [1 :]
197- elif column_type .startswith ("Tuple" ): # Tuple(String, Enum8('a' = 1, 'b' = 2))
190+ # Tuple(String, Enum8('a' = 1, 'b' = 2))
191+ elif column_type .startswith ("Tuple" ):
198192 yield "models.TupleField(["
199193 remain = yield from self .inspect_field_type (column_type [6 :])
200194 while remain [0 ] == "," :
@@ -205,7 +199,8 @@ def inspect_field_type(self, column_type, param=""):
205199 yield f", { param } "
206200 yield ")"
207201 return remain [1 :]
208- elif column_type .startswith ("Map" ): # Map(String, Int8)
202+ # Map(String, Int8)
203+ elif column_type .startswith ("Map" ):
209204 yield "models.MapField("
210205 remain = yield from self .inspect_field_type (column_type [4 :])
211206 yield ", "
@@ -225,7 +220,8 @@ def inspect_field_type(self, column_type, param=""):
225220 yield f"models.{ column_type [:i ]} Field({ param } )"
226221 return column_type [i :]
227222
228- def consume_enum_choice (self , s ): # 'a' = 1
223+ def consume_enum_choice (self , s ):
224+ # 'a' = 1
229225 has_bytes = False
230226 i = 1
231227 while True :
0 commit comments