【问题标题】:filtering ForeignKey by object ID按对象 ID 过滤 ForeignKey
【发布时间】:2012-07-23 06:38:00
【问题描述】:

我有一个 CarType,在我的 models.py 中有一个 ForeignKey BodyMaterial:

class BodyMaterial(models.Model):
    location                = models.ForeignKey('CarType')
    name                    = models.CharField(max_length=255)

class CarType(models.Model):
    name                    = models.CharField(max_length=255)
    default_body_material   = models.ForeignKey(BodyMaterial, null = True, blank = True, default = "", limit_choices_to={'location__exact': 1})

BodyMaterial 是我的 admin.py 中 CarType 中的内联:

class BodyMaterial_Inline(admin.StackedInline):
    model = BodyMaterial
    extra = 1

class CarType_Admin(admin.ModelAdmin):
    inlines = [BodyMaterial_Inline]

admin.site.register(CarType, CarType_Admin)

我想过滤 default_body_material 的 ForeignKey 以仅显示相关的 BodyMaterials(出现/添加在同一管理页面上的那些)。例如,我创建了一个 2 座 CarType,并在同一页面中添加了一些 BodyMaterials。然后我创建了一个 SVU CarType 和一些其他的 BodyMaterials。当我回到 2 座 CarType 时,我只想在 default_body_material 的下拉菜单中看到相关的 BodyMaterials。

我尝试在 id 上使用 limit_choices_to 进行过滤。所以我使用 post_init 这样做是因为对象的 id 在运行时确定:

def setID(**kwargs):
    instance = kwargs.get('instance')
    default_body_material = instance._meta.get_field_by_name('default_body_material')[0]
    default_body_material.limit_choices_to = {'location__exact': instance.id}

post_init.connect(setID, CarType)

不幸的是,这无济于事。我错过了什么?是否有更好的理由为我的目的过滤 ForeignKey(这可能是非常基本的)?

请注意,此问题仅针对管理界面。

【问题讨论】:

    标签: django django-admin foreign-keys limit-choices-to


    【解决方案1】:

    你想看看为你的内联覆盖查询集函数。

    【讨论】:

      【解决方案2】:

      只需使用自定义ModelForm

      class CarTypeAdminForm(forms.ModelForm):
          def __init__(self, *args, **kwargs):
              super(CarTypeAdminForm, self).__init__(*args, **kwargs)
              # Can't limit it until instance has been saved at least once
              if self.instance.pk:
                  self.fields['default_body_material'].queryset = \
                      self.fields['default_body_material'].queryset \
                          .filter(location=self.instance)
      
      class CarTypeAdmin(admin.ModelAdmin):
          form = CarTypeAdminForm
          ...
      

      【讨论】:

      • 我确实有一个问题。当我运行 instance.bodymaterial_set.all() 时,即使没有您建议的代码,它也会打印出正确的外键。我对 Django 不太熟悉,无法理解 Django 在没有我明确声明查询集的情况下是如何知道的,但确实如此。我想知道是否有一种更简单的方法可以在没有查询集的情况下执行上述操作。
      • 关键是你必须实际存储一个新的过滤查询集来代替当前查询集的字段。你可以很容易地做到self.fields['default_body_material'].queryset = self.instance.bodymaterial_set.all()。但是,正如我所做的那样,过滤已经分配的查询集更加健壮,因为它会继承来自表单的任何子类等的更改,而使用此代码只会完全替换它。
      猜你喜欢
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 1970-01-01
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      相关资源
      最近更新 更多