官术网_书友最值得收藏!

Putting It All Together: Generating User Pages

This chapter has covered a lot of material. It has introduced the concepts of views, models and templates. In the final section, we will write another view and make use of all the information that we have learned so far. This view will display a list of all the bookmarks that belong to a certain user.

Creating the URL

The URL of this view will have the form: user/ username, where username is the owner of the bookmarks that we want to see. This URL is different from the first URL that we added because it contains a dynamic portion. So we will have to employ the power of regular expressions in order to express this URL. Open urls.py and edit it so that the URL table looks like this:

urlpatterns = patterns('',
  (r'^$', main_page),
  (r'^user/(\w+)/$', user_page),
)

The pattern here looks more complicated than the first one. \w means an alphanumeric character or the underscore. The + sign after it causes the regular expression to match one or more repetitions of what precedes the sign. So in effect, \w+ means any string that consists of alphanumeric characters and possibly the underscore. We have surrounded this portion of the regular expression with parentheses; this will cause Django to capture the string that matches this portion, and pass it to the view, as we will see later.

Writing the View

Now that we've added an entry for the new URL to the URL table, let's write the actual view for it. Open bookmarks/views.py and enter the following code:

from django.http import HttpResponse, Http404
from django.contrib.auth.models import User

def user_page(request, username):
  try:
    user = User.objects.get(username=username)
  except:
    raise Http404('Requested user not found.')

  bookmarks = user.bookmark_set.all()

  template = get_template('user_page.html')
  variables = Context({
    'username': username,
    'bookmarks': bookmarks
  })
  output = template.render(variables)
  return HttpResponse(output)

Most of the view should already look familiar. Therefore, we will only examine what's new:

  • Unlike our first view, user_page takes an extra parameter in addition to the familiar request object. Remember that the pattern for this URL contains capturing parentheses? Strings captured by URL patterns are passed as parameters to views. The captured string in this URL is passed as the username parameter.
  • We used User.objects.get to obtain the user object whose username is requested. We can use a similar technique to query any table by a unique column. This method throws an exception if there are no records that match the query, or if the matched record is not unique.
  • If the requested username is not available in the database, we generate a 404 "Page Not Found" error by raising an exception of the type Http404.
  • To obtain the list of bookmarks for a particular user object, we can conveniently use the bookmark_set attribute available in the user object. Django detects relations between data models and automatically generates such attributes. There is no need to worry about constructing SQL JOIN queries ourselves to obtain user bookmarks for example.

Designing the Template

The previous view loads a template called user_page.html and passes the username and bookmarks to it. We will write this template now. Create a file called user_page.html in the templates directory and enter the following code into it:

<html>
  <head>
    <title>Django Bookmarks - User: {{ username }}</title>
  </head>
  <body>
    <h1>Bookmarks for {{ username }}</h1>
    {% if bookmarks %}
      <ul>
        {% for bookmark in bookmarks %}
          <li><a href="{{ bookmark.link.url }}">
            {{ bookmark.title }}</a></li>
        {% endfor %}
      </ul>
    {% else %}
      <p>No bookmarks found.</p>
    {% endif %}
  </body>
</html>

This template is more involved than our first one. In addition to variables, it uses an 'if' condition and a 'for' loop to display bookmarks. The bookmarks variable is a list object, so we can't output it directly in the template; we have to make sure that it's not empty and then iterate through its items.

Checking whether a variable is empty or not in a template is done using the following syntax:

{% if variable %}
  <p>variable contains data.</p>
{% else %}
  <p>variable is empty</p>
{% endif %}

This 'if' condition works as expected. If the variable contains data, only the first line is printed to the browser. On the other hand, if the variable is indeed empty, only the second line is printed.

To iterate through a list and print its items, we use the following syntax:

{% for item in list %}
  {{ item }}
{% endfor %}

Finally, if a variable has attributes, you can access them in a way similar to Python:

{{ variable.attribute }}

We utilized the constructs above to create the user_page.html template. First, it checks whether bookmarks is empty or not. If bookmarks does contain items, a 'for' loop iterates through them and creates links from them. If bookmarks is empty, a message is printed saying so.

Now, launch the development server and direct your browser to http://127.0.0.1:8000/user/your_username (replacing your_username with your actual username), you should see something similar to the following:

Designing the Template

Our template worked, but the list of bookmarks is empty. This is a good opportunity to experiment with the data model API and add some bookmarks through the interactive console. As we saw earlier, you can start the console by running the following command:

$ python manage.py shell

Populating the Model with Data

First, obtain references to your user object and the link that we created in the data models section:

>>> from django.contrib.auth.models import User
>>> from bookmarks.models import *
>>> user = User.objects.get(id=1)
>>> link = Link.objects.get(id=1)

Notice that user.bookmark_set is empty:

>>> user.bookmark_set.all()
        []

Now create an object that connects the two:

>>> bookmark = Bookmark(
... title='Packt Publishing',
... user=user,
... link=link
... )
>>> bookmark.save()

Examine the user.bookmark_set attribute again:

>>> user.bookmark_set.all()
        [<Bookmark: Bookmark object>]

Great, our user object now has a bookmark. Refresh the page in your browser to see the change:

Populating the Model with Data

Experiment with adding more bookmarks if you like. You can access a bookmark's owner by using bookmark.user. This is another attribute that is automatically generated by Django. Because the relation between users and bookmarks is one-to-many, each user has a set of bookmarks accessible through the user.bookmark_set attribute, whereas each bookmark has exactly one owner who is accessible through the bookmark.user attribute.

主站蜘蛛池模板: 和田市| 新野县| 石景山区| 安国市| 林甸县| 枣庄市| 江北区| 安岳县| 黑水县| 霞浦县| 林口县| 威宁| 静宁县| 雷山县| 玉环县| 三河市| 马龙县| 宁明县| 霍林郭勒市| 泽普县| 平顶山市| 车致| 岳阳县| 德令哈市| 郧西县| 安岳县| 永德县| 南汇区| 顺昌县| 南木林县| 沈阳市| 神农架林区| 贺兰县| 静乐县| 大石桥市| 庄河市| 织金县| 朔州市| 万年县| 仙游县| 横山县|