1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

[1.7.x] Fixed #24007 -- Ensure apps registry's ready before unpickling models

This prevents AppRegistryNotReady errors when unpickling Django
models from an external script.
Backport of 108b8bf85 from master.
This commit is contained in:
Claude Paroz 2014-12-17 17:25:28 +01:00
parent 6d8c14621e
commit 47912d9f2b
3 changed files with 41 additions and 0 deletions

View File

@ -1459,6 +1459,8 @@ def model_unpickle(model_id, attrs, factory):
Used to unpickle Model subclasses with deferred fields. Used to unpickle Model subclasses with deferred fields.
""" """
if isinstance(model_id, tuple): if isinstance(model_id, tuple):
if not apps.ready:
apps.populate(settings.INSTALLED_APPS)
model = apps.get_model(*model_id) model = apps.get_model(*model_id)
else: else:
# Backwards compat - the model was cached directly in earlier versions. # Backwards compat - the model was cached directly in earlier versions.

View File

@ -151,3 +151,7 @@ Bugfixes
(:ticket:`23975`). (:ticket:`23975`).
* Made admin system checks run for custom ``AdminSite``\s (:ticket:`23497`). * Made admin system checks run for custom ``AdminSite``\s (:ticket:`23497`).
* Ensured the app registry is fully populated when unpickling models. When an
external script (like a queueing infrastructure) reloads pickled models, it
could crash with an ``AppRegistryNotReady`` exception (:ticket:`24007`).

View File

@ -2,7 +2,10 @@ from __future__ import unicode_literals
import datetime import datetime
from operator import attrgetter from operator import attrgetter
import pickle
import subprocess
import sys import sys
import tempfile
import unittest import unittest
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -245,3 +248,35 @@ class EvaluateMethodTest(TestCase):
dept = Department.objects.create(pk=1, name='abc') dept = Department.objects.create(pk=1, name='abc')
dept.evaluate = 'abc' dept.evaluate = 'abc'
Worker.objects.filter(department=dept) Worker.objects.filter(department=dept)
class ModelPickleTestCase(TestCase):
def test_unpickling_when_appregistrynotready(self):
"""
#24007 -- Verifies that a pickled model can be unpickled without having
to manually setup the apps registry beforehand.
"""
script_template = """#!/usr/bin/env python
import pickle
from django.conf import settings
data = %r
settings.configure(DEBUG=False, INSTALLED_APPS=('model_regress',), SECRET_KEY = "blah")
article = pickle.loads(data)
print(article.headline)"""
a = Article.objects.create(
headline="Some object",
pub_date=datetime.datetime.now(),
article_text="This is an article",
)
with tempfile.NamedTemporaryFile(mode='w+', suffix=".py", dir='.', delete=True) as script:
script.write(script_template % pickle.dumps(a))
script.flush()
try:
result = subprocess.check_output(['python', script.name])
except subprocess.CalledProcessError:
self.fail("Unable to reload model pickled data")
self.assertEqual(result.strip().decode(), "Some object")