问题 在django中,如何根据同一模型中的另一个字段限制异地的选择?


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

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中引用所选项目的选项。我应该覆盖模型并在那里进行查询,还是可以使用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)

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

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

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


6352
2017-11-08 11:12


起源



答案:


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


9
2017-11-10 10:52





你的 formfield_for_foreignkey 看起来它可能是一个好方向,但你必须意识到ModelAdmin(self)不会给你一个具体的例子。你必须从中得到它 request (可能是。的组合 django.core.urlresolvers.resolve 和 request.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)

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


3
2017-11-09 18:49



嗨Eternicode,谢谢你花时间解决我的问题。但是我有一个问题,这个代码是你的动态,因为在我看来,当我想创建一个location_unit时, 在里面 已经运行了,不管我选择什么项目都不会再运行。所以我必须首先选择一个项目,然后保存然后重新输入location_unit来运行 在里面 再次,然后,首先,单位将只显示属于所述项目的那些单位。我理解正确吗? - Brian
也许可以使用这样的东西: stackoverflow.com/questions/3750097/... 但我不知道如何在管理员中实现这一点 - Brian
好的,这正是我想要的:) github.com/digi604/django-smart-selects - Brian
确实,这仅在编辑location_unit时有效,而不是创建一个新的,因为在创建一个新的时,没有 instance 然而,没有项目限制选择。您必须“保存并继续编辑”才能获得限制,或者实施某种AJAX以根据项目选择(我过去也做过)获取有效选择。如果您认为自己找到了答案,请接受您的答案作为解决方案。谢谢。 - eternicode
不幸的是,这仅适用于admin,并且不会在模型级别强制执行选择。 - Cerin


答案:


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


9
2017-11-10 10:52





你的 formfield_for_foreignkey 看起来它可能是一个好方向,但你必须意识到ModelAdmin(self)不会给你一个具体的例子。你必须从中得到它 request (可能是。的组合 django.core.urlresolvers.resolve 和 request.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)

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


3
2017-11-09 18:49



嗨Eternicode,谢谢你花时间解决我的问题。但是我有一个问题,这个代码是你的动态,因为在我看来,当我想创建一个location_unit时, 在里面 已经运行了,不管我选择什么项目都不会再运行。所以我必须首先选择一个项目,然后保存然后重新输入location_unit来运行 在里面 再次,然后,首先,单位将只显示属于所述项目的那些单位。我理解正确吗? - Brian
也许可以使用这样的东西: stackoverflow.com/questions/3750097/... 但我不知道如何在管理员中实现这一点 - Brian
好的,这正是我想要的:) github.com/digi604/django-smart-selects - Brian
确实,这仅在编辑location_unit时有效,而不是创建一个新的,因为在创建一个新的时,没有 instance 然而,没有项目限制选择。您必须“保存并继续编辑”才能获得限制,或者实施某种AJAX以根据项目选择(我过去也做过)获取有效选择。如果您认为自己找到了答案,请接受您的答案作为解决方案。谢谢。 - eternicode
不幸的是,这仅适用于admin,并且不会在模型级别强制执行选择。 - Cerin