Represent a Django Model. Don't use the actual Model class as it's not designed to have its options changed - instead, mutate this one and then render it into a Model as required. Note that while you are allowed to mutate .fields, you are not allowed to mutate the Field instanc
| 735 | |
| 736 | |
| 737 | class ModelState: |
| 738 | """ |
| 739 | Represent a Django Model. Don't use the actual Model class as it's not |
| 740 | designed to have its options changed - instead, mutate this one and then |
| 741 | render it into a Model as required. |
| 742 | |
| 743 | Note that while you are allowed to mutate .fields, you are not allowed |
| 744 | to mutate the Field instances inside there themselves - you must instead |
| 745 | assign new ones, as these are not detached during a clone. |
| 746 | """ |
| 747 | |
| 748 | def __init__( |
| 749 | self, app_label, name, fields, options=None, bases=None, managers=None |
| 750 | ): |
| 751 | self.app_label = app_label |
| 752 | self.name = name |
| 753 | self.fields = dict(fields) |
| 754 | self.options = options or {} |
| 755 | self.options.setdefault("indexes", []) |
| 756 | self.options.setdefault("constraints", []) |
| 757 | self.bases = bases or (models.Model,) |
| 758 | self.managers = managers or [] |
| 759 | for name, field in self.fields.items(): |
| 760 | # Sanity-check that fields are NOT already bound to a model. |
| 761 | if hasattr(field, "model"): |
| 762 | raise ValueError( |
| 763 | 'ModelState.fields cannot be bound to a model - "%s" is.' % name |
| 764 | ) |
| 765 | # Ensure that relation fields are NOT referring to a model class. |
| 766 | if field.is_relation and hasattr(field.related_model, "_meta"): |
| 767 | raise ValueError( |
| 768 | 'Model fields in "ModelState.fields" cannot refer to a model class ' |
| 769 | f'- "{self.app_label}.{self.name}.{name}.to" does. Use a string ' |
| 770 | "reference instead." |
| 771 | ) |
| 772 | if field.many_to_many and hasattr(field.remote_field.through, "_meta"): |
| 773 | raise ValueError( |
| 774 | 'Model fields in "ModelState.fields" cannot refer to a model class ' |
| 775 | f'- "{self.app_label}.{self.name}.{name}.through" does. Use a ' |
| 776 | "string reference instead." |
| 777 | ) |
| 778 | # Sanity-check that indexes have their name set. |
| 779 | for index in self.options["indexes"]: |
| 780 | if not index.name: |
| 781 | raise ValueError( |
| 782 | "Indexes passed to ModelState require a name attribute. " |
| 783 | "%r doesn't have one." % index |
| 784 | ) |
| 785 | |
| 786 | @cached_property |
| 787 | def name_lower(self): |
| 788 | return self.name.lower() |
| 789 | |
| 790 | def get_field(self, field_name): |
| 791 | if ( |
| 792 | field_name == "_order" |
| 793 | and self.options.get("order_with_respect_to") is not None |
| 794 | ): |
no outgoing calls