Django Select Query to Fetch Data form All Child Tables - django

I have Django Models Says,
class JobApplication(models.Model):
job_application_id = models.AutoField(primary_key=True)
user_id = models.ForeignKey(User)
resume_id = models.ForeignKey(Resume)
class Resume(models.Model):
resume_id = models.AutoField(primary_key=True)
resume_name = models.CharField()
.... other fields
class Education(models.Model):
education_id = models.AutoField(primary_key=True)
resume_id = models.ForeignKey(Resume)
degree_name = models.CharField()
.... other fields
class Experience(models.Model):
experience_id = models.AutoField(primary_key=True)
resume_id = models.ForeignKey(Resume)
company_name = models.CharField()
.... other fields
class Skills(models.Model):
skill_id = models.AutoField(primary_key=True)
resume_id = models.ForeignKey(Resume)
skill_name = models.CharField()
.... other fields
I want to a query-set that against a given job_id in jobapplication model, it should fetch all its related education, experience, skills etc with reference to resume id against job id.
For Now, I do this in Single quires, like i fetch resume_id from job_application then fetch resume details with reference
resume_against_job =Jobapplication.objects.get_query_set().get_complete_Jobapplication(job_id)
for resum in resume_against_job:
resume_dict = {}
resume_id = resum['resume_id']
user_id = resum['user_id']
then against these user_id and resume_id, i wrote another queries to fetch user details and their resume detail.

To answer your question, you can only do separate queries on each model if you have the resume_id (I see it on each model you have), maybe you can wrap them in one function, but it doesn't get any simpler than that.
I think your fundamental problem is in the database design. If you have resume_id in each model, why not merge all of them into Resume model? Sounds like they all belong to that model, if each Education, Experience, Skill is Resume specific. You only create separate model if resumes share common Education, Experience or Skill, but then they should be foreign keys on the Resume model. Also in this case, you only query on Resume model and get all other information instead of searching on multiple places.

Related

How to change the primary key of manytomany table in django

I am changing the primary key of the legacy database. I was able to change the primary key by setting id as the primary key.
Before
class User(models.Model):
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
After
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
Then
python manage.py makemigrations
python manage.py migrate
This is working fine.
But I also want to change the default primary key of the tables created via ManyToMany feild.
User Model
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
UserProfile Model
class UserProfile(models.Model):
id = models.BigIntegerField(primary_key=True)
address = models.CharField(max_length=5)
father_name = models.CharField(max_length=5)
pincode = models.CharField(max_length=5)
user = models.ManyToManyField(User)
The ManytoMany field creates table called User_user_userprofile with id as Autofield basically previous or default django primary key.
id, user_id, userprofile_id
ManytoMany Table
Now, How to change the primarykey of ManytoMany Feild ie id created by Django?
PS:
Django: 1.11
Python: 2.7.5
DB: Sqlite3 3.7.17 2013-05-20
I stumbled upon this problem today, and ended up solving it by using the through argument of the ManyToManyField. I solved it for Django v3.2.6 however, but the documentation for v1.11 mentions the same behavior for the same argument, so hopefully the solution should work for your version of Django too. Here's the link to the documentation for v1.11 ManyToManyField.through
What the through argument allows you to do is to create the intermediary table (created automatically by ManyToManyField) yourself. You get finer control of how the intermediary table should look like, what fields it should have and what their behavior should be. Hope you are getting a picture.
Let me give you the example of the problem I faced and how I solved it. Hopefully that will make this clearer.
I was trying to establish a many-to-many relationship between two of my existing models.
My first model looks like this,
class BanglaWords(models.Model):
class Meta:
verbose_name_plural = 'Bangla Words'
bng_id = models.CharField(max_length=16, primary_key=True)
bangla_word = models.CharField(max_length=64)
def __str__(self):
return self.bangla_word
and the second one looks like,
class EnglishWords(models.Model):
class Meta:
verbose_name_plural = 'English Words'
eng_id = models.IntegerField(primary_key=True)
word = models.CharField(max_length=64)
bangla_word = models.ManyToManyField(BanglaWords)
def __str__(self):
return self.word
But this resulted in an intermediary table wordnet_englishwords_bangla_word which looked like this,
wordnet_englishwords_bangla_word
id
englishwords_id
banglawords_id
But I didn't want this, I wanted bng_id to be the pk for this table. I solved the problem with ManyToManyField.through as follows,
I defined the intermediary model(table) myself and with the through argument, I pointed to the new intermediary model I created and instructed django to create the table the way I wanted it.
First I created the intermediary model,
class BanglaEnglishRelations(models.Model):
class Meta:
verbose_name_plural = 'Bangla English Relations'
bng_id = models.OneToOneField('BanglaWords', primary_key=True, on_delete=models.CASCADE)
eng_id = models.ForeignKey('EnglishWords', on_delete=models.CASCADE)
which defines bng_id as the primary key as I desired.
Second, I told the ManyToManyField in EnglishWords to base the table on BanglaEnglishRelations like,
bangla_word = models.ManyToManyField(BanglaWords, through=BanglaEnglishRelations)
This resulted in the table wordnet_banglaenglishrelations which looked like,
wordnet_banglaenglishrelations
bng_id_id
eng_id_id
and surved my purposes. You can do something similar to solve your problem and promote whatever field to a pk.

Saving many-to-many relationship through intermediate model

I have a model that looks like this:
class Post(models.Model):
title = models.CharField(max_length=100, null=False)
content = HTMLField()
created_at = models.DateField(auto_now_add=True)
authors = models.ManyToManyField(User)
When I create a post like this:
x = Post(title="blah", content="blah)
How can I add multiple authors to this Post? The authors model is created as an intermediate model and I have not defined it.
Firstly, you need to save the model instance before adding any many to many relationships (refer documentation).
x.save()
To add multiple users, loop it through the user's queryset.
users = User.objects.filter(foo=bars)
for item in users:
x.authors.add(item)

How to fetch all records from 2 tables

I have 2 models
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
employee_id = models.CharField(max_length=13, unique=True)
class UserRole(models.Model):
employee_id = models.ForeignKey(CustomUser, to_field='employee_id', unique=True, on_delete=models.CASCADE)
supervisor_id = models.CharField(max_length=20, null=True)
and have defined seriallizers for both models
class UserSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = models.CustomUser
class UserRoleSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = models.UserRole
consider i have 5 records in both tables
How to fetch all records from both tables (email, employee_id, supervisor_id )
like, where CustomUser.employee_id = UserRole.employee_id
I tried with
models.CustomUser.objects.select_related('UserRole')
But, not able to fetch records from UserRole table.
UserRole.objects.select_related('employee_id')
-- this is fetching only userRole records
Thanks in Advance
You don't get automatic joins in Django, no need for it because you can just follow the ForeignKey relation on the object (the_object_you_get.its_foreign_key). Now, of course, that will hit the DB twice. if you'd rather avoid that, you can use something like .prefetch_related('employee_id') on whatever queryset you need to use. This will prevent you from hitting the DB multiple times (at the price of one larger initial query of course).
Finally, if you wanna serialize a ForeignKey relation, the answer Shakil gave is pretty comprehensive. Only thing is that you don't necessarily need to set the employee_id field as read_only=True (a bit of a limitation). You can also override the UserRoleSerializer .create() the method so that it calls the .create() method of UserSerializer.
I think from UserRole you want to all information about employe's too. What i am thinking you want to get all details information of employee_id foreign_key relation. This can be done by
UserRole.objects.all()
with the following serializers.
class UserSerializer(serializers.ModelSerializer):
class Meta:
fields = ('email','employee_id',)
model = models.CustomUser
class UserRoleSerializer(serializers.ModelSerializer):
employee_id = UserSerializer()
class Meta:
fields = ('employee_id','supervisor_id',)
model = models.UserRole

Get all related field in Django model

I am struggling to understand how one-to-many and many-to-many relation works in Django model. My schema looks something like this so far, I am open for suggestions to make it better.
A many-to-many relation between users and team. Also, there will be schedules that belong to a particular user of a team.
This is how my model looks like so far,
class Team(models.Model):
tid = models.AutoField(primary_key=True)
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
class Schedule(models.Model):
sid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
class BelongsTo(models.Model):
bid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE)
Question: I want to get the information of each user, what are their schedules and which team each schedule belongs to. How would I to do it? I have tried BelongsTo.objects.select_related().all(), but it is not working for me.
Note: I am open for suggestions, if something is wrong with my schema or model or the approach, please let me know.
BelongsTo is seems like utility table.So
BelongsTo.objects.all().values('user', 'team__team_name', 'schedule')
Your schema looks almost right, but I would modify it a little bit. In particular, I will change how Schedule is implemented. Instead of having a sid in the User Belongs To join-table, I would include the user and team in the Schedule table as foreign keys.
This is how the Django models should then look like:
class User(models.Model):
username = models.CharField(max_length = 200)
# put other fields like password etc. here
class Team(models.Model):
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
user = models.ManyToManyField("User")
class Schedule(models.Model):
user = models.ForeignKey("User")
team = models.ForeignKey("Team")
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
Note the following:
You don't need to have a primary key field in the models because Django adds a primary key field called pk or id automatically.
Note the absence of the User Belongs To model. Django implements join-tables like User Belongs To automatically when you use a ManyToManyField. See the Django docs on many-to-many relationships.
You also don't need on_delete = models.CASCADE on ForeignKey fields, because this is the default behavior.
To see how to get information about users, teams and schedule from this configuration of models, consult the Django documentation on making db queries. It's quite easy.

Return all of users posts and favourites? Django

I'm creating a summary page of all of the posts the user has liked and all of the posts which the user has created.
I have two models in my db: Aircraft & Airline. The user can upload posts to either model that they prefer. I'm just slightly clueless on how to retrieve their posts?
Aircraft Model
class Aircraft(AircraftModelBase):
manufacturer = SortableForeignKey(Manufacturer)
aircraft_type = SortableForeignKey(AircraftType)
body = SortableForeignKey(Body)
engines = models.PositiveSmallIntegerField(default=1)
Airline Model
class Airline(AirlineModelBase):
fleet_size = models.PositiveSmallIntegerField()
alliance = models.CharField(max_length=100, null=True)
average_fleet_age = models.PositiveSmallIntegerField()
In my Accounts app I've made a model of the following:
class FavoritedAircraft(models.Model):
user = models.ForeignKey(User)
aircraft = models.ForeignKey(Aircraft)
def __str__(self):
return self.aircraft.name
class FavoritedAirline(models.Model):
user = models.ForeignKey(User)
airline = models.ForeignKey(Aircraft)
def __str__(self):
return self.airline.name
How do I essentially return the users favourite posts and if the user has uploaded anything, those posts as well?
Thanks for any help!
EDIT
class UploadedAircraft(models.Model):
user = models.ForeignKey(User)
aircraft = models.ForeignKey(Aircraft)
def __str__(self):
return self.aircraft.name
The favourited category you can query with something like FavoritedAirline.objects.filter(user=<the_user_here>), and it will return an iterable queryset.
However, judging for the implementation of the Aircraft and Airline models you posted, you have no field referencing who created the post (unless it's defined in your base class). If you add it there as a foreign key, just like you did in the FavoritedAirline model, you can use the same sort of query as above.