Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django CharFIeld with unique=True update error "Instance with this Name already exists"

I'm building a Django project for a client that requires me to not user a simple form.save() method to update a model field.

Basically, it looks like this:

I have this model with a CharField who has unique=True:

# models.py

class Course(models.Model):
    name = models.CharField(max_length=20, unique=True)
    other_field = models.CharField(max_length=10, null=True)

    def __str__(self):
        return self.name

That model has a form in forms.py:

# forms.py

class CourseCreateForm(forms.ModelForm):
    class Meta:
        model = Course
        fields = ['name', 'other_field']

I need to update this field through a function view (can't be class based in this scenario. Of course, literally it can, but for my student's project requirements it can't be) and I can't use the simple form.save() function, so I need to do the full update code as if it was a normal form:

# views.py

def course_update(request, pk):
    course = Course.objects.get(pk=pk)
    course_queryset = Course.objects.filter(pk=pk)


    if request.method == "POST":
        form = CourseCreateForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            other_field = form.cleaned_data['other_field']
            course_queryset.update(name=name, other_field=other_field)  # <-- Where I try to update
        else:
            print(form.errors)
        return HttpResponseRedirect('../')
    else:
        form = CourseCreateForm(instance=course)

        context = {
            "form": form,
        }

        return render(request, 'base/course_update.html', context)

When I try to only update the other_field, the change isn't made and in the formerrors I receive the error "Course with this Name already exists.", so I can't only change the other_field data without also having to change the name field because the name field is unique.

How can you update a model instance's field that has unique=True without changing the unique value?

Hope this makes sense!

Thanks.

UPDATE:

Also wanted to add that it works perfectly fine when unique=True is turned off. I'm just curious how do you update a field normally when unique=True and you're adding in the same variable from a model form.

like image 527
Zack Plauché Avatar asked Sep 11 '25 17:09

Zack Plauché


1 Answers

The reason that this will fail is because the ModelForm thinks you are creating a new record, and thus it will check if an object with the given name already exists, and if so, it of course finds out the name already exists, hence the form is not valid.

You can pass the instance to the form. In that case the form will exclude that item from the unique check:

def course_update(request, pk):
    course = Course.objects.get(pk=pk)
    course_queryset = Course.objects.filter(pk=pk)
    if request.method == 'POST':
        form = CourseCreateForm(request.POST, instance=course)
        if form.is_valid():
            name = name_form.cleaned_data['name']
            other_field = course_form.cleaned_data['other_field']
            course_queryset.update(name=name, other_field=other_field)
            return HttpResponseRedirect('../')
        else:
            print(form.errors)
    else:
        form = CourseCreateForm(instance=course)
        context = {
            'name_form': name_form,
            'course_form': course_form,
        }
        return render(request, 'base/course_update.html', context)
like image 152
Willem Van Onsem Avatar answered Sep 14 '25 07:09

Willem Van Onsem