#18005: Add support for ManyToManyFields on proxy models
-------------------------------------------------+--------------------
     Reporter:  Bradley Ayers <bradley.ayers@…>  |      Owner:  nobody
         Type:  New feature                      |     Status:  new
    Component:  Database layer (models, ORM)     |    Version:  1.4
     Severity:  Normal                           |   Keywords:
 Triage Stage:  Unreviewed                       |  Has patch:  0
Easy pickings:  0                                |      UI/UX:  0
-------------------------------------------------+--------------------
 It appears Django already supports this, but explicitly checks for and
 prevents it from working:

 
https://code.djangoproject.com/browser/django/trunk/django/db/models/base.py#L123
 {{{
 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, ``ManyToManyField``s
 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 ``./manage.py sql users`` shows that the correct SQL is generated:

 {{{
 BEGIN;
 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")
 )
 ;
 COMMIT;
 }}}

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

 {{{
 user = User.objects.create_user("username", "f...@example.com",
 "password")
 district = District.objects.create(name="Foo")
 user.districts.add(district)

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

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

 The Django test suite passes using SQLite:

 {{{
 $ ./runtests.py --settings=test_sqlite
 Creating test database for alias 'default'...
 Creating test database for alias 'other'...
 ...<snip>....
 ----------------------------------------------------------------------
 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?

-- 
Ticket URL: <https://code.djangoproject.com/ticket/18005>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to