How to inherit a model object instead of the model class - django

For some reasons, I want my Boolean Fields in my class Items(models.Model) to have a foreign key in my class ItemsGotten(models.Model). Here's my code for better understanding...
Items(models.Model):
title=models.Charfield(max_length=180)
description=models.Textfield(max_length=180)
paper=models.BooleanField(default=False, blank=True)
skin=models.BooleanField(default=False, blank=True)
ItemsGotten(models.Model):
user=models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
paperitem = models.ForeignKey(???)
skinitem = models.ForeignKey(???)```
I know that you can simply get the value of the whole model class e.g paperitem = models.ForeignKey(Items). But that's not what I want to achieve, I want to get only the object from the Items model. e.g skinitem = models.ForeignKey(Items.skin). Thanks

Related

how to filter data from parant model based on if there relationship with child model

I have these models
class Tree(models.Model):
field = models.TextField()
class TaskProgress(models.Model):
base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
tree = models.ForeignKey(Tree, on_delete=models.CASCADE)
class BaseTask(models.Model):
trees=models.ManyToManyField(Tree, through='TaskProgress')
class TaskType1(BaseTask):
child1_field = models.TextField()
class TaskType2(BaseTask):
child2_field = models.TextField()
how to get all taskprogress when related to TaskType2 ,
TaskProgress.objects.filter(???)
I added extra field on BaseTask class
TASK_TYPE =[('I','Irrigation'),('C','Care'),('A','Assessment'),('O','Other')]
class BaseTask(models.Model):
trees=models.ManyToManyField(Tree, through='TaskProgress')
worker = models.ManyToManyField(User)
task_type = models.CharField(max_length=1,choices=TASK_TYPE,null=True)
And the filter will be like this
TaskProgress.objects.filter(base_task__task = "I")
I do not think what you are asking is possible, if the models are designed like described. The base_task ForeignKey is specifically pointing at a BaseTask. Even though TaskType1 and TaskType2 inherit from BaseTask, they have no relation in the database. They only look similar.
Option 1: Look into Generic Relations in Django. Basically it allows you to have a ForeignKey relation with more than one type of model. I would not recommend it though. Generic relations are a mess if you don't know want you are doing.
Option 2: Rethink your layout. Maybe you can move the relation to the two TaskTypes instead and adress them via related_name.
class TaskProgress(models.Model):
# base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
tree = models.ForeignKey(Tree, on_delete=models.CASCADE)
class TaskType1(BaseTask):
task_progress = models.OneToOneField(TaskProgress, related_name='task_type_1'
child1_field = models.TextField()
class TaskType2(BaseTask):
task_progress = models.OneToOneField(TaskProgress, related_name='task_type_2'
child2_field = models.TextField()
This way you create a one-to-one-relation between the TaskProgress and the TaskType. You should be able to query one or the other by checking whether a relation exists, e.g. all TaskProgress instances with a relation to a TaskType1 instance.
# Query all TaskProgress instances, that have a TaskType1
TaskProgress.objects.filter(task_type_1__isnull=False)

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.

Getting a queryset using a foreign key field in the "other side" of a foreign key relation

Forgive me if the question does not make sense, trying to teach myself django. I've been trying to search how to do this but i'm not sure if i'm using the right words in my search.
I have the following models.
class Category(models.Model):
code = models.CharField(max_length=10, unique=True)
description = models.CharField(max_length=50)
class UserGroupHeader(models.Model):
code = models.CharField(max_length=10, unique=True)
description = models.CharField(max_length=50)
class UserGroupDetail(models.Model):
usergroupheader = models.ForeignKey(UserGroupHeader, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
How do i get a query set from the Category model using the UserGroupHeader? so far what i've got is something like this UserGroupHeader.objects.get(pk=9).usergroupdetail_set.all(), now from the result of this how do i get the Category model?
I'm not sure if I understood exactly what you are trying to do, but in general, while querying, you can follow relations using double underscores. Below are a couple of possible queries:
my_group_header = UserGroupHeader.objects.get(...)
Category.objects.filter(usergroupdetail__usergroupheader=my_group_header) # Gets Category objects related to my_group_header through UserGroupDetail model
Category.objects.filter(usergroupdetail__usergroupheader__code='abc') # Gets Category objects related to UserGroupHeader object with code 'abc' through UserGroupDetail model
UserGroupHeader.objects.filter(usergroupdetail__category__code='abc') # Gets UserGroupHeader objects related to Category object with code 'abc' through UserGroupDetail model
Your query UserGroupHeader.objects.get(pk=9).usergroupdetail_set.all() would return a QuerySet of UserGroupDetail objects. In order to get the category of each UserGroupDetail, you can:
for user_group_detail in UserGroupHeader.objects.get(pk=9).usergroupdetail_set.all():
category = user_group_detail.category
print(category. description)
Or something similar according to your needs

Update multiple fields of member of an instance simultaneously

Suppose I have a User model and this model
class modelEmployer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
employer_image = models.ImageField(upload_to='images/', default='')
Now suppose i have an instance of modelEmployer and I would like to update the content of the user object in it. I know I can do this
instance.user.email = new value
instance.first_name = new value
instance.save()
I read we can run an update on a queryset (even if it returns one object). Now suppose I have a dictionary like this
dict = {"first_name : "John","last_name" : "deer",....}
How can i do something like this
modelEmployer.object.filter(instance.user.email=dict["email"]).update(only update the user objects as I would like to update the user object of this field using directly the dictionary. Any suggestions ?
You can use explicitly mention the relation and do it,
dict = {"user__first_name" : "John","user__last_name" : "deer",....}
And in the ORM, do as
modelEmployer.object.filter(instance.user.email=dict["email"]).update(**dict)
Hope this will solve your issue

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.