Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#27128 closed Bug (needsinfo)

A method model.objects.get(pk=obj.pk) returns many objects, but in a database is one.

Reported by: Seti Owned by: nobody
Component: Uncategorized Version: 1.9
Severity: Normal Keywords: GenericRelation, Testing, Models
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Seti)

Very strange behaviour of the Django ORM while testing (now I am using pytest)

I have two apps "books" and "replies".
The app "books" has two models http://pastebin.com/gDMi7UpU
The app "replies" has one model http://pastebin.com/u9FabQQA

For create new objects I am using factories for replies - http://pastebin.com/pGtiwS2m, for books and writers - http://pastebin.com/NQ6AWxib

While testing methods of queryset of the model Book I got error, where it should not be

A file querysets.py of the app "books" http://pastebin.com/FVnLLzxK
Tests for the file querysets.py of the app "books" http://pastebin.com/rmpDm0Ae

For testing I am using the pytest with next configuration in a file pytest.ini

[pytest]
addopts = -s --reuse-db --ff --maxfail=1 apps/books/tests/test_querysets.py::Tests
DJANGO_SETTINGS_MODULE=config.settings.development

Run test as next py.test

Traceback http://pastebin.com/Vv96XLzm

After many time googling and dipping in the Django`s code by the traceback I decided it is bug in the Django

I think it is the problem related with that models the Book and the Reply is related by help the field GenericRelation, but I don`t found facts for it.

Sorry for my grammar mistakes, I was no originally an English

If need another codes from my project, please tell about it

Update
Same error I had when tested a method "get_admin_url()" of the model Book with next a testing code

def test_get_admin_url(self):
        self.client.force_login(self.active_superuser)
        response = self.client.get(self.book.get_admin_url())
        self.assertEqual(response.status_code, 200)

Ending a traceback

        if not num:
            raise self.model.DoesNotExist(
                "%s matching query does not exist." %
                self.model._meta.object_name
            )
        raise self.model.MultipleObjectsReturned(
            "get() returned more than one %s -- it returned %s!" %
>           (self.model._meta.object_name, num)
        )
E       apps.books.models.MultipleObjectsReturned: get() returned more than one Book -- it returned 3!

Change History (9)

comment:1 by Seti, 8 years ago

Description: modified (diff)

comment:2 by Tim Graham, 8 years ago

Resolution: needsinfo
Status: newclosed

Yes, we need a minimal project (or a test case for Django's test suite, if possible) without any third-party apps to rule out a bug there. Please reopen if you can provide that -- and attach it to the ticket since pastebin posts will expire soon.

in reply to:  2 comment:3 by Seti, 8 years ago

Replying to timgraham:

Yes, we need a minimal project (or a test case for Django's test suite, if possible) without any third-party apps to rule out a bug there. Please reopen if you can provide that -- and attach it to the ticket since pastebin posts will expire soon.

Here two problems:

  1. If is variant with minimal project, be taken into account that I using the factory_boy for generate fake objects (it is third-party app)
  2. What is "test case for Django's test suite"? How to made it to you?

comment:4 by Tim Graham, 8 years ago

Yes, we need a project without factory_boy to ensure that the problem isn't in that library.

You can read about Django's test suite in our contributing docs.

in reply to:  4 comment:5 by Seti, 8 years ago

Replying to timgraham:

Yes, we need a project without factory_boy to ensure that the problem isn't in that library.

You can read about Django's test suite in our contributing docs.

After many hours debug my code I found a next problem

(Pdb) get_user_model().objects.all()
[<User: deniserobertson@schmidt-clark.com>, <User: othompson@adams-hess.com>, <User: salazarkatherine@gonzalez-bennett.org>, <User: knash@hotmail.com>, <User: maykristi@mahoney.info>, <User: robingonzalez@long.com>, <User: michaelbaker@hotmail.com>, <User: corygill@gmail.com>]
(Pdb) get_user_model().objects.all()[0]
<User: deniserobertson@schmidt-clark.com>
(Pdb) get_user_model().objects.all()[1]
<User: deniserobertson@schmidt-clark.com>
(Pdb) get_user_model().objects.all()[2]
<User: deniserobertson@schmidt-clark.com>
(Pdb) get_user_model().objects.all()[3]
<User: knash@hotmail.com>
(Pdb) get_user_model().objects.all()[4]
<User: maykristi@mahoney.info>
(Pdb) get_user_model().objects.all()[5]
<User: robingonzalez@long.com>

Problem with a user`s model. It on index [0] [1] and [2] return the same user. It leads to dublication in my replies.

If you know same problem, may be it fixed in the Django 1.10, if not know - I will still debug.

I wait your response

comment:6 by Tim Graham, 8 years ago

If the queryset isn't ordered, each time you index get_user_model().objects.all(), there's no guarantee that the results will be in the same order. Try indexing get_user_model().objects.order_by('pk') instead.

in reply to:  6 ; comment:7 by Seti, 8 years ago

Replying to timgraham:

If the queryset isn't ordered, each time you index get_user_model().objects.all(), there's no guarantee that the results will be in the same order. Try indexing get_user_model().objects.order_by('pk') instead.

Your method given me properly results

users = get_user_model().objects.order_by('pk')
print(users)
users[0], users[1], users[2], users[3], users[4], users[5]

[<User: blackmelissa@gutierrez.com>, <User: greencarl@francis-brock.com>, <User: admin@admin.com>, <User: christopher19@gmail.com>, <User: jane85@gmail.com>, <User: scott99@gmail.com>, <User: ann91@hotmail.com>, <User: patricia19@yahoo.com>, <User: zfuller@jones.com>]
(<User: blackmelissa@gutierrez.com>,

<User: greencarl@francis-brock.com>,
<User: admin@admin.com>,
<User: christopher19@gmail.com>,
<User: jane85@gmail.com>,
<User: scott99@gmail.com>)

My default code still return not properly results

users = get_user_model().objects.all()
print(users)
users[0], users[1], users[2], users[3], users[4], users[5]

[<User: admin@admin.com>, <User: zfuller@jones.com>, <User: ann91@hotmail.com>, <User: scott99@gmail.com>, <User: greencarl@francis-brock.com>, <User: patricia19@yahoo.com>, <User: christopher19@gmail.com>, <User: blackmelissa@gutierrez.com>, <User: jane85@gmail.com>]
(<User: admin@admin.com>,

<User: admin@admin.com>,
<User: admin@admin.com>,
<User: admin@admin.com>,
<User: greencarl@francis-brock.com>,
<User: patricia19@yahoo.com>)

But it not resolve my problem, because my user`s models has default sorting by Last_login (see SQL)

Sorting for the model if I override it

print(get_user_model().objects.only('pk').order_by('pk').query)

SELECT "user"."id" FROM "user" ORDER BY "user"."id" ASC

Sorting for the model by default is by last_login of users

print(get_user_model().objects.only('pk').query)

SELECT "user"."id" FROM "user" ORDER BY "user"."last_login" DESC

I made sort by default as 'email' or 'username' and I had properly results.

Problem with 'last_login' may be only single - not all users have this field not None

Last edited 8 years ago by Seti (previous) (diff)

in reply to:  7 ; comment:8 by Shai Berger, 8 years ago

Replying to setivolkylany:

Hi,

You are unlikely to get any more responses on this ticket -- it looks like your original problem is not caused by a bug in Django, and now you have started to ask about a different issue.

Please use the support channels (#django IRC channel, django-users mailing list) to ask more questions.

in reply to:  8 comment:9 by Seti, 8 years ago

Replying to shaib:

Replying to setivolkylany:

Hi,

You are unlikely to get any more responses on this ticket -- it looks like your original problem is not caused by a bug in Django, and now you have started to ask about a different issue.

Please use the support channels (#django IRC channel, django-users mailing list) to ask more questions.

I just made an assumption, but I just in case I am sorry about it, if this caused offence in you

And about the the #django IRC channel the django-users mailing list much help there can not be obtained

So, I am try to resolve my problems alone.

Note: See TracTickets for help on using tickets.
Back to Top