Query between three tables, many to many relationship - python

I have three databases in GAE. Hobby, Attendee and Event.
class Hobby(db.Model):
name = db.StringProperty()
htest = Hobby.get_or_insert('tennis')
htest.name = 'tennis'
htest.put()
htest = Hobby.get_or_insert('basketball')
htest.name = 'basketball'
htest.put()
htest = Hobby.get_or_insert('food')
class Event(db.Model):
title = db.StringProperty(required=True)
description = db.TextProperty()
time = db.DateTimeProperty()
location = db.TextProperty()
creator = db.UserProperty()
edit_link = db.TextProperty()
gcal_event_link = db.TextProperty()
gcal_event_xml = db.TextProperty()
hobby = db.ReferenceProperty(Hobby)
class Attendee(db.Model):
email = db.StringProperty()
hobbies = db.ListProperty(db.Key)
event = db.ReferenceProperty(Event)
Each Attendee can pick however many hobby as they desire. When a event is created, user chooses a hobby to associate the event with and invitation will be send to every attendee who has chosen that hobby. Hobby DB is preloaded database.
I want to make a query that does that.
after reading Nick's blog
http://blog.notdot.net/2010/10/Modeling-relationships-in-App-Engine
which was very helpful I feel like I'm supposed to use the method that was mentioned in there
attendees = Attendee.all()filter('hobbies =', basketball).fetch(100)
however, i'm stuck there... any help would be really appreciated.

I think you should record the invitations send in a table, say "invitationsSend" with two fields : event and attendee, which two fields are making a unique primary key.
To build this, you will have to select the data between both your tables event and attendees :
insert into invitationsSend(select E.Event, A.Attendee from Event as E, Attendee as A where E.Hobby = A.Hobby)
But I'm not familiar with your "db.listProperty" used for "hobbies" and I do not know how to look into that list. I should do this as a separate table with data "Attendee, Hobby", both as primary key.
Regards,

Related

How to change join and group by SQL to ORM in Django

I'm new in Django. So, I want to join two models which are company and client and count the number of clients for each of the company. Here the SQL
SELECT Company_company.name, count(Client_client.cid)
FROM Company_company
LEFT JOIN Client_client
ON Company_company.comid = Client_client.comid_id
GROUP BY Company_company.name;
But since in Django, we use ORM. So I'm a little bit confusing since I'm a beginner. I already refer few SQL to ORM converter website such as Django ORM and do some try and error. But, I didn't know where the problem since I want the output from the ORM to be classified into a different array. Here is my code:
labels = []
data = []
queryClientCompany = client.objects.values('comid').annotate(c=Count('cid')).values('comid__name','c')
for comp in queryClientCompany:
labels.append(comp.comid__name)
data.append(comp.c)
Here some of the relevant things in the client and company models:
class client (models.Model):
#client info
cid = models.AutoField(primary_key = True)
comid = models.ForeignKey(company,related_name='companys',
on_delete = models.DO_NOTHING,verbose_name="Company",null = True, blank = True)
class company(models.Model):
comid = models.AutoField(_('Company'),primary_key = True)
#company info
name = models.CharField(_('Company Name'),max_length = 50)
The error stated that the comid__name is not defined. So actually how to append the result? I hope someone can help me. Thank you for helping in advanced.
You should query from the opposite side to perform the LEFT OUTER JOIN between company and client (and not client and company):
from django.db.models import Count
labels = []
data = []
queryClientCompany = company.objects.annotate(
c=Count('companys__cid')
)
for comp in queryClientCompany:
labels.append(comp.name)
data.append(comp.c)
The companys part is due to the related_name='copanys', but it does not make much sense to name this relation that way. The related_name=… parameter [Django-doc] specifies how to access the Clients for a given Company, so clients is a more appropriate value for the related_name:
class client (models.Model):
cid = models.AutoField(primary_key=True)
comid = models.ForeignKey(
company,
related_name='clients',
on_delete = models.DO_NOTHING,
verbose_name="Company",
null = True,
blank = True
)
then the query is:
from django.db.models import Count
labels = []
data = []
queryClientCompany = company.objects.annotate(
c=Count('clients__cid')
)
for comp in queryClientCompany:
labels.append(comp.name)
data.append(comp.c)

how to use backref in peewee

basically im trying to write a index route that returns the posts of a business that a user is subscribed to
the last line is throwing an error for the backref (business.posts)
# query that finds all the subscriptions of the logged in user
subscriptions_query = models.Subscription.select().join(models.User).where(models.User.id == current_user.id)
# gets the businesses being followed from the subscriptions
businesses_being_followed = [subscription.following for subscription in subscriptions_query]
post_dicts = [model_to_dict(business.posts) for business in businesses_being_followed]
this is my posts model
class Post(BaseModel):
business = ForeignKeyField(Business, backref='posts')
image = CharField()
content = CharField()
date = DateTimeField(default=datetime.datetime.now)
Your example is REALLY inefficient.
Can you just do:
(Post
.select()
.join(Business)
.join(Subscription)
.where(Subscription.user == the_user_id))

Creating unique index with peewee for table with foreign key

Say that I have a table called TBL_ACCOUNT which contains all of my users, and a table called TBL_EMAIL_SUBSCRIPTION where it contains the feeds that a user is subscribed to. I'm trying to make it so that there can only be one entry of each user+feed combination, so user1 can only be subscribed to feed1 once, but user1 can be subscribed to feed1 and feed2 simultaneously.
This is what my model looks like:
class TBL_ACCOUNT(BaseModel):
USERNAME = CharField(unique=True)
PASSWORD = CharField()
EMAIL = CharField(unique=True)
class TBL_EMAIL_SUBSCRIPTION(BaseModel):
USER = ForeignKeyField(TBL_ACCOUNT)
FEED = CharField()
class Meta:
indexes = (("USER_id", "FEED", True))
I have also tried just using "USER" for the indexes, but that didn't work out as the database still received duplicates.
Please refer to the peewee docs: http://docs.peewee-orm.com/en/latest/peewee/models.html#indexes-and-constraints
In your case it should look like this:
class Meta:
indexes = (
(("USER_id", "FEED"), True),
)
Note the use of commas! They are very important, because indexes are a tuple of tuples.

Django query: Joining two models with two fields

I have the following models:
class AcademicRecord(models.Model):
record_id = models.PositiveIntegerField(unique=True, primary_key=True)
subjects = models.ManyToManyField(Subject,through='AcademicRecordSubject')
...
class AcademicRecordSubject(models.Model):
academic_record = models.ForeignKey('AcademicRecord')
subject = models.ForeignKey('Subject')
language_group = IntegerCharField(max_length=2)
...
class SubjectTime(models.Model):
time_id = models.CharField(max_length=128, unique=True, primary_key=True)
subject = models.ForeignKey(Subject)
language_group = IntegerCharField(max_length=2)
...
class Subject(models.Model):
subject_id = models.PositiveIntegerField(unique=True,primary_key=True)
...
The academic records have list of subjects each with a language code and the subject times have a subject and language code.
With a given AcademicRecord, how can I get the subject times that matches with the AcademicRecordSubjects that the AcademicRecord has?
This is my approach, but it makes more queries than needed:
# record is the given AcademicRecord
times = []
for record_subject in record.academicrecordsubject_set.all():
matched_times = SubjectTime.objects.filter(subject=record_subject.subject)
current_times = matched_times.filter(language_group=record_subject.language_group)
times.append(current_times)
I want to make the query using django ORM not with raw SQL
SubjectTime language group has to match with Subject's language group aswell
I got it, in part thanks to #Robert Jørgensgaard Eng
My problem was how to do the inner join using more than 1 field, in which the F object came on handly.
The correct query is:
SubjectTime.objects.filter(subject__academicrecordsubject__academic_record=record,
subject__academicrecordsubject__language_group=F('language_group'))
Given an AcademicRecord instance academic_record, it is either
SubjectTime.objects.filter(subject__academicrecordsubject_set__academic_record=academic_record)
or
SubjectTime.objects.filter(subject__academicrecordsubject__academic_record=academic_record)
The results reflect all the rows of the join that these ORM queries become in SQL. To avoid duplicates, just use distinct().
Now this would be much easier, if I had a django shell to test in :)

Querying a ManyToMany Field in a Django model

So I have these two models:
class Player(models.Model):
playerName = models.CharField(max_length= 50)
playerTeam = models.CharField(max_length=20)
class Role(models.Model):
roleName = models.CharField(max_length= 50)
players = models.ManyToManyField(Player)
Now, storing different players under one role was easy. My aim is to retrieve distinct 'playerTeam' under one role. To make it clear, I want the values of the different teams in string format. So, if two Player object is stored as:
p = Player(playerName='Zidane', playerTeam = 'Real Madrid')
p1 = Player(playerName='Laudrup', playerTeam = 'Barcelona')
and both are added to one Role object, say:
r = Role(roleName='playmaker')
r.save()
r.add(p)
r.add(p1)
r.save()
I want to write a query which will give me 'Real Madrid' and 'Barcelona' as results.
Writing the query for it is proving to be a challenge. Any help I can get?
What you need is:
r.players.values_list('playerTeam', flat=True)
Where r is the Role for which you want to get the teams.
If you want to get distinct teams, just put the result in a set().

Categories

Resources