Anonymous user
Django for ISchoolers: Difference between revisions
→Chunk 3
imported>Aldeka No edit summary |
imported>Aldeka |
||
Line 523:
* Import the model classes we just wrote:
<code>
>>> from qandabear.models import Question, Answer</code>
* List all the current Questions:
<code>
>>> Question.objects.all()<br>
[]</code>
How many questions is this?
Zen koan: Can there be an Answer for a Question that doesn’t yet exist?
=== Add our first Question ===
<code
>>> q = Question(text="What is the Weirdest Cookbook Ever?")
# We could specify the value for pub_date as well here, but we don't have to since
* Try getting the ID number of our new question 'q' by typing <code>q.id</code>. What happens?
* Save the Question instance into the database. You have to call save() explicitly.
<
>>> q.save()</code>
* Get the id of the Question instance. Because it’s been saved, it has an ID in the database
<code>
>>> q.id
1</code>
* Access the database columns (Fields, in Django parlance) as Python attributes:
<code
>>> q.text
"What is the Weirdest Cookbook Ever?"
>>> q.pub_date
datetime.datetime(2011, 12, 1, 3, 3, 55, 841929)
</code>
* Send the Question back in time:
<code># Change values by changing the attributes, then calling save().<br>
>>>
>>> q.pub_date = datetime.datetime(2011, 4, 1, 0, 0)<br>
>>> q.save()<br>
>>> q.pub_date<br>
Line 581 ⟶ 590:
# ...
def __unicode__(self):
# return the answer text, or if the text is longer than 37 characters, return a summary with an ellipsis
if len(self.text) > 37:
summary = summary + '...'
return summary</code>
It’s important to add __unicode__() methods to your models, not only for your own sanity when dealing with the interactive prompt, but also because
=== Adding custom methods to models ===
Enough of these normal python methods! Let's build in some useful functionality to our models in qandabear/models.py.
<code>import datetime
Line 601 ⟶ 609:
return self.pub_date.date() == datetime.date.today()</code>
Note the addition of <code>import datetime</code> to reference Python’s standard datetime module. This allows us to use the datetime library module in models.py by calling it with datetime.
* Save these changes to the models.py file.
Line 609 ⟶ 617:
Start a new Python interactive shell by running python manage.py shell:
<code>
>>> from qandabear.models import Question, Answer
Verify our __unicode__() addition worked:
>>>
[<Question: What is the Weirdest Cookbook Ever?>]
Search your database using the filter method on the objects attribute of Question.
>>> questions = Question.objects.filter(text="What is the Weirdest Cookbook Ever?")
>>> questions
[<Poll: What is the Weirdest Cookbook Ever?>]
>>> questions[0].id # remember python lists start with element 0.
1
</code>
If you try to search for a question that does not exist, filter will give you the empty list. The get method will always return one hit, or raise an exception.
<code>
>>> Question.objects.filter(text="Who framed Roger Rabbit?")
[]
>>> Question.objects.get(id=1)
<Question: What is the Weirdest Cookbook Ever?>
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist:
</code>
===Add Answers===
Observe: there is a Question in the database, but it has no Answers! Let's fix that.
<code>
>>> q = Question.objects.get(id=1)
>>> q.answer_set.all()
[]
Create three
>>>
<
>>>
<
>>>
>>>
<
</code>
Go in reverse! Find the question a particular answer belongs to:
<code>
>>> a.question
<Question: What is the Weirdest Cookbook Ever?>
</code>
Because a Question can have more than one Answer, Django creates the answer_set attribute on each Question. You can use that to look at the list of available Answer, or to create them.
<code>
>>> q.answer_set.all()
[<Answer: To Serve Man>, <Answer: The Original Road Kill Cookbook>, <Answer: Mini-Mart A La Carte>]
>>> q.answer_set.count()
3
</code>
Can one be a Answer for a Question that doesn’t yet exist?:
<code>
>>> koan = Answer("Is this even an answer")
>>> koan.question_id
>>> koan.question
</code>
<!--- Adding pre-written data would go here. -->
=== Changing your models ===
Oh no! Our client, LulzTech, has decided to change the spec for this prototype. Two changes, in fact. First, they've decided that tracking the pub_date of Questions is silly, and they want to remove that field. Second, they want to add a votes field to each Answer, to track how many upvotes it has. Which means we’re going to have to change our models.
* Open qandabear/models.py and edit the Question class:
<code>
class Question(models.Model):
question = models.CharField(max_length=200)
</code>
* Edit the Answer class too:
<code>
class Answer(models.Model):
question = models.ForeignKey(Question)
text = models.TextField()
votes = models.IntegerField(default=0)
pub_date = models.DateTimeField(auto_now_add=True)
</code>
The default parameter lets us set a default value for this field if an answer's vote count isn't explicitly specified. Most new answers are going to have zero votes, so we set our default to 0.
* Make a migration so the database knows we deleted Question.pub_date and added Answer.votes:
<code>
$ python manage.py schemamigration qandabear --auto
</code>
* Apply the migration.
<code>
$ python manage.py migrate qandabear
</code>
===Save and commit===
You know the drill!
== Database migrations and South, part two ==
|