Opened 20 years ago
Closed 20 years ago
#1496 closed enhancement (fixed)
[patch] [magic-removal] Equality test doesn't work between models and model wrappers, e.g. User and UserWrapper
| Reported by: | Antti Kaihola | Owned by: | Adrian Holovaty | 
|---|---|---|---|
| Component: | Core (Other) | Version: | |
| Severity: | minor | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
If I have a model with a ForeignKey(User), I can't do this in my template:
 {% ifequal user myobject.user %} 
but must use
 {% ifequal user.id myobject.user.id %} 
Attachments (3)
Change History (11)
by , 20 years ago
| Attachment: | compare-users.diff added | 
|---|
comment:1 by , 20 years ago
| Summary: | Can't test user equality directly, must use user.id → [patch] [magic-removal] Can't test user equality directly, must use user.id | 
|---|
The above patch allows for the more intuitive user equality test syntax.
I hope the patch doesn't have bad side-effects.
comment:2 by , 20 years ago
| priority: | normal → lowest | 
|---|---|
| Severity: | normal → minor | 
| Type: | defect → enhancement | 
Ok, as I feared, it wasn't that simple. Trouble in admin. I'll try to find what's causing it.
comment:3 by , 20 years ago
By the way, the patch has problems in the change to middleware.py: it defines __eq__ twice (the second one should be __ne__).
by , 20 years ago
| Attachment: | model_wrapper_equality.diff added | 
|---|
Enhanced equality test for models; works correctly for wrappers like UserWrapper
comment:4 by , 20 years ago
| Summary: | [patch] [magic-removal] Can't test user equality directly, must use user.id → [patch] [magic-removal] Equality test doesn't work between models and model wrappers, e.g. User and UserWrapper | 
|---|
Thanks, Malcolm.
I decided to look at the problem from a broader perspective of camparing any models and their wrapper classes. I came up with a different patch, which refines the equality test at the django.db.models.Model level.
The current equality test is based on two criteria. If x is a subclass of django.db.models.Model, x == y is True if:
- isinstance(y, x.class), and
- both objects have the same primary key value.
I enhanced this logic to work correctly also for wrapper classes like django.contrib.auth.middleware.UserWrapper. The criteria are now:
- a) isinstance(y, x.class), OR b) y._meta exists and is the same object as x._meta AND
- both objects have the same primary key value.
This works, because UserWrapper passes through all attributes (_meta among them) of the wrapped User object.
I quickly tested several operations in Admin and didn't find anything broken after applying this patch.
I also wrote a unit test (see next patch).
by , 20 years ago
Unit test for enhanced equality test. Could go in tests/modeltests/wrappers/.
comment:5 by , 20 years ago
What problem did you encounter with the first patch? It would be *much* cleaner to make a change to UserWrapper than change the equality logic framework-wide.
comment:6 by , 20 years ago
FWIW UserWrapper needs to die a horrible death, or at least be changed quite a bit. See #1488 for one possible patch. A reasonable solution to that would also resovle this ticket.
comment:7 by , 20 years ago
Adrian, no problem with the first patch apart from the typo Malcolm found.
I simply noticed that a generic fix to make wrapper class equality tests work is easy to do on the model level. Is there a drawback there?
comment:8 by , 20 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | new → closed | 
Yeah, the drawback is that your patch solves a non-problem: Wrapper classes aren't a common solution, and it's overengineering to solve this on a generic level. (I can't think of any wrapper class other than the UserWrapper thing.)
And the UserWrapper problem was solved in another ticket -- #1488 and [2590] -- so I'm marking this one as fixed.
models.User and middleware.UserWrapper equality tests for contrib.auth