I am currently having the following
class Profile(models.Model):
gender = models.BooleanField()
class Q(models.Model):
name = models.CharField(max_length=128)
class A(models.Model):
q = models.ForeignKey(Q)
profile = models.ForeignKey(Profile)
What I try to do is to query Q and get the number of Answers given by either male or female?
Unfortunately, I don't even have a better idea than writing custom SQL, which I'd rather avoid for the sake of database portability. How would I start?
You're there. You just need to actually use the right filter syntax. If you're trying filter on the gender field on profile, then you do that with profile__gender, so:
males_answering = question.answers.filter(profile__gender="male").count()
Related
Lets say that i have 2 models :
Class OrderEvent(models.Model):
isPaid = models.Booleanfield()
Class Participant(models.Model):
orderEvent = models.ForeignKey(OrderEvent)
participantFirstName = models.CharField()
participantLastName = models.CharField()
#etc...
And i want to get all the participants where Orderevent.isPaid = True.
I think that i struggle to do something very simple...
It is very simple;
Participant.objects.filter(orderEvent__isPaid=True)
As a suggestion you can follow,
naming conventions from here.
Django making queries from here.
I have the following models:
class Street(models.Model):
name = models.CharField(max_length=40)
class House(models.Model):
street = models.ForeignKey(Street, models.PROTECT)
number = models.CharField(max_length=10)
class Meta:
unique_together = ('street', 'number')
class Room(models.Model):
house = models.ForeignKey(House, models.PROTECT)
number = models.CharField(max_length=10)
class Meta:
unique_together = ('house', 'number')
I already know the ID of a Street and would like to get all the rooms of all the houses in that street. In SQL that is easy:
SELECT *
FROM room JOIN house ON house.id = room.house_id
WHERE house.street_id = xyz;
Now how do I do this in Django? I tried
Room.objects.select_related('house').filter(street=xyz)
But I get an exception saying I can't access this field:
django.core.exceptions.FieldError: Cannot resolve keyword 'street' into field. Choices are: house, house_id, id, number
Because of the amounts of data I am facing, I would really like to be able to join and filter using a single query! When giving up one or the other, I would have to resort to either making multiple queries or filtering in Python, both of which are inherently inefficient. An alternative would be raw queries, I guess...
You can get access to related object's field with __ syntax:
Room.objects.select_related('house').filter(house__street=xyz)
This can be done as much time as you need, to select rooms by street name you can do this:
Room.objects.select_related('house').filter(house__street__name=xyz)
Chech details here.
Maybe this is a very newbie question, but I am stuck in this point. I do not know if the problem is the model or I do not understand very well aggregations and annotations.
I have a model like this:
class User(models.Model):
collection = models.ManyToManyField(Book, through='BookCollection')
class Book(models.Model):
name = models.CharField(max_length=200)
class BookCollection(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
score = models.IntegerField(default=0)
I want to get the score average for all the books and all users, excluding that ones that has a default score equals to 0 (this value represents that the user has the book in the collection, but it has not been rated). I am trying to use an annotation like this:
Book.objects.exclude(collection__score=0).annotate(avg=Avg('collection__score'))
but if there is a book rated with 0 and 3, for example, both entries are excluded.
Is there any way to tell Avg() that it should take into account only values greater than 0?
Thanks in advance.
There is no way to do that in the Django ORM without raw SQL.
A better model would be to allow null values in your score field. Null values are ignored in Avg():
class BookCollection(models.Model):
...
score = models.IntegerField(null=True, blank=True, default=None)
None is generally the best way to describe a lack of an entry in a field. This avoids confusion, e.g. in calculations such as calculating the average.
Suppose there is family, each family member can login to my app, when the user login, I want to show the relation between him and the other family member instead of just the family member name.
the real challenge is the relation is dynamic according to the login user, for example:
A is the father of B
C is the wife of B
B and C have a child D
if D login the relation will be
A = granddad
B = father
C = mother
D = me
but if A log in , the relation will be
A = me
B = son
C = daughter in law
D = grandson
the example is fairly simple but the real world situation is much more complicated, like borther and sister, aunt,uncle etc.
Am using django and this is how my model is defined:
class UserProfile(models.Model):
user = models.OneToOneField(User)
family = models.ManyToManyField(FamilyProfile,related_name='family_members')
realname = models.CharField(max_length=100)
date_of_birth = models.DateField(
'user born date', null=True, blank=True)
is_male = models.BooleanField(default=False) # True male
relation_level = models.IntegerField(null=False,blank=False,default=9999)
is_foreign = models.BooleanField(default=False) # True foreign
is_host = models.BooleanField(default=False) # Ture host,
objects = profileManager()
because the relation ship is dynamic , I can't save it to the database, instead, I use the profileManager to calculate the relation ship and add it to the member: member.relation_name, but this is too complicated for me, right now I'm using a lot of if...else statement and its really long, and really stupid, so please help me with this problem .
If you look at it from a DB point-of-view the correct way to do this is to add an 'id' field to the UserProfile model, and also add another class like:
class Relations(models.Model):
relation_id = models.IntegerField()
relation_name = models.CharField()
which would be filled with the relations (like: (1, "son of"), (2, "father of"), etc..) (you might also need to make one string for male and one for female. That's the least interesting point here.
After you've created this list of Relations you need to assign the relations to users, and therefore we make another model:
class UserToRelations(models.Model):
user_a_id = models.IntegerField()
user_b_id = models.IntegerField()
relation_id = models.IntegerField()
[You might just do that with the keys, I really don't remember django that well]
So now you need to populate the UserToRelations table just each time you add a member to the DB. You calculate the relationships there.
The selecting part is where you see the profit of this. Every time a member logs in, you just need to get all the relevant rows from the UserToRelations model and you just present them.
Just starting in Python/Django framework so sorry if this is dumb... but i cant find any solution.
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField(Contact)
class Contact(models.Model):
name = models.CharField(max_length=200)
dealers = models.ManyToManyField(Dealer)
I have this relation set up however when I run SyncDB it doesnt work. It tells me that Contact is not defined on this line
contacts = models.ManyToManyField(Contact)
Im more familiar with compiled languages. Is there anyway to tell python that the contact class exists, or better yet is there a special syntax im missing for defining this kind of relation.
I dont see a need for a two way ManyToMany in both the models, as they are a M:N relationship (2 way relationship).
Your issue here is, Contact is not defined at the point of execution of this code:
contacts = models.ManyToManyField(Contact)
So You need to wrap it in quotes for it to work
contacts = models.ManyToManyField('Contact')
Documentation on that can be found here
I would recommend the following models:
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField('Contact')
class Contact(models.Model):
name = models.CharField(max_length=200)
and It would do exactly what you are looking for.
You can read about ManyToMany relationships here. The same link also covers how to handle Reverse m2m queries
If you want to do a two way ManyToMany both, you just only need to do this:
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField('Contact', blank=True)
class Contact(models.Model):
name = models.CharField(max_length=200)
dealers = models.ManyToManyField('Dealer', through=Dealer.projects.through, blank=True)
I guess it will work to you.