How can I make a django query-set that uses two classes? - python

How can I link two classes in a django query set. For example I have a class Person and a class Department. A person has an attribute salary and a Department has the attribute leader. How can I do a query that gives me the salary of the leader of a department.
I am happy for any help :)

You don't need a special query, the leader attribute on the Department object gives you access to a full Person object, with all its properties:
department = Department.objects.get(pk=1)
print(department.leader.salary)
Behind the scenes the code above will generate two SQL queriers. To make sure only one query is issued you can optionally use select_related:
department = Department.objects.select_related('leader').get(pk=1)
print(department.leader.salary)
This way Django will fetch information about the leader's Person object during the original query (instead of the usual "lazy" approach of waiting until it is actually needed). This however is only an optimization and often times isn't really needed.
In case you want to filter a queryset using a field from an object across a relationship, you can use the __ notation, which represents the relationship between two models:
departments = Department.objects.filter(leader__salary=100)

Related

Calculate weighted score from Salesforce data in Django

I'm looking to connect my website with Salesforce and have a view that shows a breakdown of a user's activities in Salesforce, then calculate an overall score based on assigned weights to each activity. I'm using Django-Salesforce to initiate the connection and extend the Activity model, but I'm not sure I've setup the Activity or OverallScore classes correctly.
Below is my code for what I already have. Based on other questions I've seen that are similar, it seems like a custom save method is the suggested result, but my concern is that my database would quickly become massive, as the connection will refresh every 5 minutes.
The biggest question I have is how to setup the "weighted_score" attribute of the Activity class, as I doubt what I have currently is correct.
class Activity(salesforce.models.Model):
owner = models.ManyToManyField(Profile)
name = models.CharField(verbose_name='Name', max_length=264,
unique=True)
weight = models.DecimalField(verbose_name='Weight', decimal_places=2,
default=0)
score = models.IntegerField(verbose_name='Score', default=0)
weighted_score = weight*score
def __str__(self):
return self.name
class OverallScore(models.Model):
factors = models.ManyToManyField(Activity)
score = Activity.objects.aggregate(Sum('weighted_score'))
def __str__(self):
return "OverallScore"
The ideal end result would be each user logged in gets a "live" look at their activity scores and one overall score which is refreshed every 5 minutes from the Salesforce connection, then at the end of the day I would run a cron job to save the end of day results to the database.
Excuse a late partial response only to parts of question that are clear.
The implementation of arithmetic on fields in weighted_score depends on your preferences if your prefer an expression on Django side or on Salesforce side.
The easiest, but very limited solution is by #property decorator on a method.
class Activity(salesforce.models.Model):
... # the same fields
#property
def weighted_score(self)
return self.weight * self.score
This can be used in Python code as self.weighted_score, but it can not be passed any way to SOQL and it gives you not more power than if you would write a longer (self.weight * self.score) on the same place.
Salesforce SOQL does not support arithmetic expressions in SELECT clause, but you can define a custom "Formula" field in Salesforce setup of the Activity object and use it as normal numeric read only field in Django. If the Activity would be a Master-Detail Relationship of any other Salesforce object you can apply very fast Sum, max or average formula on that object.
ManyToMany field require to create the binding object in Salesforce Setup manually and to assign it to the through attribute of the ManyToMany field. An example is on wiki Foreign Key Support. As a rule of thumb your object definition must first exist in Salesforce with useful relationships (it can be Lookup Relationship or Lookup Relationship) and manageable data structure. Then you can run python manage.py inspectdb --database=salesforce ... table names (optionally a list of API Names of used tables, separated by spaces) That is much code to prune many unnecessary fields and choices, but still easier and reliably functional than to ask someone. Salesforce has no special form of custom ManyToMany relationship, therefore everything is written by ForeignKey in models.py. Master-Detail is only a comment on the ForeignKey. You can finally create a ManyToMany field manually, but it is mainly only a syntactic sugar to have nice mnemonic name for a forward and reverse traversing by the two foreign keys on the "through=" binding object.
(The rest of question was too broad and unclear for me.)

Can you help me understand the nbd Key Class Documentation or rather ancestor relationship?

I am trying to wrap my head 'round gae datastore, but I do not fully understand the documentation for the Key Class / or maybe it is ancestor relationships in general I do not grasp.
I think what I want is multiple ancestors.
Example:
Say I wanted to model our school's annual sponsored run for charity; school kids run rounds around the track and their relatives (=sponsors) donate to charity for each round completed.
In my mind, I would create the following kinds:
Profile (can be both runner and sponsor)
Run (defines who (cf. profile) runs for what charity, rounds actually completed)
Sponsorship (defines who (cf. profile) donates how much for what run, whether the donation has been made)
I've learned that datastore is a nosql, non-relational database, but haven't fully grasped it. So my questions are:
a. Is creating an entity for "Sponsorship" even the best way in datastore? I could also model it as a has-a relationship (every run has sponsors) - but since I also want to track the amount sponsored, whether sponsor paid up and maybe more this seems inappropriate
b. I'd like to easily query all sponsorhips made by a single person and also all sponsorships belonging to a certain run.
So, I feel, this would be appropriate:
Profile --is ancestor of--> Run
Profile --is ancestor of--> Sponsorship
Run --is ancestor of--> Sponsorship
Is that sensible?
I can see a constructor for a Key that takes several kinds in ancestor order as arguments. Was that designed for this case? "Run" and "profile" would be at the same "level" (i.e. mum&dad ancestors not father&grandfather) - what would that constructor look like in python?
The primary way of establishing relationships between entities is via the key properties in the entity model. Normally no ancestry is needed.
For example:
class Profile(ndb.Model):
name = ndb.StringProperty()
class Run(ndb.Model):
runner = ndb.KeyProperty(kind='Profile')
rounds = ndb.IntegerProperty()
sponsorship = ndb.KeyProperty(kind='Sponsorship')
class Sponsorship(ndb.Model):
run = ndb.KeyProperty(kind='Run')
donor = ndb.KeyProperty(kind='Profile')
done = ndb.BooleanProperty()
The ancestry just places entities inside the same entity group (which can be quite limiting!) while enforcing additional relationships on top of the ones already established by the model. See Transactions and entity groups and maybe Contention problems in Google App Engine.

SQLAlchemy: add a child in many-to-many relationship by IDs

I am looking for a way to add a "Category" child to an "Object" entity without wasting the performance on loading the child objects first.
The "Object" and "Category" tables are linked with many-to-many relationship, stored in "ObjectCategory" table. The "Object" model is supplied with the relationsip:
categories = relationship('Category', secondary = 'ObjectCategory', backref = 'objects')
Now this code works just fine:
obj = models.Object.query.get(9)
cat1 = models.Category.query.get(22)
cat2 = models.Category.query.get(28)
obj.categories.extend([cat1, cat2])
But in the debug output I see that instantiating the obj and each category costs me a separate SELECT command to the db server, in addition to the single bulk INSERT command. Totally unneeded in this case, because I was not interested in manipulating the given category objects. Basically all I need is to nicely insert the appropriate category IDs.
The most obvious solution would be to go ahead and insert the entries in the association table directly:
db.session.add(models.ObjectCategory(oct_objID=9, oct_catID=22))
db.session.add(models.ObjectCategory(oct_objID=9, oct_catID=28))
But this approach is kind of ugly, it doesn't seem to use the power of the abstracted SQLAlchemy relationships. What's more it produces separate INSERT for every add(), vs the nice bulk INSERT as in the obj.categories.extend([list]) case. I imagine there could be some lazy object mode that would let the object live with only it's ID (unverified) and load the other fields only if they are requested. That would allow adding children in one-to-many or many-to-many relationships without issuing any SELECT to the database, yet letting to use the powerful ORM abstraction (ie, treating the list of children as a Python list).
How should I adjust my code to carry out this task using the power of SQLAlchemy but being conservative on the database use?
Do you have a ORM mapping for the ObjectCategory table? If so you could create and add ObjectCategory objects:
session.add(ObjectCategory(obj_id=9, category_id=22)
session.add(ObjectCategory(obj_id=9, category_id=28)

Python AppEngine Sort By Referenced Property

I have a model Entry
class Entry(db.Model):
year = db.StringProperty()
.
.
.
and for whatever reason the last name field is stored in a different model LastName:
class LastName(db.Model):
entry = db.ReferenceProperty(Entry, collection_name='last_names')
last_name = db.StringProperty()
If I query Entry and sort it by year (or any other property) using .order() how would I then sort that by the last name? I'm new to python but coming from Java I would guess there's some kind of comparator equivalent; or I'm completely wrong and there's another way to do it. I for sure cannot change my model at this point in time, though that may be the solution later. Any suggestions?
EDIT: I'm currently paginating through the results using offsets (moving to cursors soon, but I think it would be the same issue). So if I try to sort outside of the datastore I would only be sorting the current set; it's possible that the first page will be all 'B's and the second page will have 'A's, so it will only be sorted by page not by overall set. Am I screwed the way my models are currently set up?
A few issues here.
There's no way to do this sorting directly in the datastore API, either in Python or Java - as you no doubt know, the datastore is non-relational, and indirect lookups like this aren't supported.
If this was just a straight one-to-one relationship, which gave you an accessor from the Entry entity to the LastName one, you could use the standard Python sort function to sort the list:
entries.sort(key=lambda e: e.last_name.last_name)
(note that this sorts the list in place but returns None, so don't try assigning from it).
However, this won't work, because what you've actually got here is a one-to-many relationship: there are potentially many LastNames for each Entry. The definition actually recognises this: the collection_name attribute, which defines the accessor from Entry to LastName, is called last_names, ie plural.
So what you're asking doesn't really make sense: which of the potentially many LastNames do you want to sort on? You can certainly do it the other way round - given a query of LastNames, sort by entry year - but given your current structure there's not really any way of doing it.
I must say though, although I don't know the rest of your models, I suspect you have actually got that relationship the wrong way round: the ReferenceProperty should probably live on Entry pointing to LastName rather than the other way round as it is now. Then it would simply be the sort call I gave above.

Grouping model objects in Django

I have an app with 2 models: Product and Photo, each of which corresponds to a MySQL table (drived by MyISAM).
Product is a ForeignKey field of Photo. Several Photo objects may share a single Product object.
Now, the question: I need Photo objects to be further subgrouped into sets representing the same real world object (instance of a product) photographed from different aspects. I want to differentiate this different real world objects, but still have them all connected to their Product object.
What's the best way to group the photos in terms of efficiency of both database querying and manual data input?
Thanks to #shawnwall, more ideas:
Maybe Product should be connected not to individual Photo objects but to sets of photos.
There should be a set for each real-word object, even if there's only 1 photo of it now.
The set should be represented by an ID field on the Photo table, common between certain Photo objects and a Product object. (What kind of field is that?)
Seems like your approach is decent so far. I considered a manytomany field from product to photos, but it doesn't sound like its needed. You could add an 'aspect' column that relates to a list of 'choices' on the photo table. Also remember django will let you query both ways:
Photo.objects.filter(product__id=1)
or
Product.objects.filter(photo__id=2)
You can also access them through instances:
photo.product
or
product.photo_set

Categories