Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django form fails validation on a unique field

Tags:

I have a simple model that is defined as:

class Article(models.Model):
    slug  = models.SlugField(max_length=50,  unique=True)
    title = models.CharField(max_length=100, unique=False)

and the form:

class ArticleForm(ModelForm):
    class Meta:
       model = Article

The validation here fails when I try to update an existing row:

 if request.method == 'POST':
     form = ArticleForm(request.POST)

     if form.is_valid(): # POOF
         form.save()

Creating a new entry is fine, however, when I try to update any of these fields, the validation no longer passes.

The "errors" property had nothing, but I dropped into the debugger and deep within the Django guts I saw this:

slug: "Article with this None already exists"

So it looks like is_valid() fails on a unique value check, but all I want to do is update the row.

I can't just do:

form.save(force_update=True)

... because the form will fail on validation.

This looks like something very simple, but I just can't figure it out.

I am running Django 1.0.2

What croaks is BaseModelForm.validate_unique() which is called on form initialization.

like image 569
Andrei Taranchenko Avatar asked Feb 08 '09 21:02

Andrei Taranchenko


2 Answers

I don't think you are actually updating an existing article, but instead creating a new one, presumably with more or less the same content, especially the slug, and thus you will get an error. It is a bit strange that you don't get better error reporting, but also I do not know what the rest of your view looks like.

What if you where to try something along these lines (I have included a bit more of a possible view function, change it to fit your needs); I haven't actually tested my code, so I am sure I've made at least one mistake, but you should at least get the general idea:

def article_update(request, id):
   article = get_objects_or_404(Article, pk=id)

   if request.method == 'POST':
      form = ArticleForm(request.POST, instance=article)

      if form.is_valid():
         form.save()

         return HttpResponseRedirect(to-some-suitable-url)

   else:
      form = ArticleForm(instance=article)

   return render_to_response('article_update.html', { 'form': form })

The thing is, as taurean noted, you should instantiate your model form with the object you wish to update, otherwise you will get a new one.

like image 98
Johan Avatar answered Sep 20 '22 01:09

Johan


I was also searching for a way to update an existing record, even tried form.save(force_update=True) but received errors?? Finally by trial & error managed to update existing record. Below codes tested working. Hope this helps...

models.py from djangobook

class Author(models.Model):
    first_name = models.CharField(max_length=30)

    last_name = models.CharField(max_length=40)

    email = models.EmailField(blank=True, verbose_name='e-mail')

    objects = models.Manager()

    sel_objects=AuthorManager()

    def __unicode__(self):
        return self.first_name+' '+ self.last_name

class AuthorForm(ModelForm):
    class Meta:
        model = Author


# views.py
# add new record

def authorcontact(request):

    if request.method == 'POST':

        form = AuthorForm(request.POST)

        if form.is_valid():

            form.save()

            return HttpResponseRedirect('/contact/created')

    else:

        form = AuthorForm()

    return render_to_response('author_form.html', {'form': form})

update existing record

def authorcontactupd(request,id):

    if request.method == 'POST':

        a=Author.objects.get(pk=int(id))

        form = AuthorForm(request.POST, instance=a)

        if form.is_valid():

            form.save()

            return HttpResponseRedirect('/contact/created')

    else:
        a=Author.objects.get(pk=int(id))

        form = AuthorForm(instance=a)

    return render_to_response('author_form.html', {'form': form})
like image 44
mcwong Avatar answered Sep 20 '22 01:09

mcwong