web-dev-qa-db-fra.com

Comment ajouter un champ de clé étrangère à un ModelForm dans Django?

Ce que je voudrais faire, c'est afficher un seul formulaire qui permet à l'utilisateur:

  • Entrez un titre de document (à partir du modèle Document)
  • Sélectionnez l'un de leurs user_defined_code choix dans une liste déroulante (remplie par le modèle UserDefinedCode)
  • Tapez un unique_code (stocké dans le modèle Code)

Je ne sais pas comment afficher les champs des relations de clé étrangère dans un formulaire. Je sais que dans une vue, vous pouvez utiliser document.code_set (par exemple) pour accéder aux objets associés pour l'objet document actuel, mais je ne sais pas comment l'appliquer à un ModelForm.

Mon modele:

class UserDefinedCode(models.Model):
    name = models.CharField(max_length=8)
    owner = models.ForeignKey(User)

class Code(models.Model):
    user_defined_code = models.ForeignKey(UserDefinedCode)
    unique_code = models.CharField(max_length=15)

class Document(models.Model):
    title = models.CharField(blank=True, null=True, max_length=200)
    code = models.ForeignKey(Code)
    active = models.BooleanField(default=True)

My ModelForm

class DocumentForm(ModelForm):
    class Meta:
        model = Document
23
Ben S

En ce qui concerne l'affichage d'un champ de clé étrangère dans un formulaire, vous pouvez utiliser le forms.ModelChoiceField et passez-lui un ensemble de requêtes.

donc, forms.py:

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user','')
        super(DocumentForm, self).__init__(*args, **kwargs)
        self.fields['user_defined_code']=forms.ModelChoiceField(queryset=UserDefinedCode.objects.filter(owner=user))

views.py:

def someview(request):
    if request.method=='post':
        form=DocumentForm(request.POST, user=request.user)
        if form.is_valid():
            selected_user_defined_code = form.cleaned_data.get('user_defined_code')
            #do stuff here
    else:
        form=DocumentForm(user=request.user)

    context = { 'form':form, }

    return render_to_response('sometemplate.html', context, 
        context_instance=RequestContext(request))

de votre question:

Je sais que dans une vue, vous pouvez utiliser document.code_set (par exemple) pour accéder aux objets associés pour l'objet de document actuel, mais je ne sais pas comment appliquer cela à un ModelForm.

En fait, vos objets Document n'auraient pas de .code_set puisque la relation FK est définie dans votre modèle de documents. Il définit une relation plusieurs à un avec Code, ce qui signifie qu'il peut y avoir plusieurs Document objets par Code objet, et non l'inverse. Vos objets Code auraient un .document_set. Ce que vous pouvez faire à partir de l’objet document, c’est l’accès à Code qui est lié à l’utilisation de document.code.

edit: Je pense que cela fera ce que vous cherchez. (non testé)

forms.py:

class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
        exclude = ('code',)

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user','')
        super(DocumentForm, self).__init__(*args, **kwargs)
        self.fields['user_defined_code']=forms.ModelChoiceField(queryset=UserDefinedCode.objects.filter(owner=user))
        self.fields['unique_code']=forms.CharField(max_length=15)

views.py:

def someview(request):
    if request.method=='post':
        form=DocumentForm(request.POST, user=request.user)
        if form.is_valid():
            uniquecode = form.cleaned_data.get('unique_code')
            user_defined_code = form.cleaned_data.get('user_defined_code')
            doc_code = Code(user_defined_code=user_defined_code, code=uniquecode)
            doc_code.save()
            doc = form.save(commit=False)
            doc.code = doc_code
            doc.save()
            return HttpResponse('success')
    else:
        form=DocumentForm(user=request.user)

    context = { 'form':form, }

    return render_to_response('sometemplate.html', context, 
        context_instance=RequestContext(request))

en fait, vous voulez probablement utiliser get_or_create lors de la création de votre objet Code au lieu de cela.

doc_code = Code(user_defined_code=user_defined_code, code=uniquecode)
34
DTing