Search code examples
pythondjangoinclusion

Django Inclusion Tag doesn't post to database


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!


Solution

  • 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.