Brigitte Maillère
Brigitte Maillère

Reputation: 865

How to use django smart-selects with modelform?

I'm using smart-selects.

Edited : Here is the code that works for me, after adding {{ form.media.js }} in the template , thanks to @Evangelos

models.py :

from django.db import models
from smart_selects.db_fields import ChainedForeignKey, ChainedManyToManyField

class ChoixTangente(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class ChoixModele(models.Model):
    name = models.CharField(max_length=255)
    tangentes = models.ManyToManyField('Choixtangente', blank=True)

    def __str__(self):
        return self.name    

class TypeModele(models.Model):
    tangente = models.ForeignKey(ChoixTangente, blank=True, null=True)
    type_modele = ChainedForeignKey(
        ChoixModele,
        chained_field="tangente",
        chained_model_field="tangentes",
        show_all=False, 
        auto_choose=True,
        blank=True, null=True
    )

    def __unicode__(self):
        return str(self.pk)

form.py :

from django import forms
from .models import ChoixTangente, ChoixModele, TypeModele

class TypeModeleForm(forms.ModelForm):
    class Meta:
        model = TypeModele
        fields = ('tangente', 'type_modele')

views.py

from .models import ChoixTangente, ChoixModele, TypeModele
from .forms import TypeModeleForm

def type_modele_new(request):
    if request.method == "POST":
        form = TypeModeleForm(request.POST)
        if form.is_valid():

            modele_instance = form.save()

            return redirect('calculs.views.type_modele_detail', pk=modele_instance.pk)

    else: 
        form = TypeModeleForm()  

    return render(request, 'calculs/type_modele_new.html', {'form': form})

def type_modele_detail(request, pk):
    modele_instance = get_object_or_404(TypeModele, pk=pk)
    return render(request, 'calculs/type_modele_detail.html', {'modele_instance': modele_instance})

template : type_modele_new.html

{% load staticfiles %}

<form method="POST">
    {% csrf_token %}
    **{{ form.media.js }}**
    {{ form.as_p}}
    <input type="submit" value="Submit">
</form>  

urls.py

from django.conf.urls import url, include
from . import views
from smart_selects import urls as smart_selects_urls

urlpatterns = [
    url(r'^chaining/', include('smart_selects.urls')), 
    url(r'^type_modele/new/$', views.type_modele_new, name='modele_new'),
    url(r'^type_modele/(?P<pk>[0-9]+)/$', views.type_modele_detail, name='modele_detail'),

]

Edited : and here was the problem :

I have it working fine in admin :

  1. I create ChoixTangente instances
  2. I create ChoixModele instances and select ChoixTangentes instances in the list
  3. I can create TypeModele" instances by selecting "tangente" in a list of ChoixTangente and "type_modele" in the list of corresponding ChoixModele choices resulting from the steps 1) and 2)

see Admin form screenshot

I whish to have my users do the same through a form. But I can't have it working.

the field "Tangente" is populated with the list of ChoixTangente but when I choose a value the field "type_modele" stays empty instead of displaying a list of corresponding choices.

see form screenshot for the users

Upvotes: 2

Views: 2739

Answers (1)

Evangelos
Evangelos

Reputation: 279

First of all where is your views?

Try to post more complete question with files for better understanding.

Where is the model Appareil in the models.py you are refering to in forms.py?

And your fields should be in list [].

Your forms.py should look like:

from django import forms

from .models import Modele

class AppareilForm(forms.ModelForm):
    class Meta:
        model = Modele
        fields =['tangente', 'modele']

You don't need to write javascript.

Just remember to include url(r'^chaining/', include('smart_selects.urls')) to your urls.py

in your view call the AppareilForm Read about forms in views for details.

And in the template just use {{form.as_p}} and {{ form.media.js }} before to load javascript and make sure to load static in your template. {% load static % }

Your template should look something like this

{% load static % }

<form action="your url that points to your view" method="POST">
    {% csrf_token %}
    {{ form.media.js }}
    {{ form.as_p}}
    <input type="submit" value="Submit">
</form>

Read the django-selects description carefully.

Upvotes: 4

Related Questions