Say you the table Users (one): id and activities (many): type, created_on , how do you get all users who's latest activity.type is 'message'?
Heres the query I have so far:
User.objects.filter(activity__type='message').annotate(Max('activity__created_on'))
But its not working since:
User.objects.filter(activity__type='message').annotate(Max('activity__created_on'))[0].activity.latest('created_on').type
is not equal to 'message'.
I believe it does not work because when you filter(activity__type='message') Django is going through all the activities for that User and discarding the User if it has an activity with type other than message, it's not discarding the activities.
If you're using PostgreSQL you can use distinct and get fields from the User model, not actual instances of them though, but that might be enough for you:
Activity.objects.order_by('user__username', 'created_on')\
.distinct('user__username')\
.filter(type='message')\
.values('user__username')
If you are not using PostgreSQL or need full User instances you'll need to do it manually in Python, something like:
users_with_message_activity = []
for u in User.objects.all():
if u.activities_set.latest('created_on').type == 'message':
users_with_message_activity.append(u)
Which is not ideal since it means more queries.
Hope that helps.
Related
I'm having an issue here that I want clarification with, see, I'm making a program that does analysis of data.
I wanted to query data from different users, the data is numerical by the way, whenever I'd get subject marks from a user, I want the system to return the name of the user who has those marks.
It was all working fine until I tried querying the users with the same marks, and all I could get was an error
analyzer.models.ResultsALevel.MultipleObjectsReturned: get() returned more than one
ResultsALevel -- it returned 4!
So I was trying to find a way to still query and return the name of users with that subject mark, even if they have the same marks.
I believe that should be possible since the users have different id's and stuff, help would be much appreciated!
Here's my views.py
biology_marks = []
for student in ResultsALevel.objects.all():
biology_marks.append(student.advanced_biology_1)
value_1_biology =
ResultsALevel.objects.get(advanced_biology_1=biology_marks[-1]).student_name.last_name
value_2_biology =
ResultsALevel.objects.get(advanced_biology_1=biology_marks[-2]).student_name.last_name
value_3_biology =
ResultsALevel.objects.get(advanced_biology_1=biology_marks[-3]).student_name.last_name
value_4_biology =
ResultsALevel.objects.get(advanced_biology_1=biology_marks[-4]).student_name.last_name
ObjectManager.get() is used to retrieve single instances, usually selected by a primary key field.
Using ObjectManager.get() on a field where multiple data exists which matches the query, an error is returned (MultipeObjectsReturned)
Use ObjectManager.filter() in stead.
This is probably really simple but I don't think I've come across this problem before.
I have an object in my database called WeatherForecast, this object has a foreign key to User, so the user can have a number of different forecasts displayed in a template.
class WeatherForecast(models.Model):
owner = models.ForeignKey(User, null=True)
I create the forecasts and set the foreign key as such:
newForecast = WeatherForecast.objects.create(owner = request.user)
When I call WeatherForecast.objects.all(), it returns an empty query set. However, when I call user.weatherforecast_set.all() it returns the WeatherForecasts with the correct foreign key.
I'm probably missing something obvious, but why is this happening?
EDIT:
Here is where I am calling it.
Originally, I was doing this to get a number of selected forecasts (selections were made from the template via a form, the IDs were taken from the form and put into a list and I have verified that the IDs are being passed from the form correctly).
for weatherForecastID in selectedIDs:
selectedForecast = WeatherForecast.objects.get(id = weatherForecastID)
I was getting WeatherForecast matching this query does not exist errors from that. After looking into it, I found the issue I am having, where the objects.all() is empty but the weatherforecast_set.all() isn't.
To make sure I wasn't missing something silly, I also printed the query sets like so:
print "all weather forecasts:", WeatherForecast.objects.all()
print "user weather forecasts:", request.user.weatherforecast_set.all()
which gives:
all weather forecasts: <QuerySet []>
user weather forecasts: <QuerySet [<WeatherForecast: WeatherForecast object>]>
EDIT 2
FIXED! There was a model in a different app with the same name, causing the query to be looking in the wrong table! Feel like a bit of an idiot now!
Thank you everyone for the help!
A user accesses his contacts on his mobile device. I want to send back to the server all the phone numbers (say 250), and then query for any User entities that have matching phone numbers.
A user has a phone field which is indexed. So I do User.query(User.phone.IN(phone_list)), but I just looked at AppStats, and is this damn expensive. It cost me 250 reads for this one operation, and this is something I expect a user to do often.
What are some alternatives? I suppose I can set the User entity's id value to be his phone number (i.e when creating a user I'd do user = User(id = phone_number)), and then get directly by keys via ndb.get_multi(phones), but I also want to perform this same query with emails too.
Any ideas?
You could create a PhoneUser model like so:
from google.appengine.ext import ndb
class PhoneUser(ndb.Model):
number = ndb.StringProperty()
user = ndb.KeyProperty()
class User(ndb.Model):
pass
u = User()
u.put()
p = PhoneUser(id='123-456-7890', number='123-456-7890', user=u.key)
p.put()
u2 = User()
u2.put()
p2 = PhoneUser(id='555-555-5555', number='555-555-5555', user=u2.key)
result = ndb.get_multi([ndb.Key(PhoneUser, '123-456-7890'), ndb.Key(PhoneUser, '555-555-5555')])
I think that would work in this situation. You would just have to add/delete your PhoneUser model whenever you update your User. You can do this using post hooks: https://developers.google.com/appengine/docs/python/ndb/modelclass#Model__post_delete_hook
I misunderstood part of your problem, I thought you were issuing a query that was giving you 250 entities.
I see what the problem is now, you're issuing an IN query with a list of 250 phone numbers, behind the scenes, the datastore is actually doing 250 individual queries, which is why you're getting 250 read ops.
I can't think of a way to avoid this. I'd recommend avoiding searching on long lists of phone numbers. This seems like something you'd need to do only once, the first time the user logs in using that phone. Try to find some way to store the results and avoid the query again.
there is no efficient way to do an IN query.
so instead avoid it all together.
how?
invert the query, instead of finding all people that belong to this guys phone list.
try
finding all people that have this users phoneid in their list.
this however is not without some extra cost.
the phonelist for each user much be stored and indexed.
class User(ndb.Model):
phoneList = ndb.PropertyList()
phone_id= ndb.StringProperty()
select from where User.phoneList = :this_phone_number
I have the code User.objects.values_list('last_login',flat= True) Which gives me a list of all of the last logins for all of the users but I'm unsure how you slim that done to a specific user. I tried code along the lines of User.objects.get(username='user1').values_list('last_login',flat= True) But that didn't work. I think I need something between the first set of paren's and values_list but I not sure what I would put there in order for them to link up?
Try this:
user = User.objects.get(username='user1')
last_login = user.last_login
As you look at Django docs values_list is under Methods that return new QuerySets. So it is not applicable on single object as you did. And last_login is field of User model so you can access it directly by,
User.objects.get(username='user1').last_login
Help! Can't figure this out! I'm getting a Integrity error on get_or_create even with a defaults parameter set.
Here's how the model looks stripped down.
class Example(models.Model):model
user = models.ForeignKey(User)
text = models.TextField()
def __unicode__(self):
return "Example"
I run this in Django:
def create_example_model(user, textJson):
defaults = {text: textJson.get("text", "undefined")}
model, created = models.Example.objects.get_or_create(
user=user,
id=textJson.get("id", None),
defaults=defaults)
if not created:
model.text = textJson.get("text", "undefined")
model.save()
return model
I'm getting an error on the get_or_create line:
IntegrityError: (1062, "Duplicate entry '3020' for key 'PRIMARY'")
It's live so I can't really tell what the input is.
Help? There's actually a defaults set, so it's not like, this problem where they do not have a defaults. Plus it doesn't have together-unique. Django : get_or_create Raises duplicate entry with together_unique
I'm using python 2.6, and mysql.
You shouldn't be setting the id for objects in general, you have to be careful when doing that.
Have you checked to see the value for 'id' that you are putting into the database?
If that doesn't fix your issue then it may be a database issue, for PostgreSQL there is a special sequence used to increment the ID's and sometimes this does not get incremented. Something like the following:
SELECT setval('tablename_id_seq', (SELECT MAX(id) + 1 FROM
tablename_id_seq));
get_or_create() will try to create a new object if it can't find one that is an exact match to the arguments you pass in.
So is what I'm assuming is happening is that a different user has made an object with the id of 3020. Since there is no object with the user/id combo you're requesting, it tries to make a new object with that combo, but fails because a different user has already created an item with the id of 3020.
Hopefully that makes sense. See what the following returns. Might give a little insight as to what has gone on.
models.Example.objects.get(id=3020)
You might need to make 3020 a string in the lookup. I'm assuming a string is coming back from your textJson.get() method.
One common but little documented cause for get_or_create() fails is corrupted database indexes.
Django depends on the assumption that there is only one record for given identifier, and this is in turn enforced using UNIQUE index on this particular field in the database. But indexes are constantly being rewritten and they may get corrupted e.g. when the database crashes unexpectedly. In such case the index may no longer return information about an existing record, another record with the same field is added, and as result you'll be hitting the IntegrityError each time you try to get or create this particular record.
The solution is, at least in PostgreSQL, to REINDEX this particular index, but you first need to get rid of the duplicate rows programmatically.