The Polls tutorial implies that the template dot syntax lookup order is 1. Instance dict 2. Dynamic attribute lookup 3. List index lookup & so on
The Polls tutorial also explicitly states that, in the case of question.question_text
the 2. Dynamic attribute lookup succeeds @line 373
Thereby, implying that the 1. instance dict lookup failed
Therefore, I am expecting question.__dict__['question_text'] to fail
But I found by setting a breakpoint in the template using Pycharm that question.dict was:
first Django does a dictionary lookup on the object question.
This is not making a reference to an attribute lookup. Itâs saying that itâs first going to try to use question as a dict - question['question_text']. Itâs not saying that itâs performing the attribute lookup, thatâs the second step:
Failing that, it tries an attribute lookup
(Keep in mind that when question is an object, question.__dict__['question_text']isquestion.question_text, so using your interpretation would mean that it would be doing the same thing twice.)
So no, the implication is not what youâre listing. The implication is (1) Dictionary lookup then (2) Attribute lookup, etc.
Merry Christmas Ken!
Thanks a lot for taking a look at my question.
I disagree with this conclusion:-
I have prepared a twisted example just to show that question.__dict__['question_text']is not alwaysquestion.question_text
My twisted example:-
class TwistedQuestion:
"""
This is a convoluted example, just to showcase a point.
This does not represent a Django Model Class in any shape or form :)
"""
def __getattr__(self, name):
if name == "question_text":
return "How are you? (Note: got through attribute lookup)"
raise AttributeError(f'TwistedQuestion class has no attribute {name}')
question = TwistedQuestion()
print(question.__dict__) # => {}
print(question.__dict__['question_text']) # raises KeyError
print(question.question_text) # => 'How are you? (Note: got through attribute lookup)'
Let me restate my earlier question more succintly:-
Context:- Question is a Django Model defined as:-
class Question(models.Model):
question_text = models.CharField(max_length=200)
question is an instance of the above Django Model
In the Polls tutorial, we are rendering the question_text into a django template.
The template looks like this:-
<li>{{ question.question_text }}</li>
The Django docs is explaining how the above templateâs dot-syntax works.
The Django docs states:-
The template system uses dot-lookup syntax to access variable
attributes. In the example of {{ question.question_text }}, first
Django does a dictionary lookup on the object question, which fails in this case (implied)
Failing that, it tries an attribute lookup â which works, in this case.
If even attribute lookup had failed, it wouldâve tried a list-index lookup.
But I find that the dictionary lookup on the object does not fail in the above case when I run my code. Hence my question.
Yes, a dictionary lookup fails. Itâs looking for question['question_text'], notquestion.__dict__['question_text']. Thatâs the answer to your question. (Unless youâre saying that question[âquestion_textâ] is working, which is not my understanding from your example.)
Custom classes
Custom class types are typically created by class definitions (see section Class definitions). A class has a namespace implemented by a dictionary object. Class attribute references are translated to lookups in this dictionary, e.g., C.x is translated to C.__dict__["x"] (although there are a number of hooks which allow for other means of locating attributes).
So yes, I was making reference to the common case in my statement, without explicitly acknowledging the exceptions.
I realize my misunderstanding now.
The dictionary lookup means question["question_text"]
It was wrong of me to interpret it as question.__dict__["question_text"]
Thanks a lot! Ken
In case someone wants to try out the lookup order in action,
pass an instance of this TwistedQuestion_v2 into the template context:-
class TwistedQuestion_v2:
def __getattr__(self, name):
"This method is a fallback"
if name == "question_text":
return "How are you? (Note: got through __getattr__)"
raise AttributeError(f'Question class has no attribute {name}')
def __getitem__(self, name):
if name == "question_text":
return "Are you not entertained!? (Note: got through __getitem__)"
Then, during rendering of templates, it will first resolve to question["question_text"] which happens to be 'Are you not entertained?...'