В 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. Я также пробовал 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)

Но это не работает (на самом деле я пробовал много вариантов, да, я новичок в джанго)


person Brian    schedule 08.11.2010    source источник


Ответы (2)


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

person Brian    schedule 10.11.2010

Ваш formfield_for_foreignkey выглядит как хорошее направление, но вы должны понимать, что ModelAdmin (self) не даст вам конкретный экземпляр. Вам придется вывести это из request (возможно, из комбинации django.core.urlresolvers.resolve и request.path)


Если вам нужна эта функциональность только в администраторе (а не проверка модели в целом), вы можете использовать пользовательскую форму с классом администратора модели:

формы.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)

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

person eternicode    schedule 09.11.2010
comment
Привет, Eternicode, спасибо, что уделили время моей проблеме. Но у меня вопрос, этот ваш код динамический, потому что мне кажется, что когда я хочу создать location_unit, init уже был запущен, и не будет запускаться снова, несмотря ни на что проект, который я выбираю. Так что мне нужно сначала выбрать проект, затем сохранить, а затем повторно ввести location_unit, чтобы снова запустить init, и сначала единицы будут отображать только те, которые принадлежат указанному проекту. Я правильно это понял? - person Brian; 10.11.2010
comment
Возможно, можно использовать что-то вроде этого: stackoverflow.com/questions/3750097/, но я понятия не имею, как реализовать это в админке - person Brian; 10.11.2010
comment
Хорошо, это именно то, что я хочу :) github.com/digi604/django-smart-selects< /а> - person Brian; 10.11.2010
comment
Это правда, что это будет работать только при редактировании location_unit, а не при создании нового, потому что при создании нового еще нет instance и, следовательно, нет проекта, которым можно ограничить выбор. Вам нужно будет сохранить и продолжить редактирование, чтобы получить ограничения, или реализовать какой-то AJAX для получения допустимых вариантов на основе выбора проекта (что я также делал в прошлом). Если вы думаете, что нашли ответ самостоятельно, пожалуйста, примите ваш ответ как решение. Спасибо. - person eternicode; 10.11.2010
comment
К сожалению, это работает только с администратором и не применяет выбор на уровне модели. - person Cerin; 04.12.2012