В django, как ограничить выбор чужого поля на основе другого поля в той же модели? - PullRequest
11 голосов
/ 08 ноября 2010

У меня есть эти модели (я ограничил количество полей только необходимыми)

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)

Ответы [ 2 ]

9 голосов
/ 10 ноября 2010

Это ответ, он блестящий: https://github.com/digi604/django-smart-selects

3 голосов
/ 09 ноября 2010

Ваш 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)

(только что написал этина лету без тестирования, поэтому нет гарантии, что они будут работать, но это должно быть близко.)

...