Milestone 5

due at 23:59 on Sun 25 Mar

Again, the following commands will update your repository to the latest code that I may have added:

liucs:~$ cd cs164/bookswap
liucs:~/cs164/bookswap$ git pull

Before continuing, make sure you are caught up on Milestone 4.

If you got stuck on M4:

Here is how you can abandon your changes and continue your project using mine. Do this only if you feel you need it to make progress, or if I advise you to! After finishing this sequence of commands, send me an email to let me know how it went (or report anything that looks like an error).

## Use these commands ONLY if you are stuck on M4
liucs:~/cs164/bookswap$ git commit -am "unsaved changes"
liucs:~/cs164/bookswap$ git merge -X theirs origin/solution
liucs:~/cs164/bookswap$ git push
liucs:~/cs164/bookswap$ rm -f dbfile
liucs:~/cs164/bookswap$ python manage.py syncdb --noinput
liucs:~/cs164/bookswap$ python manage.py loaddata sample

After adding the sample data, your admin interface username is admin and the password is admin.

(A) Improve your templates

We discussed in class two ways to improve your templates: (1) don’t hard-code URLs, and (2) use template inheritance. See the notes from 27 February for details.

Improve your search.html and book.html by making the href links to /book/X/ and /user/Y/ use the {% url %} syntax as described in the notes.

Create a templates/base.html as shown in the notes, and then surround each of your other templates with the {% block %} syntax, like this:

{% extends "base.html" %}
{% block content %}
    ....original template goes here....
{% endblock %}

For the user.is_authenticated logic in base.html to work, you will need to pass 'user': request.user to every template:

 return render_to_response('search.html',
                           {'results': results, 'user': request.user})

This may cause a problem with your user profile page, where you may already have a user parameter. We need to distinguish between the user who is browsing (request.user) and the user who is being displayed (given by the id). You may want to call the latter profile instead of user. Fix up your userprofile view and your user.html template accordingly.

def userprofile(request, id):
    u = User.objects.get(id=id)
    return render_to_response('user.html',
                              {'profile': u, 'user': request.user})

(B) Create a search form

Create a URL pattern, view function, and template (this technique should be familiar by now) for a “home” page. The correct URL pattern for the home page is r'^$' – this indicates an empty path. Use the same template inheritance technique to make your home page template inherit from base.html.

For this form, it’s simplest not to use the Django Forms API (because there is relatively little validation) – instead, just hand-code the HTML form, starting with this:

<form method="GET" action="{% url search %}">
  ISBN <input name="isbn" type="text" /><br />
  Author <input name="authors" type="text" /><br />
  <input type="submit" value="Submit" />
</form>

The action parameter specifies the URL to which the form will be submitted. We are using the {% url %} template tag, which relies on one of your URL patterns having name='search'.

The method parameter can have the value GET or POST. The GET will put the search parameters in the query string that is part of the URL (example: /search?isbn=1234&authors=Darwin). You will need to add other fields for all the search parameters your search view is expecting.

Here is a look at this initial search page:

Continue developing it until it works well with your search function.

You may want to have the course prefixes selectable from a drop-down. The HTML code for a drop-down menu looks like this:

<select name='prefix'>
  <option value='ACC'>ACC</option>
  <option value='ART'>ART</option>
  <option value='BIO'>BIO</option>
  <option value='CS'>CS</option>
</select>

And here’s the form rendered in a browser:

Of course, we don’t want to hard-code the prefixes; we should instead load them from the liu.models.Course model in the database. We did not learn yet how to query for distinct values, of just one field. Here is the code to do that:

from liu.models import Course
prefixes = Course.objects.values('prefix').distinct().order_by('prefix')

Try that in the python shell, and you’ll see a huge list of prefixes:

[{'prefix': u'ACC'}, {'prefix': u'ANT'}, {'prefix': u'ART'},
 {'prefix': u'BIC'}, {'prefix': u'BIO'}, {'prefix': u'CH'},
 {'prefix': u'CHM'}, {'prefix': u'COOP'}, {'prefix': u'COS'},
 {'prefix': u'CS'}, {'prefix': u'DNC'}, {'prefix': u'DSM'},
 '...(remaining elements truncated)...']

Send that list to the template, and use a for loop to output the <option> values.

(C) Add a new listing

At the bottom of the “search results” page, we should have a form for users to add a new book to the database. In this case, you should use the Django Form API. See the notes from 27 February for an extended example of form processing and saving a Book to the database.

(D) I want to buy/sell

On the book listings page (showbook function), provide links for users to say “I want to buy” or “I want to sell.” On those pages, you will collect the information needed for the user to create their own listing that will appear on the page.

We can assume that the user is already logged in. You get the currently logged in user using request.user in a view function, as we saw when we added “You are logged in as” to the base template.

comments powered by Disqus

 

©2012 Christopher League · some rights reserved · CC by-sa