x.objects.all() empty, user.x_set.all() not empty - python

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!

Related

Django Database querying

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.

WTForms Selectfield - How to fetch only the values of a particular column?

First thing, I have started with Flask recently so I am total newbie for now, but I like it and hopefully will improve my skills later on in the process. However, there may be some very basic things that I am missing such as the following: I have created Form with selectfield included:
class AddProductForm(Form):
subcategory = SelectField('')
And afterwards I'm fetching the results from the query and applying them to the choices of the SelectField.
...
cur = conn.cursor()
cur.execute("SELECT name FROM subcategory")
subcategories = cur.fetchall()
cur.close()
form = AddProductForm(CombinedMultiDict((request.files, request.form)))
form.subcategory.choices = [(subcat, subcat) for subcat in subcategories]
...
Everything is working good so far, I got all of the results in the SelectField, but I got them returned with the name of the column too, so basically the value for each option of the select field looks formatted like this (where 'name' is the name of the column in the database:
{'name': 'Gears and bolts'}
My question - Instead of this entire previous line, is it possible to display only the value (in this case, "Gears and bolts") as an option text of the select field?
Thanks.
I figured out, based on this answer here, and I will put the answer here just in case there is somebody in need of it. Basically, I've changed this line:
form.subcategory.choices = [(subcat, subcat) for subcat in subcategories]
to the following:
form.subcategory.choices = [(subcat, subcat['name']) for subcat in subcategories]
And damn... that was some basic stuff, man. Previously, I was trying to use subcat.name instead of subcat['name'], which obviously was was wrong way to access the value, and I was getting AttributeError: 'dict' object has no attribute 'name'

Django Query: Get from one where latest of many is x?

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.

Variable interpolation in python/django, django query filters [duplicate]

Given a class:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
Is it possible, and if so how, to have a QuerySet that filters based on dynamic arguments? For example:
# Instead of:
Person.objects.filter(name__startswith='B')
# ... and:
Person.objects.filter(name__endswith='B')
# ... is there some way, given:
filter_by = '{0}__{1}'.format('name', 'startswith')
filter_value = 'B'
# ... that you can run the equivalent of this?
Person.objects.filter(filter_by=filter_value)
# ... which will throw an exception, since `filter_by` is not
# an attribute of `Person`.
Python's argument expansion may be used to solve this problem:
kwargs = {
'{0}__{1}'.format('name', 'startswith'): 'A',
'{0}__{1}'.format('name', 'endswith'): 'Z'
}
Person.objects.filter(**kwargs)
This is a very common and useful Python idiom.
A simplified example:
In a Django survey app, I wanted an HTML select list showing registered users. But because we have 5000 registered users, I needed a way to filter that list based on query criteria (such as just people who completed a certain workshop). In order for the survey element to be re-usable, I needed for the person creating the survey question to be able to attach those criteria to that question (don't want to hard-code the query into the app).
The solution I came up with isn't 100% user friendly (requires help from a tech person to create the query) but it does solve the problem. When creating the question, the editor can enter a dictionary into a custom field, e.g.:
{'is_staff':True,'last_name__startswith':'A',}
That string is stored in the database. In the view code, it comes back in as self.question.custom_query . The value of that is a string that looks like a dictionary. We turn it back into a real dictionary with eval() and then stuff it into the queryset with **kwargs:
kwargs = eval(self.question.custom_query)
user_list = User.objects.filter(**kwargs).order_by("last_name")
Additionally to extend on previous answer that made some requests for further code elements I am adding some working code that I am using
in my code with Q. Let's say that I in my request it is possible to have or not filter on fields like:
publisher_id
date_from
date_until
Those fields can appear in query but they may also be missed.
This is how I am building filters based on those fields on an aggregated query that cannot be further filtered after the initial queryset execution:
# prepare filters to apply to queryset
filters = {}
if publisher_id:
filters['publisher_id'] = publisher_id
if date_from:
filters['metric_date__gte'] = date_from
if date_until:
filters['metric_date__lte'] = date_until
filter_q = Q(**filters)
queryset = Something.objects.filter(filter_q)...
Hope this helps since I've spent quite some time to dig this up.
Edit:
As an additional benefit, you can use lists too. For previous example, if instead of publisher_id you have a list called publisher_ids, than you could use this piece of code:
if publisher_ids:
filters['publisher_id__in'] = publisher_ids
Django.db.models.Q is exactly what you want in a Django way.
This looks much more understandable to me:
kwargs = {
'name__startswith': 'A',
'name__endswith': 'Z',
***(Add more filters here)***
}
Person.objects.filter(**kwargs)
A really complex search forms usually indicates that a simpler model is trying to dig it's way out.
How, exactly, do you expect to get the values for the column name and operation?
Where do you get the values of 'name' an 'startswith'?
filter_by = '%s__%s' % ('name', 'startswith')
A "search" form? You're going to -- what? -- pick the name from a list of names? Pick the operation from a list of operations? While open-ended, most people find this confusing and hard-to-use.
How many columns have such filters? 6? 12? 18?
A few? A complex pick-list doesn't make sense. A few fields and a few if-statements make sense.
A large number? Your model doesn't sound right. It sounds like the "field" is actually a key to a row in another table, not a column.
Specific filter buttons. Wait... That's the way the Django admin works. Specific filters are turned into buttons. And the same analysis as above applies. A few filters make sense. A large number of filters usually means a kind of first normal form violation.
A lot of similar fields often means there should have been more rows and fewer fields.

Django get_or_create raises Duplicate entry for key Primary with defaults

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.

Categories

Resources