Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with Django internal when using pytest >= 4.2 #710

Open
debnet opened this issue Mar 13, 2019 · 21 comments
Open

Error with Django internal when using pytest >= 4.2 #710

debnet opened this issue Mar 13, 2019 · 21 comments

Comments

@debnet
Copy link

debnet commented Mar 13, 2019

Hello,

Since I updated pytest to 4.2, I've got errors inside Django internals for some tests.
These tests worked fine with 4.1 and still work fine with Django embedded unittests.

Here the error:

______________________________________________________________________________ UserPageCheckTest.test_get_view_user_by_organisation _______________________________________________________________________________

self = <drop.front.tests.test_pages.UserPageCheckTest testMethod=test_get_view_user_by_organisation>, url = <URLPattern 'user/<int:pk>/' [name='view_user']>, pk_required = True, login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:69: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:611: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:624: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:73: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:718: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:748: in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>, force_insert = False, force_update = False, using = 'default', update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:816: DatabaseError

As you can see, the error occurs when updating the last login date inside Django, but it happens only for few tests, which is very odd.

Here my current requirements:

Django==2.1.7
Pillow==5.4.1
pytest==4.3.1
pytest-cov==2.6.1
pytest-django==3.4.8
pytest-env==0.6.2

Thanks for any help or insight provided. ;)

@blueyed blueyed transferred this issue from pytest-dev/pytest Mar 13, 2019
@blueyed
Copy link
Contributor

blueyed commented Mar 13, 2019

Please git-bisect it.
Might be related to 5a9405b.
A minimal reproducible example would also be helpful.

@debnet
Copy link
Author

debnet commented Mar 15, 2019

Trying to bisect both pytest and pytest-django with no success because of the dependency between pytest>4.1 and pytest-django>3.4.4.

When bisecting pytest until 4.1.1 with latest pytest-django, I got errors with database transactions.
And bisecting pytest-django with the latest pytest leads to incompatibilities, too noisy.

As I said, the last version of pytest-django works fine with pytest==4.1.1 but not with pytest>=4.2, but it works fine with older versions of pytest-django too.

I'm kind of lost here, and I'm not a specialist unfortunalty.

@debnet
Copy link
Author

debnet commented Mar 15, 2019

By the way, ignoring the others fails and errors by git bisect and focusing on the tests which fails with the newer version tends to give the following commit as guilty of charges:

(python) [marc@marcbook pytest-django]$ git bisect good
5a9405ba8c1f2f042042c3c7e5a16679dfdb7e8a is the first bad commit
commit 5a9405ba8c1f2f042042c3c7e5a16679dfdb7e8a
Author: Daniel Hahler <github@thequod.de>
Date:   Sun Feb 3 19:54:38 2019 +0100

    Fix disabling/handling of unittest methods with pytest 4.2+ (#700)
    
    Fixes https://github.com/pytest-dev/pytest-django/issues/698.

:100644 100644 c73d1107d289aea3582665968fea6d45da3c0031 413fac5b2cd2da30970d6345ed700a6114a5c688 M	.travis.yml
:040000 040000 daa7c0b05d433bfa5b737cc16cca94c5dc68899b 3738a9fd2957b249bf78d1900980ccf35326d390 M	pytest_django
:100755 100755 c6e66fd87b0fc2db60903513f202917f7c7deec8 d38a89020a1ce66d38e966888e80e79f9251cad0 M	setup.py
:040000 040000 5439ab125e9feca105cfeff3845c6f9772183e6b 9112fbe0f45ff011b313c5999c48d8ab44a140f4 M	tests
:100644 100644 0582d0f7786f91712502283d83b805c9f4db5b4b 1265bda1d4dd4882f1f222ea3bad388ca6852787 M	tox.ini```

@blueyed
Copy link
Contributor

blueyed commented Mar 15, 2019

Thanks for the info - this is what I suspected.

  1. Can you provide a minimal example to reproduce this?
  2. Does it this fail with latest pytest/pytest-django if you force this to be True? 5a9405b#diff-87c0c2cb9262dd6c4384e140e51d8e64R54

@debnet
Copy link
Author

debnet commented Mar 19, 2019

OK, thanks. I'll try the second tomorrow and give you a feedback soon.
For the first, I encountered the same issue in another project, I will try to remove unnecessary parts.

@debnet
Copy link
Author

debnet commented Apr 4, 2019

Sorry for the delay. I confirm the tests pass with this constant forced to True.
But previously passing tests in my case now fail (and some are in error due to MPTT). :D
Do you have any clue?

@evenicoulddoit
Copy link

I also just came across this when bumping dependencies for my DRF package.

I didn't manage to bisect, only to confirm that the issue was definitely present in 4.2.0, and not in 4.1.1. I was going to look into it further, and started reviewing the changes between said versions, but before going deeper I decided to bump this package to its latest, and it worked fine, so I guess I'd consider the issue solved.

The test failure I had only occurred when running the entire suite, not on a subset. I was using the Django override_settings() decorator to provide settings on a per-test basis, and the non-overloaded test was the one which was failing, which suggests some kind of setup/teardown issues. Before bumping the versions I was able to fix the issue by applying the decorator with the setting I wanted to test missing, but that would have been an ugly solution.

I could apply a bisect should you need, but I'd consider this closed?

@blueyed
Copy link
Contributor

blueyed commented Apr 21, 2019

@debnet
Please try it with latest pytest, too.

@debnet
Copy link
Author

debnet commented Apr 23, 2019

Same error with pytest==4.4.1.

@blueyed
Copy link
Contributor

blueyed commented Apr 23, 2019

@debnet
Thanks for the update.
Can you provide a minimal example?

It would be great to have it in a test for pytest-django, e.g. based on pytest's testdir fixture.

@blueyed
Copy link
Contributor

blueyed commented May 30, 2019

Sorry for the delay. I confirm the tests pass with this constant forced to True.

Interesting.

But previously passing tests in my case now fail (and some are in error due to MPTT). :D
Do you have any clue?

How do those fail then?

The problem here is that pytest itself added handling of unittest classes, but apparently it behaves a bit different.

We really need a way to reproduce this to being able to fix this. The best would be to have a failing test in pytest-django's testsuite, of course.
I am not using unittest myself typically, but could imagine that e.g. using pytest with Django's own tests might also run into this (I've started experimenting with using pytest there, but there is not much interest apparently (https://code.djangoproject.com/ticket/30415)).

@blueyed
Copy link
Contributor

blueyed commented May 30, 2019

(likely only related to when using --pdb)

Just found this: https://code.djangoproject.com/ticket/27391 ("Support unittest.TestCase.debug() method"), which might be related?!

Related code in pytest: https://github.com/blueyed/pytest/blob/ace3a02cd485d1024a07d93dc8d58708a882587e/src/_pytest/unittest.py#L220-L227

pytest-django unconditionally sets cls.debug: https://github.com/blueyed/pytest-django/blob/ec5c4e9ec1fa8551fdd910365874ffd8a97e1a12/pytest_django/plugin.py#L523-L537

@blueyed
Copy link
Contributor

blueyed commented May 30, 2019

@debnet
In case you want to investigate, please use master - I've revisited some code in this area/regard (#740).

In the long run I think pytest-django will require pytest >= 4.2, which means that a lot of this code will be removed here, but might just mean that we need to fix this in pytest then instead, or some smaller fix in pytest-django (if it turns out to be a bug after all).

@blueyed
Copy link
Contributor

blueyed commented Jun 4, 2019

Likely related issue in pytest: pytest-dev/pytest#5390

@debnet
Copy link
Author

debnet commented Jun 16, 2019

Still have the issue with the latest release of pytest.
Not tested with master though.
I will try to provide a minimal test case when I could.

@debnet
Copy link
Author

debnet commented Jul 8, 2019

Error is still present in 5.0.1 for information.

@debnet
Copy link
Author

debnet commented Sep 30, 2019

Still present in 5.2.0.

@debnet
Copy link
Author

debnet commented Oct 7, 2019

Can't give you a small testcase at the moment but here the complete trace from pytest:

=============================== test session starts ===============================
platform linux -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
Django settings: drop.settings (from ini file)
rootdir: /home/marc/Git/drop, inifile: pytest.ini
plugins: cov-2.8.1, django-3.5.1, env-0.6.2
collected 540 items                                                               

drop/core/tests/test_admin.py ............................................. [  8%]
.......................................................FFFFF                [ 19%]
drop/core/tests/test_api.py ............................................... [ 28%]
........................................................................... [ 42%]
........................................................................... [ 55%]
........................................................................... [ 69%]
.........................                                                   [ 74%]
drop/front/tests/test_pages.py ............................................ [ 82%]
........................................................................... [ 96%]
...........FFFFFFFF                                                         [100%]

==================================== FAILURES =====================================
__________ AttributeAdminPageCheckTest.test_admin_get_drop_attribute_add __________

s = <drop.core.tests.test_admin.AttributeAdminPageCheckTest testMethod=test_admin_get_drop_attribute_add>
u = <URLPattern 'add/' [name='drop_attribute_add']>, p = False

>   setattr(test, f'test_admin_get_{url.name}', lambda s, u=url, p=pk_required: s.get(u, p))

drop/core/tests/test_admin.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/core/tests/test_admin.py:38: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
________ AttributeAdminPageCheckTest.test_admin_get_drop_attribute_change _________

s = <drop.core.tests.test_admin.AttributeAdminPageCheckTest testMethod=test_admin_get_drop_attribute_change>
u = <URLPattern '<path:object_id>/change/' [name='drop_attribute_change']>
p = True

>   setattr(test, f'test_admin_get_{url.name}', lambda s, u=url, p=pk_required: s.get(u, p))

drop/core/tests/test_admin.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/core/tests/test_admin.py:38: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
______ AttributeAdminPageCheckTest.test_admin_get_drop_attribute_changelist _______

s = <drop.core.tests.test_admin.AttributeAdminPageCheckTest testMethod=test_admin_get_drop_attribute_changelist>
u = <URLPattern '' [name='drop_attribute_changelist']>, p = False

>   setattr(test, f'test_admin_get_{url.name}', lambda s, u=url, p=pk_required: s.get(u, p))

drop/core/tests/test_admin.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/core/tests/test_admin.py:38: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
________ AttributeAdminPageCheckTest.test_admin_get_drop_attribute_delete _________

s = <drop.core.tests.test_admin.AttributeAdminPageCheckTest testMethod=test_admin_get_drop_attribute_delete>
u = <URLPattern '<path:object_id>/delete/' [name='drop_attribute_delete']>
p = True

>   setattr(test, f'test_admin_get_{url.name}', lambda s, u=url, p=pk_required: s.get(u, p))

drop/core/tests/test_admin.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/core/tests/test_admin.py:38: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
________ AttributeAdminPageCheckTest.test_admin_get_drop_attribute_history ________

s = <drop.core.tests.test_admin.AttributeAdminPageCheckTest testMethod=test_admin_get_drop_attribute_history>
u = <URLPattern '<path:object_id>/history/' [name='drop_attribute_history']>
p = True

>   setattr(test, f'test_admin_get_{url.name}', lambda s, u=url, p=pk_required: s.get(u, p))

drop/core/tests/test_admin.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/core/tests/test_admin.py:38: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
_________ AgreementPageCheckTest.test_get_change_agreement_by_corporation _________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_change_agreement_by_corporation>
url = <URLPattern 'agreement/<int:pk>/edit/' [name='change_agreement']>
pk_required = True, login_required = True

    def test_get_by_corporation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
________ AgreementPageCheckTest.test_get_change_agreement_by_organisation _________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_change_agreement_by_organisation>
url = <URLPattern 'agreement/<int:pk>/edit/' [name='change_agreement']>
pk_required = True, login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
_________ AgreementPageCheckTest.test_get_delete_agreement_by_corporation _________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_delete_agreement_by_corporation>
url = <URLPattern 'agreement/<int:pk>/delete/' [name='delete_agreement']>
pk_required = True, login_required = True

    def test_get_by_corporation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
________ AgreementPageCheckTest.test_get_delete_agreement_by_organisation _________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_delete_agreement_by_organisation>
url = <URLPattern 'agreement/<int:pk>/delete/' [name='delete_agreement']>
pk_required = True, login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
__________ AgreementPageCheckTest.test_get_list_agreement_by_corporation __________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_list_agreement_by_corporation>
url = <URLPattern 'agreement/' [name='list_agreement']>, pk_required = False
login_required = True

    def test_get_by_corporation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
_________ AgreementPageCheckTest.test_get_list_agreement_by_organisation __________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_list_agreement_by_organisation>
url = <URLPattern 'agreement/' [name='list_agreement']>, pk_required = False
login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
__________ AgreementPageCheckTest.test_get_view_agreement_by_corporation __________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_view_agreement_by_corporation>
url = <URLPattern 'agreement/<int:pk>/' [name='view_agreement']>
pk_required = True, login_required = True

    def test_get_by_corporation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
_________ AgreementPageCheckTest.test_get_view_agreement_by_organisation __________

self = <drop.front.tests.test_pages.AgreementPageCheckTest testMethod=test_get_view_agreement_by_organisation>
url = <URLPattern 'agreement/<int:pk>/' [name='view_agreement']>
pk_required = True, login_required = True

    def test_get_by_organisation(self, url=url, pk_required=pk_required, login_required=login_required):
>       base_url, view_name = self.get(url, pk_required, login_required)

drop/front/tests/test_pages.py:74: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
drop/front/tests/test_pages.py:49: in get
    self.client.force_login(self.user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:619: in force_login
    self._login(user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/test/client.py:632: in _login
    login(request, user, backend)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/__init__.py:132: in login
    user_logged_in.send(sender=user.__class__, request=request, user=user)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in send
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/dispatch/dispatcher.py:175: in <listcomp>
    for receiver in self._live_receivers(sender)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/models.py:20: in update_last_login
    user.save(update_fields=['last_login'])
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/contrib/auth/base_user.py:66: in save
    super().save(*args, **kwargs)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:741: in save
    force_update=force_update, update_fields=update_fields)
../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:779: in save_base
    force_update, using, update_fields,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <User: admin>, raw = False, cls = <class 'drop.core.models.base.User'>
force_insert = False, force_update = False, using = 'default'
update_fields = frozenset({'last_login'})

    def _save_table(self, raw=False, cls=None, force_insert=False,
                    force_update=False, using=None, update_fields=None):
        """
        Do the heavy-lifting involved in saving. Update or insert the data
        for a single table.
        """
        meta = cls._meta
        non_pks = [f for f in meta.local_concrete_fields if not f.primary_key]
    
        if update_fields:
            non_pks = [f for f in non_pks
                       if f.name in update_fields or f.attname in update_fields]
    
        pk_val = self._get_pk_val(meta)
        if pk_val is None:
            pk_val = meta.pk.get_pk_value_on_save(self)
            setattr(self, meta.pk.attname, pk_val)
        pk_set = pk_val is not None
        if not pk_set and (force_update or update_fields):
            raise ValueError("Cannot force an update in save() with no primary key.")
        updated = False
        # If possible, try an UPDATE. If that doesn't update anything, do an INSERT.
        if pk_set and not force_insert:
            base_qs = cls._base_manager.using(using)
            values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False)))
                      for f in non_pks]
            forced_update = update_fields or force_update
            updated = self._do_update(base_qs, using, pk_val, values, update_fields,
                                      forced_update)
            if force_update and not updated:
                raise DatabaseError("Forced update did not affect any rows.")
            if update_fields and not updated:
>               raise DatabaseError("Save with update_fields did not affect any rows.")
E               django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

../../.pyenv/versions/drop/lib/python3.7/site-packages/django/db/models/base.py:855: DatabaseError
================================ warnings summary =================================
drop/front/tests/test_pages.py::test::test_get_change_agreement_by_corporation
  /home/marc/.pyenv/versions/drop/lib/python3.7/site-packages/compressor/filters/base.py:123: RemovedInDjango31Warning: The FILE_CHARSET setting is deprecated. Starting with Django 3.1, all files read from disk must be UTF-8 encoded.
    settings.FILE_CHARSET if settings.is_overridden('FILE_CHARSET') else

-- Docs: https://docs.pytest.org/en/latest/warnings.html
=================== 13 failed, 527 passed, 1 warnings in 55.42s ===================

And the same result with Django unittest instead:

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
----------------------------------------------------------------------
Ran 527 tests in 40.361s

OK
Destroying test database for alias 'default'...

@debnet
Copy link
Author

debnet commented Oct 7, 2019

As you can see, Django doesn't fail any of the tests whereas some test failed in pytest but always at the same spot (inside Django internals).

@blueyed
Copy link
Contributor

blueyed commented Oct 7, 2019

@debnet

  1. Does running pytest -k test_admin_get_drop_attribute_add fail the test then (always) again? Or does it depend on other tests being run? What fixtures is the test using? Can you provide the full test_admin_get_drop_attribute_add test?
  2. What args/options are you using to run pytest?
  3. Can you show the output with --tb=full --showlocals?

@blueyed
Copy link
Contributor

blueyed commented Oct 16, 2019

(likely only related to when using --pdb)

Are you using that? (#771)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants