Django model organization: food item locations in different grocery stores - django

I'm working on a cookbook app and I want to sort the ingredients of a recipe by their aisle in the grocery store. Since different grocery stores have different configurations, I want users to be able to sort the lists of ingredients by a selected store. I'm new to Django and am stuck on figuring out the models that I'll need for this. I think I want to have a many to many relationship between my Food model and a Store model. I think I want to use the through argument and have another intermediary Location model that connects the 'Food' and 'Store' and also contains which the aisle.
If possible, I'd like to have the choices for aisle have a certain description that depends on the selection of the Store object
class Food(models.Model):
name = models.CharField(max_length=100)
grocery_aisle = models.ManytoManyField(Store, through='Location')
class Store(models.Model):
name = models.CharField(max_length=100)
aisles = { # Not really sure how to store this kind of information which would be different for each Store object.
0: 'Produce Section',
1: 'Aisle 1: bread and peanutbutter',
2: 'Frozen Desserts',
3: 'Pharmacy'
}
class Location(models.Model):
food = models.ForeignKey(Food, on_delete=models.CASCADE)
store = models.ForeignKey(Store, on_delete=models.CASCADE)
aisle = models.SmallIntegerField(choices=MEASUREMENT_CHOICES) # option descriptions depend on selected store object
Any ideas would be greatly appreciated. I like Django a lot so far, but this is my first time using it, so I'm fumbling a bit.

Try this. It'll allow you to store multiple Aisles within a Store, then assign every Food to multiple Aisles using a many-to-many relationship.
class Store(models.Model):
name = models.CharField(max_length=100)
class Aisle(models.Model):
name = models.CharField(max_length=100)
store = models.ForeignKey(Store)
class Food(models.Model):
name = models.CharField(max_length=100)
aisle = models.ManytoManyField(Aisle)
class Recipe(models.Model):
name = models.CharField()
food = models.ManyToManyField(Food)
def find_in_store(self, store):
"""
Write a method here that finds a given recipe in a store, and call it with recipe.find_in_store(store). This will be a bit of a complex function, but a naive implementation (if you are running a small-scale project) would be to loop through all Aisle objects in the given store and determine whether any Food objects needed for the Recipe can be found in the given Aisle.
"""

Related

How to call a a field of one model A into another model B so that b can work as a view

I have created a model called Department, Course. Models are as follow
This is the model for departments and course
class Departments(models.Model):
Department_Id = models.IntegerField(primary_key=True)
Department_Name = models.CharField(max_length=200)
Department_Code = models.CharField(max_length=200)
class Course(models.Model):
Course_Id = models.IntegerField(primary_key=True)
Department_Id = models.ForeignKey(Departments, on_delete=models.CASCADE)
Course_Name = models.CharField(max_length=200)
Course_Code = models.CharField(max_length=200)
I want to create a model called view which can be later on called for search. I want a view model in a such a way that it consit of the data in concat form i.e. name= Department_name+ Course_Name
class View (models.model):
view_id= models.IntegerField(primary_key=True)
Name= Department_name(I want this from Departments table)
+ Course_Name(I want this from Course table)
I try using one to one relation . I would really appricate the help
It's not clear why you'd want to do that. It's never a good idea to duplicate data from one model into another one, as it can lead to inconsistencies.
You can add a ForeignKey in View to your Course model and then when you do f"{view.course.name} {view.course.department.name}" you already have your string:
class View(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def name(self):
return f"{self.course.name} {self.course.department.name}"
Notes:
Don't call your foreign key Department_id because it's not referring to the id but to the object itself in the Django ORM: department = models.ForeignKey(Department, on_delete=models.CASCADE). As you can see, this makes reading the code much simpler: self.course.Department_id is a Department object not an integer, so self.course.department makes more sense.
Don't prefix your field names with the class, it just makes the code so much less readable: Do you prefer department.name or department.Department_name?
The View model is still a mystery to me, as you can search without it. You can search for example for courses with a matching department name like this:
Course.objects.filter(department__name__icontains="maths")
which will return all courses with "maths" in their department name.
Remove all the ids from your models, they are created automatically by Django anyway (and called id). Again, department.id is much easier to read than department.Department_id. Also in your code, you have to generate the ids yourself since you don't set them to auto-populate.

Django sorting based on first object of many to many field

Here i wanted to sort the user based on the first object of car field .And For Foreign key i was doing like this and this is what i tried. User.objects.all().order_by('car__name').
But for many to many field how can i do it for the first or last object.
class Car(models.Model):
name = models.CharField(max_length=40)
class User(models.Model):
name = models.CharField(max_length=40)
car = models.ManyToManyField(Car)
You can use annotation together with subqueries to achieve what you want, as follows:
cars = Car.objects.filter(user=OuterRef('pk')).order_by('some_ordering')
user = User.objects.annotate(first_car_name=Subquery(cars.values('name')[1])).order_by('first_car_name')
More info can be found here: https://docs.djangoproject.com/en/2.1/ref/models/expressions/#subquery-expressions

How to retrieve a set of objects, filtered and ordered by fields of other objects, for which the desired object is a foreign key?

To rephrase the title to the context of my problem: How to retrieve a set of foods, filtered and ordered by fields of other objects, for which the food object is a foreign key?
I have the following models:
class Food(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
description = models.CharField(max_length=200, blank=True)
class DayOfFood(models.Model):
user = models.ForeignKey(User)
date = models.DateField()
unique_together = ("user", "date")
class FoodEaten(models.Model):
day = models.ForeignKey(DayOfFood, on_delete=models.CASCADE)
food = models.ForeignKey(Food, on_delete=models.CASCADE)
servings = models.FloatField(default=1)
I want to be able to retrieve the foods that a given user ate most recently. This collection of foods will be passed to a template so it must be a QuerySet to allow the template to loop over the food objects.
This is how far I got
days = DayOfFood.objects.filter(user=request.user)
foodeatens = FoodEaten.objects.filter(day__in=days)
foodeatens = foodeatens.order_by('day__date')
Now it feels like I am almost there, all the foods I want are contained in the FoodEaten objects in the resulting QuerySet. I do not know how to use "for ... in:" to get the food objects and still have them stored in a QuerySet. Is there a way to perform foreach or map to a QuerySet?
I do not want to rewrite the template to accept FoodEaten objects instead because the template is used by other views which do simply pass food objects to the template.
The solution
The answer from Shang Wang helped me write code that solves my problem:
days = DayOfFood.objects.filter(user=request.user)
foods = Food.objects.filter(
foodeaten__day__in=days,
foodeaten__day__user=request.user) \
.order_by('-foodeaten__day__date')
That could be done using chain of relations:
Food.objects.filter(foodeaten__day__in=days,
foodeaten__day__user=request.user) \
.order_by('foodeaten__day__date')
By the way, I'm not sure why do you have user on multiple models Food and DayOfFood. If you really need user relations on both of them, maybe make the field name more explicit with the user's role in each model, otherwise you will get confused very quickly.

How would I represent and model this relation?

So I have the following logic. A user creates a trade, this trade contains items a user wants and items a user has. These has and wants are represented as two separate many to many relationships.
However, here is where I am getting a little confused. These items can come from different models. For example I have a model set up for particular items, say business items which have unique characteristics and a second model for engineer items. Now these items can both be traded within the same trade.
Furthermore if I were to add more models representing other unique trade items how would I be able to add this to the many to many relationship without overhaul of the structure or data.
For illustration:
class ItemTrade(models.Model):
id = models.CharField(max_length=10, primary_key=True)
user = models.ForeignKey(get_user_model())
have_items = models.ManyToManyField()
want_items = models.ManyToManyField()
num_watch = models.IntegerField(max_length=10)
num_views = models.IntegerField(max_length=20)
class Model1(models.Model):
index = models.IntegerField(max_length=20, primary_key=True)
name = models.CharField(max_length=100)
type = models.ForeignKey('DotaItemType',null=True,blank=True)
class Model2(models.Model):
index= models.IntegerField(max_length=20, primary_key=True)
name = models.CharField(max_length=100)
type = models.ForeignKey('DotaItemType',null=True,blank=True)
desc = models.CharField(max_length=20)
The indexes will overlap for each item which means that I would also need to have secondary field to identify which model the item belongs to. What is the best possible method to represent this relation?
The only way I can think of is to have a unique many to many field for each model relation within the trade but I am not sure if this is the simplest and most effective way of accomplishing this.

Django: distinct QuerySet based on a related field

In my Django app I allow users to create collections of movies by category. This is represented using 3 models, Movie, Collection, and Addition (the Addition model stores movie, collection, and user instances). Simplified versions of all three models are below.
class Movie(models.Model):
name = models.CharField(max_length=64)
class Collection(models.Model):
name = models.CharField(max_length=64)
user = models.ForeignKey(User)
class Addition(models.Model):
user = models.ForeignKey(User)
movie = models.ForeignKey(Movie)
collection = models.ForeignKey(Collection)
So for example a user could create a collection called "80's movies", and add the movie "Indiana Jones" to their collection.
My question is: how do I display a distinct list of movies based on a set of query filters? Right now I am getting a bunch of duplicates for those movies that have been added to more than one collection. I would normally use distinct() to get distinct objects, but in this case I need distinct movies rather than distinct additions, but I need to query the Addition model because I want to allow the user to view movies added by their friends.
Am I setting up my models in an optimal way? Any advice/help would be much appreciated.
Thanks!
First. I don't think you need Addition model here. You try to create many-to-many relation, but there's documented way of doing this:
class Movie(models.Model):
name = models.CharField(max_length=64)
class Collection(models.Model):
name = models.CharField(max_length=64)
user = models.ForeignKey(User)
movies = models.ManyToManyField('Movie', blank=True, null=True)
Second. The documentation says: "To refer to a "reverse" relationship, just use the lowercase name of the model".
So the answer is (for the setup above):
Movie.objects.filter(collection__user=user).distinct()