6

I've tried solutions from the following posts:

Saving data from ModelForm : Didn't work

ModelForm data not saving django : Didn't work.

I'm trying to save data from a ModelForm into the model.

models.py:

class Testimonials(models.Model):
    name = models.CharField(max_length=128)
    credentials = models.CharField(max_length=128)
    test = models.CharField(max_length=2000)
    id = models.AutoField(primary_key=True)
    NO = 'NO'
    YES = 'YES'
    APPROVAL = ((NO, 'no'), (YES, 'yes'))
    verified = models.CharField(choices=APPROVAL, default=NO, max_length=3) #Field for making sure only verified testimonials are displayed

    def __unicode__(self):
        return self.id

forms.py:

class TestimonialForm(forms.ModelForm):
    name = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control input-area', 'placeholder': 'Enter your name'}), required=True)
    credentials = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control input-area', 'placeholder': 'Enter your designation'}), required=True)
    test = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control test-form-area', 'placeholder': 'Testimonial', 'rows': '5'}), required=True)
    verified = forms.ChoiceField(widget=forms.HiddenInput())

    class Meta:
        model = Testimonials  

views.py

def add_testimonial(request):
    context = RequestContext(request)
    if request.method == 'POST':
        form = TestimonialForm(request.POST)

        if form.is_valid():
            form.save(commit=True)
            return HttpResponseRedirect('/testimonials/thanks/')
        else:
            print form.errors

    else:
        form = TestimonialForm()

    return render_to_response('templates/add_testimonial.html', {'form': form}, context)

Template:

<form id="testimonial_form" method="POST" action="/testimonials/thanks/">
    {% csrf_token %}
    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}
    {% for field in form.visible_fields %}
        {{ field.help_text}}
        {{ field }}
    {% endfor %}
    <input type="submit" name="submit" value="Add testimonial" class="btn btn-info test-button"/>
</form>

EDIT:

urls.py

url(r'^testimonials/all/', views.testimonials, name='testimonial'),
url(r'^testimonials/thanks/', views.testimonials_thanks, name='testimonial_thanks'),
url(r'^add_testimonial', views.add_testimonial, name='add_testimonial'),

However, on redirect, it doesn't save the form into the model which I'm checking from both PHPMyAdmin (using a MySQLdb) and the Django Admin panel. Any idea why?

Community
  • 1
  • 1
Newtt
  • 6,050
  • 13
  • 68
  • 106

1 Answers1

5

You are POSTing to /testimonials/thanks/ which should be changed to your add_testimonial route to have your view handle the POST. So, the solution is to change the action value in your template's form tag.

If you can post the relevant code from your urls.py I can provide a more specific answer as to what the value of the action attribute should be.

Update

The redirect will happen in your view when a valid form is POSTed. Change your template's action attribute value to:

<form id="testimonial_form" method="POST" action="{% url 'add_testimonial' %}">

In your view:

if form.is_valid():
    form.save()
    return HttpResponseRedirect(reverse('testimonial_thanks'))

And make sure you include the following import in your view:

from django.core.urlresolvers import reverse

Update 2

Display your form errors in your template:

<form id="testimonial_form" method="POST" action="{% url 'add_testimonial' %}">
    {% csrf_token %}
    {% if form.non_field_errors %}
        <div class="form-group text-error">
            {{ form.non_field_errors }}
        </div>
    {% endif %}

    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}
    {% for field in form.visible_fields %}
        {{ field.help_text}}
        {{ field }}
        {% if field.errors %}
            <span>{{ field.errors|striptags }}</span>
        {% endif %}
    {% endfor %}
    <input type="submit" name="submit" value="Add testimonial" class="btn btn-info test-button"/>
</form>

Update 3

Now that you can see your form errors, you will need to provide your default value to the hidden field, and there's no need to make it a ChoiceField if the user has no choice (it's hidden!). So change the verified form field to:

verified = forms.CharField(widget=forms.HiddenInput(), initial='no')

Also, it would be a good idea to verify the value in your view since even though the field is hidden, an enterprising, evil user can still POST other values.

Fiver
  • 9,909
  • 9
  • 43
  • 63
  • Added urls.py. Also, my original code did have action as 'add_listing'. That saved to the model, but I wanted to redirect to another url on success so I changed action to `testimonials/thanks` – Newtt May 15 '14 at 23:08
  • Great, I've updated my answer. Let me know how you get along. – Fiver May 15 '14 at 23:12
  • And any changes to be made in the views.py? Because I tried this and there was no effect. It didn't redirect to `testimonials/thanks/`. If it helps, my form data in the console is as follows: `verified:` `name:Save` `credentials:Save` `test:Save` `submit:Add testimonial` – Newtt May 15 '14 at 23:19
  • Ok, you may need to use your "thanks" url name in the view. see update – Fiver May 15 '14 at 23:25
  • Doesn't seem to be working. You can try it out [here](http://silverinnings.herokuapp.com/add_testimonial) – Newtt May 15 '14 at 23:38
  • It may be that you have form errors, try displaying both the field errors and non-field errors on your template. – Fiver May 15 '14 at 23:51
  • Yep, there's an error in the hidden input field.I've assigned it a default value of 'No', but it doesn't send it across to the model as the default shows empty. – Newtt May 16 '14 at 00:01
  • That's your issue, set an initial value for the field. Also, there's no need to have verified be a choice field if the user has no choice since it's hidden. I've updated the answer again, this should do the trick! – Fiver May 16 '14 at 12:48
  • hello, im new to django, and was wondering if you can explain what this part means action="{% url 'add_testimonial' %}" , im basically trying to use one template for my "posts/new" url and "posts//update" url. not sure if that's the best way to go but was just following a tutorial – gdubs Mar 31 '20 at 16:04