Skip to content

Commit

Permalink
Merge pull request #148 from pythonsd/incorporate-feedback-from-rise
Browse files Browse the repository at this point in the history
Incorporate feedback from Rise's issues
  • Loading branch information
macro1 committed Nov 22, 2014
2 parents 33446cb + d6ba14a commit 2e17243
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 34 deletions.
7 changes: 6 additions & 1 deletion tutorials/02-models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ To create the database table for our ``Entry`` model we need to make a migration
$ python manage.py makemigrations
$ python manage.py migrate
Don't worry about migrations just yet, we'll get to them later.
Don't worry about the details of migrations just yet, we'll learn about them in a later section of the tutorial. For now, just think of migrations as Django's way of managing changes to models and the corresponding database.

.. TIP::
If you notice, this code is written in a very particular way. There are
Expand Down Expand Up @@ -214,6 +214,11 @@ Now we're ready to create a real test.
Anything you would do in the base `unittest` class will work in
Django's `TestCase` as well.

You can read more about `django.test.TestCase`_ in the Django documentation and the `unittest.TestCase`_ parent class in the Python documentation.

.. _django.test.TestCase: https://docs.djangoproject.com/en/1.7/topics/testing/tools/#django.test.TestCase
.. _unittest.TestCase: https://docs.python.org/3.4/library/unittest.html#unittest.TestCase

Let's write our test to ensure that a blog entry's string representation is equal to its title. We need to modify our tests file like so:

.. code-block:: python
Expand Down
49 changes: 32 additions & 17 deletions tutorials/03-views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Now inform Django of this new ``templates`` directory by adding this at the bott
# Template files
# https://docs.djangoproject.com/en/1.7/topics/templates/
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
Expand Down Expand Up @@ -420,7 +420,7 @@ We should add a test for that
response = self.client.get('/')
self.assertContains(response, 'No blog entries yet.')
And that gives us the expected failure
This test gives us the expected failure

.. code-block:: bash
Expand All @@ -439,18 +439,21 @@ And that gives us the expected failure
FAILED (failures=1)
Destroying test database for alias 'default'...
The easiest way to add this is to use the `empty`_ clause. See if you can add this in yourself to make the test pass.
The easiest way to implement this feature is to use the `empty`_ clause. See if you can add this in yourself to make the test pass.
.. HINT::
Remember that the phrase in the empty clause must contain the same phrase we check for in our test ("No blog entries yet.").
What about viewing an individual blog entry?
Blog Entry Detail
-----------------
Blog Entries, URLs, and Views
-----------------------------
To save a bit of time let's make our urls look like ``http://myblog.com/ID/`` where ID is the database ID of the blog entry we want to see.
For simplicity, let's agree on a project guideline to form our urls to look like ``http://myblog.com/ID/`` where ID is the database ID of the specific blog entry that we want to display. In this section, we will be creating a `blog entry detail` page and using our project's url guideline.
Before we create this page, let's move the template content that displays our blog entries on our homepage into a separate template file so we can reuse it on our blog entry detail page.
Before we create this page, let's move the template content that displays our blog entries on our homepage (``templates/index.html``) into a new, separate template file so we can reuse the blog entry display logic on our `blog entry details` page.
Let's make a file called ``templates/_entry.html`` and put the following in it:
Let's make a template file called ``templates/_entry.html`` and put the following in it:

.. code-block:: html

Expand Down Expand Up @@ -490,7 +493,7 @@ Now let's change our homepage template (``templates/index.html``) to include the

We use the ``with entry=entry only`` convention in our ``include`` tag for better encapsulation (as mentioned in `An Architecture for Django Templates`_). Check the Django documentation more information on the `include tag`_.

Let's write a test our new blog entry pages:
Great job. Now, let's write a test our new blog entry pages:

.. code-block:: python
Expand All @@ -505,9 +508,11 @@ Let's write a test our new blog entry pages:
response = self.client.get(self.entry.get_absolute_url())
self.assertEqual(response.status_code, 200)
This test fails because we didn't define the ``get_absolute_url`` method for our model (`Django Model Instance Documentation`_). We need to create a URL and a view for blog entry pages now. We'll need to create a ``blog/urls.py`` file and reference it in the ``myblog/urls.py`` file.
This test fails because we didn't define the ``get_absolute_url`` method for our ``Entry`` model (`Django Model Instance Documentation`_). We will need an absolute URL to correspond to an individual blog entry.

We need to create a URL and a view for blog entry pages now. We'll make a new ``blog/urls.py`` file and reference it in the ``myblog/urls.py`` file.

Our ``blog/urls.py`` file is the very short
Our ``blog/urls.py`` file is the very short:

.. code-block:: python
Expand Down Expand Up @@ -537,11 +542,12 @@ The urlconf in ``myblog/urls.py`` needs to reference ``blog.urls``:
]
Now we need to define an ``EntryDetail`` view in our ``blog/views.py``
Remember, we are working on creating a way to see individual entries.
Now we need to define an ``EntryDetail`` view class in our ``blog/views.py``
file. To implement our blog entry page we'll use another class-based
generic view: the `DetailView`_. The ``DetailView`` is a view for
displaying the details of an instance of a model and rendering it to a
template. Let's replace our ``blog/views.py`` file with the following:
template. Let's replace the contents of ``blog/views.py`` file with the following:

.. code-block:: python
Expand All @@ -553,7 +559,7 @@ template. Let's replace our ``blog/views.py`` file with the following:
model = Entry
Finally we need to create the ``get_absolute_url()`` function which should return the entry detail URL for each entry. We should create a test first. Let's add the following test to our ``EntryModelTest`` class:
Let's look at how to create the ``get_absolute_url()`` function which should return the individual, absolute entry detail URL for each blog entry. We should create a test first. Let's add the following test to our ``EntryModelTest`` class:

.. code-block:: python
Expand All @@ -573,9 +579,16 @@ Now we need to implement our ``get_absolute_url`` method in our ``Entry`` class
def get_absolute_url(self):
return reverse('entry_detail', kwargs={'pk': self.pk})
We should now have passing tests again.
.. TIP::
For further reading about the utility function, reverse, see the
Django documentation on `django.core.urlresolvers.reverse`_.

.. _django.core.urlresolvers.reverse: https://docs.djangoproject.com/en/1.7/ref/urlresolvers/


Let's make the blog entry detail page actually display a blog entry. First we'll write some tests in our ``EntryViewTest`` class:
Now, run the tests again. We should have passing tests since we just defined a ``get_absolute_url`` method.

Let's make the blog entry detail view page actually display a blog entry. First we'll write some tests in our ``EntryViewTest`` class:

.. code-block:: python
Expand Down Expand Up @@ -625,7 +638,9 @@ Now we'll see some ``TemplateDoesNotExist`` errors when running our tests again:
FAILED (errors=3)
Destroying test database for alias 'default'...

These errors are telling us that we're referencing a ``blog/entry_detail.html`` template but we haven't created that file yet. Let's create a ``templates/blog/entry_detail.html``. The ``DetailView`` should provide us with a ``entry`` context variable that we can use to reference our ``Entry`` model instance. Our template should look similar to this:
These errors are telling us that we're referencing a ``blog/entry_detail.html`` template but we haven't created that file yet.

We're very close to being able to see individual blog entry details. Let's do it. First, create a ``templates/blog/entry_detail.html`` as our blog entry detail view template. The ``DetailView`` will use an ``entry`` context variable to reference our ``Entry`` model instance. Our new blog entry detail view template should look similar to this:

.. code-block:: html

Expand Down
13 changes: 6 additions & 7 deletions tutorials/04-more-views.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ gets synced to our SQLite database.
Applying blog.0002_auto_20141019_0232... OK
Add a ``__str__`` method for our ``Comment`` model, similar to the one
we previously added for our ``Entry`` model.
Before we create a ``__str__`` method for our ``Comment`` model
similar to the one we previously added for our ``Entry`` model, let's create a test in ``blog/tests.py``.

Now we need to create a test in ``blog/tests.py``. Our test should look
very similar to the ``__str__`` test we wrote in ``EntryModelTest``
earlier. This should suffice:
Our test should look very similar to the ``__str__`` test we wrote in
``EntryModelTest`` earlier. This should suffice:

.. code-block:: python
Expand Down Expand Up @@ -129,7 +128,7 @@ Displaying comments on the website

Now we can create comments in the admin interface, but we can't see them on the website yet. Let's display comments on the detail page for each blog entry.

At the end of our ``content`` block in ``templates/blog/entry_detail.html`` let's add the following:
After the ``<hr>`` element inside of our content block in ``templates/blog/entry_detail.html`` let's add the following:

.. code-block:: html

Expand All @@ -146,7 +145,7 @@ At the end of our ``content`` block in ``templates/blog/entry_detail.html`` let'

We forgot to add tests for this! Why don't you add a test to make sure
comments appear on the blog entry page and a test to make sure the "No
comments yet" message shows up appropriately. This test should probably be
comments yet" message shows up appropriately. These tests should probably be
added to our ``EntryViewTest`` class.

Now we can see our comments on the website.
7 changes: 4 additions & 3 deletions tutorials/05-forms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,9 @@ Now our tests pass again:
OK
Destroying test database for alias 'default'...

Let's test that our form actually submits. We should write two tests:
one to test for errors, and one to test a successful form submission.
Let's test that our form actually submits. We should write two tests
in our ``EntryViewTest``: one to test for errors, and one to test a
successful form submission.

.. code-block:: python
Expand Down Expand Up @@ -511,7 +512,7 @@ Now only one test fails:
FAILED (errors=1)
Destroying test database for alias 'default'...

Let's fix this by adding a ``get_success_url`` to our view:
Let's fix this by adding a ``get_success_url`` to our view, ``EntryDetail``, in ``blog/views.py``:

.. code-block:: python
Expand Down
14 changes: 10 additions & 4 deletions tutorials/07-templatetags.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ Creating an inclusion tag
-------------------------

Let's create an `inclusion tag`_ to query for recent blog entries and render a list
of them. We'll name our template tag ``entry_history``. To start we'll render a
``blog/_entry_history.html`` template.
of them. We'll name our template tag ``entry_history``.

Let's start by rendering an empty template with an empty template context
dictionary. First let's create a ``templates/blog/_entry_history.html``
Expand Down Expand Up @@ -209,7 +208,7 @@ case also:
.. code-block:: python
def test_many_posts(self):
for n in range(1, 6):
for n in range(6):
Entry.objects.create(author=self.user, title="Post #{0}".format(n))
rendered = self.TEMPLATE.render(Context({}))
self.assertIn("Post #5", rendered)
Expand Down Expand Up @@ -263,7 +262,14 @@ Try to fix the bugs on your own but don't be afraid to ask for help.

.. HINT::

There are multiple bugs in our test code.
There are multiple bugs in our test code. Let's give you a couple of hints on how you can approach debugging and resolving them.

First of all, for the ``test_no_posts``, think about what is initially being set up in the function ``setUp``. How many entries have been created? What could we do to have no entries created when ``test_no_posts`` is called and executed?

Secondly, for ``test_many_posts``, read about `slicing`_ and the `range`_ function to resolve the errors that appear during testing.

.. _range: https://docs.python.org/2/library/functions.html?highlight=slice#range
.. _slicing: https://docs.python.org/2/library/functions.html?highlight=slice#slice


.. _custom template tag: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
Expand Down
10 changes: 8 additions & 2 deletions tutorials/09-readable-urls.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,14 @@ Now let's run our tests and make sure they still pass.
If you try to add an entry in the admin, you will notice that you
must write a slug (it isn't optional) but then whatever you write
is overwritten in the ``Entry.save()`` method. There are a couple
ways to resolve this but one way is to set the ``SlugField`` to be
``editable=False`` which will hide it in the admin or other forms.
ways to resolve this but one way is to set the ``SlugField`` in
our ``Entry`` model to be ``editable=False`` which will hide it in
the admin or other forms:

.. code-block:: python
slug = SlugField(editable=False)
See the Django docs on editable_ for details.

.. _editable: https://docs.djangoproject.com/en/1.7/ref/models/fields/#editable

0 comments on commit 2e17243

Please sign in to comment.