Boston Python Workshop/Saturday/Web app project: Difference between revisions

Revert to pre-spam
No edit summary
imported>Paulproteus
(Revert to pre-spam)
 
(45 intermediate revisions by 12 users not shown)
Line 8:
 
This is based ''heavily'' on the official tutorial for the Django web programming framework.
 
This page should say what you should actually expect to know. It is okay that you don't understand everything you are typing in. After a lot more learning, you will be able to. The first time, though, it's okay if you don't. Will and Katie have feedback for this page.
 
== Writing your first Django app, part 1 ==
Line 173 ⟶ 175:
choice = models.CharField(max_length=200)
votes = models.IntegerField()
 
Save the models.py file.
 
All models in Django code are represented by a class that subclasses django.db.models.Model. Each model has a number of class variables, each of which represents a database field in the model.
Line 206 ⟶ 210:
'polls',
)
 
Save the settings.py file.
 
Now Django knows to include the polls app.
Line 275 ⟶ 281:
[<Poll: Poll object>]
 
Wait a minute. <Poll: Poll object> is, an utterly, an unhelpful representation of this object. Let's fix that by editing the polls model (in the polls/models.py file) and adding a __unicode__() method to both Poll and Choice:
Use your '''text editor''' to open the polls/models.py file and adding a __unicode__() method to both Poll and Choice:
 
class Poll(models.Model):
Line 301 ⟶ 308:
 
Note the addition of import datetime to reference Python's standard datetime module.
FIXME: add explanation of why we did this
 
Save these changes to the models.py file, and then start a new Python interactive shell by running python manage.py shell again:
 
>>> from polls.models import Poll, Choice
Line 313 ⟶ 321:
If you want to search your database, you can do it using the '''filter''' method on the ''objects'' attribute of Poll. For example:
 
>>> ppolls = Poll.objects.filter(question="What's up?")
>>> ppolls
[<Poll: What's up?>]
>>> ppolls[0].id
1
 
Line 335 ⟶ 343:
Right now, we have a Poll in the database, but it has no Choices. See:
 
>>> p = Poll.objects.get(pkid=1)
>>> p.choice_set.all()
[]
Line 346 ⟶ 354:
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)
>>> c
<Choice: Just hacking again>
 
Line 463 ⟶ 472:
ROOT_URLCONF = 'workshop_mysite.urls'
 
That means that the default URLconf inis workshop_mysite/urls.py.
 
Time for an example. Edit mysitethe file workshop_mysite/urls.py so it looks like this:
 
<pre>
from django.conf.urls.defaults import *
 
Line 475 ⟶ 485:
(r'^polls/(\d+)/vote/$', 'polls.views.vote'),
)
</pre>
 
This is worth a review. When somebody requests a page from your Web site -- say, "/polls/23/", Django will load the ''urls.py'' Python module, because it's pointed to by the ROOT_URLCONF setting. It finds the variable named urlpatterns and traverses the regular expressions in order. When it finds a regular expression that matches -- r'^polls/(\d+)/$' -- it loads the function detail() from polls/views.py. Finally, it calls that detail() function like so:
 
Line 510 ⟶ 520:
return HttpResponse("Hello, world. You're at the poll index.")
 
This is the simplest view possible. GoSave the views.py file, then go to "/polls/" in your browser, and you should see your text.
 
Now letslet's add a few more views by adding to the views.py file. These views are slightly different, because they take an argument (which, remember, is passed in from whatever was captured by the regular expression in the URLconf):
 
def detail(request, poll_id):
Line 523 ⟶ 533:
return HttpResponse("You're voting on poll %s." % poll_id)
 
TakeSave the views.py file. Now take a look in your browser, at "/polls/34/". It'll run the detail() method and display whatever ID you provide in the URL. Try "/polls/34/results/" and "/polls/34/vote/" too -- these will display the placeholder results and voting pages.
 
=== Write views that actually do something ===
Line 533 ⟶ 543:
All Django wants is that HttpResponse. Or an exception.
 
Most of the Django views in the world use Django's own database API, which we covered in Tutorial 1. Let's do that, too. Here's one stab at the index() view, which displays the latest 5 poll questions in the system, separated by commas, according to publication date. Continue editing the file views.py:
 
from polls.models import Poll
Line 543 ⟶ 553:
return HttpResponse(output)
 
Now go to "http://localhost:8000/polls/" in your Web browser. You should see the text of the first poll. There's a problem here, though: The page's design is hard-coded in the view. If you want to change the way the page looks, you'll have to edit this Python code. So let's use Django's template system to separate the design from Python:
 
from django.shortcuts import render_to_response
Line 590 ⟶ 600:
</pre>
 
Load the page in"http://localhost:8000/polls/" into your Web browser again, and you should see a bulleted-list containing the "What's up" poll from Tutorial 1. The link points to the poll's detail page.
 
=== Raising 404 ===
 
Now, let's tackle the poll detail view -- the page that displays the question for a given poll. Continue editing the ''views.py'' file. This view uses Python ''exceptions'':
 
from django.http import Http404
Line 600 ⟶ 610:
def detail(request, poll_id):
try:
p = Poll.objects.get(pkid=poll_id)
except Poll.DoesNotExist:
raise Http404
Line 607 ⟶ 617:
The new concept here: The view raises the Http404 exception if a poll with the requested ID doesn't exist.
 
If you'd like to quickly get the above example working, just create a new template file and name it ''detail.html''. Enter in it just one line of code:
 
<pre>
Line 613 ⟶ 623:
</pre>
 
willto get you started for now.
 
Does your detail view work? Try it: http://127.0.0.1:8000/polls/1/
Add it to a new template file that you create, ''detail.html''.
 
DoesYou yourcan detailalso viewtry work?to Tryload ita poll page that does not exist, just to test out the pretty 404 error: http://127.0.0.1:8000/polls/detail/132/
 
=== Adding more detail ===
Line 637 ⟶ 647:
 
Method-calling happens in the {% for %} loop: poll.choice_set.all is interpreted as the Python code poll.choice_set.all(), which returns a sequence of Choice objects and is suitable for use in the {% for %} tag.
 
Load the new detail page in your browser: http://127.0.0.1:8000/polls/1/ The poll choices now appear.
 
=== Adding some style ===
Line 671 ⟶ 683:
* Since we're creating a POST form (which can have the effect of modifying data), we need to worry about Cross Site Request Forgeries. Thankfully, you don't have to worry too hard, because Django comes with a very easy-to-use system for protecting against it. In short, all POST forms that are targeted at internal URLs should use the {% csrf_token %} template tag.
 
The {% csrf_token %} tag requires information from the request object, which is not normally accessible from within the template context. To fix this, a small adjustment needs to be made to the detail view in the "views.py" file, so that it looks like the following:
 
<pre>
Line 682 ⟶ 694:
</pre>
 
The details of how this works are explained in the [http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext documentation for RequestContext].
 
Now, let's create a Django view that handles the submitted data and does something with it. Remember, in Tutorial 3, we created a URLconf for the polls application that includes this line:
Line 789 ⟶ 801:
Okay, not quite finally. You might need to go to https://admin.alwaysdata.com/advanced/processes/ and click ''Restart my applications''.
 
Go to your alwaysdata site's /adminpolls/ page. For me, I'd go to:
 
* http://paulproteus.alwaysdata.com/adminpolls/
 
You should see your poll!
Create a poll! Create some choices. Find your views, and show them to the world.
 
== Part 4: Editing your polls in the Django admin interface ==
Line 957 ⟶ 969:
 
That's the basics of the Django admin interface!
 
Create a poll! Create some choices. Find your views, and show them to the world.
 
== Part 4.5: Deploy again, again! ==
Anonymous user