2010-11-08 7 views
11

Je ces modèles (je suis limité le nombre de champs à seulement ceux nécessaires)Dans django, comment limiter les choix d'un champ étranger basé sur un autre champ dans le même modèle?

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)  

Ma tête novice ne peut pas saisir comment limiter les deux champs, l'emplacement et l'unité, dans le modèle location_unit pour ne montrer les choix qui se réfèrent au projet sélectionné dans location_unit. Dois-je redéfinir le modelform et y faire une requête ou puis-je utiliser le limit_choices_to. De toute façon j'ai échoué à essayer les deux

Modifier: Juste pour clarifier, je veux que cela se produise dans l'Admin Django. J'ai également essayé formfield_for_foreignkey, mais toujours un pas pour moi.

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) 

Les travaux de extrait de code ci-dessus. Mais bien sûr, je ne veux pas que le projet pointe vers 1. Comment faire référence aux modèles project_id? J'ai essayé ceci:

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

Mais cela ne fonctionne pas (en fait, je l'ai essayé beaucoup de variations, oui je suis un débutant django)

Répondre

3

Votre formfield_for_foreignkey ressemble à ce pourrait être une bonne direction, mais vous devez réaliser que ModelAdmin (self) ne vous donnera pas une instance spécifique. Vous devrez déduire que du request (peut-être une combinaison de django.core.urlresolvers.resolve et request.path)


Si vous ne souhaitez que cette fonctionnalité dans l'admin (et modèle non validation en général), vous pouvez utiliser un formulaire personnalisé avec la classe admin modèle:

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) 

(Just a écrit ce à la volée sans test, donc aucune garantie qu'ils vont travailler, mais il devrait être proche.)

+0

Salut Eternicode, merci de prendre votre temps sur mon problème. Mais j'ai une question, est ce que votre code est dynamique, car il me semble que quand je veux créer un location_unit, le __init__ a déjà été exécuté, et ne sera pas exécuté à nouveau, quel que soit le projet que je sélectionne. Pour que je doive d'abord sélectionner un projet, puis enregistrer, puis entrer à nouveau dans location_unit pour exécuter à nouveau __init__ et d'abord, les unités ne montreront que celles qui appartiennent à ce projet. Ai-je bien compris? – Brian

+0

Peut-être quelque chose comme ça peut être utilisé: http://stackoverflow.com/questions/3750097/how-to-read-write-input-fields-in-django-admin-tabular-inlines-using-ajax mais je n'ai pas idée comment implémenter cela dans l'admin – Brian

+3

D'accord, cela fait exactement ce que je veux :) https://github.com/digi604/django-smart-selects – Brian

Questions connexes