Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMike Nedelko
8,991 PointsDjango - Forms - Quiz model iterable with lambda
Hi Treehouse Community
I have a question about the 'Quiz Model' episode in the django forms module.
The modifications we are making to the def course_detail(request,pk) function seem logical, but I would like to understand some of the finder details associated with that. As such I realized that this episode raised a few question around inheritance which I would love to get some advice on:
i.e. When we implement this steps = sorted(chain(course.text_set.all(), course.quiz_set.all()), key = lambda step:step.order)
I would like to know the following:
A) I understand that chain makes one big iterable by taking everything from course.text_set.all() and course.quiz_set.all(). But what form does this iterable take. Is this a list of tuples of [(text_set1, quiz_set1), (text_set2, quiz_set2),...] or are we looking at a dictionary of form {1:[text_set1,quiz_set1], 2:[text_set1,quiz_set1],....}
B) When we add the lambda key to the sorted method, we are refering to step:step.oder. That said, I did notice however that both text questions and quiz questions can have their order manually modified in the admin. In case, a Text and a Quiz have the same value for the 'order' field, what does Django default back to. The ID? If so this raises the third question.
C) ID and abstract models. When Django generates models these models automatically get their own IDs (very handy). But how is this handeled in sbract models. Does Django generate two IDs - ie one for the abstract model and one for the model that inherits based on the abstract model, or does it only generate IDs for the model that inherited form the abstract model.
D) If the latter is the case, how can we define lambda as step:step.oder? Isn't step an abstract model mmeaning that we can't query against it? Or is STEP, 'THE MOTHER OF ALL TEXT AND QUIZZ CLASSES', meaning that instanciation of text is also an instanciation of step. The implication here would be that Django generates IDs for steps only, and that Text and Quizz just get the next 'Step_Id' whenever a new Text of Quiz model is instanciated. However this raises another question:
E) If Text and Quiz share a stream of IDs (as they are both inheriting IDs from Step) how would we be managin foreighn Keys? Can one make reference to a foreighnKey Field of an inherited class or woudl that automatically defualt back to the ID of the abstract class it was inherited from?
I know these are quite a few questions, but any advice would be highly appreciated.
:) To the Treehouse team: Thanks for the great lession and to the Treehouse Community, thank you for the advice!
Mike
2 Answers
Chris Freeman
Treehouse Moderator 68,441 PointsHi Mike, Let's work through your questions
A) I understand that chain makes one big iterable by taking everything from course.text_set.all() and course.quiz_set.all(). But what form does this iterable take?
chain
does not necessarily make a uniform object from its arguments. It gets the iterator of the first item, exhausts it, then gets the iterator from the second item. The two iterators may be different. In this case, the argument is a QuerySet
and the iterator is a generator that returns one object at a time. The first generator returns Text
objects, the second produces Quiz
objects. The behavior is similar to a list
of the form [text_set[[0], text_set[1], text_set[2],... quiz_set[0], quiz_set[1], quiz_set[2],...]
, where each text_set
object is a Text
object and each quiz_set
object is a Quiz
object.
B) When we add the lambda key to the sorted method, we are referring to step:step.order. That said, I did notice however that both text questions and quiz questions can have their order manually modified in the admin. In case, a Text and a Quiz have the same value for the 'order' field, what does Django default back to. The ID? If so this raises the third question.
Python sorting is "guaranteed to be stable" which means that if two key values are the same then their order remains the same. This implies that if text_set
is ahead of quiz_set
in the chain, then if the two orders
are the same, the Text
object will appear before the Quiz
object.
C) ID and abstract models. When Django generates models these models automatically get their own IDs (very handy). But how is this handled in abstract models. Does Django generate two IDs - ie one for the abstract model and one for the model that inherits based on the abstract model, or does it only generate IDs for the model that inherited form the abstract model.
It only generates tables and IDs for inheriting subclass Quiz and Text. Inspecting using python manage.py dbshell
, you can see that the tables have been flattened to include the abstract class.
sqlite> .schema courses_quiz
CREATE TABLE "courses_quiz" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(255) NOT NULL, "description" text NOT NULL,
"order" integer NOT NULL, "total_questions" integer NOT NULL,
"course_id" integer NOT NULL REFERENCES "courses_course" ("id"));
CREATE INDEX "courses_quiz_ea134da7" ON "courses_quiz" ("course_id");
sqlite> .schema courses_text
CREATE TABLE "courses_text" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(255) NOT NULL, "description" text NOT NULL,
"order" integer NOT NULL,
"course_id" integer NOT NULL REFERENCES "courses_course" ("id"),
"content" text NOT NULL);
CREATE INDEX "courses_step_ea134da7" ON "courses_text" ("course_id");
D) If the latter is the case, how can we define lambda as step:step.order? Isn't step an abstract model meaning that we can't query against it? Or is STEP, 'THE MOTHER OF ALL TEXT AND QUIZ CLASSES', meaning that instantiation of text is also an instantiation of step. The implication here would be that Django generates IDs for steps only, and that Text and Quiz just get the next 'Step_Id' whenever a new Text of Quiz model is instantiated.
Perhaps you're confusing the class Step
with the variable name in the lambda function step
. The step
in the lambda function is simply a name for a local variable. It could also have been 'thing' as in:
steps = sorted(chain(course.text_set.all(), course.quiz_set.all()),
key = lambda thing; thing.order)
For each "thing
" in the chain results, sorted will use the thing.step
value as the sort key. This means it will be text_set[0].step
, etc. for the Text
objects and quiz_set[0].step
, etc. for the Quiz
objects.
E) If Text and Quiz share a stream of IDs (as they are both inheriting IDs from Step) how would we be managing foreign Keys? Can one make reference to a foreignKey Field of an inherited class or would that automatically default back to the ID of the abstract class it was inherited from?
The stream of IDs are separate and independent for both the Text and Quiz objects.
Bonus 1: If Text and Quiz (which are both inherited from Step), get their own tables, wouldn't Django generate IDs for each instance of these models?
Yes, each table gets it's own set of IDs
Bonus 2: If so, what would Django do if there was a conflict in terms of ordering our Steps on the course_details page?
The ordering is not in terms of Steps
, but rather the value of the order
attribute of each instance of either Quiz
or Text
Bonus 3: i.e. value of order field is the same in both Text and Quizz --> Django defaults back to ID BUT ID is also the same in both Table and Quizz instances?
The IDs do not enter into the sort. It is solely based on the key
argument. In cases of ties, its first-seen-first-listed so, as mentioned above, the sort stability will preserve whichever instance was seen first.
Did that cover it? Post back for more details if needed.
Mike Nedelko
8,991 PointsDear Chris. Thank you VERY much for this detailed reponse. Everything is much clearer now. I really appreciate the time and effort reflected in your response. This is great! Thank you!
Mike Nedelko
8,991 PointsMike Nedelko
8,991 PointsOk - UPDATE:
I noticed that abstract inheritance means that we actually don't have a Step table... this makes question C above even more important for me.
If Text and Quiz (which are both inherited from Step), get their own tables, wouldn't Django generate IDs for each instance of these models? If so, what would Django do if there was a conflict in terms of ordering our Steps on the course_details page?
i.e. value of order field is the same in both Text and Quizz --> Django defaults back to ID BUT ID is also the same in both Table and Quizz instances?