Raf Rasenberg
Raf Rasenberg

Reputation: 674

How to combine values filter with a Queryset of a certain Foreignkey field on my Django Model

I have this field in my model:

class PlayerDetailPage(Page):
    picture = models.ForeignKey('wagtailimages.Image', null=True, on_delete=models.SET_NULL, related_name='+', help_text=_('Player profile picture.'))

And I want to create a inclusion tag, where I access different fields on this Wagtail page model. For db efficiency I use values but on the picture field I want the full query set. Not just a value in a dictionary because I need to render the image.

Right now I have this view:

PlayerDetailPage.objects.values('title', 'path' , 'slug', 'owner__age', 'owner__nationality', )

So far so good, I am pulling only the fields I need and I get a nice dictionary with one query. However for the picture field I want the full query set because it is a Wagtail picture field. It has some nice render options attached. How can I combine this in my view to get the best db efficient query?

And unfortunately direct url is not a field in the image model I guess it is a property, I tried picture__url but that resolved in:

Cannot resolve keyword 'url' into field. Choices are: collection, collection_id, created_at, file, file_hash, file_size, focal_point_height, focal_point_width, focal_point_x, focal_point_y, height, id, renditions, tagged_items, tags, title, uploaded_by_user, uploaded_by_user_id, width

My view:

@register.inclusion_tag('wdashboard/tags/player_widget.html', takes_context=True)
def player_widget(context):

    qs = PlayerDetailPage.objects.values('title', 'path' , 'picture__file', 'slug', 'owner__age', 'owner__nationality', )
    for ins in qs:
        ins['picture'] = Image(file=ins['picture__file'])

        return {'values1': qs,'request': context['request'],}

Upvotes: 3

Views: 690

Answers (1)

Nafees Anwar
Nafees Anwar

Reputation: 6598

The thing you are looking for is not possible without a tricky solution IMHO. The reason is that values method runs a very well defined query only once on db and then converts results into dict. So you are never going to get original PlayerDetailPage object but a dict. For example if you have a model MyModel and you do following

x = MyModel.objects.get(id=1)
print(type(x)) # <class 'MyModel'>

But for values the case is different

x = MyModel.objects.values('id').get(id=1)
print(type(x)) # <class 'dict'>

So you lose original object and get a dict.

A little clever solution

If you have no other choice then using values, I would suggest following solution.

Build your query and also get data you need from Image model.

 qs = PlayerDetailPage.objects.values('picture__name') # assume there is a name field.

Now loop over qs, initialize an Image object, (don't save it) and add it to your dictionary like this

from wagtail.images.models import Image

for ins in qs:
    ins['picture'] = Image(name=ins['picture__name'])

Now you have an picture in your values qs as instance and you can use nice render options attached with it.

Upvotes: 2

Related Questions