How to limit objects on ManyToManyField in admin interface only to related objects?

4 views
Skip to first unread message

Vasily Sulatskov

unread,
Dec 27, 2006, 12:57:26 PM12/27/06
to Django users
I have models similar to following:

class User(models.Model):
name = models.CharField(maxlength=100)

class Keyword(models.Model):
name = models.CharField(maxlength=100)
user = models.ForeignKey(User)

class Article(models.Model):
name = models.CharField(maxlength=100)
user = models.ForeignKey(User)
keywords = model.ManyToManyField(Keyword,
filter_interface=models.HORIZONTAL)

Admin works but displays on Article edit page Keywords of all users,
while I want it to display Keywords only of the same User only.

I tried 'limit_choices_to', but with no success because I can't pass
in(or can't find how to do it) edited article instance, and therefore
access it's user__id

I tried subclassing ManyToManyFIeld and overriding it
get_choices_default() but with no success because it is supposed to be
class attribute.

Perhaps it has to do something with ForeignRelatedObjectsDescriptor and
such, but google finds surprisingly little on this subject.

Perhaps it's a trvial problem but I am new to Django so any help will
be appreciated.

Jeremy Dunck

unread,
Dec 27, 2006, 7:56:28 PM12/27/06
to django...@googlegroups.com
On 12/27/06, Vasily Sulatskov <redv...@gmail.com> wrote:
>
> I have models similar to following:
>
> class User(models.Model):
> name = models.CharField(maxlength=100)
>
> class Keyword(models.Model):
> name = models.CharField(maxlength=100)
> user = models.ForeignKey(User)
>
> class Article(models.Model):
> name = models.CharField(maxlength=100)
> user = models.ForeignKey(User)
> keywords = model.ManyToManyField(Keyword,
> filter_interface=models.HORIZONTAL)
>
> Admin works but displays on Article edit page Keywords of all users,
> while I want it to display Keywords only of the same User only.

This isn't exactly what you asked for, but perhaps it'll help:
http://code.djangoproject.com/wiki/CookBookPredicates

Vasily Sulatskov

unread,
Dec 28, 2006, 2:35:52 AM12/28/06
to Django users

On 28 Дек., 05:56, "Jeremy Dunck" <jdu...@gmail.com> wrote:


> On 12/27/06, Vasily Sulatskov <redvas...@gmail.com> wrote:
>
>
>
>
>
> > I have models similar to following:
>
> > class User(models.Model):
> > name = models.CharField(maxlength=100)
>
> > class Keyword(models.Model):
> > name = models.CharField(maxlength=100)
> > user = models.ForeignKey(User)
>
> > class Article(models.Model):
> > name = models.CharField(maxlength=100)
> > user = models.ForeignKey(User)
> > keywords = model.ManyToManyField(Keyword,
> > filter_interface=models.HORIZONTAL)
>
> > Admin works but displays on Article edit page Keywords of all users,

> > while I want it to display Keywords only of the same User only.This isn't exactly what you asked for, but perhaps it'll help:http://code.djangoproject.com/wiki/CookBookPredicates

Thanks for the reply but that didn't help.

I find a workaround for this problem, imho it's even clunky enough to
be called kludge :-)

class RelatedManyToManyField(models.ManyToManyField):
def __init__(self, *args, **kwds):
self.related_set_name = kwds.pop('related_set_name')
self.__manipulator = None

models.ManyToManyField.__init__(self, *args, **kwds)

def get_manipulator_fields(self, opts, manipulator, change,
name_prefix='', rel=False, follow=True):
self.__manipulator = manipulator
return super(RelatedManyToManyField,
self).get_manipulator_fields(
opts, manipulator, change, name_prefix, rel, follow)

def get_choices_default(self):
if hasattr(self.__manipulator, 'original_object'):
profile = self.__manipulator.original_object.user_profile
objects = list(getattr(profile,
self.related_set_name).all())
choices = [(obj.id, str(obj)) for obj in objects]
else:
# Fallback for AddManipulator case

# Possible solution
#choices = models.Field.get_choices(self,
include_blank=False)

# I dont't want any choices until object is fully created
choices = []
self.__manipulator = None
return choices

I examinded calls django makes during form creation and find out that
call to get_manipulator_fields() is the last call which have
information about manipulator it's related to and therefore can access
it's original_object. So I overrided get_manipulator_fields() to store
manipulator and used that information in get_choices_default().

It works for me.

Is there any better solution?

Or perhaps it's possible to improve this solution to the point it will
make way to mainline Django?

ElGranAzul

unread,
Dec 28, 2006, 8:09:44 PM12/28/06
to Django users
I don't know if i understand it good, but if you want that keywords in
Article where related to user in the same model, it can't be done in
server level, because the behaviour is in browser side. You could do it
with javascript, DOM and some ajax to retrieve the list of keywords
related with the current selected user. Or you can also reload the form
each time a new user is selected and do the select in server side.

I hope it helps. :)

Reply all
Reply to author
Forward
0 new messages