简体   繁体   中英

How can I specify form validation errors when they occur?

I'm quite new to Django Forms, and I'm facing a problem that I cannot solve. I've been googling and reading the docs, but I can't find the place where this is explained. My problem is that I have an Animal Model and a ModelForm :

class Animal(models.Model):
    name = models.CharField(max_length=300)
    age = models.PositiveSmallIntegerField()
    race = models.ForeignKey(Race)
    description = models.TextField()
    state = models.ForeignKey(State)
    pub_date = models.DateTimeField(auto_now_add=True)
    adoption_limit = models.DateTimeField(blank=True, null=True)
    location = models.ForeignKey(Location)
    publisher = models.ForeignKey(User)
    def __unicode__(self):
        return self.name

class AnimalForm(ModelForm):
    class Meta:
        model = Animal

I render this info via urls.py, calling this view:

@login_required
def new_animal(request):
    if request.method == "POST":
        form = AnimalForm(request.POST)
        if form.is_valid():
            form.save()
            return render_to_response('/')
        else:
            variables = RequestContext(request, {'e': form.errors})
            return render_to_response('web/error.html', variables)
    else:
        form = AnimalForm()
    variables = RequestContext(request, {'form': form})
    return render_to_response('web/animal_form.html', variables)

It seems that I have an error introducing the adoption_limit field, so the data does not get saved in DB. This is because I just set a date and not a time into the text field displayed by the form.

I would like to know how can I do two things:

  1. How can I send the error message to the form again, so that I can add a text next to the field that I have not set correctly? Ie, like the admin does.
  2. How can I put the same input type for DateTimeField that I have in the admin interface? (with the Today and Now functions)

The way you have written your view, to display form errors, in your web/error.html template, simply output the errors:

{%if e %}
  You had some errors in your submission!<br />
  {{ e }}
{% endif %}

However, you don't have explicitly pass the errors list, it is part of the form itself. A bit of simplification:

variables = RequestContext(request, {'form': form})
return render_to_response('web/error.html', variables)

Then, in your template:

{% if form.errors %}
   You have some errors!<br />
   {{ form.errors }}
{% endif %}

For the second part of your question - to display the django date time widget - things get a bit more involved:

# First, you need to import the widget:
from django.contrib.admin.widgets import AdminSplitDateTime
from django.forms import TextField

# In your form class, you have to specify the widget
# for the field.

class AnimalForm(forms.ModelForm):
   pub_date = models.TextField(widget=AdminSplitDateTime)
   class Meta:
      model = Animal

In order for this to work though, you have to make sure your admin media directory is accessible from your project (since all the javascript and css is included there). You'll also to have make sure that all the stylesheets are also added. It is much easier (and simpler) to use your own javascript form widget from your preferred library.

Finally, as stated in the documentation , if you override any fields, you need to add all the other validation logic yourself:

If you explicitly instantiate a form field like this, Django assumes that you want to completely define its behavior; therefore, default attributes (such as max_length or required) are not drawn from the corresponding model. If you want to maintain the behavior specified in the model, you must set the relevant arguments explicitly when declaring the form field.

burhan's answer is spot on. Additionaly, You might probably want to hide the publisher on the form and deal with it in your view.

To do this, add exclude = ('publisher',) to class Meta in your ModelForm.

And then in your view:

if form.is_valid():
    animal = form.save(commit=false)
    animal.publisher = request.user
    animal.save()

Otherwise, as it stands I think your form will show all users in a dropdown, which might not be what you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM