I'm trying to do a group by clause on a foreign key but am having a couple of issues.
The code;
status_applications = DevelopmentAssessment.objects.values('status').annotate(total = Count('status'))
The field status only returns an integer for the status value instead of the related object. Is there a way to have it return the related object so I can use the field names in the related table in a for loop?
Cheers,
Ben
You basically already have an answer.
status_applications is a QuerySet that contains a set of related objects (statuses) you are asking for.
status_applications[0] would be the first, [1] second and so on.
To access the count of each simply do:
for status in status_applications:
print status, status.total
If you need the whole rows of the table then simply don't use values or leave it empty:
applications = DevelopmentAssessment.objects.annotate(total = Count('status'))
or
applications = DevelopmentAssessment.objects.values().annotate(total = Count('status'))
Related
I've read the documentation and all the other answers on here but I can't seem to get my head around it.
I need to count the number of foreign keys in an other table connected by a foreign key to a row from a queryset.
class PartReference(models.Model):
name = models.CharField(max_length=10)
code = models.IntegerField()
class Part(models.Model):
code = models.ForeignKey(PartReference)
serial_number = models.IntegerField()
I'll do something like:
results = PartReference.objects.all()
But I want a variable containing the count of the number of parts like any other field, something like:
results[0].count
to ultimately do something like:
print(results[0].name, results[0].code, results[0].count)
I can't wrap my head around the Django documentation- There is a some stuff going on with entry_set in the example, but doesn't explain where entry came from or how it was defined.
_set is used by django to look up reverse queries on database relationships and is appended to the end of a foreign key field name to state that you want to query all objects related so in your case that would be part_set, which means for any given result you can access the count of that part set as follows:
results = PartReference.objects.all()
for result in results:
print(result.name, result.code, results.part_set.count())
I can't wrap my head around the Django documentation- There is a some
stuff going on with entry_set in the example, but doesn't explain
where entry came from or how it was defined.
entry_set comes from the Entry table, that's weird I have to say that Django doc doesn't explain that, it's kind of implicit, e.g. if B is linked to A, then it will be b_set to access B from A.
Coming back to your problem, I think this was asked many times here, e.g. Django count related objects
I want to filter data based on multiple fields in Django python. The scenario is, if a GET request to webserver comes as /searchStudent/?firstName=&lastName=xyzage=23&class=&city= and we dont know what can be the possible parameter in query string, some of them can come with value and some variable doesnot comes with value. The question is, is there any to get the variable which have only value or which dont have values from request. I know we can simply getting value by using request.GET.get('city') but I am finding way for getting the non null variable from query string, is there any way to find the non value variable from query string? In above scenario city, class, and firstName doesn't have values and I dont want to add it on filter. what will be the right approach? please suggest the right way.
To get a dict of non-empty query parameters use this code:
non_empty_params = dict((field, value)
for field, value in request.GET.iteritems() if value)
But do not build queryset this way. You should never ever trust data from the user input. So you have to have a list of fields to search and use this list to filter out incorrect field names:
fields = ('firstName', 'lastName', 'age', 'class', 'city', )
filter_params = dict((field, value)
for field, value in request.GET.iteritems()
if value and field in fields)
students = Student.objects.filter(**filter_params)
I did this way and I get answer for filtering dynamically
filter_args={}
if request.GET.get('firstName') :
filter_args['firstName']=request.GET.get('firstName')
if request.GET.get('lastName') :
filter_args['lastName']=request.GET.get('lastName')
if request.GET.get('city') :
filter_args['city']=request.GET.get('city')
Student.object.filter(**filter_args)
This is know as Dynamic Queries, I was not aware with this. Thanks #catavaran, for suggesting concept. also refered this link Dynamic Django Queries
MongoDB is using string(hash) _id field instead of integer; so, how to get classic id primary key? Increment some variable each time I create my class instance?
class Post(Document):
authors_id = ListField(IntField(required=True), required=True)
content = StringField(max_length=100000, required=True)
id = IntField(required=True, primary_key=True)
def __init__(self):
//what next?
Trying to create new user raises exception:
mongoengine.queryset.OperationError: Tried to save duplicate unique keys
(E11000 duplicate key error index: test.user.$_types_1_username_1
dup key: { : "User", : "admin" })
Code:
user = User.create_user(username='admin', email='example#mail.com',
password='pass')
user.is_superuser = True
user.save()
Why?
There is the SequenceField which you could use to provide this. But as stated incrementing id's dont scale well and are they really needed? Can't you use ObjectId or a slug instead?
If you want to use an incrementing integer ID, the method to do it is described here:
http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field
This won't scale for a vary large DB/app but it works well for small or moderate application.
1) If you really want to do it you have to override the mongoengine method saving your documents, to make it look for one document with the highest value for your id and save the document using that id+1. This will create overhead (and one additional read every write), therefore I discourage you to follow this path. You could also have issues of duplicated IDs (if you save two records at the exactly same time, you'll read twice the last id - say 1 and save twice the id 1+1 = 2 => that's really bad - to avoid this issue you'd need to lock the entire collection at every insert, by losing performances).
2) Simply you can't save more than one user with the same username (as the error message is telling you) - and you already have a user called "admin".
Basically, I have a table with a bunch of foreign keys and I'm trying to query only the first occurrence of a particular key by the "created" field. Using the Blog/Entry example, if the Entry model has a foreign key to Blog and a foreign key to User, then how can I construct a query to select all Entries in which a particular User has written the first one for the various Blogs?
class Blog(models.Model):
...
class User(models.Model):
...
class Entry(models.Model):
blog = models.Foreignkey(Blog)
user = models.Foreignkey(User)
I assume there's some magic I'm missing to select the first entries of a blog and that I can simple filter further down to a particular user by appending:
query = Entry.objects.magicquery.filter(user=user)
But maybe there's some other more efficient way. Thanks!
query = Entry.objects.filter(user=user).order_by('id')[0]
Basically order by id (lowest to highest), and slice it to get only the first hit from the QuerySet.
I don't have a Django install available right now to test my line, so please check the documentation if somehow I have a type above:
order by
limiting querysets
By the way, interesting note on 'limiting queysets" manual section:
To retrieve a single object rather
than a list (e.g. SELECT foo FROM bar
LIMIT 1), use a simple index instead
of a slice. For example, this returns
the first Entry in the database, after
ordering entries alphabetically by
headline:
Entry.objects.order_by('headline')[0]
EDIT: Ok, this is the best I could come up so far (after yours and mine comment). It doesn't return Entry objects, but its ids as entry_id.
query = Entry.objects.values('blog').filter(user=user).annotate(Count('blog')).annotate(entry_id=Min('id'))
I'll keep looking for a better way.
Ancient question, I realise - #zalew's response is close but will likely result in the error:
ProgrammingError: SELECT DISTINCT ON expressions must match initial
ORDER BY expressions
To correct this, try aligning the ordering and distinct parts of the query:
Entry.objects.filter(user=user).distinct("blog").order_by("blog", "created")
As a bonus, in case of multiple entries being created at exactly the same time (unlikely, but you never know!), you could add determinism by including id in the order_by:
To correct this, try aligning the ordering and distinct parts of the query:
Entry.objects.filter(user=user).distinct("blog").order_by("blog", "created", "id")
Can't test it in this particular moment
Entry.objects.filter(user=user).distinct("blog").order_by("id")
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.