Django MTMField: limit_choices_to = 同模型的其他外键字段?

6 投票
3 回答
5671 浏览
提问于 2025-04-11 20:09

我有几个Django模型,长得像这样:

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

我在尝试让limit_choices_to在Gallery模型上工作时遇到了各种各样的麻烦。我的目标是只让管理员看到属于同一个网站的照片选项。这样做可以吗?

3 个回答

-1

根据文档的说法,“在使用中间表的多对多字段上,limit_choices_to没有任何效果”。我理解这句话的意思是,它根本没有效果,因为多对多字段本身就会使用中间表……

我还没有尝试在管理网站上让它工作,但在你自己的视图中,你可以创建一个表单,并覆盖用来填充选择列表的查询集:

form.fields["photos"].queryset = request.user.photo_set.all()
6

没错。你需要重写管理员用来管理Gallery模型的表单,然后在这个表单中限制photos字段的数据范围:

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)
2

我会在我的 Photo 模型中删除 site 字段,然后在 Gallery 中添加一个 ForeignKey。同时,我会把 Gallery 模型中 photos 字段的 limit_choices_to 去掉。

因为你使用的是指向 SiteForeignKey,这意味着每个网站的画廊和照片是独立的,互不共享。所以我提到的那些东西其实已经没什么用处了。

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

一旦你在一个画廊上设置了 site,那么这个画廊里的所有照片都会继承这个属性。你可以通过 photo_instance.gallery.site 来访问这个网站:

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

这样做就像你有一个 site 字段一样。不过我还没有测试过这个。

如果你决定一个画廊或照片可以出现在多个网站上,那情况就会有所不同。

撰写回答