0

I'm doing the following, which works nicely when the user proceeds down the golden path:

class MyUpdate(UpdateView)
    # ...

class MyDuplicate(MyUpdate):
    def get_context_data(self, **kwargs):
        context = super(MyDuplicate, self).get_context_data(**kwargs)
        context['action'] = "Duplicate"
        return context

    # where should I call Klass::duplicate?

    def form_valid(self, form):
        name = form.instance.full_name
        video_url = form.instance.video_url

        # This doesn't work because it can result in unhandled uniqueness 
        # constraint violations.
        form.instance = Klass.duplicate(
            form.instance,
            name,
            video_url
        )
        return super(MyDuplicate, self).form_valid(form)

However, if the user attempts to submit an existing full_name (which must be unique), then the call to Klass.duplicate results in an unhandled uniqueness constraint violation.

So, my question is: where should I make the call to Klass.duplicate (unsets pk, resets other values and then calls save -- elided for brevity) in the UpdateView lifecycle?

UPDATE:

It looks like overriding post might be one way to do this. Unfortunately, I can't just pass the form instance along to Klass.duplicate as its fields are empty by default.

pdoherty926
  • 9,895
  • 4
  • 37
  • 68
  • 1
    I find this website a great reference for Django CBV: https://ccbv.co.uk/projects/Django/1.11/django.views.generic.edit/UpdateView/ I often look at it when working out where I need to override. – Mark Bailey Apr 24 '19 at 16:27
  • Thanks! This is a great supplement to the viewing the source and it's certainly easier to pin down the version you're interested in. – pdoherty926 Apr 24 '19 at 16:33

1 Answers1

0

The solution I came up with was to provide a ModelForm subclass to the CBV via form_class and use its overridden is_valid method to handle any potential exceptions and provide feedback to the end user.

So, based on the example in my original question, the solution would look something like:

class MyDuplicateForm(forms.ModelForm):
    class Meta:
        model = Klass
        fields = [...]

    def is_valid(self):
        valid = super(MyDuplicateForm, self).is_valid()
        if not valid:
            return False
        try:
            self.instance = Klass.duplicate(self.instance)
        except Exception as exception:
            self._errors[NON_FIELD_ERRORS] = exception
            return False

        return True

class MyDuplicate(UpdateView):
    form_class = MyDuplicateForm
    model = klass
pdoherty926
  • 9,895
  • 4
  • 37
  • 68