Peter Maciejko
Peter Maciejko

Reputation: 811

Custom error_messages. Django 1.8.6

This day I have read the mass of information about overiding form default error_messages and I just can not handle it. I do not know what is wrong with my code and why my custom message does not work:

This is my views.py

### views.py ###
from django.shortcuts import render
from django.shortcuts import render_to_response
from django.core.urlresolvers import reverse
from django.views import generic
from django.template import RequestContext
from django.http import JsonResponse

from comments.models import Comment
from companies.models import Company

# Create your views here.

class IndexView(generic.ListView):
    model = Comment

    def get_queryset(self):
        return  Comment.objects.filter(company = self.kwargs['pk']).order_by('-add_date')

class AjaxAdd(object):
    def form_invalid(self, form):
        response = super(AjaxAdd, self).form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status = 400)
        else:
            return response

    def form_valid(self, form):
        form.instance.company = Company.objects.get(pk = self.kwargs['company'])
        response = super(AjaxAdd, self).form_valid(form)
        if self.request.is_ajax():
            five_comments_list = Comment.objects.order_by('-add_date').filter(company = self.object.company)
            data = {}
            data['five_comments_list'] = five_comments_list

            return render_to_response('companies/includes/_five_comments_list.html', data, context_instance=RequestContext(self.request))
        else:
            return response

class AddView(AjaxAdd, generic.edit.CreateView):
    model = Comment
    fields = ['text']

    def get_success_url(self):
        return reverse('companies:detail', args = (self.kwargs['company'],))

class AjaxDelete(object):
    def dispatch(self, *args, **kwargs):
        response = super(AjaxDelete, self).dispatch(*args, **kwargs)
        if self.request.is_ajax():
            five_comments_list = Comment.objects.order_by('-add_date').filter(company = self.object.company)
            data = {}
            data['five_comments_list'] = five_comments_list
            return render_to_response('companies/includes/_five_comments_list.html', data, context_instance=RequestContext(self.request))
        else:
            return response

class DeleteView(AjaxDelete, generic.edit.DeleteView):
    model = Comment

    def get_success_url(self):
        return reverse('companies:detail', args = (self.kwargs['company'],))

and this is my forms.py

### forms.py ###
# -*- coding: utf-8 -*-

from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext as _


from comments.models import Comment

class CommentForm(ModelForm):

    class Meta:
        model = Comment
        fields = ['text',]

        labels = {
            'text': '',
        }

        error_messages = {
            'text': {
                'required': _("lknlkjnlkjnl"),
            },
        }

        widgets = {
            'text': forms.Textarea(
                attrs = {
                    'id': 'text-comment-input',
                    'placeholder': 'Wpisz tu treść zgłoszenia...',
                }
            ),
        }

    def __init__(self, *args, **kwargs):
        self.fields['text'].error_messages = {'required': 'First Name is Required'}

Im calling add comment action from 'company' app like so:

###company view.py
class DetailView(generic.DetailView):
    model = Company

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)
        context['five_comments_list'] = self.object.get_latest_comments()
        context['add_comment_form'] = CommentForm
        return context

and template:

###company_detail.html

<form id="add-comment-form" method="post" action="{% url 'comments:add' company.id %}">
  {% csrf_token %}
  {{ add_comment_form }}
  <input type="submit" value="Dodaj">
</form>

<div id="company-comments">
    {% include 'companies/includes/_five_comments_list.html' %}
</div>

My javascript:

function AddComment() {

  handle_submit = function(event) {
    event.preventDefault();

    $.ajax({
      url : $('#add-comment-form').attr('action'),
      type : $('#add-comment-form').attr('method'),
      data : {
        text : $('#text-comment-input').val(),
      },

      success : function(json) {
        $('#company-comments').empty();
        $('#company-comments').prepend(json);
      },

      error : function(xhr, errmsg, err) {

        console.log(xhr.responseText);
        /*var old_placeholder_text = 'Wpisz tu treść zgłoszenia...';
        var new_placeholder_text = JSON.parse(xhr.responseText).text[0];

        $('textarea').attr('placeholder', new_placeholder_text);
                $('textarea').addClass('form-error');

                $(document).on('click', 'textarea', function(){
                    $('textarea').removeClass('form-error');
                    $('textarea').attr('placeholder', old_placeholder_text);
                });*/
      }
    });
  };

  init = function() {
    $(document).on('submit', '#add-comment-form', handle_submit);
  };
  init();
};

function DeleteComment() {

  handle_submit = function(event) {
    event.preventDefault();

    $.ajax({
      url : $('#delete-comment-form').attr('action'),
      type : $('#delete-comment-form').attr('method'),

      success : function(json) {
        $('#company-comments').empty();
        $('#company-comments').prepend(json);
      },

      error : function(xhr, errmsg, err) {
        console.log(xhr.status + ': ' + xhr.responseText);
      }
    });
  };

  init = function() {
    $(document).on('submit', '#delete-comment-form', handle_submit);
  };
  init();
};

$(document).ready(function() {

  new AddComment();
  new DeleteComment();

});

Upvotes: 1

Views: 683

Answers (1)

Alasdair
Alasdair

Reputation: 308849

You need to tell Django to use your custom form in the view, by setting form_class, for example.

class AddView(AjaxAdd, generic.edit.CreateView):
    model = Comment
    form_class = CommentForm

Your __init__ method looks wrong, because it's not calling super(). I would remove the following line from the __init__ method, it will undo the customisation.

       self.fields['text'].error_messages = {'required': 'First Name is Required'}

If that's the only thing in the __init__ method, then remove it completely.

A working example

When I submit the following empty form, I see the custom error message. It appears to work for ajax requests as well.

Model

class MyModel(models.Model):
    name = models.CharField(max_length=100)

Model Form

class MyModelForm(forms.ModelForm):

    class Meta:
        fields = '__all__'
        model = MyModel
        error_messages = {'name': {'required': 'Custom required error message'}}

View

from django.views.generic.edit import UpdateView
from django.http import JsonResponse

class MyUpdateView(UpdateView):
    model = MyModel
    form_class = MyModelForm

    template_name = 'my_template.html'

    def form_invalid(self, form):
        response = super(MyUpdateView, self).form_invalid(form)
        if not self.request.is_ajax():
            return JsonResponse(form.errors, status = 400)
        else:
            return response

URL

urlpatterns = [
    url(r'^(?P<pk>\d+)/$', MyUpdateView.as_view()),
]

Upvotes: 1

Related Questions