I'm trying to build a form to save Names and Email Adresses to my database. However, it doesn't save... I've used an Inclusion Tag because I want to use the same form in different templates. This is my models.py:
class Contact(models.Model):
FRAU = 'FR'
HERR= 'HR'
GENDER_CHOICES = (
(FRAU, 'Frau'),
(HERR, 'Herr'),
)
gender = models.CharField(max_length=2, choices=GENDER_CHOICES, default=FRAU)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=200)
email = models.EmailField()
def __unicode__(self):
return "%s %s" %(self.first_name, self.last_name)
This is my forms.py:
class FragenContactForm(ModelForm):
class Meta:
model = Contact
fields = ['gender', 'first_name', 'last_name', 'email']
This is my custom tags module:
from django import template
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from fragen.forms import FragenContactForm
register = template.Library()
@register.inclusion_tag('fragen/askforoffer.html', takes_context=True)
def askforoffer(context):
form = FragenContactForm(context['request'].POST or None)
if context['request'].method=='POST':
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('fragen/thanks.html'))
else:
messages.error(context['request'], "Error")
return {'form': FragenContactForm()}
After I fill in and submit the form, I see nothing in my database. Am I missing something? Thanks!
I've used an Inclusion Tag because I want to use the same form in different templates.
You can simply reuse the form - or as your form in this case is very simple, you can use the CreateView
generic class based view and reduce your code even further.
Your view would contain just the following:
class OfferForm(CreateView):
template_name = 'fragen/askforoffer.html'
model = Contact
fields = ['gender', 'first_name', 'last_name', 'email']
success_url = 'fragen/thanks.html'
Django will automatically create the ModelForm
, and handle the error redirection and saving of the fields for you.
In your fragen/askforoffer.html
template, you need just this:
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create" />
</form>
Finally, in your urls.py
:
url(r'^submit-offer/$', OfferForm.as_view(), name='offer-form')
To display the same form in multiple places, just map it to a URL:
url(r'^another-form/$', OfferForm.as_view(), name='another-form')
Finally, __unicode__
method should return a unicode object; so in your model:
def __unicode__(self):
return u"{} {}".format(self.first_name, self.last_name)
The way you are trying to do it will not work because the template tag code will be executed before the template is rendered; so by the time the user sees the form, your tag code is already finished. There is no way to "trigger" it again; which is why you need a traditional view method which will accept the data entered into the form.