Code

Opened 5 years ago

Closed 5 years ago

Last modified 3 years ago

#10953 closed (fixed)

Proxy model of a proxy model is of incorrect type.

Reported by: mrmachine Owned by: jacob
Component: Database layer (models, ORM) Version: master
Severity: Keywords: proxy type foreign key
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

If you proxy a model that is already a proxy, it will be of the same type as the first proxy. If the second proxy is used in a foreign key, you will not be able to create any model objects which have a value for that foreign key because they will fail the type check validation.

This means we can only ever proxy actual models, and cannot create a base proxy model to subclass as necessary.

# models.

from django.contrib.auth import models as auth_models
from django.db import models

class User1(auth_models.User):
	class Meta:
		proxy = True

class User2(User1):
	class Meta:
		proxy = True

class Something(models.Model):
	user = models.ForeignKey(User2)

# interactive shell.

>>> from myapp.models import User1, User2, Something

>>> type(User1.objects.get(username='admin'))
<class 'myapp.models.User1'>

>>> type(User2.objects.get(username='admin'))
<class 'myapp.models.User1'>

>>> Something.objects.create(user=User2.objects.get(username='admin'))
Traceback (most recent call last):
  File "<console>", line 1, in ?
  File "/path/to/django/db/models/manager.py", line 126, in create
    return self.get_query_set().create(**kwargs)
  File "/path/to/django/db/models/query.py", line 283, in create
    obj = self.model(**kwargs)
  File "/path/to/django/db/models/base.py", line 308, in __init__
    setattr(self, field.name, rel_obj)
  File "/path/to/django/db/models/fields/related.py", line 270, in __set__
    raise ValueError('Cannot assign "%r": "%s.%s" must be a "%s" instance.' %
ValueError: Cannot assign "<User1: admin>": "Something.user" must be a "User2" instance.

Attachments (2)

proxy-proxy.diff (1.8 KB) - added by Alex 5 years ago.
proxy-proxy.2.diff (3.2 KB) - added by Alex 5 years ago.

Download all attachments as: .zip

Change History (8)

comment:1 Changed 5 years ago by mrmachine

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Looks like the incorrect model is being assigned to the manager (or simply being copied unchanged from the base proxy class). This causes any querysets from the manager to create model objects of the wrong type.

>>> User1.objects.model
<class 'myapp.models.User1'>
>>> User2.objects.model
<class 'myapp.models.User1'>

Changed 5 years ago by Alex

comment:2 Changed 5 years ago by Alex

  • Has patch set
  • milestone set to 1.1
  • Triage Stage changed from Unreviewed to Accepted

Changed 5 years ago by Alex

comment:3 Changed 5 years ago by mitsuhiko

  • Owner changed from nobody to mitsuhiko

The fix for this ticket, including the one for #10955 which is related is attached to my github repo: http://github.com/mitsuhiko/django/tree/ticket-10953

comment:4 Changed 5 years ago by jacob

  • Owner changed from mitsuhiko to jacob
  • Status changed from new to assigned

comment:5 Changed 5 years ago by jacob

  • Resolution set to fixed
  • Status changed from assigned to closed

(In [10738]) Fixed #10953, #10955: proxies of proxies now work correctly, though I still don't quite understand why you'd want to do such a thing. Thanks, Armin Ronacher.

comment:6 Changed 3 years ago by jacob

  • milestone 1.1 deleted

Milestone 1.1 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.