4

I have a model with the following fields and decorators:

class Item(models.Model):

    title = models.CharField(db_index=True, max_length=100)
    thumb = models.CharField(max_length=1000)
    vendor = models.CharField(max_length=15)
    url = models.CharField(max_length=255, unique=True)
    views = models.CharField(max_length=64)

    @property
    def parsed_thumb()
        return = self.url + "/static/" + self.thumb

which I query in a class based view with:

results = Items.objects.filter(title__icontains=query).order_by('-views')[offset:limit].values('id', 'url', 'title', 'vendor', 'thumb')

The problem is the call to values() returns db fields and, as far as I know, has no way of interacting with @property decorators that belong to the Items model.

I need the return value from parsed_thumb(). What are my options?

Sayse
  • 42,633
  • 14
  • 77
  • 146
Sam
  • 2,172
  • 3
  • 24
  • 43

2 Answers2

2

Querysets are there to interact with the database, where as properties are only accessible to model. You could annotate the property to work with the queryset using Concat, but this won't be using the property

results = Items.objects.filter(title__icontains=query).order_by('-views')
results = results.annotate(parsed_thumb=Concat('url', Value('/static/'), 'thumb'))[offset:limit].values('id', 'url', 'title', 'vendor', 'thumb', 'parsed_thumb')
Sayse
  • 42,633
  • 14
  • 77
  • 146
  • I like this solution, it works for the problem I had, so I'll mark it as correct. Unfortunately, I'd simplified the problem so I could explain it easily. I also have other fields that need to be converted from binary to decimal, as well as other modifications. I quickly tried to expand your answer to work for my other problems like so: `results = results.annotate(dec_num=self.bin_to_dec(bin_field))` but it looks like I can only use the Django Database Functions from the link you provided. Still, thanks for providing a good answer to the question I did ask. – Sam Aug 24 '17 at 13:54
  • @Sam - You might struggle (See [Django custom annotation function](https://stackoverflow.com/q/30416270/1324033)). The answer here suggests use extra but there are big warnings about using extra in the django docs. – Sayse Aug 24 '17 at 13:57
  • 1
    Yeah, the more I look at this problem, the more I realise how messy it could get. I really don't want to use `extra()` for obvious reasons. – Sam Aug 24 '17 at 14:03
1

If you have such simple method you can try to use QuerySet.extra

results = Items.objects.extra(
    select={'parsed_thumb': "url || '/static/' || thumb"}
).filter(title__icontains=query).order_by('-views')[offset:limit].values(
'id', 'url', 'title', 'vendor', 'thumb', 'parsed_thumb') 
Brown Bear
  • 19,655
  • 10
  • 58
  • 76