3

I'm doing the CS50 Web programming course, learning to use Django. The learning exercise basically has you recreating this pizza restaurant menu with django.

I've created some models for the data, and now I'm trying to use Django templating to create a menu page for the pizzas.

Here are my models:

from django.db import models

class intToppings(models.Model):
    name = models.CharField(max_length=16)
    intToppings = models.IntegerField() # 0 Cheese, 1/2/3, 5 Special

    def __str__(self):
        return f"{self.name}"

class Size(models.Model):
    size = models.CharField(max_length=16)

    def __str__(self):
        return f"{self.size}"

class PizzaBase(models.Model):
    base = models.CharField(max_length=16)

    def __str__(self):
        return f"{self.base}"

class Toppings(models.Model):
    topping = models.CharField(max_length=32)

    def __str__(self):
        return f"{self.topping}"

class Pizza(models.Model):
    size = models.ForeignKey(Size, on_delete=models.CASCADE) # CASCADE will delete all Regular Pizzas if their size is deleted (as opposed to .SET_NULL)
    base = models.ForeignKey(PizzaBase, on_delete=models.CASCADE)
    intToppings = models.ForeignKey(intToppings, on_delete=models.CASCADE)
    price = models.IntegerField() # price in cents

    def __str__(self):
        return f"{self.size} {self.base} {self.intToppings} Pizza"

There's an entry "small" and "large" in the Size db, and for intToppings there is one entry with name "cheese" and an int of 0, another for "1 topping" with an int of 1, etc.

And for the Pizza model, I made an entry for every combo on the menu, ie:

<QuerySet [<Pizza: small Regular Cheese Pizza>, <Pizza: small Regular 1 Topping Pizza>, <Pizza: small Regular 2 Toppings Pizza>,  ...
... <Pizza: large Sicilian 2 Toppings Pizza>, <Pizza: large Sicilian 3 Toppings Pizza>, <Pizza: large Sicilian Special Pizza>]>

On my views.py, I can't really pass that whole data set to the django template because it's not sensible/possible to loop through it to create an html table. (my html table is identical to the one on their website, one table for regular pizza, one for sicilian.)

I'm trying to solve this issue by first constructing a list/array or dict object that will pass data to the django template in a structure that is easy to loop through. And to do this I want to query the Pizza model.

Essentially, all I'm looking to do is (pseudo code: SELECT Pizza WHERE size="small" base="Regular", intToppings=0 and get the price for that pizza. I don't seem to be able to query the foreign keys though;

Pizza.objects.all().filter(price=1220)

works but isn't what I need. What I need is;

p = Pizza.objects.all().filter(base="Regular", size="small", intToppings=0)
print(p.price)

which doesn't work.

1
  • 1
    read this about lookups that span relationships.
    – dirkgroten
    Commented Aug 23, 2019 at 14:44

2 Answers 2

1

Have you tried to use the field names of the related models? Like this:

p = Pizza.objects.filter(
    base__base="Regular",
    size__size="small",
    intToppings__intToppings=0)
print(p)

Like the docs say, you first access the related model (say base) and then you access the field of that related model (__base) and compare that to the string you want, resulting in base__base='something'.

Maybe you even could rename the field PizzaBase.base to PizzaBase.name to make it less confusing.

1
  • Thanks! That works perfectly, except the last one I had to do intToppings__intToppings=0. And yes I agree, with that syntax, definitely best to rename them to name.
    – gazm2k5
    Commented Aug 27, 2019 at 11:23
1

Try this:

p = Pizza.objects.filter(
    base__base = "Regular",
    size__size = "small",
    intToppings_id = 0, 
)

Note that I changed intToppings to intToppings_id. If you need to filter by a foreign key, you can pass in the intToppings object, or you can add _id to the end of the column name and simply insert the pk value.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.