Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6373703
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 25, 20262026-05-25T01:23:43+00:00 2026-05-25T01:23:43+00:00

django nonrel’s documentation states: you have to manually write code for merging the results

  • 0

django nonrel’s documentation states: “you have to manually write code for merging the results of multiple queries (JOINs, select_related(), etc.)”.

Can someone point me to any snippets that manually add the related data? @nickjohnson has an excellent post showing how to do this with the straight AppEngine models, but I’m using django-nonrel.

For my particular use I’m trying to get the UserProfiles with their related User models. This should be just two simple queries, then match the data.

However, using django-nonrel, a new query gets fired off for each result in the queryset. How can I get access to the related items in a ‘select_related’ sort of way?

I’ve tried this, but it doesn’t seem to work as I’d expect. Looking at the rpc stats, it still seems to be firing a query for each item displayed.

all_profiles = UserProfile.objects.all()
user_pks = set()
for profile in all_profiles: 
    user_pks.add(profile.user_id)  # a way to access the pk without triggering the query

users = User.objects.filter(pk__in=user_pks)
for profile in all_profiles:
    profile.user = get_matching_model(profile.user_id, users)


def get_matching_model(key, queryset):
    """Generator expression to get the next match for a given key"""
    try:
        return (model for model in queryset if model.pk == key).next()
    except StopIteration:
        return None

UPDATE:
Ick… I figured out what my issue was.

I was trying to improve the efficiency of the changelist_view in the django admin. It seemed that the select_related logic above was still producing additional queries for each row in the results set when a foreign key was in my ‘display_list’. However, I traced it down to something different. The above logic does not produce multiple queries (but if you more closely mimic Nick Johnson’s way it will look a lot prettier).

The issue is that in django.contrib.admin.views.main on line 117 inside the ChangeList method there is the following code: result_list = self.query_set._clone(). So, even though I was properly overriding the queryset in the admin and selecting the related stuff, this method was triggering a clone of the queryset which does NOT keep the attributes on the model that I had added for my ‘select related’, resulting in an even more inefficient page load than when I started.

Not sure what to do about it yet, but the code that selects related stuff is just fine.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-25T01:23:43+00:00Added an answer on May 25, 2026 at 1:23 am

    I don’t like answering my own question, but the answer might help others.

    Here is my solution that will get related items on a queryset based entirely on Nick Johnson’s solution linked above.

    
    from collections import defaultdict
    
    def get_with_related(queryset, *attrs):
        """
        Adds related attributes to a queryset in a more efficient way
        than simply triggering the new query on access at runtime.
    
        attrs must be valid either foreign keys or one to one fields on the queryset model
        """
        # Makes a list of the entity and related attribute to grab for all possibilities
        fields = [(model, attr) for model in queryset for attr in attrs]
    
        # we'll need to make one query for each related attribute because
        # I don't know how to get everything at once. So, we make a list
        # of the attribute to fetch and pks to fetch.
        ref_keys = defaultdict(list)
        for model, attr in fields:
            ref_keys[attr].append(get_value_for_datastore(model, attr))
    
        # now make the actual queries for each attribute and store the results
        # in a dict of {pk: model} for easy matching later
        ref_models = {}
        for attr, pk_vals in ref_keys.items():
            related_queryset = queryset.model._meta.get_field(attr).rel.to.objects.filter(pk__in=set(pk_vals))
            ref_models[attr] = dict((x.pk, x) for x in related_queryset)
    
        # Finally put related items on their models
        for model, attr in fields:
            setattr(model, attr, ref_models[attr].get(get_value_for_datastore(model, attr)))
    
        return queryset
    
    def get_value_for_datastore(model, attr):
        """
        Django's foreign key fields all have attributes 'field_id' where
        you can access the pk of the related field without grabbing the
        actual value.
        """
        return getattr(model, attr + '_id')
    

    To be able to modify the queryset on the admin to make use of the select related we have to jump through a couple hoops. Here is what I’ve done. The only thing changed on the ‘get_results’ method of the ‘AppEngineRelatedChangeList’ is that I removed the self.query_set._clone() and just used self.query_set instead.

    
    class UserProfileAdmin(admin.ModelAdmin):
        list_display = ('username', 'user', 'paid')
        select_related_fields = ['user']
    
        def get_changelist(self, request, **kwargs):
            return AppEngineRelatedChangeList
    
    class AppEngineRelatedChangeList(ChangeList):
    
        def get_query_set(self):
            qs = super(AppEngineRelatedChangeList, self).get_query_set()
            related_fields = getattr(self.model_admin, 'select_related_fields', [])
            return get_with_related(qs, *related_fields)
    
        def get_results(self, request):
            paginator = self.model_admin.get_paginator(request, self.query_set, self.list_per_page)
            # Get the number of objects, with admin filters applied.
            result_count = paginator.count
    
            # Get the total number of objects, with no admin filters applied.
            # Perform a slight optimization: Check to see whether any filters were
            # given. If not, use paginator.hits to calculate the number of objects,
            # because we've already done paginator.hits and the value is cached.
            if not self.query_set.query.where:
                full_result_count = result_count
            else:
                full_result_count = self.root_query_set.count()
    
            can_show_all = result_count  self.list_per_page
    
            # Get the list of objects to display on this page.
            if (self.show_all and can_show_all) or not multi_page:
                result_list = self.query_set
            else:
                try:
                    result_list = paginator.page(self.page_num+1).object_list
                except InvalidPage:
                    raise IncorrectLookupParameters
    
            self.result_count = result_count
            self.full_result_count = full_result_count
            self.result_list = result_list
            self.can_show_all = can_show_all
            self.multi_page = multi_page
            self.paginator = paginator
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Given that django-nonrel has got JOINs working, does this mean we have M2M fields
I have an app using using Django Nonrel on AppEngine. I'd like to use
I'm using django-nonrel on GAE. For now update queries are not implemented in django-nonrel
I've ported my GAE project to django-nonrel, and now I would like to have
Django's views documentation states that the default 500 view passes no variables to this
I'm using Django-nonrel on Google App Engine and have the following models (they are
I am using django-nonrel and django-mongodb-engine I have a Django model stored on PostgreSQL
I have the latest versions of virtualenv,django-nonrel, djangotoolbox and django_mongodb_engine. The virtualenv was created
I have been using django-appengine and am now trying a project with django-nonrel. Before
I have a django-nonrel app running in Google App Engine and am wanting all

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.