Search code examples
djangoclass-method

Django call @classmethod create from SystemCreateView


I want to call the @classmethod create of the System model by the SystemCreateView. However currently the create classmethod is not called and therefore the z-property of the System model is not calculated but remains at it's default value of 4.

The simplified version of the model Class is:

class System(models.Model):
    project     = models.ForeignKey('solgeo.Project', related_name='systems', on_delete=models.CASCADE)
    x           = models.IntegerField(default=1)
    y           = models.IntegerField(default=4)

    # calculated properties
    z = models.IntegerField(default=4)

    @classmethod
    def create( cls, project, x, y):
        system = cls(project=project, x=x, y=y)

        # Calculated properties
        system.z = x*y
        return system

The SystemForm is defined as:

class SystemForm(forms.ModelForm):
    class Meta:
        model = System
        fields = [
            'x',
            'y'
        ]

The CreateView is currently as follows:

class SystemCreateView(LoginRequiredMixin, CreateView):
    model = System
    template_name = 'system/create.html'
    form_class = SystemForm

    def form_valid(self, form):
        obj = form.save(commit=False)
        project_id = self.kwargs['pk']
        project = get_object_or_404(Project, pk=project_id)
        obj.project = project
        return super(SystemCreateView, self).form_valid(form)

    def get_context_data(self, *args, **kwargs):
        context = super(SystemCreateView, self).get_context_data(*args, **kwargs)
        context['project_id'] = self.kwargs['pk']
        return context

Solution

  • Instead of saving the form, you can call your class method with values from the form’s cleaned data. You should then return a redirect response instead of calling super() (which would save the form.

    self.obj = System.create(project, x=form.cleaned_data['x'], y=form.cleaned_data['y'])
    return redirect(self.get_success_url())