Django MTMField: limit_choices_to = other_ForeignKeyField_on_same_model?
Asked Answered
B

3

6

I've got a couple django models that look like this:

from django.contrib.sites.models import Site

class Photo(models.Model):
    title = models.CharField(max_length=100)
    site = models.ForeignKey(Site)
    file = models.ImageField(upload_to=get_site_profile_path) 

    def __unicode__(self):
        return self.title


class Gallery(models.Model):    
    name = models.CharField(max_length=40)
    site = models.ForeignKey(Site)
    photos = models.ManyToManyField(Photo, limit_choices_to = {'site':name} )    

    def __unicode__(self):
        return self.name

I'm having all kinds of fun trying to get the limit_choices_to working on the Gallery model. I only want the Admin to show choices for photos that belong to the same site as this gallery. Is this possible?

Brumaire answered 5/12, 2008 at 22:32 Comment(0)
S
2

I would delete site field on my Photo model and add a ForeignKey to Gallery. I would remove limit_choices_to from photos fields on Gallery model.

Because you are using ForeignKeys to Sites, that means sites don't share galleries and photos. Therefore having those I mentioned above is already useless.

class Photo(models.Model):
    title = models.CharField(max_length=100)
    gallery = models.ForeignKey(Gallery, related_name='photos')
    file = models.ImageField(upload_to=get_site_profile_path) 

    def __unicode__(self):
        return self.title


class Gallery(models.Model):    
    name = models.CharField(max_length=40)
    site = models.ForeignKey(Site)

    def __unicode__(self):
        return self.name

Once you set the site on a gallery all its photos will inherit this property. And the site will be accessible as photo_instance.gallery.site:

@property
def site(self):
    return self.gallery.site

This should work as if you had a site field. But I haven't tested it.

Things change or course, if you decide that a gallery or a photo can appear in multiple sites.

Schonfeld answered 5/12, 2008 at 23:41 Comment(1)
Late comment... This solves the asker problem with a better design, but doesn't answer the question! I have the same problem but the design change can't be done, It's like a CustomUser having a set of possible options (M2M to Options) that only a high level manager can change, but among them a set of active options (second M2M to Options, choice among the ones in the first list). Subsets of the same set of options must be assigned also to other objects, so reversing relations isn't possible.Metatarsus
D
6

Yes. You need to override the form that admin uses for the Gallery model, then limit the queryset of the photos field in that form:

class GalleryAdminForm(django.forms.ModelForm):

    class Meta:
        model = Gallery

    def __init__(self, *args, **kwargs):
        super(GalleryAdminForm, self).__init__(*args, **kwargs)
        self.fields['segments'].queryset = Photo.objects.filter(site=self.instance.site)


class GalleryAdmin(django.contrib.admin.ModelAdmin):
    form = GalleryAdminForm

django.contrib.admin.site.register(Gallery, GalleryAdmin)
Dobbs answered 10/12, 2009 at 14:3 Comment(0)
S
2

I would delete site field on my Photo model and add a ForeignKey to Gallery. I would remove limit_choices_to from photos fields on Gallery model.

Because you are using ForeignKeys to Sites, that means sites don't share galleries and photos. Therefore having those I mentioned above is already useless.

class Photo(models.Model):
    title = models.CharField(max_length=100)
    gallery = models.ForeignKey(Gallery, related_name='photos')
    file = models.ImageField(upload_to=get_site_profile_path) 

    def __unicode__(self):
        return self.title


class Gallery(models.Model):    
    name = models.CharField(max_length=40)
    site = models.ForeignKey(Site)

    def __unicode__(self):
        return self.name

Once you set the site on a gallery all its photos will inherit this property. And the site will be accessible as photo_instance.gallery.site:

@property
def site(self):
    return self.gallery.site

This should work as if you had a site field. But I haven't tested it.

Things change or course, if you decide that a gallery or a photo can appear in multiple sites.

Schonfeld answered 5/12, 2008 at 23:41 Comment(1)
Late comment... This solves the asker problem with a better design, but doesn't answer the question! I have the same problem but the design change can't be done, It's like a CustomUser having a set of possible options (M2M to Options) that only a high level manager can change, but among them a set of active options (second M2M to Options, choice among the ones in the first list). Subsets of the same set of options must be assigned also to other objects, so reversing relations isn't possible.Metatarsus
K
-1

According to the docs, "limit_choices_to has no effect when used on a ManyToManyField with an intermediate table". By my reading, that means it has no effect at all, because ManyToManyFields use intermediate tables...

I haven't tried to make it work in the Admin site, but from your own views, you can create a form and override the queryset used to populate the list of choices:

form.fields["photos"].queryset = request.user.photo_set.all()
Kirkpatrick answered 5/12, 2008 at 22:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.