2010-11-08 4 views
11

ho questi modelli (ho limitato il numero di campi a solo quelli necessari)In django, come limitare le scelte di un campo straniero basato su un altro campo nello stesso modello?

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)  

La mia testa newbie solo non può cogliere come limitare i due campi, la posizione e l'unità, nel modello location_unit al solo spettacolo le scelte che si riferiscono al progetto selezionato in location_unit. Devo scavalcare il modello e creare una query o posso usare il limit_choices_to. In entrambi i casi ho fallito nel provare entrambi

Modifica: solo per chiarire, voglio che questo accada nell'amministratore di Django. Ho anche provato formfield_for_foreignkey, ma ancora un no go per me.

EDIT 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) 

Le suddette opere frammento di codice. Ma ovviamente non voglio che il progetto indichi a 1. Come faccio a fare riferimento ai modelli project_id? Ho provato questo:

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

Ma questo non funziona (in realtà ho provato un sacco di varianti, sì, io sono un novizio Django)

risposta

3

tuo formfield_for_foreignkey sembra che potrebbe essere una buona direzione, ma devi capire che ModelAdmin (self) non ti darà un'istanza specifica. Dovrete derivare che dal request (forse una combinazione di django.core.urlresolvers.resolve e request.path)


Se desideri solo questa funzionalità in admin (e non modello di validazione in generale), è possibile utilizzare un modulo personalizzato con la classe del modello di amministrazione:

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) 

(appena scritto questi al volo con nessun test, in modo da nessuna garanzia che funzioneranno, ma dovrebbe essere vicino.)

+0

Hi Eternicode, grazie per aver dedicato tempo al mio problema Ma ho una domanda, è questo tuo codice dinamico, perché mi sembra che quando voglio creare un location_unit, il __init__ sia già stato eseguito, e non verrà eseguito di nuovo, non importa quale progetto seleziono. Per prima cosa devo selezionare un progetto, quindi salvare e quindi reinserire il location_unit per eseguire di nuovo __init__ e, in primo luogo, le unità mostreranno solo quelle che appartengono a detto progetto. Ho capito bene? – Brian

+0

Forse qualcosa di simile può essere usato: http://stackoverflow.com/questions/3750097/how-to-read-write-input-fields-in-django-admin-tabular-inlines-using-ajax ma non ho idea di come implementarlo nell'amministratore – Brian

+3

Ok, questo fa esattamente quello che voglio :) https://github.com/digi604/django-smart-selects – Brian