Sort queryset by a generic foreign key (django)? - django

I am using Django's comment framework which utilizes generic foreign keys.
Question: How do I sort a given model's queryset by their comment count using the generic foreign key lookup?
Reading the django docs on the subject it says one needs to calculate them not using the aggregation API:
Django's database aggregation API doesn't work with a GenericRelation. [...] For now, if you need aggregates on generic relations, you'll need to calculate them without using the aggregation API.
The only way I can think of, though, would be to iterate through my queryset, generate a list with content_type and object_id's for each item, then run a second queryset on the Comment model filtering by this list of content_type and object_id ... sort the objects by the count, then re-create a new queryset in this order by pulling the content_object for each comment ...
This just seems wrong and I'm not even sure how to pull it off.
Ideas? Someone must have done this before.
I found this post online but it requires me handwriting SQL -- is that really necessary ?

The way you found in the blog post linked in your question is the way I'd do it (and, indeed, pretty much the way I did it in one of my own projects earlier this week)

Related

Django Many to Many - polymorphic

In a Django application, I have three models:
Service
Product
AppliedTax
I want to create a many-to-many relationship between Service and AppliedTax and between Product and AppliedTax. Normally I would have an intermediate model (i.e. AppliedTaxTaxable) with three fields (applied_tax_id, taxable_type and taxable_id) and taxable_type + taxable_id would be a composite foreign key for each related model with taxable_type having as value the name of the related model (Service or Product in my case) and the taxable_id field the id of the related record of the respective model.
I understand how to make it work with raw queries, but Is there a "Django" way to do that with a ManyToMany relationship? So far I had no luck with that. I don't have much experience with Django, but I hope there is a way to do that without using raw queries.
Help :)
Well, after some thought, I did a better search and stumbled upon django-polymorphic. Here is a pretty straightforward explanation on how it works, for a basic set up and it does what I am describing in my question. The implemented schema differs a bit from what my description, but in the end we will home one intermediate table for all associated models.

Usage of latest() method with field types other than date field (Django)

I have just learned about the latest() method. I went to the django's documentation to find out more about it. In the docs it is written:
latest(field_name=None)
Returns the latest object in the table, by date, using the field_name provided as the date field.
However in the tutorial ,that I am following, this method is used together with field name for models.PositiveIntegerField() field(and the model does not specify get_latest_by). I have been trying to search for explanation and similar use of this method, where the field_name is different than date field.
I have found some information here where it is said that:
...it probably does work with other total-ordered types too, but not sure...
and
It does work with primary keys ...
Also I have found similar case here, where the latest() method is used with id field.
However still I did not find an answer whether it is ok to use this method with something other than date field? Is there any other method which is more appropriate for this kind of task?
Here's the source code for _earliest_or_latest, which powers the latest method. As you can see, it basically uses whatever field name you specify and tries its best to order your lookup by that field at the database level. It does this through the add_ordering method, which is documented in the source code here.
There's nothing fancy at all going on under the hood - Django is just passing an ORDER BY and letting the database try to sort things out. That's why you see inconsistent behavior between database environments, like how SQLite sorts nulls below non-nulls while MySQL and PostgreSQL do the reverse. Django isn't really ordering the queryset, it's the underlying database.
Things like dates, incremented IDs, etc. are easy for databases to order and therefore work well with latest. A UUIDField, on the other hand, probably wouldn't work so well.

Third-party-app for merging Django user objects?

I need to merge two users in a Django database.
So I wonder if there is any simple way (maybe a dedicated app) to do that?
For example:
We have user_a and user_b and some models that have foreign keys to the User model (Books, Interests, Teams and so on…).
By merging users, I want to delete the object user_b and to set all foreign keys pointing to this object to point to user_a. And – this is my main concern – I want the objects that need to be changed because they reference the to-be-deleted object to be determined automatically without having to specify a list of those Models and foreign key fields in them manually.
Is this already implemented and I'm reinventing the wheel?
Is this possible?
If not, please show me the way to do it: how can I build a list of Django models that have a foreign key to a specific model (User in my case) in runtime?
Thank you for your time.
I found this snippet http://djangosnippets.org/snippets/2283/ . I'm going to have to modify it though, to make it recursive. I will share my code once I'm done.
With Django 1.8 and beyond, you could achieve this robustly using the Model _meta API.
Specifically, you could use Options.get_fields. This will even let you handle generic relations.
You'll need to consider for each related field whether you want to add or replace on merge. This decision depends on your application logic and corresponding schema choices.
u = User.objects.get(pk=123)
related_fields = [
f for f in u._meta.get_fields()
if (f.one_to_many or f.one_to_one)
and not f.concrete
]
for f in related_fields:
# use field's attributes to perform an update

What do I use instead of ForiegnKey relationship for multi-db relation

I need to provide my users a list of choices from a model which is stored in a separate legacy database. Foreign keys aren't supported in django multi-db setups. The ideal choice would be to use a foreign key, but since thats not possible I need to some up with something else.
So instead I created an IntegerField on the other database and tried using choices to get a list of available options.
class OtherDBTable(models.Model):
client = models.IntegerField(max_length=20, choices=Client.objects.values_list('id','name'))
the problem I'm having is that the choices seem to get populated once but never refreshed. How do I ensure that whenever the client list changes that those newest options area available to pick.
What I was really looking for was a way that I could simulate the behavior of a Foreign key field, at least as far as matching up ID's go.
There wasn't a clear way to do this, since it doesn't seem like you can actually specify an additional field when you instantiate a model (you can with forms, easily)
In any case to deal with the problem, since the database is MySQL based, I ended up creating views from the tables I needed in the other database.
To build on #Yuji's answer - if you do self.fields['field'].choices = whatever in the model's __init__, whatever can be any iterable.
This means you can inherit from iterable, and have that object interface to your legacy database, or you can use a generator function (in case you are unfamiliar, look up the yield keyword).
Citing a Django's manual:
Finally, note that choices can be any iterable object -- not necessarily a list or tuple. This lets you construct choices dynamically. But if you find yourself hacking choices to be dynamic, you're probably better off using a proper database table with a ForeignKey. choices is meant for static data that doesn't change much, if ever.
Why dont you want just export data from the legacy database and to import it into the new one? This could be done periodically, if the legacy database still in use.

Filter through a related model django

How can I generate a query_set through a related model?
For example, how can I do this:
UserProfile.objects.filter(user.is_active=True) # Can't use user.is_active to filter
Trivial question, trivial answer. But I'll keep it here for posterity's sake.
UserProfile.objects.filter(user__is_active=True)
This is well documented in the Django docs.
From the Django documention
Django offers a powerful and intuitive way to "follow" relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
In your example this would be:
UserProfile.objects.filter(user__is_active=True)
The easiest way to follow a relationship is to use a simple "__".
UserProfile.objects.filter(user__is_active=True)
These can be changed together as well (ie user_parent_email='abc#def.com')