mirror of
https://github.com/django/django.git
synced 2025-01-03 06:55:47 +00:00
Fixed #35545, Refs #32833 -- Fixed ContentTypeManager.get_for_models() crash in CreateModel migrations.
Thank you to Csirmaz Bendegúz for the report and Simon Charettes for the review.
This commit is contained in:
parent
2a082d827d
commit
f1705c8780
@ -75,7 +75,7 @@ class ContentTypeManager(models.Manager):
|
|||||||
ct = self._get_from_cache(opts)
|
ct = self._get_from_cache(opts)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
needed_models[opts.app_label].add(opts.model_name)
|
needed_models[opts.app_label].add(opts.model_name)
|
||||||
needed_opts[opts].append(model)
|
needed_opts[(opts.app_label, opts.model_name)].append(model)
|
||||||
else:
|
else:
|
||||||
results[model] = ct
|
results[model] = ct
|
||||||
if needed_opts:
|
if needed_opts:
|
||||||
@ -89,18 +89,13 @@ class ContentTypeManager(models.Manager):
|
|||||||
)
|
)
|
||||||
cts = self.filter(condition)
|
cts = self.filter(condition)
|
||||||
for ct in cts:
|
for ct in cts:
|
||||||
opts_models = needed_opts.pop(
|
opts_models = needed_opts.pop((ct.app_label, ct.model), [])
|
||||||
ct._meta.apps.get_model(ct.app_label, ct.model)._meta, []
|
|
||||||
)
|
|
||||||
for model in opts_models:
|
for model in opts_models:
|
||||||
results[model] = ct
|
results[model] = ct
|
||||||
self._add_to_cache(self.db, ct)
|
self._add_to_cache(self.db, ct)
|
||||||
# Create content types that weren't in the cache or DB.
|
# Create content types that weren't in the cache or DB.
|
||||||
for opts, opts_models in needed_opts.items():
|
for (app_label, model_name), opts_models in needed_opts.items():
|
||||||
ct = self.create(
|
ct = self.create(app_label=app_label, model=model_name)
|
||||||
app_label=opts.app_label,
|
|
||||||
model=opts.model_name,
|
|
||||||
)
|
|
||||||
self._add_to_cache(self.db, ct)
|
self._add_to_cache(self.db, ct)
|
||||||
for model in opts_models:
|
for model in opts_models:
|
||||||
results[model] = ct
|
results[model] = ct
|
||||||
|
@ -2,7 +2,7 @@ from django.apps import apps
|
|||||||
from django.contrib.contenttypes.models import ContentType, ContentTypeManager
|
from django.contrib.contenttypes.models import ContentType, ContentTypeManager
|
||||||
from django.contrib.contenttypes.prefetch import GenericPrefetch
|
from django.contrib.contenttypes.prefetch import GenericPrefetch
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.migrations.state import ProjectState
|
from django.db.migrations.state import ModelState, ProjectState
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.test.utils import isolate_apps
|
from django.test.utils import isolate_apps
|
||||||
|
|
||||||
@ -99,6 +99,25 @@ class ContentTypesTests(TestCase):
|
|||||||
cts, {ContentType: ContentType.objects.get_for_model(ContentType)}
|
cts, {ContentType: ContentType.objects.get_for_model(ContentType)}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@isolate_apps("contenttypes_tests")
|
||||||
|
def test_get_for_models_migrations_create_model(self):
|
||||||
|
state = ProjectState.from_apps(apps.get_app_config("contenttypes"))
|
||||||
|
|
||||||
|
class Foo(models.Model):
|
||||||
|
class Meta:
|
||||||
|
app_label = "contenttypes_tests"
|
||||||
|
|
||||||
|
state.add_model(ModelState.from_model(Foo))
|
||||||
|
ContentType = state.apps.get_model("contenttypes", "ContentType")
|
||||||
|
cts = ContentType.objects.get_for_models(FooWithUrl, Foo)
|
||||||
|
self.assertEqual(
|
||||||
|
cts,
|
||||||
|
{
|
||||||
|
Foo: ContentType.objects.get_for_model(Foo),
|
||||||
|
FooWithUrl: ContentType.objects.get_for_model(FooWithUrl),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_for_models_full_cache(self):
|
def test_get_for_models_full_cache(self):
|
||||||
# Full cache
|
# Full cache
|
||||||
ContentType.objects.get_for_model(ContentType)
|
ContentType.objects.get_for_model(ContentType)
|
||||||
|
Loading…
Reference in New Issue
Block a user