plain.models 0.50.0__py3-none-any.whl → 0.51.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. plain/models/CHANGELOG.md +14 -0
  2. plain/models/README.md +26 -42
  3. plain/models/__init__.py +2 -0
  4. plain/models/backends/base/creation.py +2 -2
  5. plain/models/backends/base/introspection.py +8 -4
  6. plain/models/backends/base/schema.py +89 -71
  7. plain/models/backends/base/validation.py +1 -1
  8. plain/models/backends/mysql/compiler.py +1 -1
  9. plain/models/backends/mysql/operations.py +1 -1
  10. plain/models/backends/mysql/schema.py +4 -4
  11. plain/models/backends/postgresql/operations.py +1 -1
  12. plain/models/backends/postgresql/schema.py +3 -3
  13. plain/models/backends/sqlite3/operations.py +1 -1
  14. plain/models/backends/sqlite3/schema.py +61 -50
  15. plain/models/base.py +116 -163
  16. plain/models/cli.py +4 -4
  17. plain/models/constraints.py +14 -9
  18. plain/models/deletion.py +15 -14
  19. plain/models/expressions.py +1 -1
  20. plain/models/fields/__init__.py +20 -16
  21. plain/models/fields/json.py +3 -3
  22. plain/models/fields/related.py +73 -71
  23. plain/models/fields/related_descriptors.py +2 -2
  24. plain/models/fields/related_lookups.py +1 -1
  25. plain/models/fields/related_managers.py +21 -32
  26. plain/models/fields/reverse_related.py +8 -8
  27. plain/models/forms.py +12 -12
  28. plain/models/indexes.py +5 -4
  29. plain/models/meta.py +505 -0
  30. plain/models/migrations/operations/base.py +1 -1
  31. plain/models/migrations/operations/fields.py +6 -6
  32. plain/models/migrations/operations/models.py +18 -16
  33. plain/models/migrations/recorder.py +9 -5
  34. plain/models/migrations/state.py +35 -46
  35. plain/models/migrations/utils.py +1 -1
  36. plain/models/options.py +182 -518
  37. plain/models/preflight.py +7 -5
  38. plain/models/query.py +119 -65
  39. plain/models/query_utils.py +18 -13
  40. plain/models/registry.py +6 -5
  41. plain/models/sql/compiler.py +51 -37
  42. plain/models/sql/query.py +77 -68
  43. plain/models/sql/subqueries.py +4 -4
  44. plain/models/utils.py +4 -1
  45. {plain_models-0.50.0.dist-info → plain_models-0.51.0.dist-info}/METADATA +27 -43
  46. {plain_models-0.50.0.dist-info → plain_models-0.51.0.dist-info}/RECORD +49 -48
  47. {plain_models-0.50.0.dist-info → plain_models-0.51.0.dist-info}/WHEEL +0 -0
  48. {plain_models-0.50.0.dist-info → plain_models-0.51.0.dist-info}/entry_points.txt +0 -0
  49. {plain_models-0.50.0.dist-info → plain_models-0.51.0.dist-info}/licenses/LICENSE +0 -0
@@ -28,6 +28,8 @@ if TYPE_CHECKING:
28
28
  from plain.models.base import Model
29
29
  from plain.models.constraints import BaseConstraint
30
30
  from plain.models.fields import Field
31
+ from plain.models.fields.related import ForeignKey, ManyToManyField
32
+ from plain.models.fields.reverse_related import ManyToManyRel
31
33
 
32
34
  logger = logging.getLogger("plain.models.backends.schema")
33
35
 
@@ -51,7 +53,7 @@ def _is_relevant_relation(relation: Any, altered_field: Field) -> bool:
51
53
  def _all_related_fields(model: type[Model]) -> list[Any]:
52
54
  # Related fields must be returned in a deterministic order.
53
55
  return sorted(
54
- model._meta._get_fields( # type: ignore[attr-defined]
56
+ model._model_meta._get_fields(
55
57
  forward=False,
56
58
  reverse=True,
57
59
  include_hidden=True,
@@ -225,7 +227,7 @@ class BaseDatabaseSchemaEditor:
225
227
  # Create column SQL, add FK deferreds if needed.
226
228
  column_sqls = []
227
229
  params = []
228
- for field in model._meta.local_fields:
230
+ for field in model._model_meta.local_fields:
229
231
  # SQL.
230
232
  definition, extra_params = self.column_sql(model, field)
231
233
  if definition is None:
@@ -241,8 +243,8 @@ class BaseDatabaseSchemaEditor:
241
243
  params.extend(extra_params)
242
244
  # FK.
243
245
  if field.remote_field and field.db_constraint: # type: ignore[attr-defined]
244
- to_table = field.remote_field.model._meta.db_table
245
- to_column = field.remote_field.model._meta.get_field(
246
+ to_table = field.remote_field.model.model_options.db_table
247
+ to_column = field.remote_field.model._model_meta.get_field(
246
248
  field.remote_field.field_name
247
249
  ).column
248
250
  if self.sql_create_inline_fk:
@@ -262,16 +264,16 @@ class BaseDatabaseSchemaEditor:
262
264
  # variant).
263
265
  if field.get_internal_type() in ("PrimaryKeyField",):
264
266
  autoinc_sql = self.connection.ops.autoinc_sql(
265
- model._meta.db_table, field.column
267
+ model.model_options.db_table, field.column
266
268
  )
267
269
  if autoinc_sql:
268
270
  self.deferred_sql.extend(autoinc_sql)
269
271
  constraints = [
270
272
  constraint.constraint_sql(model, self)
271
- for constraint in model._meta.constraints
273
+ for constraint in model.model_options.constraints
272
274
  ]
273
275
  sql = self.sql_create_table % {
274
- "table": self.quote_name(model._meta.db_table),
276
+ "table": self.quote_name(model.model_options.db_table),
275
277
  "definition": ", ".join(
276
278
  str(constraint)
277
279
  for constraint in (*column_sqls, *constraints)
@@ -442,11 +444,13 @@ class BaseDatabaseSchemaEditor:
442
444
 
443
445
  if self.connection.features.supports_comments:
444
446
  # Add table comment.
445
- if model._meta.db_table_comment:
446
- self.alter_db_table_comment(model, None, model._meta.db_table_comment)
447
+ if model.model_options.db_table_comment:
448
+ self.alter_db_table_comment(
449
+ model, None, model.model_options.db_table_comment
450
+ )
447
451
  # Add column comments.
448
452
  if not self.connection.features.supports_comments_inline:
449
- for field in model._meta.local_fields:
453
+ for field in model._model_meta.local_fields:
450
454
  if field.db_comment:
451
455
  field_db_params = field.db_parameters(
452
456
  connection=self.connection
@@ -467,13 +471,13 @@ class BaseDatabaseSchemaEditor:
467
471
  self.execute(
468
472
  self.sql_delete_table
469
473
  % {
470
- "table": self.quote_name(model._meta.db_table),
474
+ "table": self.quote_name(model.model_options.db_table),
471
475
  }
472
476
  )
473
477
  # Remove all deferred statements referencing the deleted table.
474
478
  for sql in list(self.deferred_sql):
475
479
  if isinstance(sql, Statement) and sql.references_table(
476
- model._meta.db_table
480
+ model.model_options.db_table
477
481
  ):
478
482
  self.deferred_sql.remove(sql)
479
483
 
@@ -553,7 +557,7 @@ class BaseDatabaseSchemaEditor:
553
557
  self.execute(
554
558
  self.sql_alter_table_comment
555
559
  % {
556
- "table": self.quote_name(model._meta.db_table),
560
+ "table": self.quote_name(model.model_options.db_table),
557
561
  "comment": self.quote_value(new_db_table_comment or ""),
558
562
  }
559
563
  )
@@ -582,11 +586,11 @@ class BaseDatabaseSchemaEditor:
582
586
  constraint_suffix = "_fk_%(to_table)s_%(to_column)s"
583
587
  # Add FK constraint inline, if supported.
584
588
  if self.sql_create_column_inline_fk:
585
- to_table = field.remote_field.model._meta.db_table
586
- to_column = field.remote_field.model._meta.get_field(
589
+ to_table = field.remote_field.model.model_options.db_table
590
+ to_column = field.remote_field.model._model_meta.get_field(
587
591
  field.remote_field.field_name
588
592
  ).column
589
- namespace, _ = split_identifier(model._meta.db_table)
593
+ namespace, _ = split_identifier(model.model_options.db_table)
590
594
  definition += " " + self.sql_create_column_inline_fk % {
591
595
  "name": self._fk_constraint_name(model, field, constraint_suffix),
592
596
  "namespace": f"{self.quote_name(namespace)}." if namespace else "",
@@ -602,7 +606,7 @@ class BaseDatabaseSchemaEditor:
602
606
  )
603
607
  # Build the SQL and run it
604
608
  sql = self.sql_create_column % {
605
- "table": self.quote_name(model._meta.db_table),
609
+ "table": self.quote_name(model.model_options.db_table),
606
610
  "column": self.quote_name(field.column),
607
611
  "definition": definition,
608
612
  }
@@ -617,7 +621,7 @@ class BaseDatabaseSchemaEditor:
617
621
  model, None, field, drop=True
618
622
  )
619
623
  sql = self.sql_alter_column % {
620
- "table": self.quote_name(model._meta.db_table),
624
+ "table": self.quote_name(model.model_options.db_table),
621
625
  "changes": changes_sql,
622
626
  }
623
627
  self.execute(sql, params)
@@ -654,7 +658,7 @@ class BaseDatabaseSchemaEditor:
654
658
  self.execute(self._delete_fk_sql(model, fk_name))
655
659
  # Delete the column
656
660
  sql = self.sql_delete_column % {
657
- "table": self.quote_name(model._meta.db_table),
661
+ "table": self.quote_name(model.model_options.db_table),
658
662
  "column": self.quote_name(field.column),
659
663
  }
660
664
  self.execute(sql)
@@ -664,7 +668,7 @@ class BaseDatabaseSchemaEditor:
664
668
  # Remove all deferred statements referencing the deleted column.
665
669
  for sql in list(self.deferred_sql):
666
670
  if isinstance(sql, Statement) and sql.references_column(
667
- model._meta.db_table, field.column
671
+ model.model_options.db_table, field.column
668
672
  ):
669
673
  self.deferred_sql.remove(sql)
670
674
 
@@ -763,7 +767,7 @@ class BaseDatabaseSchemaEditor:
763
767
  )
764
768
  if strict and len(fk_names) != 1:
765
769
  raise ValueError(
766
- f"Found wrong number ({len(fk_names)}) of foreign key constraints for {model._meta.db_table}.{old_field.column}"
770
+ f"Found wrong number ({len(fk_names)}) of foreign key constraints for {model.model_options.db_table}.{old_field.column}"
767
771
  )
768
772
  for fk_name in fk_names:
769
773
  fks_dropped.add((old_field.column,))
@@ -775,7 +779,7 @@ class BaseDatabaseSchemaEditor:
775
779
  ):
776
780
  # Find the unique constraint for this field
777
781
  meta_constraint_names = {
778
- constraint.name for constraint in model._meta.constraints
782
+ constraint.name for constraint in model.model_options.constraints
779
783
  }
780
784
  constraint_names = self._constraint_names(
781
785
  model,
@@ -786,7 +790,7 @@ class BaseDatabaseSchemaEditor:
786
790
  )
787
791
  if strict and len(constraint_names) != 1:
788
792
  raise ValueError(
789
- f"Found wrong number ({len(constraint_names)}) of unique constraints for {model._meta.db_table}.{old_field.column}"
793
+ f"Found wrong number ({len(constraint_names)}) of unique constraints for {model.model_options.db_table}.{old_field.column}"
790
794
  )
791
795
  for constraint_name in constraint_names:
792
796
  self.execute(self._delete_unique_sql(model, constraint_name))
@@ -800,7 +804,7 @@ class BaseDatabaseSchemaEditor:
800
804
  and ((old_type != new_type) or (old_collation != new_collation))
801
805
  )
802
806
  if drop_foreign_keys:
803
- # '_meta.related_field' also contains M2M reverse fields, these
807
+ # '_model_meta.related_field' also contains M2M reverse fields, these
804
808
  # will be filtered out
805
809
  for _old_rel, new_rel in _related_non_m2m_objects(old_field, new_field):
806
810
  rel_fk_names = self._constraint_names(
@@ -827,7 +831,7 @@ class BaseDatabaseSchemaEditor:
827
831
  )
828
832
  ):
829
833
  # Find the index for this field
830
- meta_index_names = {index.name for index in model._meta.indexes}
834
+ meta_index_names = {index.name for index in model.model_options.indexes}
831
835
  # Retrieve only BTREE indexes since this is what's created with
832
836
  # db_index=True.
833
837
  index_names = self._constraint_names(
@@ -847,7 +851,7 @@ class BaseDatabaseSchemaEditor:
847
851
  new_db_check = self._field_db_check(new_field, new_db_params)
848
852
  if old_db_check != new_db_check and old_db_check:
849
853
  meta_constraint_names = {
850
- constraint.name for constraint in model._meta.constraints
854
+ constraint.name for constraint in model.model_options.constraints
851
855
  }
852
856
  constraint_names = self._constraint_names(
853
857
  model,
@@ -857,7 +861,7 @@ class BaseDatabaseSchemaEditor:
857
861
  )
858
862
  if strict and len(constraint_names) != 1:
859
863
  raise ValueError(
860
- f"Found wrong number ({len(constraint_names)}) of check constraints for {model._meta.db_table}.{old_field.column}"
864
+ f"Found wrong number ({len(constraint_names)}) of check constraints for {model.model_options.db_table}.{old_field.column}"
861
865
  )
862
866
  for constraint_name in constraint_names:
863
867
  self.execute(self._delete_check_sql(model, constraint_name))
@@ -865,14 +869,14 @@ class BaseDatabaseSchemaEditor:
865
869
  if old_field.column != new_field.column:
866
870
  self.execute(
867
871
  self._rename_field_sql(
868
- model._meta.db_table, old_field, new_field, new_type
872
+ model.model_options.db_table, old_field, new_field, new_type
869
873
  )
870
874
  )
871
875
  # Rename all references to the renamed column.
872
876
  for sql in self.deferred_sql:
873
877
  if isinstance(sql, Statement):
874
878
  sql.rename_column_references(
875
- model._meta.db_table, old_field.column, new_field.column
879
+ model.model_options.db_table, old_field.column, new_field.column
876
880
  )
877
881
  # Next, start accumulating actions to do
878
882
  actions = []
@@ -939,7 +943,7 @@ class BaseDatabaseSchemaEditor:
939
943
  self.execute(
940
944
  self.sql_alter_column
941
945
  % {
942
- "table": self.quote_name(model._meta.db_table),
946
+ "table": self.quote_name(model.model_options.db_table),
943
947
  "changes": sql,
944
948
  },
945
949
  params,
@@ -949,7 +953,7 @@ class BaseDatabaseSchemaEditor:
949
953
  self.execute(
950
954
  self.sql_update_with_default
951
955
  % {
952
- "table": self.quote_name(model._meta.db_table),
956
+ "table": self.quote_name(model.model_options.db_table),
953
957
  "column": self.quote_name(new_field.column),
954
958
  "default": "%s",
955
959
  },
@@ -961,7 +965,7 @@ class BaseDatabaseSchemaEditor:
961
965
  self.execute(
962
966
  self.sql_alter_column
963
967
  % {
964
- "table": self.quote_name(model._meta.db_table),
968
+ "table": self.quote_name(model.model_options.db_table),
965
969
  "changes": sql,
966
970
  },
967
971
  params,
@@ -1020,7 +1024,9 @@ class BaseDatabaseSchemaEditor:
1020
1024
  self.execute(
1021
1025
  self.sql_alter_column
1022
1026
  % {
1023
- "table": self.quote_name(new_rel.related_model._meta.db_table),
1027
+ "table": self.quote_name(
1028
+ new_rel.related_model.model_options.db_table
1029
+ ),
1024
1030
  "changes": fragment[0],
1025
1031
  },
1026
1032
  fragment[1],
@@ -1049,7 +1055,7 @@ class BaseDatabaseSchemaEditor:
1049
1055
  # Does it have check constraints we need to add?
1050
1056
  if old_db_check != new_db_check and new_db_check:
1051
1057
  constraint_name = self._create_index_name(
1052
- model._meta.db_table, [new_field.column], suffix="_check"
1058
+ model.model_options.db_table, [new_field.column], suffix="_check"
1053
1059
  )
1054
1060
  self.execute(
1055
1061
  self._create_check_sql(model, constraint_name, new_db_params["check"])
@@ -1061,7 +1067,7 @@ class BaseDatabaseSchemaEditor:
1061
1067
  model, old_field, new_field, drop=True
1062
1068
  )
1063
1069
  sql = self.sql_alter_column % {
1064
- "table": self.quote_name(model._meta.db_table),
1070
+ "table": self.quote_name(model.model_options.db_table),
1065
1071
  "changes": changes_sql,
1066
1072
  }
1067
1073
  self.execute(sql, params)
@@ -1157,7 +1163,7 @@ class BaseDatabaseSchemaEditor:
1157
1163
  """
1158
1164
  other_actions = []
1159
1165
  if collate_sql := self._collate_sql(
1160
- new_collation, old_collation, model._meta.db_table
1166
+ new_collation, old_collation, model.model_options.db_table
1161
1167
  ):
1162
1168
  collate_sql = f" {collate_sql}"
1163
1169
  else:
@@ -1199,7 +1205,7 @@ class BaseDatabaseSchemaEditor:
1199
1205
  return (
1200
1206
  self.sql_alter_column_comment
1201
1207
  % {
1202
- "table": self.quote_name(model._meta.db_table),
1208
+ "table": self.quote_name(model.model_options.db_table),
1203
1209
  "column": self.quote_name(new_field.column),
1204
1210
  "comment": self._comment_sql(new_db_comment),
1205
1211
  },
@@ -1210,37 +1216,45 @@ class BaseDatabaseSchemaEditor:
1210
1216
  return self.quote_value(comment or "")
1211
1217
 
1212
1218
  def _alter_many_to_many(
1213
- self, model: type[Model], old_field: Field, new_field: Field, strict: bool
1219
+ self,
1220
+ model: type[Model],
1221
+ old_field: ManyToManyField,
1222
+ new_field: ManyToManyField,
1223
+ strict: bool,
1214
1224
  ) -> None:
1215
1225
  """Alter M2Ms to repoint their to= endpoints."""
1226
+ # Type narrow for ManyToManyField.remote_field
1227
+ old_rel: ManyToManyRel = old_field.remote_field # type: ignore[assignment]
1228
+ new_rel: ManyToManyRel = new_field.remote_field # type: ignore[assignment]
1229
+
1216
1230
  # Rename the through table
1217
1231
  if (
1218
- old_field.remote_field.through._meta.db_table # type: ignore[attr-defined]
1219
- != new_field.remote_field.through._meta.db_table # type: ignore[attr-defined]
1232
+ old_rel.through.model_options.db_table
1233
+ != new_rel.through.model_options.db_table
1220
1234
  ):
1221
1235
  self.alter_db_table(
1222
- old_field.remote_field.through, # type: ignore[attr-defined]
1223
- old_field.remote_field.through._meta.db_table, # type: ignore[attr-defined]
1224
- new_field.remote_field.through._meta.db_table, # type: ignore[attr-defined]
1236
+ old_rel.through,
1237
+ old_rel.through.model_options.db_table,
1238
+ new_rel.through.model_options.db_table,
1225
1239
  )
1226
1240
  # Repoint the FK to the other side
1227
1241
  self.alter_field(
1228
- new_field.remote_field.through, # type: ignore[attr-defined]
1242
+ new_rel.through,
1229
1243
  # The field that points to the target model is needed, so we can
1230
1244
  # tell alter_field to change it - this is m2m_reverse_field_name()
1231
1245
  # (as opposed to m2m_field_name(), which points to our model).
1232
- old_field.remote_field.through._meta.get_field( # type: ignore[attr-defined]
1246
+ old_rel.through._model_meta.get_field(
1233
1247
  old_field.m2m_reverse_field_name() # type: ignore[attr-defined]
1234
1248
  ),
1235
- new_field.remote_field.through._meta.get_field( # type: ignore[attr-defined]
1249
+ new_rel.through._model_meta.get_field(
1236
1250
  new_field.m2m_reverse_field_name() # type: ignore[attr-defined]
1237
1251
  ),
1238
1252
  )
1239
1253
  self.alter_field(
1240
- new_field.remote_field.through, # type: ignore[attr-defined]
1254
+ new_rel.through,
1241
1255
  # for self-referential models we need to alter field from the other end too
1242
- old_field.remote_field.through._meta.get_field(old_field.m2m_field_name()), # type: ignore[attr-defined]
1243
- new_field.remote_field.through._meta.get_field(new_field.m2m_field_name()), # type: ignore[attr-defined]
1256
+ old_rel.through._model_meta.get_field(old_field.m2m_field_name()),
1257
+ new_rel.through._model_meta.get_field(new_field.m2m_field_name()),
1244
1258
  )
1245
1259
 
1246
1260
  def _create_index_name(
@@ -1290,7 +1304,7 @@ class BaseDatabaseSchemaEditor:
1290
1304
  return ""
1291
1305
  return Statement(
1292
1306
  " INCLUDE (%(columns)s)",
1293
- columns=Columns(model._meta.db_table, columns, self.quote_name),
1307
+ columns=Columns(model.model_options.db_table, columns, self.quote_name),
1294
1308
  )
1295
1309
 
1296
1310
  def _create_index_sql(
@@ -1318,7 +1332,7 @@ class BaseDatabaseSchemaEditor:
1318
1332
  compiler = Query(model, alias_cols=False).get_compiler()
1319
1333
  columns = [field.column for field in fields]
1320
1334
  sql_create_index = sql or self.sql_create_index
1321
- table = model._meta.db_table
1335
+ table = model.model_options.db_table
1322
1336
 
1323
1337
  def create_index_name(*args: Any, **kwargs: Any) -> str:
1324
1338
  nonlocal name
@@ -1346,7 +1360,7 @@ class BaseDatabaseSchemaEditor:
1346
1360
  ) -> Statement:
1347
1361
  return Statement(
1348
1362
  sql or self.sql_delete_index,
1349
- table=Table(model._meta.db_table, self.quote_name),
1363
+ table=Table(model.model_options.db_table, self.quote_name),
1350
1364
  name=self.quote_name(name),
1351
1365
  )
1352
1366
 
@@ -1355,7 +1369,7 @@ class BaseDatabaseSchemaEditor:
1355
1369
  ) -> Statement:
1356
1370
  return Statement(
1357
1371
  self.sql_rename_index,
1358
- table=Table(model._meta.db_table, self.quote_name),
1372
+ table=Table(model.model_options.db_table, self.quote_name),
1359
1373
  old_name=self.quote_name(old_name),
1360
1374
  new_name=self.quote_name(new_name),
1361
1375
  )
@@ -1374,10 +1388,10 @@ class BaseDatabaseSchemaEditor:
1374
1388
  Return a list of all index SQL statements (field indexes, Meta.indexes) for the specified model.
1375
1389
  """
1376
1390
  output: list[Statement | None] = []
1377
- for field in model._meta.local_fields:
1391
+ for field in model._model_meta.local_fields:
1378
1392
  output.extend(self._field_indexes_sql(model, field))
1379
1393
 
1380
- for index in model._meta.indexes:
1394
+ for index in model.model_options.indexes:
1381
1395
  if (
1382
1396
  not index.contains_expressions
1383
1397
  or self.connection.features.supports_expression_indexes
@@ -1430,14 +1444,16 @@ class BaseDatabaseSchemaEditor:
1430
1444
  }
1431
1445
 
1432
1446
  def _create_fk_sql(
1433
- self, model: type[Model], field: Field, suffix: str
1447
+ self, model: type[Model], field: ForeignKey, suffix: str
1434
1448
  ) -> Statement:
1435
- table = Table(model._meta.db_table, self.quote_name)
1449
+ table = Table(model.model_options.db_table, self.quote_name)
1436
1450
  name = self._fk_constraint_name(model, field, suffix)
1437
- column = Columns(model._meta.db_table, [field.column], self.quote_name)
1438
- to_table = Table(field.target_field.model._meta.db_table, self.quote_name) # type: ignore[attr-defined]
1451
+ column = Columns(model.model_options.db_table, [field.column], self.quote_name)
1452
+ to_table = Table(
1453
+ field.target_field.model.model_options.db_table, self.quote_name
1454
+ )
1439
1455
  to_column = Columns(
1440
- field.target_field.model._meta.db_table, # type: ignore[attr-defined]
1456
+ field.target_field.model.model_options.db_table,
1441
1457
  [field.target_field.column], # type: ignore[attr-defined]
1442
1458
  self.quote_name,
1443
1459
  )
@@ -1453,15 +1469,15 @@ class BaseDatabaseSchemaEditor:
1453
1469
  )
1454
1470
 
1455
1471
  def _fk_constraint_name(
1456
- self, model: type[Model], field: Field, suffix: str
1472
+ self, model: type[Model], field: ForeignKey, suffix: str
1457
1473
  ) -> ForeignKeyName:
1458
1474
  def create_fk_name(*args: Any, **kwargs: Any) -> str:
1459
1475
  return self.quote_name(self._create_index_name(*args, **kwargs))
1460
1476
 
1461
1477
  return ForeignKeyName(
1462
- model._meta.db_table,
1478
+ model.model_options.db_table,
1463
1479
  [field.column],
1464
- split_identifier(field.target_field.model._meta.db_table)[1], # type: ignore[attr-defined]
1480
+ split_identifier(field.target_field.model.model_options.db_table)[1],
1465
1481
  [field.target_field.column], # type: ignore[attr-defined]
1466
1482
  suffix,
1467
1483
  create_fk_name,
@@ -1544,7 +1560,7 @@ class BaseDatabaseSchemaEditor:
1544
1560
  return None
1545
1561
 
1546
1562
  compiler = Query(model, alias_cols=False).get_compiler()
1547
- table = model._meta.db_table
1563
+ table = model.model_options.db_table
1548
1564
  columns = [field.column for field in fields]
1549
1565
  if name is None:
1550
1566
  name = self._unique_constraint_name(table, columns, quote=True)
@@ -1624,7 +1640,7 @@ class BaseDatabaseSchemaEditor:
1624
1640
  return None
1625
1641
  return Statement(
1626
1642
  self.sql_create_check,
1627
- table=Table(model._meta.db_table, self.quote_name),
1643
+ table=Table(model.model_options.db_table, self.quote_name),
1628
1644
  name=self.quote_name(name),
1629
1645
  check=check,
1630
1646
  )
@@ -1639,7 +1655,7 @@ class BaseDatabaseSchemaEditor:
1639
1655
  ) -> Statement:
1640
1656
  return Statement(
1641
1657
  template,
1642
- table=Table(model._meta.db_table, self.quote_name),
1658
+ table=Table(model.model_options.db_table, self.quote_name),
1643
1659
  name=self.quote_name(name),
1644
1660
  )
1645
1661
 
@@ -1667,7 +1683,7 @@ class BaseDatabaseSchemaEditor:
1667
1683
  ]
1668
1684
  with self.connection.cursor() as cursor:
1669
1685
  constraints = self.connection.introspection.get_constraints(
1670
- cursor, model._meta.db_table
1686
+ cursor, model.model_options.db_table
1671
1687
  )
1672
1688
  result: list[str] = []
1673
1689
  for name, infodict in constraints.items():
@@ -1692,7 +1708,7 @@ class BaseDatabaseSchemaEditor:
1692
1708
  constraint_names = self._constraint_names(model, primary_key=True)
1693
1709
  if strict and len(constraint_names) != 1:
1694
1710
  raise ValueError(
1695
- f"Found wrong number ({len(constraint_names)}) of PK constraints for {model._meta.db_table}"
1711
+ f"Found wrong number ({len(constraint_names)}) of PK constraints for {model.model_options.db_table}"
1696
1712
  )
1697
1713
  for constraint_name in constraint_names:
1698
1714
  self.execute(self._delete_primary_key_sql(model, constraint_name))
@@ -1700,13 +1716,15 @@ class BaseDatabaseSchemaEditor:
1700
1716
  def _create_primary_key_sql(self, model: type[Model], field: Field) -> Statement:
1701
1717
  return Statement(
1702
1718
  self.sql_create_pk,
1703
- table=Table(model._meta.db_table, self.quote_name),
1719
+ table=Table(model.model_options.db_table, self.quote_name),
1704
1720
  name=self.quote_name(
1705
1721
  self._create_index_name(
1706
- model._meta.db_table, [field.column], suffix="_pk"
1722
+ model.model_options.db_table, [field.column], suffix="_pk"
1707
1723
  )
1708
1724
  ),
1709
- columns=Columns(model._meta.db_table, [field.column], self.quote_name),
1725
+ columns=Columns(
1726
+ model.model_options.db_table, [field.column], self.quote_name
1727
+ ),
1710
1728
  )
1711
1729
 
1712
1730
  def _delete_primary_key_sql(self, model: type[Model], name: str) -> Statement:
@@ -28,7 +28,7 @@ class BaseDatabaseValidation:
28
28
  # Ignore fields with unsupported features.
29
29
  db_supports_all_required_features = all(
30
30
  getattr(self.connection.features, feature, False)
31
- for feature in field.model._meta.required_db_features
31
+ for feature in field.model.model_options.required_db_features
32
32
  )
33
33
  if db_supports_all_required_features:
34
34
  field_type = field.db_type(self.connection)
@@ -66,7 +66,7 @@ class SQLUpdateCompiler(compiler.SQLUpdateCompiler, SQLCompiler):
66
66
  if self.query.order_by:
67
67
  order_by_sql = []
68
68
  order_by_params = []
69
- db_table = self.query.get_meta().db_table
69
+ db_table = self.query.get_model_meta().db_table
70
70
  try:
71
71
  for resolved, (sql, params, _) in self.get_order_by():
72
72
  if (
@@ -233,7 +233,7 @@ class DatabaseOperations(BaseDatabaseOperations):
233
233
  if not fields:
234
234
  return "", ()
235
235
  columns = [
236
- f"{self.quote_name(field.model._meta.db_table)}.{self.quote_name(field.column)}"
236
+ f"{self.quote_name(field.model.model_options.db_table)}.{self.quote_name(field.column)}"
237
237
  for field in fields
238
238
  ]
239
239
  return "RETURNING {}".format(", ".join(columns)), ()
@@ -125,7 +125,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
125
125
  if self.skip_default(field) and field.default not in (None, NOT_PROVIDED):
126
126
  effective_default = self.effective_default(field)
127
127
  self.execute(
128
- f"UPDATE {self.quote_name(model._meta.db_table)} SET {self.quote_name(field.column)} = %s",
128
+ f"UPDATE {self.quote_name(model.model_options.db_table)} SET {self.quote_name(field.column)} = %s",
129
129
  [effective_default],
130
130
  )
131
131
 
@@ -154,7 +154,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
154
154
  return False
155
155
 
156
156
  storage = self.connection.introspection.get_storage_engine(
157
- self.connection.cursor(), model._meta.db_table
157
+ self.connection.cursor(), model.model_options.db_table
158
158
  )
159
159
  # No need to create an index for ForeignKey fields except if
160
160
  # db_constraint=False because the index from that constraint won't be
@@ -197,7 +197,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
197
197
  if not first_field_name:
198
198
  return
199
199
 
200
- first_field = model._meta.get_field(first_field_name)
200
+ first_field = model._model_meta.get_field(first_field_name)
201
201
  if first_field.get_internal_type() == "ForeignKey":
202
202
  column = self.connection.introspection.identifier_converter(
203
203
  first_field.column
@@ -206,7 +206,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
206
206
  constraint_names = [
207
207
  name
208
208
  for name, infodict in self.connection.introspection.get_constraints(
209
- cursor, model._meta.db_table
209
+ cursor, model.model_options.db_table
210
210
  ).items()
211
211
  if infodict["index"] and infodict["columns"][0] == column
212
212
  ]
@@ -270,7 +270,7 @@ class DatabaseOperations(BaseDatabaseOperations):
270
270
  if not fields:
271
271
  return "", ()
272
272
  columns = [
273
- f"{self.quote_name(field.model._meta.db_table)}.{self.quote_name(field.column)}"
273
+ f"{self.quote_name(field.model.model_options.db_table)}.{self.quote_name(field.column)}"
274
274
  for field in fields
275
275
  ]
276
276
  return "RETURNING {}".format(", ".join(columns)), ()
@@ -173,7 +173,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
173
173
  or (old_type.startswith("citext") and not new_type.startswith("citext"))
174
174
  ):
175
175
  index_name = self._create_index_name(
176
- model._meta.db_table, [old_field.column], suffix="_like"
176
+ model.model_options.db_table, [old_field.column], suffix="_like"
177
177
  )
178
178
  self.execute(self._delete_index_sql(model, index_name))
179
179
 
@@ -186,7 +186,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
186
186
  new_internal_type = new_field.get_internal_type()
187
187
  old_internal_type = old_field.get_internal_type()
188
188
  # Make ALTER TYPE with IDENTITY make sense.
189
- table = strip_quotes(model._meta.db_table)
189
+ table = strip_quotes(model.model_options.db_table)
190
190
  auto_field_types = {"PrimaryKeyField"}
191
191
  old_is_auto = old_internal_type in auto_field_types
192
192
  new_is_auto = new_internal_type in auto_field_types
@@ -306,7 +306,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
306
306
  or new_field.primary_key
307
307
  ):
308
308
  index_to_remove = self._create_index_name(
309
- model._meta.db_table, [old_field.column], suffix="_like"
309
+ model.model_options.db_table, [old_field.column], suffix="_like"
310
310
  )
311
311
  self.execute(self._delete_index_sql(model, index_to_remove))
312
312
 
@@ -439,7 +439,7 @@ class DatabaseOperations(BaseDatabaseOperations):
439
439
  if not fields:
440
440
  return "", ()
441
441
  columns = [
442
- f"{self.quote_name(field.model._meta.db_table)}.{self.quote_name(field.column)}"
442
+ f"{self.quote_name(field.model.model_options.db_table)}.{self.quote_name(field.column)}"
443
443
  for field in fields
444
444
  ]
445
445
  return "RETURNING {}".format(", ".join(columns)), ()