-2

I asking for help sorting the reason for the form being invalid.

In the application, Programmes run on specific dates, stored in the 'DAY' model. One or more Profs may be added to one or more days of a programme. In FORMS, I've filtered the day=ModelChoiceField so that only the dates related to the programme to which the prof should be added are available for selection.

However on save, I'm getting a form invalid. All help much appreciated. Thank you.

Models:

class Programme(models.Model):
    name = models.CharField('Programme Name', max_length=50, editable=True)
    slug = models.SlugField(unique=True, max_length=10)

class Prof(models.Model):
    programme = models.ForeignKey(Programme, on_delete=models.CASCADE)
    prof = models.ForeignKey(User, on_delete=models.CASCADE)
    day = models.ForeignKey(Day, on_delete=models.CASCADE)

class Day(models.Model):
    programme = models.ForeignKey(Programme, on_delete=models.CASCADE)
    date = models.DateTimeField(editable=True)
    start_time = models.TimeField(editable=True, blank=True, null=True)
    end_time = models.TimeField(editable=True, blank=True, null=True)

class Role(models.Model):
    role = models.CharField(max_length=50, editable=True, unique=True)

Views:

class ProfCreate(CreateView):
    model = Prof
    form_class = ProfCreateForm
    context_object_name = 'obj'
    template_name = 'programme/prof_create.html'
    extra_context = {'page_title': 'Add Prof'}
    success_url = reverse('programme:programme_detail')

    def get_form_kwargs(self):
        #pass programme_id to form modelchoicefield filter
        kwargs = super().get_form_class()
        programme = Programme.objects.get(slug=self.kwargs['slug')
        self.kwargs['programme_id'] = programme.id
        return self.kwargs

    def form_valid(self, form):
        if form.is_valid:
            prof = form.save(commit=False)
            programme = Programme.objects.get(slug=self.kwargs['slug'])
            prof.programme_id = self.programme_id
            prof.save()
        return redirect('programme:programme_detail', self.kwargs['slug'])

    def form_invalid(self, form):
        print ('FORM INVALID - - WHY?')
        return redirect('programme:programme_detail', self.kwargs['slug'])

Forms:

class ProfCreateForm(ModelForm):
    #filter programme days available in day ModelChoiceField
    def __init__(self, *args, **kwargs):
        programme_id = kwargs.pop('programme_id')
        slug =kwargs.pop('slug')
        print ('id, slug', programme_id, slug)
        super(CxoCreateForm, self).__init__(*args, **kwargs)
        self.fields['day'].queryset=Day.objects.filter(programme_id=programme_id)

    prof = ModelChoiceFieldName(queryset=User.objects.filter(is_contractor=True))
    role = ModelChoiceField(queryset=Role.objects.all())
    day = ModelChoiceField(queryset=Day.objects.all())

    class Meta:
        model = Prof
        fields = ('prof', 'role', 'day')
William
  • 115
  • 1
  • 2
  • 12
  • `if form.is_valid:` <- this should be `.is_valid()`, otherwise it will return `True` every time as you just check if `is_valid` property exists. Next line: `prof.programme_id = self.programme_id` - where do you even set the `self.programme_id` property? – yedpodtrzitko Aug 16 '20 at 13:12
  • Thanks for the catch. The missing line of code (programme = Programme.objects.get(slug=self.kwargs['slug'])) has been added to the form_valid section. As an additional note, if I remove the ModelChoiceField filter (so all dates for all programmes are shown, and remove the get_form_kwargs section, the form is saves correctly. It seems that with the filter in place the form_valid bit is never run. – William Aug 16 '20 at 22:16
  • Have tracked down this error but am unclear how to resolve: FORM ERRORS = > – William Aug 17 '20 at 00:36

1 Answers1

0

Solution: <views.py>

class ProfCreate(CreateView):
    model = Prof
    form_class = ProfCreateForm
    context_object_name = 'prof'
    template_name = 'programme/prof_create.html'
    extra_context = {'page_title': 'CxO'}

    def get_form_kwargs(self, *args, **kwargs):
        kwargs = super(ProfCreate, self).get_form_kwargs(*args, **kwargs)
        programme =  Programme.objects.get(slug=self.kwargs['slug'])
        kwargs['programme_id'] = programme.id
        return kwargs

    def form_valid(self, form):
        if form.is_valid:
            prof = form.save(commit=False)
            programme = Programme.objects.get(slug=self.kwargs['slug'])
            prof.programme_id = programme.id
            prof.save()
        return redirect('programme:programme_detail', self.kwargs['slug'])

<forms.py>

class ProfCreateForm(ModelForm):
    def __init__(self, *args, **kwargs):
        programme_id = kwargs.pop('programme_id')
        super(ProfCreateForm, self).__init__(*args, **kwargs)
        self.fields['day'].queryset=Day.objects.filter(programme_id=programme_id)

    prof = ModelChoiceFieldName(queryset=User.objects.filter(is_contractor=True))
    role = ModelChoiceField(queryset=ProfRole.objects.all())
    day = ModelChoiceField(queryset=Day.objects.all())

    class Meta:
        model = Prof
        fields = ('prof', 'role', 'day')
William
  • 115
  • 1
  • 2
  • 12