ian design
ian design

Reputation: 25

apply a filter to the choices field of my model

Hi I have problems with some filters in django. I have my own view where I can choose the day of the week which is a select choice field once chosen it is saved in the db. I would like to filter those already present so as not to repeat them if I had to choose another day. Can anyone help me out please?

models.py

class Piano(models.Model):
  nome_piano = models.CharField(max_length=100)
  data_inizio = models.DateField()
  data_fine = models.DateField()
  utente_piano = models.ForeignKey(
    User, 
    on_delete = models.CASCADE,
    related_name = 'utente_piano'
  )
  
  def __str__(self):
    return self.nome_piano

  class Meta:
    verbose_name = "Piano alimentare"
    verbose_name_plural = "Piani alimentari"

class PianoSingleDay(models.Model):
    giorni_settimana_scelta = [
        ("1","Lunedì"),
        ("2","Martedì"),
        ("3","Mercoledì"),
        ("4","Giovedì"),
        ("5","Venerdì"),
        ("6","Sabato"),
        ("7","Domenica")
    ]
    giorni_settimana = models.CharField(
        choices = giorni_settimana_scelta,
        max_length = 300
    )
    single_piano = models.ForeignKey(
        Piano,
        on_delete = models.CASCADE, 
        related_name = 'single_piano'
    )

    def __str__(self):
        return self.giorni_settimana
  
    class Meta:
        verbose_name = "Piano singolo"
        verbose_name_plural = "Piani singoli"

views.py

@login_required
def PianoSingleView(request, id):
    piano = get_object_or_404(models.Piano, id = id, utente_piano = request.user)

    if request.method == 'POST':
        giorno_form = PianoSingleDayForm(request.POST, prefix = 'giorno')
        if giorno_form.is_valid():
            day_piano = giorno_form.save(commit = False)
            day_piano.single_piano = piano
            day_piano.save()

            return redirect('gestione-piano', id = piano.id)

    else:
        giorno_form = PianoSingleDayForm(prefix = 'giorno')

    context = {'piano': piano, 'giorno_form': giorno_form}
    return render(request, 'crud/create/gestione_piano_single.html', context)

forms.py

class PianoSingleDayForm(forms.ModelForm):

    class Meta:
        model = models.PianoSingleDay
        exclude = ['single_piano']

1

enter image description here

2

enter image description here

Upvotes: 1

Views: 644

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476594

You can let the PianoSingleDayForm exclude the days that have already been selected for that Piano with:

class PianoSingleDayForm(forms.ModelForm):
    def __init__(self, *args, piano=None, **kwargs):
        super().__init__(*args, **kwargs)
        if piano is not None:
            days = set(PianoDaySingle.objects.filter(
                single_piano=piano
            ).values_list('giorni_settimana', flat=True))
            self.fields['giorni_settimana'].choices = [
                (k, v)
                for k, v in self.fields['giorni_settimana'].choices
                if k not in days
            ]

    class Meta:
        model = models.PianoSingleDay
        exclude = ['single_piano']

We can then use this in the view by passing the Piano object to the form both in the GET and POST codepath:

@login_required
def PianoSingleView(request, id):
    piano = get_object_or_404(models.Piano, id=id, utente_piano=request.user)
    if request.method == 'POST':
        giorno_form = PianoSingleDayForm(request.POST, piano=piano, prefix='giorno')
        if giorno_form.is_valid():
            giorno_form.instance.single_piano = piano
            giorno_form.save()
            return redirect('gestione-piano', id=piano.id)
    else:
        giorno_form = PianoSingleDayForm(piano=piano, prefix='giorno')
    
    context = {'piano': piano, 'giorno_form': giorno_form}
    return render(request, 'crud/create/gestione_piano_single.html', context)

Upvotes: 1

Related Questions