92 | | # Look for an application configuration to attach the model to. |
93 | | app_config = apps.get_containing_app_config(module) |
94 | | |
95 | | if getattr(meta, 'app_label', None) is None: |
96 | | |
97 | | if app_config is None: |
98 | | # If the model is imported before the configuration for its |
99 | | # application is created (#21719), or isn't in an installed |
100 | | # application (#21680), use the legacy logic to figure out the |
101 | | # app_label by looking one level up from the package or module |
102 | | # named 'models'. If no such package or module exists, fall |
103 | | # back to looking one level up from the module this model is |
104 | | # defined in. |
105 | | |
106 | | # For 'django.contrib.sites.models', this would be 'sites'. |
107 | | # For 'geo.models.places' this would be 'geo'. |
108 | | |
109 | | msg = ( |
110 | | "Model class %s.%s doesn't declare an explicit app_label " |
111 | | "and either isn't in an application in INSTALLED_APPS or " |
112 | | "else was imported before its application was loaded. " % |
113 | | (module, name)) |
114 | | if abstract: |
115 | | msg += "Its app_label will be set to None in Django 1.9." |
| 89 | new_class.add_to_class('_meta', Options(meta)) |
| 90 | |
| 91 | def _setup(sender, **kwargs): |
| 92 | assert sender is new_class |
| 93 | if not abstract: |
| 94 | new_class.add_to_class( |
| 95 | 'DoesNotExist', |
| 96 | subclass_exception( |
| 97 | str('DoesNotExist'), |
| 98 | tuple(x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (ObjectDoesNotExist,), |
| 99 | module, |
| 100 | attached_to=new_class)) |
| 101 | new_class.add_to_class( |
| 102 | 'MultipleObjectsReturned', |
| 103 | subclass_exception( |
| 104 | str('MultipleObjectsReturned'), |
| 105 | tuple(x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (MultipleObjectsReturned,), |
| 106 | module, |
| 107 | attached_to=new_class)) |
| 108 | if base_meta and not base_meta.abstract: |
| 109 | # Non-abstract child classes inherit some attributes from their |
| 110 | # non-abstract parent (unless an ABC comes before it in the |
| 111 | # method resolution order). |
| 112 | if not hasattr(meta, 'ordering'): |
| 113 | new_class._meta.ordering = base_meta.ordering |
| 114 | if not hasattr(meta, 'get_latest_by'): |
| 115 | new_class._meta.get_latest_by = base_meta.get_latest_by |
| 116 | |
| 117 | is_proxy = new_class._meta.proxy |
| 118 | |
| 119 | # If the model is a proxy, ensure that the base class |
| 120 | # hasn't been swapped out. |
| 121 | if is_proxy and base_meta and base_meta.swapped: |
| 122 | raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped)) |
| 123 | |
| 124 | if getattr(new_class, '_default_manager', None): |
| 125 | if not is_proxy: |
| 126 | # Multi-table inheritance doesn't inherit default manager from |
| 127 | # parents. |
| 128 | new_class._default_manager = None |
| 129 | new_class._base_manager = None |
117 | | msg += "This will no longer be supported in Django 1.9." |
118 | | warnings.warn(msg, RemovedInDjango19Warning, stacklevel=2) |
119 | | |
120 | | model_module = sys.modules[new_class.__module__] |
121 | | package_components = model_module.__name__.split('.') |
122 | | package_components.reverse() # find the last occurrence of 'models' |
123 | | try: |
124 | | app_label_index = package_components.index(MODELS_MODULE_NAME) + 1 |
125 | | except ValueError: |
126 | | app_label_index = 1 |
127 | | kwargs = {"app_label": package_components[app_label_index]} |
128 | | |
129 | | else: |
130 | | kwargs = {"app_label": app_config.label} |
| 131 | # Proxy classes do inherit parent's default manager, if none is |
| 132 | # set explicitly. |
| 133 | new_class._default_manager = new_class._default_manager._copy_to_model(new_class) |
| 134 | new_class._base_manager = new_class._base_manager._copy_to_model(new_class) |
| 135 | |
| 136 | # Add all attributes to the class. |
| 137 | for obj_name, obj in attrs.items(): |
| 138 | new_class.add_to_class(obj_name, obj) |
| 139 | |
| 140 | # All the fields of any type declared on this model |
| 141 | new_fields = ( |
| 142 | new_class._meta.local_fields + |
| 143 | new_class._meta.local_many_to_many + |
| 144 | new_class._meta.virtual_fields |
| 145 | ) |
| 146 | field_names = set(f.name for f in new_fields) |
132 | | else: |
133 | | kwargs = {} |
134 | | |
135 | | new_class.add_to_class('_meta', Options(meta, **kwargs)) |
136 | | if not abstract: |
137 | | new_class.add_to_class( |
138 | | 'DoesNotExist', |
139 | | subclass_exception( |
140 | | str('DoesNotExist'), |
141 | | tuple(x.DoesNotExist for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (ObjectDoesNotExist,), |
142 | | module, |
143 | | attached_to=new_class)) |
144 | | new_class.add_to_class( |
145 | | 'MultipleObjectsReturned', |
146 | | subclass_exception( |
147 | | str('MultipleObjectsReturned'), |
148 | | tuple(x.MultipleObjectsReturned for x in parents if hasattr(x, '_meta') and not x._meta.abstract) or (MultipleObjectsReturned,), |
149 | | module, |
150 | | attached_to=new_class)) |
151 | | if base_meta and not base_meta.abstract: |
152 | | # Non-abstract child classes inherit some attributes from their |
153 | | # non-abstract parent (unless an ABC comes before it in the |
154 | | # method resolution order). |
155 | | if not hasattr(meta, 'ordering'): |
156 | | new_class._meta.ordering = base_meta.ordering |
157 | | if not hasattr(meta, 'get_latest_by'): |
158 | | new_class._meta.get_latest_by = base_meta.get_latest_by |
159 | | |
160 | | is_proxy = new_class._meta.proxy |
161 | | |
162 | | # If the model is a proxy, ensure that the base class |
163 | | # hasn't been swapped out. |
164 | | if is_proxy and base_meta and base_meta.swapped: |
165 | | raise TypeError("%s cannot proxy the swapped model '%s'." % (name, base_meta.swapped)) |
166 | | |
167 | | if getattr(new_class, '_default_manager', None): |
168 | | if not is_proxy: |
169 | | # Multi-table inheritance doesn't inherit default manager from |
170 | | # parents. |
171 | | new_class._default_manager = None |
172 | | new_class._base_manager = None |
173 | | else: |
174 | | # Proxy classes do inherit parent's default manager, if none is |
175 | | # set explicitly. |
176 | | new_class._default_manager = new_class._default_manager._copy_to_model(new_class) |
177 | | new_class._base_manager = new_class._base_manager._copy_to_model(new_class) |
178 | | |
179 | | # Add all attributes to the class. |
180 | | for obj_name, obj in attrs.items(): |
181 | | new_class.add_to_class(obj_name, obj) |
182 | | |
183 | | # All the fields of any type declared on this model |
184 | | new_fields = ( |
185 | | new_class._meta.local_fields + |
186 | | new_class._meta.local_many_to_many + |
187 | | new_class._meta.virtual_fields |
188 | | ) |
189 | | field_names = set(f.name for f in new_fields) |
190 | | |
191 | | # Basic setup for proxy models. |
192 | | if is_proxy: |
193 | | base = None |
194 | | for parent in [kls for kls in parents if hasattr(kls, '_meta')]: |
195 | | if parent._meta.abstract: |
196 | | if parent._meta.fields: |
197 | | raise TypeError("Abstract base class containing model fields not permitted for proxy model '%s'." % name) |
| 148 | # Basic setup for proxy models. |
| 149 | if is_proxy: |
| 150 | base = None |
| 151 | for parent in [kls for kls in parents if hasattr(kls, '_meta')]: |
| 152 | if parent._meta.abstract: |
| 153 | if parent._meta.fields: |
| 154 | raise TypeError("Abstract base class containing model fields not permitted for proxy model '%s'." % name) |
| 155 | else: |
| 156 | continue |
| 157 | if base is not None: |
| 158 | raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name) |
199 | | continue |
200 | | if base is not None: |
201 | | raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name) |
202 | | else: |
203 | | base = parent |
204 | | if base is None: |
205 | | raise TypeError("Proxy model '%s' has no non-abstract model base class." % name) |
206 | | if (new_class._meta.local_fields or |
207 | | new_class._meta.local_many_to_many): |
208 | | raise FieldError("Proxy model '%s' contains model fields." % name) |
209 | | new_class._meta.setup_proxy(base) |
210 | | new_class._meta.concrete_model = base._meta.concrete_model |
211 | | else: |
212 | | new_class._meta.concrete_model = new_class |
| 160 | base = parent |
| 161 | if base is None: |
| 162 | raise TypeError("Proxy model '%s' has no non-abstract model base class." % name) |
| 163 | if (new_class._meta.local_fields or |
| 164 | new_class._meta.local_many_to_many): |
| 165 | raise FieldError("Proxy model '%s' contains model fields." % name) |
| 166 | new_class._meta.setup_proxy(base) |
| 167 | new_class._meta.concrete_model = base._meta.concrete_model |
| 168 | else: |
| 169 | new_class._meta.concrete_model = new_class |
214 | | # Collect the parent links for multi-table inheritance. |
215 | | parent_links = {} |
216 | | for base in reversed([new_class] + parents): |
217 | | # Conceptually equivalent to `if base is Model`. |
218 | | if not hasattr(base, '_meta'): |
219 | | continue |
220 | | # Skip concrete parent classes. |
221 | | if base != new_class and not base._meta.abstract: |
222 | | continue |
223 | | # Locate OneToOneField instances. |
224 | | for field in base._meta.local_fields: |
225 | | if isinstance(field, OneToOneField): |
226 | | parent_links[field.rel.to] = field |
227 | | |
228 | | # Do the appropriate setup for any model parents. |
229 | | for base in parents: |
230 | | original_base = base |
231 | | if not hasattr(base, '_meta'): |
232 | | # Things without _meta aren't functional models, so they're |
233 | | # uninteresting parents. |
234 | | continue |
| 171 | # Collect the parent links for multi-table inheritance. |
| 172 | parent_links = {} |
| 173 | for base in reversed([new_class] + parents): |
| 174 | # Conceptually equivalent to `if base is Model`. |
| 175 | if not hasattr(base, '_meta'): |
| 176 | continue |
| 177 | # Skip concrete parent classes. |
| 178 | if base != new_class and not base._meta.abstract: |
| 179 | continue |
| 180 | # Locate OneToOneField instances. |
| 181 | for field in base._meta.local_fields: |
| 182 | if isinstance(field, OneToOneField): |
| 183 | parent_links[field.rel.to] = field |
| 184 | |
| 185 | # Do the appropriate setup for any model parents. |
| 186 | for base in parents: |
| 187 | original_base = base |
| 188 | if not hasattr(base, '_meta'): |
| 189 | # Things without _meta aren't functional models, so they're |
| 190 | # uninteresting parents. |
| 191 | continue |
236 | | parent_fields = base._meta.local_fields + base._meta.local_many_to_many |
237 | | # Check for clashes between locally declared fields and those |
238 | | # on the base classes (we cannot handle shadowed fields at the |
239 | | # moment). |
240 | | for field in parent_fields: |
241 | | if field.name in field_names: |
242 | | raise FieldError( |
243 | | 'Local field %r in class %r clashes ' |
244 | | 'with field of similar name from ' |
245 | | 'base class %r' % (field.name, name, base.__name__) |
246 | | ) |
247 | | if not base._meta.abstract: |
248 | | # Concrete classes... |
249 | | base = base._meta.concrete_model |
250 | | if base in parent_links: |
251 | | field = parent_links[base] |
252 | | elif not is_proxy: |
253 | | attr_name = '%s_ptr' % base._meta.model_name |
254 | | field = OneToOneField(base, name=attr_name, |
255 | | auto_created=True, parent_link=True) |
256 | | # Only add the ptr field if it's not already present; |
257 | | # e.g. migrations will already have it specified |
258 | | if not hasattr(new_class, attr_name): |
259 | | new_class.add_to_class(attr_name, field) |
260 | | else: |
261 | | field = None |
262 | | new_class._meta.parents[base] = field |
263 | | else: |
264 | | # .. and abstract ones. |
| 193 | parent_fields = base._meta.local_fields + base._meta.local_many_to_many |
| 194 | # Check for clashes between locally declared fields and those |
| 195 | # on the base classes (we cannot handle shadowed fields at the |
| 196 | # moment). |
| 198 | if field.name in field_names: |
| 199 | raise FieldError( |
| 200 | 'Local field %r in class %r clashes ' |
| 201 | 'with field of similar name from ' |
| 202 | 'base class %r' % (field.name, name, base.__name__) |
| 203 | ) |
| 204 | if not base._meta.abstract: |
| 205 | # Concrete classes... |
| 206 | base = base._meta.concrete_model |
| 207 | if base in parent_links: |
| 208 | field = parent_links[base] |
| 209 | elif not is_proxy: |
| 210 | attr_name = '%s_ptr' % base._meta.model_name |
| 211 | field = OneToOneField(base, name=attr_name, |
| 212 | auto_created=True, parent_link=True) |
| 213 | # Only add the ptr field if it's not already present; |
| 214 | # e.g. migrations will already have it specified |
| 215 | if not hasattr(new_class, attr_name): |
| 216 | new_class.add_to_class(attr_name, field) |
| 217 | else: |
| 218 | field = None |
| 219 | new_class._meta.parents[base] = field |
| 220 | else: |
| 221 | # .. and abstract ones. |
| 222 | for field in parent_fields: |
| 223 | new_class.add_to_class(field.name, copy.deepcopy(field)) |
| 224 | |
| 225 | # Pass any non-abstract parent classes onto child. |
| 226 | new_class._meta.parents.update(base._meta.parents) |
| 227 | |
| 228 | # Inherit managers from the abstract base classes. |
| 229 | new_class.copy_managers(base._meta.abstract_managers) |
| 230 | |
| 231 | # Proxy models inherit the non-abstract managers from their base, |
| 232 | # unless they have redefined any of them. |
| 233 | if is_proxy: |
| 234 | new_class.copy_managers(original_base._meta.concrete_managers) |
| 235 | |
| 236 | # Inherit virtual fields (like GenericForeignKey) from the parent |
| 237 | # class |
| 238 | for field in base._meta.virtual_fields: |
| 239 | if base._meta.abstract and field.name in field_names: |
| 240 | raise FieldError( |
| 241 | 'Local field %r in class %r clashes ' |
| 242 | 'with field of similar name from ' |
| 243 | 'abstract base class %r' % (field.name, name, base.__name__) |
| 244 | ) |
274 | | # Proxy models inherit the non-abstract managers from their base, |
275 | | # unless they have redefined any of them. |
276 | | if is_proxy: |
277 | | new_class.copy_managers(original_base._meta.concrete_managers) |
278 | | |
279 | | # Inherit virtual fields (like GenericForeignKey) from the parent |
280 | | # class |
281 | | for field in base._meta.virtual_fields: |
282 | | if base._meta.abstract and field.name in field_names: |
283 | | raise FieldError( |
284 | | 'Local field %r in class %r clashes ' |
285 | | 'with field of similar name from ' |
286 | | 'abstract base class %r' % (field.name, name, base.__name__) |
287 | | ) |
288 | | new_class.add_to_class(field.name, copy.deepcopy(field)) |
289 | | |
290 | | if abstract: |
291 | | # Abstract base models can't be instantiated and don't appear in |
292 | | # the list of models for an app. We do the final setup for them a |
293 | | # little differently from normal models. |
294 | | attr_meta.abstract = False |
295 | | new_class.Meta = attr_meta |
296 | | return new_class |
297 | | |
298 | | new_class._prepare() |
299 | | new_class._meta.apps.register_model(new_class._meta.app_label, new_class) |
| 256 | class_registered.connect(_setup, sender=new_class, weak=False) |
| 257 | new_class._meta.apps.register_model(new_class) |