This reverts commit 2cd0edaa47.
This commit was the cause of a memory leak. See ticket for more details.
Thanks Anssi Kääriäinen for identifying the source of the bug.
Model.save() will use UPDATE - if not updated - INSERT instead of
SELECT - if found UPDATE else INSERT. This should save a query when
updating, but will cost a little when inserting model with PK set.
Also fixed#17341 -- made sure .save() commits transactions only after
the whole model has been saved. This wasn't the case in model
inheritance situations.
The save_base implementation was refactored into multiple methods.
A typical chain for inherited save is:
save_base()
_save_parents(self)
for each parent:
_save_parents(parent)
_save_table(parent)
_save_table(self)
The sql/query.py add_q method did a lot of where/having tree hacking to
get complex queries to work correctly. The logic was refactored so that
it should be simpler to understand. The new logic should also produce
leaner WHERE conditions.
The changes cascade somewhat, as some other parts of Django (like
add_filter() and WhereNode) expect boolean trees in certain format or
they fail to work. So to fix the add_q() one must fix utils/tree.py,
some things in add_filter(), WhereNode and so on.
This commit also fixed add_filter to see negate clauses up the path.
A query like .exclude(Q(reversefk__in=a_list)) didn't work similarly to
.filter(~Q(reversefk__in=a_list)). The reason for this is that only
the immediate parent negate clauses were seen by add_filter, and thus a
tree like AND: (NOT AND: (AND: condition)) will not be handled
correctly, as there is one intermediary AND node in the tree. The
example tree is generated by .exclude(~Q(reversefk__in=a_list)).
Still, aggregation lost connectors in OR cases, and F() objects and
aggregates in same filter clause caused GROUP BY problems on some
databases.
Fixed#17600, fixed#13198, fixed#17025, fixed#17000, fixed#11293.
Before there was need to have both .relabel_aliases() and .clone() for
many structs. Now there is only relabeled_clone() for those structs
where alias is the only mutable attribute.
Since "unless managed" now means "if database-level autocommit",
committing or rolling back doesn't have any effect.
Restored transactional integrity in a few places that relied on
automatically-started transactions with a transitory API.
enter_transaction_management() was nearly always followed by managed().
In three places it wasn't, but they will all be refactored eventually.
The "forced" keyword argument avoids introducing behavior changes until
then.
This is mostly backwards-compatible, except, of course, for managed
itself. There's a minor difference in _enter_transaction_management:
the top self.transaction_state now contains the new 'managed' state
rather than the previous one. Django doesn't access
self.transaction_state in _enter_transaction_management.
There were a couple of errors in ._dirty flag handling:
* It started as None, but was never reset to None.
* The _dirty flag was sometimes used to indicate if the connection
was inside transaction management, but this was not done
consistently. This also meant the flag had three separate values.
* The None value had a special meaning, causing for example inability
to commit() on new connection unless enter/leave tx management was
done.
* The _dirty was tracking "connection in transaction" state, but only
in managed transactions.
* Some tests never reset the transaction state of the used connection.
* And some additional less important changes.
This commit has some potential for regressions, but as the above list
shows, the current situation isn't perfect either.
When iteration over a queryset raised an exception, the result cache
remained initialized with an empty list, so subsequent iterations returned
an empty list instead of raising an exception
Querying the reverse side of nullable to_field relation, where both
sides can contain null values resulted in incorrect results. The reason
was not detecting '' as NULL.
Refs #17541
There was a regression in case two models inherited the same parent,
and one contained a foreign key to other. When select_related travelled
the foreign key the other model reused the parent join made by the
first model. This was likely caused by Query.join_parent_model()
addition in commit 68985db482.
Thanks to Trac alias loic84 for report & tests.
The join promote=True was over-aggressive in select_related handling.
After that was removed, the only other user was query.combine(). That
use case is very easy to handle locally, so there is no more need for
the join(promote=True) flag.
Refs #19849.
This controls whether or not a database level cosntraint is created. This is useful in a few specialized circumstances, but in general should not be used!
The refactoring mainly concentrates on making sure the inner and outer
query agree about the split position. The split position is where the
multijoin happens, and thus the split position also determines the
columns used in the "WHERE col1 IN (SELECT col2 from ...)" condition.
This commit fixes a regression caused by #10790 and commit
69597e5bcc. The regression was caused
by wrong cols in the split position.
Thanks Carl Meyer for the review.
Squashed commit of the following:
commit 4f290bdb60
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Wed Feb 13 21:21:30 2013 +0100
Used '0:00' instead of 'UTC' which doesn't always exist in Oracle.
Thanks Ian Kelly for the suggestion.
commit 01b6366f3c
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Wed Feb 13 13:38:43 2013 +0100
Made tzname a parameter of datetime_extract/trunc_sql.
This is required to work around a bug in Oracle.
commit 924a144ef8
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Wed Feb 13 14:47:44 2013 +0100
Added support for parameters in SELECT clauses.
commit b4351d2890
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Feb 11 22:30:22 2013 +0100
Documented backwards incompatibilities in the two previous commits.
commit 91ef84713c
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Feb 11 09:42:31 2013 +0100
Used QuerySet.datetimes for the admin's date_hierarchy.
commit 0d0de288a5
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Feb 11 09:29:38 2013 +0100
Used QuerySet.datetimes in date-based generic views.
commit 9c0859ff7c
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:43:25 2013 +0100
Implemented QuerySet.datetimes on Oracle.
commit 68ab511a4f
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:43:14 2013 +0100
Implemented QuerySet.datetimes on MySQL.
commit 22d52681d3
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:42:29 2013 +0100
Implemented QuerySet.datetimes on SQLite.
commit f6800fd04c
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:43:03 2013 +0100
Implemented QuerySet.datetimes on PostgreSQL.
commit 0c829c23f4
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:41:08 2013 +0100
Added datetime-handling infrastructure in the ORM layers.
commit 104d82a777
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Feb 11 10:05:55 2013 +0100
Updated null_queries tests to avoid clashing with the __second lookup.
commit c01bbb3235
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 23:07:41 2013 +0100
Updated tests of .dates().
Replaced .dates() by .datetimes() for DateTimeFields.
Replaced dates with datetimes in the expected output for DateFields.
commit 50fb7a5246
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 21:40:09 2013 +0100
Updated and added tests for QuerySet.datetimes.
commit a8451a5004
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 22:34:46 2013 +0100
Documented the new time lookups and updated the date lookups.
commit 29413eab2b
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Sun Feb 10 16:15:49 2013 +0100
Documented QuerySet.datetimes and updated QuerySet.dates.
value_annotation isn't very well defined. Before this change, setting it
to datetime.datetime could silently reverse the behavior of isnull
lookups. This commit doesn't have any consequences on the current code.
It's just a safeguard for future ORM hackers.
Previously it was possible to call clear_ordering without the
force_empty argument. The result was that the query was still ordered
by model's meta ordering if that was defined. By making the arg
mandatory it will be easier to spot possible errors caused by assuming
clear_ordering will remove all ordering.
Thanks to Dylan Klomparens for the suggestion. Refs #19720.
When a query had a complex where condition (a condition targeting more
than the base table) a subquery was used for deletion. However, the
query had default ordering from the model's meta and Oracle doesn't
work with ordered subqueries.
The regression was caused by fast-path deletion code introduced in
1cd6e04cd4 for fixing #18676.
Thanks to Dylan Klomparens for the report.
This undocumented method was used in an old version of the admin, is
totally untested and hails from 2008. Although it's listed in the
"public methods" section, as it's not documented or used I don't think
it needs a deprecation path.
If we think it's useful I'll write some tests/docs for it instead...
Thanks a lot to everybody participating in developing this feature.
The patch was developed by multiple people, at least Trac aliases
tonnzor, jimmysong, Fandekasp and slurms.
Stylistic changes added by committer.
The class wasn't used anywhere except in RelatedObject.bind(), which
wasn't used anywhere. The class had one method defined as
NotImplemented, yet the class wasn't subclassed anywhere. In short, the
class was dead code.
In a normal relational construct, if you're listening for an event
that signals a child was deleted, you dont expect that the parent
was deleted already.
This change ensures that post_delete signals are fired immediately
after objects are deleted in the graph.
The original problem was that queryset cloning was really expensive
when filtering with F() clauses. The __deepcopy__ went too deep copying
_meta attributes of the models used. To fix this the use of
__deepcopy__ in qs cloning was removed.
This commit results in some speed improvements across the djangobench
benchmark suite. Most query_* tests are 20-30% faster, save() is 50%
faster and finally complex filtering situations can see 2x to order
of magnitude improvments.
Thanks to Suor, Alex and lrekucki for valuable feedback.
The guarantee that no queries will be made when accessing results is
done by new EmptyWhere class which is used for query.where and having.
Thanks to Simon Charette for reviewing and valuable suggestions.
When &'ing or |'ing querysets, wrong values could be cached, and crashes
could happen.
Thanks Marc Tamlyn for figuring out the problem and writing the patch.
The added promotion logic is based on promoting any joins used in only
some of the childs of an OR clause unless the join existed before the
OR clause addition.
The ORM didn't reuse joins for direct foreign key traversals when using
chained filters. For example:
qs.filter(fk__somefield=1).filter(fk__somefield=2))
produced two joins.
As a bonus, reverse onetoone filters can now reuse joins correctly
The regression was caused by the join() method refactor in commit
68847135bc
Thanks for Simon Charette for spotting some issues with the first draft
of the patch.
This is necessary because get_model() checks are case insensitive, and if the swapable check isn't, the
swappable logic gets tied up in knots with models that are partially swapped out.
Thanks to chris@cogdon.org for the report and extensive analysis, and Preston for his work on the draft patch.
This is a rather large refactoring. The "lookup traversal" code was
splitted out from the setup_joins. There is now names_to_path() method
which does the lookup traveling, the actual work of setup_joins() is
calling names_to_path() and then adding the joins found into the query.
As a side effect it was possible to remove the "process_extra"
functionality used by genric relations. This never worked for left
joins. Now the extra restriction is appended directly to the join
condition instead of the where clause.
To generate the extra condition we need to have the join field
available in the compiler. This has the side-effect that we need more
ugly code in Query.__getstate__ and __setstate__ as Field objects
aren't pickleable.
The join trimming code got a big change - now we trim all direct joins
and never trim reverse joins. This also fixes the problem in #10790
which was join trimming in null filter cases.
The trim argument was used by split_exclude() only to trim the last
join from the given lookup. It is cleaner to just trim the last part
from the lookup in split_exclude() directly so that there is no need
to burden add_filter() with the logic needed for only split_exclude().
F() expressions reuse joins like any lookup in a .filter() call -
reuse multijoins generated in the same .filter() call else generate
new joins. Also, lookups can now reuse joins generated by F().
This change is backwards incompatible, but it is required to prevent
dict randomization from generating different queries depending on
.filter() kwarg ordering. The new way is also more consistent in how
joins are reused.
The select_related code got confused when it needed to travel a
reverse relation to a model which had different parent than the
originally travelled relation.
Thanks to Trac aliases shauncutts for report and ungenio for original
patch (committed patch is somewhat modified version of that).
The problem is the same as in #10888 which was reintroduced when
bulk_insert was added. Thanks to Jani Tiainen for report, patch and
also testing the final patch on Oracle GIS.
This is the start of a deprecation path for the depth kwarg on
select_related. Removing this will allow us to update select_related so
it chains properly and have an API similar to prefetch_related.
Thanks to Marc Tamlyn for spearheading and initial patch.
refs #16855
The dupe avoidance logic was removed as it doesn't seem to do anything,
it is complicated, and it has nearly zero documentation.
The removal of dupe_avoidance allowed for refactoring of both the
implementation and signature of Query.join(). This refactoring cascades
again to some other parts. The most significant of them is the changes
in qs.combine(), and compiler.select_related_descent().
There was a potential data-loss issue involved -- when clearing
instance's m2m assignments it was possible some other instance's
m2m data was deleted instead.
This commit also improved None handling for to_field cases.
The Query.select and Query.select_fields were collapsed into one list
because the attributes had to be always in sync. Now that they are in
one attribute it is impossible to edit them out of sync.
Similar collapse was done for Query.related_select_cols and
Query.related_select_fields.
There was a bug introduced in #18676 which caused fast-path deletes
implemented as "DELETE WHERE pk IN <subquery>" to fail if the SELECT
clause contained additional stuff (for example extra() and annotate()).
Thanks to Trac alias pressureman for spotting this regression.
Done for consistency with Q() expressions and QuerySet combining. This
will allow usage of '&' and '|' as boolean logical operators in the
future. Refs #16211.
RETURNING is an extension of the SQL standard, which is not implemented
the same by all databases. Allow DatabaseOperations.return_insert_id to
return a None to allow for other 3rd party backends with a different
implementation.
Objects can be fast-path deleted if there are no signals, and there are
no further cascades. If fast-path is taken, the objects do not need to
be loaded into memory before deletion.
Thanks to Jeremy Dunck, Simon Charette and Alex Gaynor for reviewing
the patch.
Thanks to the many people that contributed to the development and review of
this patch, including (but not limited to) Jacob Kaplan-Moss, Anssi
Kääriäinen, Ramiro Morales, Preston Holmes, Josh Ourisman, Thomas Sutton,
and Roger Barnes, as well as the many, many people who have contributed to
the design discussion around this ticket over many years.
Squashed commit of the following:
commit d84749a0f0
Merge: 531e7717c11b1a
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Wed Sep 26 18:37:04 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit 531e7715da
Merge: 29d1abb1f84b04
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Wed Sep 26 07:09:23 2012 +0800
Merged recent trunk changes.
commit 29d1abbe35
Merge: 8a527dd54c81a1
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Sep 24 07:49:46 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit 8a527dda13
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Sep 24 07:48:05 2012 +0800
Ensure sequences are reset correctly in the presence of swapped models.
commit e2b6e22f29
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 23 17:53:05 2012 +0800
Modifications to the handling and docs for auth forms.
commit 98aba856b5
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 23 15:28:57 2012 +0800
Improved error handling and docs for get_user_model()
commit 0229209c84
Merge: 6494bf98599f64
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 23 14:50:11 2012 +0800
Merged recent Django trunk changes.
commit 6494bf91f2
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Sep 17 21:38:44 2012 +0800
Improved validation of swappable model settings.
commit 5a04cde342
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Sep 17 07:15:14 2012 +0800
Removed some unused imports.
commit ffd535e413
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 20:31:28 2012 +0800
Corrected attribute access on for get_by_natural_key
commit 913e1ac84c
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 20:12:34 2012 +0800
Added test for proxy model safeguards on swappable models.
commit 280bf19e94
Merge: dbb3900935a863
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 18:16:49 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit dbb3900775
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 18:09:27 2012 +0800
Fixes for Python 3 compatibility.
commit dfd72131d8
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 15:54:30 2012 +0800
Added protection against proxying swapped models.
commit abcb027190
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 15:11:10 2012 +0800
Cleanup and documentation of AbstractUser base class.
commit a9491a8776
Merge: fd8bb4e08bcb4a
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 14:46:49 2012 +0800
Merge commit '08bcb4aec1ed154cefc631b8510ee13e9af0c19d' into t3011
commit fd8bb4e3e4
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 14:20:14 2012 +0800
Documentation improvements coming from community review.
commit b550a6d06d
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 13:52:47 2012 +0800
Refactored skipIfCustomUser into the contrib.auth tests.
commit 52a02f1110
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 13:46:10 2012 +0800
Refactored common 'get' pattern into manager method.
commit b441a6bbc7
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 16 13:41:33 2012 +0800
Added note about backwards incompatible change to admin login messages.
commit 08bcb4aec1
Author: Anssi Kääriäinen <akaariai@gmail.com>
Date: Sat Sep 15 18:30:33 2012 +0300
Splitted User to AbstractUser and User
commit d9f5e5addb
Author: Anssi Kääriäinen <akaariai@gmail.com>
Date: Sat Sep 15 18:30:02 2012 +0300
Reworked REQUIRED_FIELDS + create_user() interaction
commit 579f152e4a
Merge: 918497293e6733
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 15 20:18:37 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit 918497218c
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 15 20:18:19 2012 +0800
Deprecate AUTH_PROFILE_MODULE and get_profile().
commit 334cdfc1bb
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 15 20:00:12 2012 +0800
Added release notes for new swappable User feature.
commit 5d7bb22e8d
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 15 19:59:49 2012 +0800
Ensure swapped models can't be queried.
commit 57ac6e3d32
Merge: f2ec915abfba3b
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 15 14:31:54 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit f2ec915b20
Merge: 19526565e99a3d
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 9 08:29:51 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit 19526563b5
Merge: 2c5e833c4aa26a
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 9 08:22:26 2012 +0800
Merge recent changes from master.
commit 2c5e833a30
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 9 07:53:46 2012 +0800
Corrected admin_views tests following removal of the email fallback on admin logins.
commit 20d1892491
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sun Sep 9 01:00:37 2012 +0800
Added conditional skips for all tests dependent on the default User model
commit 40ea8b8882
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 8 23:47:02 2012 +0800
Added documentation for REQUIRED_FIELDS in custom auth.
commit e6aaf65970
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Sat Sep 8 23:20:02 2012 +0800
Added first draft of custom User docs.
Thanks to Greg Turner for the initial text.
commit 75118bd242
Author: Thomas Sutton <me@thomas-sutton.id.au>
Date: Mon Aug 20 11:17:26 2012 +0800
Admin app should not allow username discovery
The admin app login form should not allow users to discover the username
associated with an email address.
commit d088b3af58
Author: Thomas Sutton <me@thomas-sutton.id.au>
Date: Mon Aug 20 10:32:13 2012 +0800
Admin app login form should use swapped user model
commit 7e82e83d67
Merge: e29c01039aa890
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Fri Sep 7 23:45:03 2012 +0800
Merged master changes.
commit e29c010beb
Merge: 8e3fd7030bdf22
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Aug 20 13:12:57 2012 +0800
Merge remote-tracking branch 'django/master' into t3011
commit 8e3fd703d0
Merge: 507bb5026e0ba0
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Aug 20 13:09:09 2012 +0800
Merged recent changes from trunk.
commit 507bb50a92
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Jun 4 20:41:37 2012 +0800
Modified auth app so that login with alternate auth app is possible.
commit dabe362836
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Jun 4 20:10:51 2012 +0800
Modified auth management commands to handle custom user definitions.
commit 7cc0baf89d
Author: Russell Keith-Magee <russell@keith-magee.com>
Date: Mon Jun 4 14:17:28 2012 +0800
Added model Meta option for swappable models, and made auth.User a swappable model
Thanks to Jeremy Dunck for pointing out the problem with this change. If in a
single transaction, the master deletes a record and then get_or_creates a
similar record, under the new behavior the get_or_create would find the record
in the slave db and fail to re-create it, leaving the record nonexistent, which
violates the contract of get_or_create that the record should always exist
afterwards. We need to do everything against the master here in order to ensure
correctness.
This reverts commit 901af86550.
When doing deeper than one level select_related() + only queries(), the
code introduced in b6c356b7bb errored
incorrectly.
Thanks to mrmachine for report & test case.
In an ideal world, nothing except django.db.models.query should have to
import stuff from django.models.sql.*. A few things were needing to get
hold of sql.constants.LOOKUP_SEP, so this commit moves it up to
django.db.models.constants.LOOKUP_SEP.
There are still a couple of places (admin) poking into sql.* to get
QUERY_TERMS, which is unfortunate, but a slightly different issue and
harder to adjust.
Unlike other model fields, the newly introduced (1.4)
GenericIPAddressField did not accept verbose_name and name as the
first positional arguments. This commit fixes it.
Thanks Dan McGee for the report and the patch.
The joins for nested nullable foreign keys were often created as INNER
when they should have been OUTER joins. The reason was that only the
first join in the chain was promoted correctly. There were also issues
with select_related etc.
The basic structure for this problem was:
A -[nullable]-> B -[nonnull]-> C
And the basic problem was that the A->B join was correctly LOUTER,
the B->C join not.
The major change taken in this patch is that now if we promote a join
A->B, we will automatically promote joins B->X for all X in the query.
Also, we now make sure there aren't ever join chains like:
a LOUTER b INNER c
If the a -> b needs to be LOUTER, then the INNER at the end of the
chain will cancel the LOUTER join and we have a broken query.
Sebastian reported this problem and did also major portions of the
patch.
The ORM generated a query with INNER JOIN instead of LEFT OUTER JOIN
in a somewhat complicated case. The main issue was that there was a
chain of nullable FK -> non-nullble FK, and the join promotion logic
didn't see the need to promote the non-nullable FK even if the
previous nullable FK was already promoted to LOUTER JOIN. This resulted
in a query like a LOUTER b INNER c, which incorrectly prunes results.
Deferred models now automatically update only the fields which are
loaded from the db (with .only() or .defer()). In addition, any field
set manually after the load is updated on save.
* Renamed the __unicode__ methods
* Applied the python_2_unicode_compatible decorator
* Removed the StrAndUnicode mix-in that is superseded by
python_2_unicode_compatible
* Kept the __unicode__ methods in classes that specifically
test it under Python 2
* Renamed smart_unicode to smart_text (but kept the old name under
Python 2 for backwards compatibility).
* Renamed smart_str to smart_bytes.
* Re-introduced smart_str as an alias for smart_text under Python 3
and smart_bytes under Python 2 (which is backwards compatible).
Thus smart_str always returns a str objects.
* Used the new smart_str in a few places where both Python 2 and 3
want a str.