metersk
metersk

Reputation: 12499

Django form submits (I think) but does not send to database

Below is my code for what I think should be a working version of an email submit form within a bootstrap3 modal. Upon form submit I am taken to the barebones thank you page, but I do not think the email address is being sent to the database because I can't see in Django admin.

Also, another reason I think this is broken is that the form validation does not seem to be working. I can submit something that looks nothing like an email address and I am still being sent to the thank you page.

Do I have issues in all of my files, or are they isolated to a specific area?

views.py

from django.shortcuts import render
from temp.models import Email
from forms import EmailForm

def index(request):
    if request.POST:
        form = EmailForm(request.POST)
        if form.is_valid():
            email = EmailForm()
            email.save()
            return render(request, 'temp/thanks.html')

    return render(request, 'temp/index.html')

def thanks(request):
    return render(request, 'temp/thanks.html')

forms.py

from django import forms

class EmailForm(forms.Form):
    email = forms.CharField(max_length=100)

models.py

    from django.db import models

    class Email(models.Model):
        email = models.CharField(max_length=200)

        def __unicode__(self):  # Python 3: def __str__(self):
            return self.email

index.html

        <!-- Modal -->
        <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                        <h4 class="modal-title" id="myModalLabel">Sign up for the Beta</h4>
                    </div>

                    <div class="modal-body">
                        <!-- The async form to send and replace the modals content with its response -->
                        <form class="form-horizontal well" data-async data-target="#myModal" action="thanks/" method="POST">
                            {% csrf_token %}

                            <fieldset>
                                <div>Your email address:
                                    <span>


                                        <input type="text" id="modalInput"></input>

                                    </span>
                                </div>
                            </fieldset>

                    </div>

                    <div class="modal-footer">
                        <button type="submit" class="btn btn-default" data-dismiss="modal">Close</button>
                        <button type="submit" class="btn btn-primary">Submit</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
        <!-- End Modal -->

Upvotes: 0

Views: 1229

Answers (5)

elmonkeylp
elmonkeylp

Reputation: 2764

You are saving an empty form instead the from data in the model with the request data. Using a ModelForm is more simple and easy, just saving the form is enough. And use an EmailField instead a CharField is better for the validation of email address strings

forms.py

from django.forms import ModelForm
from temp.models import Email

class EmailForm(forms.ModelForm):
    class Meta:
        model = Email

views.py

from django.shortcuts import render
from temp.models import Email
from temp.forms import EmailForm

def index(request):
    if request.method == 'POST':
        # POST, get the data from the form
        form = EmailForm(request.POST)
        if form.is_valid():
            # if is valid, just save, and return a new page with thanks
            form.save()
            return render(request, 'temp/thanks.html')
        else:
            # Form has errors, re-render with data and error messages
            return render(request, 'temp/index.html', {'form': form,})
    else:
        # GET, render new empty form
        form = EmailForm()
        return render(request, 'temp/index.html', {'form': form,})

Upvotes: 1

ruddra
ruddra

Reputation: 51938

I think, your form isn't becoming valid, so its not being submitted. So why don't you write your template like this:

<form action="thanks/" method="post">
{% csrf_token %}
<div>Your email address:
{{ form.as_p }} </div> <!-- just for testing -->
<input type="submit" value="Submit" />
</form>

and in forms:

class EmailForm(forms.Form):
    email = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'id': 'myModel'})) #Seems, here you want your email's input field id to myModel

and in views:

if form.is_valid():
   emaildata=Email() #Model email instance
   emaildata.email= form.cleaned_data['email']
   emaildata.save()
   # or try saveing like zaphod suggested

Edit

If you want to keep using your template, then I suggest you to discard the form. In views, you will get data by request.body.(I think you are using ajax to save data) For example:

def index(request):
    if request.POST:
        data= request.body
        emaildata = Email() #Model Email instance
        emaildata.email= str(data)
        emaildata.save()
        return render(request, 'temp/thanks.html')

    return render(request, 'temp/index.html')

Upvotes: 1

aldo_vw
aldo_vw

Reputation: 638

You've got three errors. First, you should use the index view to pass EmailForm to index.html. Second, what you have in the index view now (corrected according to the previous answers) should be moved to the thanks view in order to retrieve what was entered in the EmailForm by the user. And finally, you have to correct your template so include the EmailForm passed along.

Upvotes: 1

zaphod
zaphod

Reputation: 2095

In the code below, you seem to be reinitializing the email with an empty form. You are also not creating or accessing an instance of the Email model in which the email will be saved.

def index(request):
    if request.POST:
        form = EmailForm(request.POST)
        if form.is_valid():
            email = EmailForm()   <<< reinitializing with empty form
            email.save()
            return render(request, 'temp/thanks.html')

What you may want to do is:

def index(request):
    if request.POST:
        form = EmailForm(request.POST)
        if form.is_valid():
            email_data = form.cleaned_data['email']   # read form data
            email = Email.objects.create(email=email_data)  # create model instance
            email.save()   # save instance
            return render(request, 'temp/thanks.html')

If you use ModelForms instead of Form, you can do the form.save() directly to save the model.

Upvotes: 2

Rohan
Rohan

Reputation: 53316

Update your view to

def index(request):
    if request.POST:
        form = EmailForm(request.POST)
        if form.is_valid():
            email = form.save() #use form to save it in DB
            return render(request, 'temp/thanks.html')

    return render(request, 'temp/index.html')

Also, use models.EmailField() for email instead of CharField(). With EmailField django will validate the data appropriately. Make your form as ModelForm so that django saves data to appropriate model/table.

class EmailForm(forms.ModelForm):
    class Meta:
        model = Email

Upvotes: 2

Related Questions