DJANGO - Filter Data from two models - django

I have two MySQL models:
class registration(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
password = models.CharField(max_length=30)
company = models.CharField(max_length=30)
class personal_details(models.Model):
reg = models.ForeignKey(registration)
job = models.CharField(max_length=30)
experience = models.IntegerField(default=0)
I want to filtering details using both experience and company as a keyword. I want to fetch and display details(name, email, company, job, experience) from both tables in my HTML page.

You can do it inside the filter() so you should do something like this
I'm working from the personal_details object now:
filteredResults = personal_details.objects.filter(experience="grasscutting", reg__company="IBM")
This will give you a list of objects found.
The magic here is that you can access ForeignKey relationships with the __ convention.

Related

Merge Django models into a view

I am attempting to merge and pull data from three Django models into a view. Players and Events relate to each other in the Details model (a player can attend many events) using models.ForeignKey.
In other platforms I would have written a DB View to join tables and the application would query that view.
From what I understand Django does not support data views within Models.
Looking for help on how I would approach this in Django.
class Players(models.Model):
firstName = models.CharField(max_length=255)
lastName = models.CharField(max_length=255)
highSchool = models.CharField(max_length=255)
gradYear = models.IntegerField()
slug = models.SlugField(default="", null=False)
class Events(models.Model):
title = models.CharField(max_length=255)
location = models.CharField(max_length=255)
date = models.DateField()
class Details(models.Model):
event = models.ForeignKey(Events, on_delete=models.CASCADE)
player = models.ForeignKey(Players, on_delete=models.CASCADE)
height = models.IntegerField(default=None, blank=True)
weight = models.IntegerField(default=None, blank=True)
def playerdetail(request,slug):
playerinfo = Details.objects.get(id=1)
template = loader.get_template('playerdetail.html')
context = {
'playerinfo': playerinfo,
}
return HttpResponse(template.render(context, request))
You are actually doing what you needed to do with the code you provided.
When you are invoking a query on a model that connects those two entities (Players,Events), it performs the join when you try to access each of these properties through the foreign key fields.
For example, for accessing the player information (which makes the Django ORM perform the join operation in the background):
# Get the first name of the player
first_name = playerinfo.player.firstName
For filtering and showing in other places, you can use the notation field__subfield
For more information, please read the examples of this website:
https://books.agiliq.com/projects/django-orm-cookbook/en/latest/index.html

Django ORM Query Optimization Issue

I am making a blog website and I am facing some issues with the Query performance.
I have 3 models
User Model -> Users (To store user email, Password etc)
Post Model -> Actual Posts
people Model -> (To store users extra information)
Post Model ->
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
title = models.CharField(max_length=255,null=True)
description = models.CharField(max_length=1000,null=True)
Likes = models.ManyToManyField(to=User, related_name='Post_likes')
favourites = models.ManyToManyField(to=User,blank=True,related_name="favourite")
People Model ->
class People(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
photo = models.ImageField(upload_to='profile_pics', blank=True,null=True)
Phone_number = models.CharField(max_length=255,null=True,blank=True)
Birth_Date = models.DateField(null=True,blank=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
Now as both of these models are connected to User model. I want to query the Post model and get the user photo in the template. Now when I use post.user.people.photo then for every post it generates a seperate query to DB resulting in slowness. I would like to use Join here to combines multiple tables and fetch all the records at once.
I am currently using following Query ->
posts = Post.objects.select_related().prefetch_related('images_set').annotate(comments_Count = Count('comments_post',distinct=True)).annotate(Count('Likes',distinct=True)).all().order_by('-id')
You can perform a .select_related(…) [Django-doc] on the user and the people with user__people, so:
posts = Post.objects.select_related(
'user__people', 'category'
).prefetch_related('images_set').annotate(
comments_Count = Count('comments_post',distinct=True),
Count('Likes',distinct=True)
).order_by('-id')
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

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.

Store List(s) in a database

My Users has phone contact LIST(s) - [3121234567,2121234567,6601234567]
Now, I want each user to be able to store as many LIST as possible. Each List must have a name(or description) attached to them under each USER account. Note: the number of LIST is dependent on Users needs. Example:
Students
[3121234567,2121234567,6601234567]
Club Member
[8101234567,8151234567,8171234567]
Now, how do I store it in a database.
Django User Model
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
phone = models.CharField(max_length=10)
email = models.EmailField(max_length=128)
street = models.CharField(max_length=128)
city = models.CharField(max_length=128)
state = models.CharField(max_length=2, choices=STATE_CHOICES, default=STATE)
zip_code = models.IntegerField(max_length=5, null=True, blank=True
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username', 'first_name', 'last_name', 'phone', 'street', 'city', 'state']
objects = CustomUserManager()
Edit(Added):
I am not looking to create Student or ClubMember models. This name is use to identify the python phone contact list. PhoneAddress one can be labelled(named) as Student for one user but called "Conference Attendant" for another. Each user have different # of Lists.
PhoneAdress PhoneAdress2 PhoneAdress3
[3121234567,2121234567,6601234567] [4121234567,3121234567,6601234567] [7121234567,8121234567,9601234567]
Lemme guess, you're coming from a NoSQL background where the database is a document in a JSON form?
If so, I am sorry, in a Relational Database, used by Django in the likes of PostgreSQL or MySQL, they call something Foreign Keys, and that is your way of storing multiple "Lists" related to a particular field.
If you want many users to store as many lists as possible, you're looking at something like this, roughly speaking:
class myUserModel(models.Model):
# your arbitrary fields here
# then you do something like this:
class Student(models.Model):
user = models.ForeignKey(User)
class clubMember(models.Model):
user = models.ForeignKey(User)
With the above setup, you can add as many Student objects associated to the myUserModel class, so as the clubMember
However, if you wish to use PostgreSQL specifically, as your backend (perhaps as perpetual storage backend), you might find some sense in using Django's support for the ArrayField
And ooh, you might need to extend the Django User Model to add any extra fields easily, unless you're willing to go down the road of a custom User Model.
More info:
Django ForeignKey
This SO answer on 'OneToManyFields', similar to adding multiple items to a single field.
I hope the above helps
Create some models:
class Club(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
date_open = models.DateField()
class Institution(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
address = models.CharField(max_length=256,blank=True,null=True)
type = models.CharField(max_length=256,blank=True,null=True) #university, college
Rather than using
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
use composition in the form of OneOnOneField
class UserProfile(models.Model):
user = models.OneOnOneField(User,blank=True,null=True)
club_member = models.ManyToManyField(Club,blank=True, null=True)
institutions = models.ManyToManyField(Institution,blank=True, null=True) # student in
Once you have this, you will be able to get and add as many institutions and clubs to the lists:
user = User.objects.get(id=user_id)
club = Club.objects.get(id=club_id)
institution = Institution.objects.get(id=institution_id)
user.profile.clubs.add(club)
user.profile.institutions.add(institution)
So to verify if the user is a member of a club
club = user.proile.clubs.get(id=club_id)
and to verify the user is a student in an institution use
institution = user.profile.institutions.get(id=institution_id)

ForeignKey field problem in Django

I have declared two of my models this way:
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
class Customer(models.Model):
.
.
.
email_address = models.ForeignKey(EmailAddress)
def __unicode__(self):
name = ''+str(self.title)+" "+str(self.first_name)+" "+str(self.last_name)
return name
The idea is that one customer can have several email addresses associated to him/her...the problem is how to do this correctly...as you can see from my code above, the customer foreign key field has to be after the customer class, but the email address foreign key field has to be after the EmailAddress class...how do I sort out this issue?
There is a serious logic flaw here - ForeignKey from Customer to Email would mean that each customer has only one email. You would want to skip that foreignkey alltogether:
class Email(models.Model):
customer = models.ForeignKey(Customer, related_name='email_addresses')
then simply do customer.email_addresses to get a list of all emails. You dont need another ForeignKey, django uses relationships defined in one model (unlike RoR and other MVC frameworks)
I don't see why you want to use a ForeignKey in EmailAddress.
Extract from Python web development with Django:
Foreign keys are generally used to
define one-to-many (or many-to-one)
relationships.
In the next example a Book has a single Author and an Author can have many Books.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author)
Just add single-quotes around Customer:
class EmailAddress(models.Model):
customer = models.ForeignKey('Customer')
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
Menda's answer is correct. There isn't really an ordering problem because the Customer model doesn't need a ForeignKey field. Just remove that and flip the order in which the classes are defined.
class Customer(models.Model):
pass
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
There's also a Django email field you can use. See Django EmailField. Just wanted to mention that in case it could add value to you application.