【问题标题】:In django, how to limit choices of a foreignfield based on another field in the same model?在 django 中,如何根据同一模型中的另一个字段限制一个外域的选择?
【发布时间】:2011-05-06 14:46:47
【问题描述】:

我有这些模型(我将字段数量限制为只需要的那些)

class unit(models.Model):
    name = models.CharField(max_length=200)

class project(models.Model):
    name = models.CharField(max_length=200)

class location(address):
    project = models.ForeignKey(project)

class project_unit(models.Model):
    project = models.ForeignKey(project)         
    unit = models.ForeignKey(unit)

class location_unit(models.Model):
    project = models.ForeignKey(project)    
      #Limit the selection of locations based on which project has been selected
    location = models.ForeignKey(location)
      #The same here for unit. But I have no idea how.
    unit = models.ForeignKey(project_unit)       

我的新手头无法掌握如何在 location_unit 模型中限制 location 和 unit 这两个字段以仅显示引用 location_unit 中所选项目的选项。我应该覆盖模型表单并在那里进行查询,还是可以使用limit_choices_to。无论哪种方式我都失败了

编辑:澄清一下,我希望这发生在 Django Admin 中。我也试过 formfield_for_foreignkey,但还是不行。

编辑 2:

def formfield_for_foreignkey(self, db_field, request, **kwargs):
    if db_field.name == "unit":
        kwargs["queryset"] = project_unit.objects.filter(project=1)
        return db_field.formfield(**kwargs)
    return super(location_unit_admin, self).formfield_for_foreignkey(db_field, request, **kwargs)

上面的代码 sn-p 有效。但我当然不希望项目指向 1。我如何引用模型 project_id? 我试过这个:

kwargs["queryset"] = project_unit.objects.filter(project=self.model.project.project_id)

但这不起作用(实际上我已经尝试了很多变体,是的,我是 django 新手)

【问题讨论】:

    标签: django foreign-keys limit


    【解决方案1】:

    这就是答案,太棒了:https://github.com/digi604/django-smart-selects

    【讨论】:

    【解决方案2】:

    您的formfield_for_foreignkey 看起来可能是一个不错的方向,但您必须意识到 ModelAdmin (self) 不会为您提供特定实例。您必须从request(可能是django.core.urlresolvers.resolverequest.path 的组合)派生出它


    如果您只想在管理员中使用此功能(而不是一般的模型验证),您可以使用带有模型管理类的自定义表单:

    forms.py:

    from django import forms
    
    from models import location_unit, location, project_unit
    
    class LocationUnitForm(forms.ModelForm):
        class Meta:
            model = location_unit
    
        def __init__(self, *args, **kwargs):
            inst = kwargs.get('instance')
            super(LocationUnitForm, self).__init__(*args, **kwargs)
            if inst:
                self.fields['location'].queryset = location.objects.filter(project=inst.project)
                self.fields['unit'].queryset = project_unit.objects.filter(project=inst.project)
    

    admin.py:

    from django.contrib import admin
    
    from models import location_unit
    from forms import LocationUnitForm
    
    class LocationUnitAdmin(admin.ModelAdmin):
        form = LocationUnitForm
    
    admin.site.register(location_unit, LocationUnitAdmin)
    

    (只是在没有测试的情况下即时编写这些,所以不能保证它们会工作,但应该很接近。)

    【讨论】:

    • 您好 Eternicode,感谢您花时间解决我的问题。但是我有一个问题,你的这段代码是动态的吗,因为在我看来,当我想创建一个 location_unit 时, init 已经运行了,无论如何都不会再次运行我选择的项目。所以我必须先选择一个项目,然后保存然后重新输入 location_unit 以再次运行 init 然后,这些单元将只显示属于所述项目的那些。我理解正确吗?
    • 也许可以使用这样的东西:stackoverflow.com/questions/3750097/… 但我不知道如何在管理员中实现这一点
    • 好的,这正是我想要的 :) github.com/digi604/django-smart-selects
    • 确实,这只会在编辑 location_unit 时起作用,而不是创建新的,因为在创建新的时,还没有 instance,因此没有项目可以限制选择.您必须“保存并继续编辑”才能获得限制,或者实施某种 AJAX 以根据项目选择获取有效选择(我过去也做过)。如果您认为自己找到了答案,请接受您的答案作为解决方案。谢谢。
    • 不幸的是,这仅适用于管理员,并且不会强制执行模型级别的选择。
    猜你喜欢
    • 2015-05-29
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    相关资源
    最近更新 更多