0

I am trying to create a form and save data to database when the submit button is clicked. But the data is not getting saved to database. i dont get any error. I am django 1.11. I referred to few stackoverflow question and that answers doesnt solve my issue. Could someone help in fixing it? Thanks in advance.

model.py

from __future__ import unicode_literals

from django.db import models

class NameForm(models.Model):
    your_name = models.CharField(max_length=200)

views.py

from __future__ import unicode_literals

from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.views import generic
from django.template.response import TemplateResponse

from home.models import NameForm
from .forms import NameForm

class NameView(generic.View):
    model_class = NameForm
    initial = {'key': 'value'}
    template_name = 'home/name.html'

    def get(self, request, *args, **kwargs):
        model = self.model_class()
        return render(request, self.template_name, {'model': NameForm})

    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            form = NameForm(request.POST)
            if form.is_valid():
                return HttpResponseRedirect('thanks/')
                if form.is_valid():
                    form.save()
                else:
                    form = NameForm()

                    return render(request, 'name.html', {'form': form})

urls.py

from django.conf.urls import url

from . import views

app_name = 'home'

urlpatterns = [
    url(r'^$', views.NameView.as_view(), name='name'),
    url(r'^your-name/$', views.NameView.as_view(), name='name'),
    url(r'^your-name/thanks/$', views.NameView.as_view(), name='name'),
]

home/name.html

<form action="your-name/" method="post">
  {% csrf_token %}
    <label for="your_name">Your name: </label>
    <input id="your_name" type="text" name="your_name" value="{{ current_name }}">
    <input type="submit" value="OK">
</form>

forms.py

from .models import NameForm
from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='Your name', max_length=100)
    class Meta:
        model = NameForm
        fields = ['your_name']
2
  • You model and your form are named the same. So when you import them both in your view, only the last one (the form class) is being used. Commented Jul 19, 2018 at 7:28
  • You're not using a forms.ModelForm, so the Meta class does nothing. Commented Jul 19, 2018 at 7:31

2 Answers 2

5

You'll get by much easier if you use the batteries included in Django. Here's a list of the fixes in the version below...

  • Don't reuse names. NameModel is a model, NameForm is a form. (However, you'd usually really elide Model from a model name – it's just that Name sounded like a silly name for a model...)
  • Use ModelForms when you're managing models. They automatically validate input against your models, let you save the models easily, etc.
  • Use the CreateView/UpdateView/FormView generic views to deal with model creation, updates, inputs, etc. No code needed, just configuration!
  • Don't template forms yourself. form.as_p will get you a barebones form; form.your_name would render that field, etc.

Just a fair warning: this is dry-coded, so there might be typos or other small silliness.

models.py

from django.db import models

class NameModel(models.Model):
    your_name = models.CharField(max_length=200)

forms.py

from django import forms

class NameForm(forms.ModelForm):
    class Meta:
        model = NameModel
        fields = ['your_name']

views.py

from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import NameModel
from .forms import NameForm

class NameView(CreateView):
    model_class = NameModel
    form_class = NameForm
    success_url = reverse_lazy('name-thanks')
    initial = {'your_name': 'value'}
    template_name = 'home/name.html'

urls.py

from django.conf.urls import url
from django.views.generic import FormView

from .views import NameView

app_name = 'home'

urlpatterns = [
    url(r'^$', NameView.as_view(), name='name'),
    url(r'^your-name/thanks/$', TemplateView.as_view({'template_name': 'home/thanks.html'}), name='name-thanks'),
]

home/name.html

<form action="your-name/" method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" value="OK">
</form>
Sign up to request clarification or add additional context in comments.

1 Comment

You've cranked it, found all issues in OP's question. Respect.
4

That's beacuse you've been redirected (return HttpResponseRedirect('thanks/')) before save

Your version:

if form.is_valid():
    return HttpResponseRedirect('thanks/')
        if form.is_valid():
            form.save()
        else:
            ...

And the version you seek, with redirect only after form saving and removed redundant second form.is_valid() check:

if form.is_valid():
    form.save()
    return HttpResponseRedirect('thanks/')
else:
    ...

4 Comments

i do this i am getting this error 'NameForm' object has no attribute 'save'
That's probably because you name your form and your model same name, which is a bad thing.
Sorry to ask. what should i change now? Name of my form or model?
Also take a look at @AKX comment, that you should inherit from forms.ModelForm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.