I experienced some obscure test failures after integrating Zinnia with my 
application. I've tracked it down to the behavior of Proxy Models and I'm 
unable
to rationalize the documentation with the behavior I see. Here's what I've 
done
to understand the issue:

If I create an app with a Proxy Model for auth.User (using get_user_model):

    # pm/models.py
    # a stripped down copy of Zinnia's Author
    from django.db import models
    from django.contrib.auth import get_user_model

    class MyUser(get_user_model()):
        objects = get_user_model()._default_manager

        def __str__(self):
            return self.get_full_name() or self.get_username()

        class Meta:
            app_label = 'pm'
            proxy = True

I see the following behavior in the shell:

    $ ./manage.py shell
    Python 2.7.4 (default, Apr 19 2013, 18:28:01) 
    [GCC 4.7.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from django.contrib.auth import get_user_model
    >>> get_user_model()
    <class 'django.contrib.auth.models.User'>
    >>> get_user_model().objects.model
    <class 'pm.models.MyUser'>
    >>> get_user_model().objects.get(pk=1)
    <MyUser: admin>
    >>> 

This seems to be contrary to the claim made in the documentation:

    "QuerySets still return the model that was requested

    There is no way to have Django return, say, a MyPerson object whenever 
you 
    query for Person objects. A queryset for Person objects will return 
those 
    types of objects. The whole point of proxy objects is that code relying 
on 
    the original Person will use those and your own code can use the 
extensions 
    you included (that no other code is relying on anyway). It is not a way 
to 
    replace the Person (or any other) model everywhere with something of 
your 
    own creation."
    
    
https://docs.djangoproject.com/en/dev/topics/db/models/#querysets-still-return-the-model-that-was-requested


If I create a second app and model with a Proxy for auth.User:

    # pm2/models.py
    from django.db import models
    from django.contrib.auth import get_user_model

    class MyUser2(get_user_model()):
        objects = get_user_model()._default_manager

        def __str__(self):
            return self.get_full_name() or self.get_username()

        class Meta:
            app_label = 'pm2'
            proxy = True
        
Then I get an AssertionError with the following traceback:
        
    $ ./manage.py shell --traceback
    Traceback (most recent call last):
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/core/management/base.py",
 
line 222, in run_from_argv
        self.execute(*args, **options.__dict__)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/core/management/base.py",
 
line 255, in execute
        output = self.handle(*args, **options)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/core/management/base.py",
 
line 385, in handle
        return self.handle_noargs(**options)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/core/management/commands/shell.py",
 
line 54, in handle_noargs
        get_models()
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/db/models/loading.py",
 
line 197, in get_models
        self._populate()
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/db/models/loading.py",
 
line 72, in _populate
        self.load_app(app_name, True)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/db/models/loading.py",
 
line 96, in load_app
        models = import_module('.models', app_name)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/utils/importlib.py",
 
line 35, in import_module
        __import__(name)
      File "~/src/django_proxy_model_test/pm/models.py", line 5, in <module>
        class MyUser(get_user_model()):
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/db/models/base.py",
 
line 134, in __new__
        new_class._default_manager = 
new_class._default_manager._copy_to_model(new_class)
      File 
"~/.virtualenvs/django_proxy_model_test/local/lib/python2.7/site-packages/django/db/models/manager.py",
 
line 95, in _copy_to_model
        assert issubclass(model, self.model)
    AssertionError

After the first Proxy Model is registered, self.model points at the Proxy 
Model 
instead of the original Model. The second Proxy Model is not a subclass of 
the 
first.

Is there a contradiction between the behavior I observe and the 
documentation? 
Or am I simply misunderstanding the documentation? Should it be possible 
for a
model to be proxied multiple times?

I appreciate any clarity that you can provide.

Aaron Spike



-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/d60b129c-c7d1-49f4-beea-8915c135f47a%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to