how to check isSubsest in django orm - python

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)

Related

Not sure I understand dependancy between 2 django models

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

models with ManyToManyField

Suppose that you want to simulate universities system, you have courses, teachers and students.
We have some courses that are taught by some teachers and students choose some courses with some teachers.
For example:
Courses: math, physics
Teachers: Jack(math), Jane(math, physics)
Students: st1(math with Jack), st2(math with Jane), st3(physics with Jane and cant choose Jack!!), every score by default=-1.
With this code:
teachers = models.ManyToManyField(teacher.objects.filter(t_courses=s_courses), verbose_name='Ostad')
I got errors like:
raise AppRegistryNotReady("Models aren't loaded yet.") and
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet
from django.db import models
class profile(models.Model):
n_id = models.IntegerField(primary_key=True, verbose_name='code melli')
name = models.CharField(max_length=24, verbose_name='Full Name')
class Meta:
ordering = ('name',)
class course(models.Model):
name = models.CharField(max_length=24, verbose_name='Class Name')
unit = models.SmallIntegerField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
class teacher(profile,models.Model):
t_id = models.AutoField(primary_key=True)
t_courses = models.ManyToManyField(course, verbose_name='Dars')
def __str__(self):
return self.name
class student(profile,models.Model):
s_id = models.AutoField(primary_key=True)
s_courses = models.ManyToManyField(course, verbose_name='Dars')
#teachers = ??????????????????????????
score = models.IntegerField(default=-1, verbose_name='Nomre')
def __str__(self):
return self.name
How do I code in the teachers part?
Thanks a lot.
You're trying to do two different things here: Define which teacher gives a course for each specific student and restrict the choices (which is more a validation thing).
You're missing the actual Class model which links the course to the teacher and that you can use to define which classes the student is following:
class Teacher(models.Model):
name = models.CharField(max_length=100)
courses = models.ManyToManyField(Course, through="Class", related_name="teachers")
class Class(models.Model):
teacher = models.ForeignKey(Teacher, related_name="classes")
course = models.ForeignKey(Course, related_name="classes")
class Student(models.Model):
classes = models.ManyToManyField(Class)
The Class model is now your intermediate model for linking teachers to courses. You could also add more information about the class, such as its number, schedule (e.g. list of weekdays and hours the class takes place) and room number. Now you can fetch all the other things like that:
# all courses a teacher teaches
teacher.courses.all()
# all teachers of a student
[class.teacher for class in student.classes.all()] # list
Teacher.objects.filter(classes__in=student.classes.all()) # QuerySet
# all courses of a student
Course.objects.filter(classes__in=student.classes.all())
Now because you associate the student with the a Class instance, you can't select a wrong teacher. If for example you have a form where the user can pick a course, you'd present the classes belonging to that course in order to link the student to a course/teacher combination:
# teachers for a course
course.teachers.all()
If you want to keep track of the marks of the students for each class, you can add a Mark model as an intermediate model for your m2m relationship:
class Mark(models.Model):
student = models.ForeignKey(Student, related_name='marks' ...)
class = models.ForeignKey(Class, ...)
grade = models.DecimalField(max_digits=3, decimal_places=1, default=-1)
class Student(models.Model):
classes = models.ManyToManyField(Class, through='Mark', related_name='students')
But probably a more suitable model is to keep track of all the marks, e.g. when there are many exams for one class and you want to keep track of all the results. Then you just keep the Mark model above but don't use it as intermediate model to classes. In that way a student can have multiple grades for the same class:
student = Student.objects.get(id=1)
student.marks.filter(class__name='math').aggregate(Avg('grade'))
>> {'grade__avg': Decimal('8.3')}

display foreign key in parent class

I could not show reverse relation in Django Rest Framework. Here in my case, a rent can have multiple images and i want to display all the images of that rent(living room image, kitchen image, bathroom image etc) in /api/v1/rent, i mean in rent resource.
So, how do I fetch these Galleries to display in the Rental resource?
class Rental(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=300, blank=False, null=False)
phone_number = models.PositiveIntegerField(null=False, blank=False)
renter = models.CharField(choices=RENTER_CHOICES, max_length=1, default=RENTER_CHOICES[0])
def __str__(self):
return self.name
def user_directory_path(instance, filename):
return 'rent_{0}/{1}'.format(instance.rent.id, filename)
class Gallery(models.Model):
rent = models.ForeignKey(Rental, related_name="rent")
image = models.FileField(upload_to=user_directory_path)
tag = models.CharField(max_length=1, choices=TAGS, null=True, blank=True)
class GallerySerializer(serializers.ModelSerializer):
rent = serializers.ReadOnlyField()
class Meta:
model = Gallery
fields = ('rent', 'image', 'tag',)
class RentalSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
# gallery = serializers.SerializerMethodField('get_children')
#
# def get_children(self, obj):
# print ('obj', obj.gallery_set)
# serializer = GallerySerializer(obj.gallery_set.all(), many=True)
# return serializer.data
gallery = GallerySerializer(source='gallery_set',many=True, read_only=True)
class Meta:
model = Rental
fields = ('user', 'name', 'phone_number','gallery',)
Right now i dont get the list of gallery, using both way, one commented way and another source='gallery_set' way.
UPDATE
if i do rent = GallerySerializer(many=True) i get the list of galleries but does it make any sense?
[
{
"user": "admin",
"name": "Sunrise Home",
"phone_number": 9842333833,
"rent": [
{
"image": "http://localhost:8000/media/rent_1/sittingRoom.jpg",
"tag": "L"
}
]
}
]
in above api you see the galleries are shown but the name shows it as a list of rent inside rental resource. Can anyone help me to design an api better way?
When you specify the foreign key relationship for Rental in your Gallery model the related_name you specify automatically defines a field on the Rental object. The name of that field is whatever you set related_name to, in this case rent.
The important thing to understand here is that the related_name will be attached to the opposite side of the relationship from where the key is declared in your models. Because the related name is going to be a property of a Rental object, a better name for it might be galleries in your example.
Assuming you change the related_name in your models from rental to galleries, you can define your Rental serializer to output a list of associated galleries:
class RentalSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
galleries = GallerySerializer(many=True, read_only=True)
class Meta:
model = Rental
fields = ('user', 'name', 'phone_number','galleries')
By declaring a GallerySerializer with the same name as the related_name defined in your foreign key relationship, it will automatically find only galleries which are associated with the Rental being serialized.
In another example:
Let's say you have several Eggs in a Basket. We would want to create a many-to-one relationship between Eggs and a Basket and would accomplish this by creating a foreign-key relationship between the two. That would be in the form of storing the ID of the associated Basket for each Egg.
In Django, we would declare that foreign key on the Egg model. This allows us to access the basket that an egg is in via egg.basket. We also want to determine what eggs are in a particular basket. We do that by defining a related_name on the foreign-key field. This tells Django what the field linking the basket to all its contained eggs should be called. Since this field refers to all eggs in a basket, we would call it eggs.
In code:
class Basket(models.Model):
color = models.CharField()
class Egg(models.Model):
color = models.CharField()
basket = models.ForeignKey(Basket, related_name="eggs")

Filtering by foreign key in dropdown

I'm using django-filters.
My Car model has a Manufacturer foreign key . What I want to do is Filter the Cars by a dropdown that is populated with all Manufacturers in the database.
class Car(models.Model):
slug = models.SlugField(unique=True)
name = models.CharField(max_length=256)
cost = models.DecimalField(max_digits=10,decimal_places=5)
manufacturer = models.ForeignKey(Manufacturer)
My filter currently is a blank text field, you can enter a manufacturer name and then submit to filter this way. The Dropdown would be much more suitable, but I haven't been able to find a way to do this. Here is the filter model as it is now:
class CarFilter(django_filters.FilterSet):
manufacturer = django_filters.CharFilter(name="manufacturer__name")
class Meta:
model = Car
fields = ['name', 'manufacturer']
Just don't define the manufacturer filter field at all and django-filter will use the default filter for this field (which is a drop down). So something like this should be working:
class CarFilter(django_filters.FilterSet):
class Meta:
model = Car
fields = ['name', 'manufacturer']

Django how to order by many to many occurences

let's say I have 2 models:
class Recipe(models.Model):
recipe = models.TextField()
ingredients = models.ManyToManyField(Ingredient)
class Ingredient(models.Model):
name = models.CharField()
and I want to know what ingredient is the most used in all the recipes.
How do I query that?
Read about aggregation and annotations at https://docs.djangoproject.com/en/dev/topics/db/aggregation/
To get the name of the most common ingredient:
from django.db.models import Count
most_common = Ingredient.objects.annotate(num_recipes=Count('recipe')).order_by('-num_recipes')[0]
print most_common.name

Categories