Django: “limit_choices_to” doesn't work on ManyToManyField
我正在运行Django 1.1并且无法获取我的ManytoManyField的"limit_choices_to"选项。
我有两个型号:
1 2 3 4 5 6 7 8 | class MemberPhoto(ImageModel): title = models.CharField(_('title'), max_length=255, blank=True, null=True) caption = models.CharField(_('caption'), max_length=255, blank=True, null=True) date_added = models.DateTimeField(_('date added'), default=datetime.now, editable=False) member = models.ForeignKey(User) def __unicode__(self): return u'%s (%s)' % (self.member.username, self.id) |
和
1 2 3 4 5 | class lock(models.Model): user = models.ForeignKey(User, related_name="owner") to_user = models.ForeignKey(User, related_name="to_user") unlocked_photos = models.ManyToManyField(MemberPhoto, blank=True, null=True, limit_choices_to = {'member':'user'}) objects = locking_manager() |
在第二个模型中,我想确保在Django的管理员中,在多个选择字段中呈现的唯一"unlocked_photos"("MemberPhoto"对象)是具有"成员"值(用户对象)的那些与"锁定"对象的"用户"(也是一个用户对象)。
我以为我已经遵循了Django文档,但它不起作用。我收到以下错误:
1 2 3 | TemplateSyntaxError Caught an exception while rendering: invalid input syntax for integer:"user" |
我已经尝试将"limit_choices_to"改为:
limit_choices_to = {'member':user} ---不起作用
limit_choices_to = {'member__username':'kyle'} ---这可行,但它没用,我只是手动指定用户名
我怎样才能从当前的"锁定"对象中获取用户并按此过滤MemberPhoto"member"属性?
感谢任何可以提供帮助的人。
凯尔
我找到了一个答案,在这个链接上实现了我想要的:Django MTMField:limit_choices_to = other_ForeignKeyField_on_same_model ?,我在这里发布我的工作代码给任何有同样问题的人。看起来似乎"limit_choices_to"可能根本无法达到我想要的效果,并且自定义管理员使用的表单是要走的路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from django.contrib import admin from django import forms from gayhop.apps.locking.models import lock from gayhop.apps.photos.models import MemberPhoto class LockAdminForm(forms.ModelForm): class Meta: model = lock def __init__(self, *args, **kwargs): super(LockAdminForm, self).__init__(*args, **kwargs) self.fields['unlocked_photos'].queryset = MemberPhoto.objects.filter(member=self.instance.user) class LockAdmin(admin.ModelAdmin): form = LockAdminForm filter_horizontal = ('unlocked_photos',) django.contrib.admin.site.register(lock, LockAdmin) |
你需要改变的是:
希望这有助于某人!
要添加凯尔的答案,
创建自定义表单是以这种方式自定义多对多字段的唯一方法。但是,就像我发现的那样,只有在更改该模型的实例时,该方法才有效。 (至少在Django 1.5中)
这是因为:
但是如果要创建该模型的实例,由于尚未创建该模型,
解决此问题的方法是创建两种形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class MyModelChangeForm(forms.ModelForm): class Meta: model = MyModel def __init__(self, *args, **kwargs): super(MyModelChangeForm, self).__init__(*args, **kwargs) my_model = self.instance self.fields['fields'].queryset = OtherRelatedModel.objects.filter(other_id=my_model.other) class MyModelCreationForm(forms.ModelForm): class Meta: model = MyModel def save(self, commit=True): my_model = super(MyModelCreationForm, self).save(commit=False) *** Do other things with the my_model if you want *** my_model.save() return my_model |
然后在admin.py中我们将为我们的创建表单创建一个单独的字段集:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class MyModelAdmin(admin.ModelAdmin): filter_horizontal = ('other') list_display = ('field1', 'field2' 'field3') fieldsets = ( ("Model info:", {'fields': ("field1","field2","field3")}), ("More Model info:", {'fields': ("other",)}), ) add_fieldsets = ( ("Initial info:", {'fields': ("field1","field2","field3")}), ) form = MyModelChangeForm add_form = MyModelCreationForm def get_fieldsets(self, request, obj=None): if not obj: return self.add_fieldsets return super(MyModelAdmin, self).get_fieldsets(request, obj) def get_form(self, request, obj=None, **kwargs): """ Use special form during MyModel creation """ defaults = {} if obj is None: defaults.update({ 'form': self.add_form, 'fields': admin.util.flatten_fieldsets(self.add_fieldsets), }) defaults.update(kwargs) return super(MyModelAdmin, self).get_form(request, obj, **defaults) |
请注意,如果obj为None(或者换句话说,如果请求是添加模型的实例),我们必须覆盖get_form和get_fieldsets,它使用MyModelCreationForm。这与django开发人员在django.contrib.auth.admin中使用的方法相同,以获取其自定义UserCreation表单和字段集。 (在那里查看该示例的源代码)
最后,模型在model.py中看起来像这样:
1 2 3 4 5 6 7 | class MyModel(models.Model): *** field definitions *** other = models.ManytoManyField(OtherRelatedModel, null=True, blank=True) class OtherRelatedModel(models.Model): other_id = model.AutoField(primary_key=True) *** more field definitions *** |
我包含模型的唯一原因是,您可以在MyModel类中看到多对多的字段定义。它不必将null和空白设置为True。请记住,如果不这样做,则必须在定义中为它们分配默认值,或者在MyModelCreationForm中的save()函数中设置它们。
希望这可以帮助! (如果完全错了,请纠正我!我也需要学习。)
-谢谢