I currently have a set of models that look similar to this contrived code:
class Pizza(models.Model):
price = models.FloatField()
topping = models.ManyToManyField(Topping, through="PizzaToppings")
class Topping(models.Model):
name = models.CharField(max_length=50)
class PizzaToppings(models.Model):
class Meta:
ordering=["order_to_add_topping"]
pizza = models.ForeignKey(Pizza)
topping = models.ForeignKey(Topping)
order_to_add_topping = models.IntegerField()
My problem is that what happens when I attempt to access the toppings of a pizza in the order specified in the PizzaToppings ManyToMany extra fields table. Assume the pizza has cheese and ham, with the order_to_add_topping in the PizzaToppings data set to 0 and 1 respectively:
>>> pizza = Pizza.objects.get(pk=490)
>>> pizza.toppings.all()[0].name
'Ham'
That should say 'Cheese'. I would have thought the RelationManager would have respected the ordering Meta class field, but it appears it doesn't. So I guess accessing the name of the first topping added to the pizza shouldn't be done with pizza.toppings.all()[0].name.
How should it be accessed? Is the problem with my model query or is it how I have my models set up?
Your model is fine you just need to query the relationship since now you have a "through" relationship with extra fields. The relationship is created automatically as topping_relationship in your case, so your query should be:
pizza.toppings.order_by('topping_relationship__order_to_add_topping')
Related
I'm using django rest framework.
and from these models, I want to get a possible cooking queryset using ingredients in fridge.
I want to get cookings that all ingredients in fridge.
How can I filter?
please help..
class Ingredient(models.Model):
name = models.CharField()
class Cooking(models.Model):
name = models.CharField()
class Fridge(models.Model):
ingredient = models.ForeignKey(Ingredient)
class CookingIngredient(models.Model):
cooking = models.ForeignKey(Cooking)
ingredient = models.ForeignKey(Ingredient)
I am struggling to understand django models relationship.
I have this arborescence:
A train have cars, and those cars are divided into parts. Then those parts all contains different references.
Like, for exemple, all the trains have the 6 cars, and the cars 6 parts. Each part have x reference to be associated.
I would like to use all of them in a template later on, where the user can select the train, the car and the part he worked on, then generate a table from his selections with only the references associated to the parts he selected.
It should update the train and the car (I'm trying to update a stock of elements for a company)
I dont really understand which model field give to each of them. After checking the doc, Ive done something like this but i am not convinced:
class Train(Car):
train = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Car(Part):
car = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Part(Reference):
part = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Reference(models.Model):
reference = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
def __str__(self):
return self.reference
Can someone please help me understand this so I can do well ? Thanks!!
1-)if you add abstract = True in your Model Meta class, your class doesn't created on database as a table. If you store data for any class, you mustn't define abstract = True.
2-)For relations, you can use models.ForeignKey . If you add a class into brackets of another class, it names: inheritance.(You can think like parent-child relation). In database management, we can use foreignkey for one-to-many relationship.
3-)In Django ORM, id field automatically generated. So you don't need to define id field.
If I understand correctly, also you want to store parts of user's selected.
So, your model can be like that:
class Train(models.Model):
name = models.CharField(max_length=200) # I think you want to save name of train
class Car(models.Model):
train = models.ForeignKey(Train,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Part(models.Model):
car = models.ForeignKey(Car,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Reference(models.Model):
part = models.ForeignKey(Part,on_delete=models.Cascade)
name = models.CharField(max_length=200)
def __str__(self):
return self.reference
#addtional table for storing user's references
class UserReference(models.Model):
user = models.ForeignKey(User,on_delete=models.Cascade)
reference = models.ForeignKey(Reference,on_delete=models.Cascade)
name = models.CharField(max_length=200)
With this definitions, you can store user's definition on UserReference table. And with Django Orm, you can access train object from UserReferenceObject.
#user_reference: UserReference object like that result of UserReference.objects.first()
user_reference.reference.part.car.train.name
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.
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.
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.
Suppose I have a model structure like this:
class Cheese(Model.models):
type = models.CharField(max_length='50')
class Sauce(Models.models):
type = models.CharField(max_length='50')
class Pizza(Models.models):
cheese = models.ForeignKey(Cheese)
sauce = models.ForeignKey(Sauce)
class PizzaOrder(Models.model):
pizza = models.ForeignKey(Pizza)
time = models.DateTimeField(auto_now_add=True)
Given this, now I want to create a new entry for PizzaOrder--but I do not want any duplicates of Cheese, Sauce, or Pizza--just PizzaOrder to represent that a pizza was just ordered.
This results in an error, which is discussed here.
How can I avoid this problem? I do not want a duplicate of object Pizza every-time I get a new PizzaOrder.
If you want to avoid creating duplicate Cheese, Sauce and Pizza, you can do like this:
class Cheese(Model.models):
type = models.CharField(max_length='50', unique=True)
class Sauce(Models.models):
type = models.CharField(max_length='50', unique=True)
class Pizza(Models.models):
cheese = models.ForeignKey(Cheese)
sauce = models.ForeignKey(Sauce)
class Meta:
unique_togather=(("cheese", "sauce"),)
Hay guys, I'm writing a simple app which logs recipes.
I'm working out my models and have stumbled across a problem
My Dish models needs to have many Ingredients. This is no problem because i would do something like this
ingredients = models.ManyToManyfield(Ingredient)
No problems, my dish now can have many ingrendients.
However, the problem is that the ingredient needs to come in different quantities.
I.E 4 eggs, 7 tablespoons sugar
My Ingredient Model is very simple at the moment
class Ingredient(models.Model):
name = models.TextField(blank=False)
slug = models.SlugField(blank=True)
How would i go about work out this problem? What fields would i need to add, would i need to use a 'through' attribute on my ManyToManyfield to solve this problem?
I think you got the right answer with a "through" table ( http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany )
Model
class Recipe(models.Model):
name = models.TextField(blank=False)
ingredients = models.ManyToManyField(Ingredient, through='Components')
class Ingredient(models.Model):
name = models.TextField(blank=False)
slug = models.SlugField(blank=True)
class Components(models.Model):
recipe = models.ForeignKey(Recipe)
ingredient = models.ForeignKey(Ingredient)
quantity = models.DecimalField()
You can put unit of quantity (gram, kilo, tablespoon, etc) on Ingredient level, but I think it is better on Ingredients level (for example you can have 1 recipe with 10 Cl of milk but one other with 1L ... So "different" units for a same ingredient.
Data Creation
By Dish you mean Recipe right ? If you have a look to previous link (http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany), they give you a good example (based on the beatles).
Basically :
1.Create a Recipe:
cake=Recipe.objects.create(name="Simple Cake")
2.Create several Ingredient (if they doesn't already exist from a previous recipe ;)):
egg = Ingredient.objects.create(name="Egg")
milk = Ingredient.objects.create(name="milk")
3.Create the relationship:
cake_ing1 = Components.objects.create(recipe=cake, ingredient=egg,quantity = 2)
cake_ing2 = Components.objects.create(recipe=cake, ingredient=milk,quantity = 200)
and so on. Plus, I'm now quite sure that unit should go to Components level, with a default unit as "piece" (that would be for yours eggs ...), and would be something like "mL" for milk.
Data Access
In order to get ingredients (Components) of a recipe just do :
cake = Recipe.objects.get(name = "Simple Cake")
components_cake = Components.objects.get(recipe = cake)