8
8
9
9
10
10
class Command (DCommand ):
11
- db_module = "clickhouse_backend"
12
-
13
11
def handle_inspection (self , options ):
14
12
connection = connections [options ["database" ]]
13
+ if connection .vendor != "clickhouse" :
14
+ return super ().handle_inspection (options )
15
15
# 'table_name_filter' is a stealth option
16
16
table_name_filter = options .get ("table_name_filter" )
17
17
@@ -31,7 +31,7 @@ def table2model(table_name):
31
31
"# Feel free to rename the models, but don't rename db_table values or "
32
32
"field names."
33
33
)
34
- yield "from %s import models" % self . db_module
34
+ yield "from clickhouse_backend import models"
35
35
known_models = []
36
36
# Determine types of tables and/or views to be introspected.
37
37
types = {"t" }
@@ -45,24 +45,18 @@ def table2model(table_name):
45
45
if not table_name_filter (table_name ):
46
46
continue
47
47
try :
48
- try :
49
- constraints = connection .introspection .get_constraints (
50
- cursor , table_name
51
- )
52
- except NotImplementedError :
53
- constraints = {}
54
48
table_description = connection .introspection .get_table_description (
55
49
cursor , table_name
56
50
)
57
51
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 } "
60
54
continue
61
55
62
56
model_name = table2model (table_name )
63
57
yield ""
64
58
yield ""
65
- yield "class %s (models.ClickhouseModel):" % model_name
59
+ yield f "class { model_name } (models.ClickhouseModel):"
66
60
known_models .append (model_name )
67
61
used_column_names = [] # Holds column names used in the table so far
68
62
column_to_field_name = {} # Maps column names to names of model fields
@@ -88,9 +82,7 @@ def table2model(table_name):
88
82
extra_params ["db_comment" ] = row .comment
89
83
90
84
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 ())
94
86
else :
95
87
param = ""
96
88
@@ -100,46 +92,45 @@ def table2model(table_name):
100
92
field_desc = f"{ att_name } = { field_define } "
101
93
if comment_notes :
102
94
field_desc += " # " + " " .join (comment_notes )
103
- yield " %s" % field_desc
95
+ yield f" { field_desc } "
96
+
104
97
comment = None
98
+ managed_comment = ""
105
99
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."
107
102
if connection .features .supports_comments :
108
103
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} "
119
111
120
112
def inspect_field_type (self , column_type , param = "" ):
121
113
column_type = ensure_str (column_type )
122
-
123
- if column_type .startswith ("LowCardinality" ): # LowCardinality(Int16)
114
+ # LowCardinality(Int16)
115
+ if column_type .startswith ("LowCardinality" ):
124
116
param = self .merge_params (param , "low_cardinality=True" )
125
117
remain = yield from self .inspect_field_type (column_type [15 :], param )
126
118
return remain [1 :]
127
- elif column_type .startswith ("Nullable" ): # Nullable(Int16)
119
+ # Nullable(Int16)
120
+ elif column_type .startswith ("Nullable" ):
128
121
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 )
132
123
return remain [1 :]
133
- elif column_type .startswith ("FixedString" ): # FixedString(20)
124
+ # FixedString(20)
125
+ elif column_type .startswith ("FixedString" ):
134
126
i = 12
135
127
while column_type [i ].isdigit ():
136
128
i += 1
137
129
param = self .merge_params (param , f"max_bytes={ column_type [12 :i ]} " )
138
130
yield f"models.FixedStringField({ param } )"
139
131
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" ):
143
134
if int (column_type [11 ]) != models .DateTime64Field .DEFAULT_PRECISION :
144
135
param = self .merge_params (param , f"precision={ column_type [11 ]} " )
145
136
yield f"models.DateTime64Field({ param } )"
@@ -150,15 +141,17 @@ def inspect_field_type(self, column_type, param=""):
150
141
i += 1
151
142
return column_type [i + 2 :]
152
143
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" ):
154
146
yield f"models.DateTimeField({ param } )"
155
147
if len (column_type ) > 8 and column_type [8 ] == "(" :
156
148
i = 10
157
149
while column_type [i ] != "'" :
158
150
i += 1
159
151
return column_type [i + 2 :]
160
152
return column_type [8 :]
161
- elif column_type .startswith ("Decimal" ): # Decimal(9, 3)
153
+ # Decimal(9, 3)
154
+ elif column_type .startswith ("Decimal" ):
162
155
i = 8
163
156
while column_type [i ].isdigit ():
164
157
i += 1
@@ -171,7 +164,8 @@ def inspect_field_type(self, column_type, param=""):
171
164
param = self .merge_params (param , max_digits , decimal_places )
172
165
yield f"models.DecimalField({ param } )"
173
166
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" ):
175
169
i = 4
176
170
while column_type [i ].isdigit ():
177
171
i += 1
@@ -185,16 +179,16 @@ def inspect_field_type(self, column_type, param=""):
185
179
param = self .merge_params (param , f"choices=[{ ', ' .join (choices )} ]" )
186
180
yield f"models.{ typ } Field({ param } )"
187
181
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" ):
191
184
yield "models.ArrayField("
192
185
remain = yield from self .inspect_field_type (column_type [6 :])
193
186
if param :
194
187
yield f", { param } "
195
188
yield ")"
196
189
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" ):
198
192
yield "models.TupleField(["
199
193
remain = yield from self .inspect_field_type (column_type [6 :])
200
194
while remain [0 ] == "," :
@@ -205,7 +199,8 @@ def inspect_field_type(self, column_type, param=""):
205
199
yield f", { param } "
206
200
yield ")"
207
201
return remain [1 :]
208
- elif column_type .startswith ("Map" ): # Map(String, Int8)
202
+ # Map(String, Int8)
203
+ elif column_type .startswith ("Map" ):
209
204
yield "models.MapField("
210
205
remain = yield from self .inspect_field_type (column_type [4 :])
211
206
yield ", "
@@ -225,7 +220,8 @@ def inspect_field_type(self, column_type, param=""):
225
220
yield f"models.{ column_type [:i ]} Field({ param } )"
226
221
return column_type [i :]
227
222
228
- def consume_enum_choice (self , s ): # 'a' = 1
223
+ def consume_enum_choice (self , s ):
224
+ # 'a' = 1
229
225
has_bytes = False
230
226
i = 1
231
227
while True :
0 commit comments