3

I have a problem with django queryset.

models:

class Rooms(models.Model,):
room_state = models.CharField(max_length=255, choices=[('emptyReady', 'empty'), ('emptyWaiting4Clean', 'clean ready'), ('busy', 'busy')])
room_type = models.IntegerField()
room_number = models.IntegerField()

and I ty to check working of queryset by typing in python shell:

for d in Rooms.objects.filter(room_state="emptyReady", id='1'):    print(d)

In my DB there is table Rooms_rooms, and inside there is column room_state, and if we make query on DB :

SELECT room_state FROM Rooms_rooms where id = 1

return value is emptyReady

But when I using queryset (like example above) I alwas get: Rooms object

What I did wrong? I try to search answer in all WEB for a 3 hours, and my patience is now over so I count on You all ;)

3 Answers 3

7

Here:

Rooms.objects.filter(room_state="emptyReady", id='1')

returns a queryset of Room objects.

Now, if you want a specific value:

Rooms.objects.filter(room_state="emptyReady", id='1').values_list('room_state', flat=True)

Read more on values_list here

Alternatively:

for d in Rooms.objects.filter(room_state="emptyReady", id='1'):    print(d.room_state)

Another way is to specify a __unicode__ attribute on class Room

class Rooms(models.Model,):
    room_state = models.CharField(max_length=255, choices=[('emptyReady', 'empty'), ('emptyWaiting4Clean', 'clean ready'), ('busy', 'busy')])
    room_type = models.IntegerField()
    room_number = models.IntegerField()

    def __unicode__(self):
        return u'%s' % self.room_state

This should prin room_state value if print d is called

Sign up to request clarification or add additional context in comments.

1 Comment

seems weird that it doesn't work for _str__. All the default classes (e.g. User) have __str__ implemented but not __unicode__.
0

If I understand, you are trying to simulate the following query with Django:

SELECT room_state FROM Rooms_rooms where id = 1

Given your models, with Django, this can be achieved by issuing:

Rooms.object.filter(room_state='emptyReady', id=1).values('room_state')

The values() function is available in Django since version 1.2 (if not earlier) and allows you to select only those fields you will need to query for. This is considerably faster than obtaining the complete model as it is only giving you a dictionary with the selected fields.

Note in your code you was sending the id as a string, not a number. Furthermore, functions like filter() or values() never return the collection but a Django object that you need to iterate over in order to get the values. So, finally you need to do something like:

Rooms.object.filter(room_state='emptyReady', id=1).values('room_state')[0]['room_state']

This is done intentionally to delay the effective work until it is truly needed.

Comments

0

Update to and refinement of @karthikr 's answer...

If you're trying to take a queryset and pass it as context to a template to then iterate through in a loop such as:

(in views.py)

# The manytomanyfield named subscribers in the Feed object points to the userprofile object which has a onetoonefield relationship with the user object
# [...]
queryset = Feed.objects.filter(subscribers=request.user.userprofile)
        context = {
                    "result_list"    : queryset,
        }
        return render(request, "subscriptions/subscriptions.html", context)

(in subscriptions.html)

# [...]
    {% for instance in result_list %}
        <p> {{ instance.pk }} |---> <a href=''>{{ instance.url }}</a> </p>
    {% endfor %}
# [...]

You will get the error:

'Feed' object has no attribute '__name__'

When changing the template to show result_list without the for-loop such as:

# [...]
{{ result_list }}
# [...]

I saw a the same output as the OP (this is what the renderer outputted):

<QuerySet [<Feed 'https://news.ycombinator.com/rss'>

In my case it was Feed object instead of Rooms object.

When originally trying to loop through result_list, the error arose when the template renderer thought the string Feed was a column of the queryset or the instance of an object in and of itself, and then tried to determine what to call it in a dictionary-like data structure.

I have no idea why Feed.objects.filter() in my case or Rooms.objects.filter() in the OP's case, decides to include the class name without quotes thus confusing the template renderer.

The solution for me was to change my query to:

queryset = Feed.objects.filter(subscribers=request.user.userprofile).values_list('pk','url', named=True)

Using named=True is important to be able to address the column values individually within the template (e.g. {{ instance.pk }}). With the above query and the for-loop in subscriptions.html template as shown above, the rendering goes through without a hitch:

1 |---> https://news.ycombinator.com/rss

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.