Django starting with 1.9 switched to using a class to provide an
iterator for the querymanager. Between 1.9 and 1.10 changes slowly
stopped referencing that function and instead started calling
_iterator_class directly.
As the functionality model-utils is patching has moved, this patch moves
the iterator logic to a class to match the changes that have been made
in Django in version 1.9.
As Django 1.8 is a LTS release that is still supported, iterator()
is retained in the InheritanceQuerySetMixin and can be removed when
support for Django 1.8 is removed. This goes for the try-except in the
import statements as well.
InheritanceQuerySet with `select_subclasses` applied as strings
raised AttributeError exception.
Adds a new test case `test_dj19_values_list_on_select_subclasses`
If a tracker is defined on an inherited model, where the parent has a ForeignKey,
the tracker will now correctly determine that the field_map takes `fk` -> `fk_id`
InheritanceQuerySetMixin._clone signature conflicts with django
ValuesQuerySet._clone code which calls super like this:
"c = super(ValuesQuerySet, self)._clone(klass, **kwargs)"
I'm not sure this test is actually useful: it's designed to show the
interaction of select_subclasses and instance_of, but I don't think
it adds much value.
By itself, .instance_of(*models) will actually call select_subclasses(*models),
which results in just those objects being cast to subclasses.
However, if you want the casting to grandchildren (which is supported only in
django 1.6+), then you may use an extra call to .select_subclasses() (without
arguments, to select all subclasses).
It doesn't deal with @kezabelle's discussion of mixed-use of select_subclasses/
instance_of, I still need to look at that.
But it does pass all current tests...
This is based upon the feature in django-polymorphic, where you
can do:
SuperClass.objects.instance_of(SubClass)
This will result in only objects of the subclass being fetched.
Note: this works with any queryset, keeping the filtering and
ordering applied there.
References #83.
Instead of patching the save method of a tracked model class, we can use
a signal handler on post_save, which means we can still pickle our model
class.
Note we can't just listen for the signal from the class we have, but
instead listen for all post_save signals. This means we actually install
a new signal handler for each tracked model class, which fires on all
model save occurrences (and returns immediately if this handler doesn't care).
We probably could improve this to have a registry of tracked models, or
something, that allows us to just install one signal handler, and filter
according to membership.
======================================================================
ERROR: test_migrate (model_utils.tests.tests.MigrationsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/user/projects/django-model-utils/model_utils/tests/tests.py", line 42, in test_migrate
call_command('migrate', fake=True)
File "/home/user/projects/django-model-utils/.tox/py27-trunk/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 167, in call_command
return klass.execute(*args, **defaults)
File "/home/user/projects/django-model-utils/.tox/py27-trunk/local/lib/python2.7/site-packages/django/core/management/base.py", line 337, in execute
output = self.handle(*args, **options)
File "/home/user/projects/django-model-utils/.tox/py27-trunk/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 138, in handle
ProjectState.from_apps(apps),
File "/home/user/projects/django-model-utils/.tox/py27-trunk/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 71, in from_apps
model_state = ModelState.from_model(model)
File "/home/user/projects/django-model-utils/.tox/py27-trunk/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 136, in from_model
e,
TypeError: Couldn't reconstruct field name_changed on tests.Monitored: MonitorField requires a "monitor" argument
When subclassing Django will copy managers from the ancestor class. Copying in turn calls `copy.copy()` which checks whether the object uses `__slots__` or `__dict__`. This could result in the manager calling `self.get_queryset()` before all models get registered with the ORM.
via a OneToOne should present the same behaviour
as the implicit ptr Django generates on
subclasses.
Thanks to Eran Rundstein for reporting the issue
and proposing the fix.
* master: (23 commits)
only accepting iterables to the when field
adding 'when' parameter to MonitorField
Update AUTHORS and changelog.
Add test to verify get_subclass() on QuerySet
Refactor to make sure get_subclass() is on QuerySet
Fixed indexing into Choices so its useful.
Fix bug with child/grandchild select_subclasses in Django 1.6+; thanks Keryn Knight.
fixed code block
Bump version for dev.
Bump version for 1.5.0 release.
Add option-groups capability to Choices.
Add Changelog note about Choices equality/addition.
Added tests to improve coverage
Alphabetised authors
Removed redundant inequality method on Choices
Moved documentation for Choices field to the right place
Corrected typo
Added self to Authors file
Added equality methods to Choices objects, and overrode + for Choices for easy concatenation with other Choices and choice-like iterables. Also wrote tests for them, and extended the readme to reflect this
Fix typo noted by @silonov
...
Conflicts:
model_utils/choices.py
There's an edge case where you might want to call get_subclass() on a
QuerySet the same way you can call get() after you have already called
various filter/exclude methods.