I am working on adding more functionality to the polls app that is made in the official Django tutorial. One of the things I am working on is making Polls/Choices creatable by logged in users (instead of in an admin screen, where the tutorial leaves us).
I am looking to create a view where a user can create the a Poll, and then as well include some Choices to associate to the Poll. The Django Admin automagically does it, and I am not sure how to go about writing this out in a view.
To start with, these are my relevant files:
models.py
import datetime
from django.db import models
from django.utils import timezone
class Poll(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question_text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
class Choice(models.Model):
question = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __unicode__(self):
return self.choice_text
forms.py
from django import forms
from .models import Poll, Choice
from datetime import datetime
class PollForm(forms.ModelForm):
question_text = forms.CharField(max_length=200, help_text="Please enter the question.")
pub_date = forms.DateTimeField(widget=forms.HiddenInput(), initial = datetime.now())
class Meta:
model = Poll
fields = ("__all__")
class ChoiceForm(forms.ModelForm):
choice_text = forms.CharField(max_length=200, help_text="Please enter choices.")
votes = forms.IntegerField(widget=forms.HiddenInput(),initial=0)
exclude = ('poll',)
views.py
def add_poll(request):
# A HTTP POST?
if request.method == 'POST':
form = PollForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save(commit=True)
# Now call the index() view.
# The user will be shown the homepage.
return render(request, 'polls/index.html', {})
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = PollForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'polls/add_poll.html', {'form': form})
Currently, my view allows me a user to add a poll. I am just not sure how to go about adapting it to pass the entered text as the Poll model's question_text, to the Choice model, and in turn, the ChoiceForm.
Here we created a viewset, we define two forms to render one is student form and the other is teacher form. We defined the HTML which we have to render. We define what to do when a form is submitted under get_success_url. In form_valid, we save the form data and verify if both the forms are right or not.
The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.
A formset is a layer of abstraction to work with multiple forms on the same page. It can be best compared to a data grid. Let's say you have the following form: >>> from django import forms >>> class ArticleForm(forms.
Formsets are the way to do it in django.
First add default
value for Poll.pub_date
field:
class Poll(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published', default=timezone.now)
Then make forms a bit simpler:
class PollForm(forms.ModelForm):
class Meta:
model = Poll
fields = ('question_text', )
class ChoiceForm(forms.ModelForm):
class Meta:
model = Choice
fields = ('choice_text',)
Add formset support to your view:
from django.forms.formsets import formset_factory
def add_poll(request):
ChoiceFormSet = formset_factory(ChoiceForm, extra=3,
min_num=2, validate_min=True)
if request.method == 'POST':
form = PollForm(request.POST)
formset = ChoiceFormSet(request.POST)
if all([form.is_valid(), formset.is_valid()]):
poll = form.save()
for inline_form in formset:
if inline_form.cleaned_data:
choice = inline_form.save(commit=False)
choice.question = poll
choice.save()
return render(request, 'polls/index.html', {})
else:
form = PollForm()
formset = ChoiceFormSet()
return render(request, 'polls/add_poll.html', {'form': form,
'formset': formset})
And finally your template:
<form method="post">
{% csrf_token %}
<table>
{{ form }}
{{ formset }}
</table>
<button>Add</button>
</form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With