Reputation: 12499
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">×</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
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
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
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
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
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