Opened 4 years ago

Closed 4 years ago

#18005 closed New feature (wontfix)

Add support for ManyToManyFields on proxy models

Reported by: Bradley Ayers <bradley.ayers@…> Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


It appears Django already supports this, but explicitly checks for and prevents it from working:

if (new_class._meta.local_fields:
        or new_class._meta.local_many_to_many):
    raise FieldError("Proxy model '%s' contains model fields." % name)

By simply removing the second half of the condition, ManyToManyFields work on
proxy models.

In my current project I'm proxying the auth.User as users.User, and I want to add a M2M
relationship to core.District. I don't want to modify core, so I'd like to
add the relationship to the users.User proxy model:

from django.contrib.auth.models import User as AuthUser

class User(AuthUser):
    districts = models.ManyToManyField("core.District")

    class Meta:
        proxy = True

Running ./ sql users shows that the correct SQL is generated:

CREATE TABLE "users_user_districts" (
    "id" integer NOT NULL PRIMARY KEY,
    "user_id" integer NOT NULL,
    "district_id" integer NOT NULL REFERENCES "core_district" ("id"),
    UNIQUE ("user_id", "district_id")

I wrote a crude test case, and it all seems to work:

user = User.objects.create_user("username", "", "password")
district = District.objects.create(name="Foo")

user = User.objects.get(  # use fresh version
assert district.users.count() == 1
assert district.users.all()[0].pk ==

user = User.objects.get(  # use fresh version
assert user.districts.count() == 0
assert list(user.districts.all()) == []

The Django test suite passes using SQLite:

$ ./ --settings=test_sqlite
Creating test database for alias 'default'...
Creating test database for alias 'other'...
Ran 4657 tests in 1007.250s

OK (skipped=115, expected failures=2)
Destroying test database for alias 'default'...
Destroying test database for alias 'other'...

Are there any arguments against this?

Change History (1)

comment:1 Changed 4 years ago by akaariai

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to wontfix
  • Status changed from new to closed

Based on a long and interesting #django-dev discussion it was decided that the answer to this issue is wontfix. As an alternative for this different ways of altering existing models was discussed. I will try to write a posting to django-developers about the ideas presented.

The reason for wontfixing is that Proxy models should not define additional fields. A counter argument is that it is already possible to add a foreign key pointing to a proxy model, but even then the fundamental idea of a Proxy model is that it has the same data as the base class, just different methods. Even the current foreign-key to proxy model is causing some problems.

Note: See TracTickets for help on using tickets.
Back to Top