关于python:Django ForeignKey limit_choices_到一个不同的ForeignKey id

Django ForeignKey limit_choices_to a different ForeignKey id

我试图用limit-choices来限制一个foreignkey的django管理员的选择,但我不知道如何正确地进行。

如果类别ID为16,则此代码执行我所需的操作,但我无法确定如何使用当前类别ID,而不是对其进行硬编码。

1
2
3
4
5
6
7
class MovieCategory(models.Model):    
    category = models.ForeignKey(Category)
    movie = models.ForeignKey(Movie)
    prefix = models.ForeignKey('Prefix', limit_choices_to={'category_id': '16'},
                               blank=True, null=True)
    number = models.DecimalField(verbose_name='Movie Number', max_digits=2,
                                 blank=True, null=True, decimal_places=0)

是否可以以某种方式引用类别foreignkey的ID?


在阅读了几个半相关的问题后,我终于明白了这一点。

你不能像我想做的那样自我引用一个模型,所以没有办法让Django按照我想要的方式使用限制选项,因为它在同一个模型中找不到不同的foreignkey的ID。

如果您改变了django的工作方式,这显然是可以做到的,但是解决这个问题的一个简单方法是改为对admin.py进行更改。

以下是我的models.py now中的情况:

1
2
3
4
5
6
7
# models.py
class MovieCategory(models.Model):    
    category = models.ForeignKey(Category)
    movie = models.ForeignKey(Movie)
    prefix = models.ForeignKey('Prefix', blank=True, null=True)
    number = models.DecimalField(verbose_name='Movie Number', max_digits=2,
                                 blank=True, null=True, decimal_places=0)

我只是简单地把选择限制到了完全。我在凯尔·邓肯发布的解决方案中发现了类似的问题。但不同的是,它使用的是manytomany而不是foreignkey。这意味着我必须删除我的班级MovieCategoryAdmin(admin.ModelAdmin):下的filter_horizontal = ('prefix',),因为这只适用于许多领域。

在admin.py中,我不得不在顶部添加from django import forms来创建一个表单。表单的外观如下:

1
2
3
4
5
6
7
8
9
10
class MovieCategoryForm(forms.ModelForm):

    class Meta:
        model = MovieCategory
        fields = ['prefix']

    def __init__(self, *args, **kwargs):
        super(MovieCategoryForm, self).__init__(*args, **kwargs)
        self.fields['prefix'].queryset = Prefix.objects.filter(
                                        category_id=self.instance.category.id)

我的管理模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
class MovieCategoryAdmin(admin.ModelAdmin):
   """
    Admin Class for 'Movie Category'.
   """

    fieldsets = [
        ('Category',      {'fields': ['category']}),
        ('Movie',         {'fields': ['movie']}),
        ('Prefix',        {'fields': ['prefix']}),
        ('Number',        {'fields': ['number']}),
    ]
    list_display = ('category', 'movie', 'prefix', 'number')
    search_fields = ['category__category_name', 'movie__title', 'prefix__prefix']
    form = MovieCategoryForm

这正是凯尔在回答中所描述的,除非我必须在表单中添加fields = ['prefix'],否则它不会运行。如果你遵循他的步骤,记住删除水平过滤器并添加你正在使用的字段,它应该可以工作。

编辑:此解决方案在编辑时工作正常,但在创建新条目时不起作用,因为它无法在不退出时搜索类别ID。我正在设法解决这个问题。


如果不想添加自定义模型窗体,另一种方法是在modeladmin的get_form()方法中处理这个问题。这对我来说更可取,因为我需要对查询集的请求对象进行简单的访问。

1
2
3
4
5
6
7
8
9
class StoryAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        form = super(StoryAdmin, self).get_form(request, obj, **kwargs)

        form.base_fields['local_categories'].queryset = LocalStoryCategory.\
            objects.filter(office=request.user.profile.office)

        return form


我也有同样的问题,你的自我回答帮助我开始了。但我也发现了另一篇文章(问题12399803)完成了答案,即如何在创建新条目时进行过滤。

在VIEW中

1
form = CustomerForm(groupid=request.user.groups.first().id)

在表格中

1
2
3
4
5
6
7
8
9
def __init__(self, *args, **kwargs):
    if 'groupid' in kwargs:
        groupid = kwargs.pop('groupid')
    else:
        groupid = None
    super(CustomerForm, self).__init__(*args, **kwargs)
    if not groupid:
        groupid = self.instance.group.id
    self.fields['address'].queryset = Address.objects.filter(group_id=groupid)

因此,无论是添加新客户还是更新现有客户,我都可以单击一个链接来添加将分配给该客户的新地址。

这是我对stackoverflow的第一个回答。希望有帮助。