#22421 closed Bug (fixed)
Loading fixtures with one-to-one inheritance on abstract model and M2M fails since 1.7 Beta
| Reported by: | Owned by: | Ramiro Morales | |
|---|---|---|---|
| Component: | Core (Serialization) | Version: | dev |
| Severity: | Release blocker | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Hi,
I am testing a project with the 1.7Beta release / master branch and Django can't load some fixtures when I am running my test-suite:
======================================================================
ERROR: test_validation_ajouter_double_page (fab4.front.tests.tests.DossierTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/test/testcases.py", line 175, in __call__
self._pre_setup()
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/test/testcases.py", line 747, in _pre_setup
self._fixture_setup()
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/test/testcases.py", line 869, in _fixture_setup
return super(TestCase, self)._fixture_setup()
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/test/testcases.py", line 788, in _fixture_setup
**{'verbosity': 0, 'database': db_name, 'skip_checks': True})
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/management/__init__.py", line 167, in call_command
return klass.execute(*args, **defaults)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/management/base.py", line 337, in execute
output = self.handle(*args, **options)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/management/commands/loaddata.py", line 60, in handle
self.loaddata(fixture_labels)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/management/commands/loaddata.py", line 89, in loaddata
self.load_label(fixture_label)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/management/commands/loaddata.py", line 146, in load_label
obj.save(using=self.using)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/core/serializers/base.py", line 176, in save
setattr(self.object, accessor_name, object_list)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/db/models/fields/related.py", line 1183, in __set__
manager = self.__get__(instance)
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/db/models/fields/related.py", line 1169, in __get__
through=self.field.rel.through,
File "/Users/stan/src/venv_dj_1_7/lib/python2.7/site-packages/Django-1.8.dev20140410233300-py2.7.egg/django/db/models/fields/related.py", line 821, in __init__
(instance, source_field_name))
ValueError: Problem installing fixture '/Users/stan/Dropbox/Projets/Aden/Publish/repos/publish/fab4/fabrication/fixtures/tests/fabrication/fabrication2.json': "<Assistant: >" needs to have a value for field "user" before this many-to-many relationship can be used.
My models are :
from django.contrib.sites.models import Site
from django.contrib.auth.models import User
class SupportManager(models.Manager):
def get_current(self):
return self.get(pk=settings.SITE_ID)
def get_by_natural_key(self, short_name):
return self.get(short_name=short_name)
class Support(Site):
short_name = models.CharField('nom court', max_length=10, unique=True)
logo = models.ImageField('logo', upload_to='images/supports', blank=True)
site_ptr = models.OneToOneField(Site, primary_key=True) # allow to do select related without an extra query to Site.
objects = SupportManager()
def __unicode__(self):
return self.name
def natural_key(self):
return (self.short_name,)
class Organisation(models.Model):
name = models.CharField(max_length=100)
short_name = models.CharField('nom court', max_length=16)
class Employe(User):
supports = models.ManyToManyField(Support)
organisation = models.ForeignKey('Organisation', null=True, blank=True)
filtre_organisation = models.BooleanField(default=False)
telephone = models.CharField(u'téléphone', max_length=100, blank=True)
class Meta:
abstract = True
def __unicode__(self):
return self.get_full_name()
class Assistant(Employe):
class Meta:
verbose_name = 'chargé de clientèle'
The fixture causing the crash is a concat from the following dumps (master version of dumpdata):
python manage.py dumpdata sites.Site --indent=2 --natural-foreign --pk=1 python manage.py dumpdata parametrage.Support --indent=2 --natural-foreign --pk=1 python manage.py dumpdata auth.Group --indent=2 --natural-foreign --pk=2 python manage.py dumpdata auth.User --indent=2 --natural-foreign --pk=8 python manage.py dumpdata parametrage.Assistant --indent=2 --natural-foreign --pk=8
Which is :
[
{
"fields": {
"domain": "proprietesdefrance.com",
"name": "Propri\u00e9t\u00e9s de France"
},
"model": "sites.site",
"pk": 1
},
{
"fields": {
"logo": "images/supports/logo_PDF.jpg",
"short_name": "PDF"
},
"model": "parametrage.support",
"pk": 1
},
{
"fields": {
"name": "Relation Client",
"permissions": [
[
"add_logentry",
"admin",
"logentry"
],
[
"change_statut_refus_bat_to_service_fab",
"fabrication",
"changementstatut"
],
[
"see_all_status",
"fabrication",
"changementstatut"
],
[
"see_chemindefer",
"fabrication",
"chemindefer"
],
[
"add_dossier",
"fabrication",
"dossier"
],
[
"change_dossier",
"fabrication",
"dossier"
],
[
"change_prix_dossier",
"fabrication",
"dossier"
],
[
"see_bat_pdf_dossier",
"fabrication",
"dossier"
],
[
"change_logoconstructeur",
"saisie",
"logoconstructeur"
],
[
"delete_logoconstructeur",
"saisie",
"logoconstructeur"
]
]
},
"model": "auth.group",
"pk": 2
},
{
"fields": {
"username": "igixxxxx",
"first_name": "Isxxxxx",
"last_name": "Gxxxxxx",
"is_active": true,
"is_superuser": false,
"is_staff": true,
"last_login": "2014-04-04T10:34:28",
"groups": [
[
"Relation Client"
]
],
"user_permissions": [],
"password": "sha1$17783$7152b7f25xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email": "igibxxxxx@xxxxxxxxx.fr",
"date_joined": "2009-10-07T16:08:28"
},
"model": "auth.user",
"pk": 8
},
{
"fields": {
"organisation": 1,
"telephone": "01 xx xx xx xx",
"groups": [
[
"Relation Client"
]
],
"user_permissions": [],
"filtre_organisation": false,
"supports": [
[
"PDF"
]
]
},
"model": "parametrage.assistant",
"pk": 8
}
]
Any idea ?
Thanks.
Attachments (2)
Change History (13)
comment:1 by , 12 years ago
| Summary: | Loading fixtures with OneToOne relation and natural keys fails since 1.7 Beta → Loading fixtures with one-to-one inheritance and M2M with natural keys fails since 1.7 Beta |
|---|
comment:2 by , 12 years ago
Here a patch on the tests that cause a failure.
I just added a proxy model.
$ git diff
diff --git a/tests/fixtures_regress/fixtures/special-article.json b/tests/fixtures_regress/fixtures/special-article.json
index a36244a..75f2d65 100644
--- a/tests/fixtures_regress/fixtures/special-article.json
+++ b/tests/fixtures_regress/fixtures/special-article.json
@@ -2,14 +2,14 @@
{
"pk": 1,
"model": "fixtures_regress.article",
- "fields": {"title": "foof"
+ "fields": {
+ "title": "foof"
}
},
{
"pk": 1,
"model": "fixtures_regress.specialarticle",
"fields": {
- "title": "Article Title 1",
"channels": []
}
}
diff --git a/tests/fixtures_regress/models.py b/tests/fixtures_regress/models.py
index 95f9488..e440184 100644
--- a/tests/fixtures_regress/models.py
+++ b/tests/fixtures_regress/models.py
@@ -66,7 +66,14 @@ class Article(models.Model):
# Subclass of a model with a ManyToManyField for test_ticket_20820
-class SpecialArticle(Article):
+class CommonSpecialArticle(Article):
+ subtitle = models.CharField(max_length=255)
+
+ class Meta:
+ abstract = True
+
+
+class SpecialArticle(CommonSpecialArticle):
pass
And the failure (tested with sqlite and MySQL):
PYTHONPATH=..:$PYTHONPATH ./runtests.py --settings=test_sqlite fixtures_regress.tests.TestFixtures.test_ticket_20820
Testing against Django installed in '/Users/stan/src/Django/repos/django/django/django'
Creating test database for alias 'default'...
Creating test database for alias 'other'...
E
======================================================================
ERROR: test_ticket_20820 (fixtures_regress.tests.TestFixtures)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/stan/src/Django/repos/django/django/tests/fixtures_regress/tests.py", line 480, in test_ticket_20820
verbosity=0,
File "/Users/stan/src/Django/repos/django/django/django/core/management/__init__.py", line 167, in call_command
return klass.execute(*args, **defaults)
File "/Users/stan/src/Django/repos/django/django/django/core/management/base.py", line 337, in execute
output = self.handle(*args, **options)
File "/Users/stan/src/Django/repos/django/django/django/core/management/commands/loaddata.py", line 60, in handle
self.loaddata(fixture_labels)
File "/Users/stan/src/Django/repos/django/django/django/core/management/commands/loaddata.py", line 90, in loaddata
self.load_label(fixture_label)
File "/Users/stan/src/Django/repos/django/django/django/core/management/commands/loaddata.py", line 147, in load_label
obj.save(using=self.using)
File "/Users/stan/src/Django/repos/django/django/django/core/serializers/base.py", line 176, in save
setattr(self.object, accessor_name, object_list)
File "/Users/stan/src/Django/repos/django/django/django/db/models/fields/related.py", line 1185, in __set__
manager = self.__get__(instance)
File "/Users/stan/src/Django/repos/django/django/django/db/models/fields/related.py", line 1171, in __get__
through=self.field.rel.through,
File "/Users/stan/src/Django/repos/django/django/django/db/models/fields/related.py", line 823, in __init__
(instance, source_field_name))
ValueError: Problem installing fixture '/Users/stan/src/Django/repos/django/django/tests/fixtures_regress/fixtures/special-article.json': "<SpecialArticle: SpecialArticle object>" needs to have a value for field "article" before this many-to-many relationship can be used.
----------------------------------------------------------------------
Ran 1 test in 0.021s
FAILED (errors=1)
Destroying test database for alias 'default'...
Destroying test database for alias 'other'...
by , 12 years ago
| Attachment: | regression-test.diff added |
|---|
Patch against master causing a test failure.
comment:3 by , 12 years ago
| Has patch: | set |
|---|---|
| Patch needs improvement: | set |
| Summary: | Loading fixtures with one-to-one inheritance and M2M with natural keys fails since 1.7 Beta → Loading fixtures with one-to-one inheritance on proxy model and M2M with natural keys fails since 1.7 Beta |
by , 12 years ago
| Attachment: | regression-test.2.diff added |
|---|
replace the previous patch (removed subtitle field to narrow down the bug).
comment:4 by , 12 years ago
| Severity: | Normal → Release blocker |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:5 by , 12 years ago
| Summary: | Loading fixtures with one-to-one inheritance on proxy model and M2M with natural keys fails since 1.7 Beta → Loading fixtures with one-to-one inheritance on abstract model and M2M fails since 1.7 Beta |
|---|
Edit:
This is not a proxy model but an abstract one.
And it does not looks like it is related to the natural keys since the regression test fails without them.
comment:6 by , 11 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 11 years ago
| Patch needs improvement: | unset |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
comment:9 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Looks like it came from this commit in django/db/models/fields/related.py#ForeignObject.get_instance_value_for_fields(instance, fields) :
https://github.com/django/django/commit/244e2b71f512605f3d0a8e1ba4c9d6b538acf69d#diff-301
Which is related to the ticket #20820
- ret.append(instance.pk) - else: - ret.append(getattr(instance, field.attname)) + possible_parent_link = opts.get_ancestor_link(field.model) + if not possible_parent_link or possible_parent_link.primary_key: + ret.append(instance.pk) + continue + ret.append(getattr(instance, field.attname)) return tuple(ret)And especially the last line:
ret.append(getattr(instance, field.attname))(<assistant obj>.idin that case) which add aNoneto the returned Tuple raising an Exception increate_many_related_manager():self.related_val = source_field.get_foreign_related_value(instance) if None in self.related_val: raise ValueError('"%r" needs to have a value for field "%s" before ' 'this many-to-many relationship can be used.' % (instance, source_field_name))Because the Assistant object has not been saved yet.
FYI, the fixture loading fails when trying to save the Assistant object (which is a one-to-one to User) because of the M2M user_permissions relation.
Hope this helps.