1

I have an issue with my Django forms and combining it with data from my database.

  1. I need to get data about tickets to generate the form via {% for ticket in tickets %}
  2. Once the user chose the ticket(s) and quantity, the form will check this request. I wanted to use Form.is_valid() and cleaned_data, however, I couldn't manage to combine this with step 1.

Do you guys have any tips or input how I can make my code more "safe"? Currently, I am skipping all the provided security Django provides with cleaned_data and is_valid(). The reason why is that I don't know how to do it.

views.py

from django.shortcuts import render

from .models import Ticket
from tickets.models import Order, Entry

# Create your views here.
def choose_ticket_and_quantity(request):

    tickets = Ticket.objects.all()

    if request.POST:
        o = Order.objects.create()
        request.session['order_id'] = o.order_id

        ticket_id = request.POST.getlist('ticket_id')
        ticket_quantity = request.POST.getlist('ticket_quantity')
        for x in range(len(ticket_id)):
            if int(ticket_quantity[x]) > 0:
                e = Entry(
                        order=Order.objects.get(order_id = o.order_id),
                        ticket=Ticket.objects.get(id = ticket_id[x]),
                        quantity=ticket_quantity[x]
                    ).save()

    return render(request, "tickets/choose_ticket_and_quantity.html", {"tickets": tickets})

models.py

class Ticket(models.Model):
    description     = models.TextField()
    name            = models.CharField(max_length=120)
    price_gross     = models.DecimalField(max_digits=19, decimal_places=2)
    quantity        = models.IntegerField()

choose_ticket_and_quantity.html

<form action="" method="post">
  {% csrf_token %}

  {% for ticket in tickets %}
    <input type="hidden" name="ticket_id" value="{{ ticket.id }}">

    {{ ticket.name }}

    <select name="ticket_quantity" >
      <option value="0">0</option>
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>

  {% endfor %}

  <p><input type="submit" value="Checkout"></p>
</form>

Here what I currently tried/started within forms.py But I don't know how to render the *.html while getting the ticket data from its model.

from django import forms

#Currently not used
INT_CHOICES = [tuple([x,x]) for x in range(0,11)]

class TicketForm(forms.Form):
    ticket_quantity     = forms.IntegerField(widget=forms.Select(choices=INT_CHOICES))
1
  • I've updated my answer and provided sample code Commented Mar 29, 2018 at 13:20

1 Answer 1

1

You can create a EntryModelForm for your Entry model and then create a FormSet of EntryModelForm.

Django Formset documentation

Here is sample view function:

from django.forms import formset_factory

def choose_ticket_and_quantity(request):

    tickets = []
    for ticket in Ticket.objects.all():
        tickets.append({'ticket': ticket})

    EntryFormSet = formset_factory(EntryModelForm, extra=0)
    formset = EntryFormSet(initial=tickets)

    if request.POST:
        o = Order.objects.create()

        formset = EntryFormSet(request.POST, initial=tickets)
        for form in formset:
            if form.is_valid():
                entry = form.save(commit=False)
                entry.order = o
                entry.save()

    return render(request, "tickets/choose_ticket_and_quantity.html",
                  {'formset': formset})

I guess your entry model class might be something like the following:

class Entry(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
    quantity = models.IntegerField(choices=INT_CHOICES)

Here is the form class:

class EntryModelForm(forms.ModelForm):
    class Meta:
        model=Entry
        exclude = ('order',)

Here is the HTML template:

<form action="" method="post">
  {% csrf_token %}
  {{ formset }}
  <p><input type="submit" value="Checkout"></p>
</form>
Sign up to request clarification or add additional context in comments.

4 Comments

Hi Nayan, that's amazing thank you. You helped me a lot with it. AND it works! I will adjust some details and implement everything afterwards. Is it okay, when I write a follow up here, in case I have one more question about the code you wrote here?
It's absolutely ok. I'll try to help as much as possible.
Hi @Nayan, I just posted an answer with a current detail problem I have. Otherwise you code works perfect, but if you have any idea would be great if you could look into it.
I just posted here my follow up question. Would be awesome if you could look into it by any chance as you understand my (your) code best: stackoverflow.com/questions/49798621/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.