Answers for Webapp Questions

Danger

Looking at these answers too soon can cause indigestion, headaches, hair loss, mass panic and other side-effects. Be cautious! Think through the question first!

Remember

  • you can do this!
  • effort matters!

How do I start a server on port 8103 and navigate to it?

  1. http://127.0.0.1:8000/
  2. Navigate to http://127.0.0.1:8103/

How do I verify the server is shut down?

go to http://127.0.0.1:8000/ and see if you get a 404, or 500!

How do I put single quote in the SECRET_KEY?

Recall (or know!) that python can single-quote, double quote, or triple quote strings:

SECRET_KEY="that's my string"

or:

SECRET_KEY='''that's my string'''

Does database.db exist?

It shouldn’t! Use ls to find out!

Why are the standard apps standard?

  • They are useful for most web projects.
  • They are tedious to write, or hard to code correctly or both.

By default, INSTALLED_APPS contains the following apps, all of which come with Django:

  • django.contrib.auth – An authentication system.
  • django.contrib.contenttypes – A framework for content types.
  • django.contrib.sessions – A session framework.
  • django.contrib.sites – A framework for managing multiple sites with one Django installation.
  • django.contrib.messages – A messaging framework.

These applications are included by default as a convenience.

Does this all seem magical?

Yes, this is all somewhat magical. Eventually, that should start to worry you, but for now, accept that it mostly works, most of the time.

Why does the dev server still work when settings.py has been deleted?

Because settings.pyc still exists, and that’s what the machine is actually looking at when you run the code that runs the dev server. That’s why the dev server does not work when you also delete settings.pyc. Now the computer has no idea what you’re talking about, since the original code and the compiled byte code are both gone.

Does database.db exist now?

Now it should! That is one of the magical bits of dbsync.

Use ls to verify it!

How do I know if my work is saved in git?

$ git status
# nothing should be in 'untracked' that suprises you.
# if there are 'modified files', then let's see what is different
$ git diff
# shows the diffs between what is on disk and what git knows about
# If there *are* diffs:
#    git add  # the files,
#    git commit -m "some message"

What are the implications of Sqlite only handling one writer?

  • performance is blocked by how fast that one writer can write
  • multiple processes can clobber each others’ data.

Is Git magical?

Django is magical. git is creepy.

Why does testing matter?

Among other reasons:

  • ensure that the features actually work as expected.
  • help make it clear what “as expected” actually means.
  • stop code changes from breaking things that used to work.
  • keep code split into reasonable, understandable chunks (“if I can’t figure out how to test it, it’s probably doing to much!”).

Why don’t we commit database.db?

Becuase database.db is just a ‘test database’ and doesn’t have anything “real” in it, we don’t care about it. Generally files that are ‘built’, like .pyc files, the build html files of this book, and the like aren’t put under version control.

Is polls importable?

We don’t know. Is it? It should be.

$ cd myproject
$ python
>>> import polls

If you got an ImportError, it’s just as it sounds! Check sys.path, file permissions, and the like.

What are these .pyc files anyway?

From PEP 3147:

CPython (the ‘standard’ variety of Python) compiles its source code into “byte code”, and for performance reasons, it caches this byte code on the file system whenever the source file has changes. This makes loading of Python modules much faster because the compilation phase can be bypassed. When your source file is foo.py, CPython caches the byte code in a foo.pyc file right next to the source.

When you import or otherwise run a piece of Python code, it will create a .pyc file of the compiled byte code automatically when it can.

What is the result of the standard test?

Some that we got when we ran things:

(pystar):myproject$ python manage.py test
Creating test database 'default'...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Installing index for auth.Permission model
Installing index for auth.Group_permissions model
Installing index for auth.User_user_permissions model
Installing index for auth.User_groups model
Installing index for auth.Message model
No fixtures found.
..........EE...E.............................................................................................................................................................
======================================================================
ERROR: test_password_change_fails_with_invalid_old_password (django.contrib.auth.tests.views.ChangePasswordTest)
----------------------------------------------------------------------

  ...
TemplateDoesNotExist: registration/password_change_form.html

======================================================================
ERROR: test_password_change_fails_with_mismatched_passwords (django.contrib.auth.tests.views.ChangePasswordTest)
----------------------------------------------------------------------
  ...
TemplateDoesNotExist: registration/password_change_form.html

======================================================================
ERROR: Logout without next_page option renders the default template
----------------------------------------------------------------------
  ...
AttributeError: 'module' object has no attribute 'handler500'

----------------------------------------------------------------------
Ran 173 tests in 3.557s

FAILED (errors=3)
Destroying test database 'default'...

Note the missing templates, which make some sense. We think the ERROR: test_password_change_fails_with_invalid_old_password has to do with sqlite, but who knows? We probably should know.

Why do I only need to restore settings.py and not settings.pyc?

Well first off, remember how we set up git to exclude .pyc files from the repo? So settings.pyc was never put into the repo and therefore cannot be recovered from it. Not to worry though. When you restore settings.py and restart the dev server, settings.pyc is built automatically. Nifty!

Which framework is right?

Which one do you think is right? Why is that, again?

You are completely correct – gold star!

Why not admin for everything?

Why not, indeed!?

The django.admin app is one django’s killer apps! It’s easy to use, powerful, decently extensible. Many sites are just admin sites, dressed in nicer clothes, and given nicer URLConf‘s.

There are some concerns though:

  • users and permissions (ensuring the right people can edit the right things)
  • the admin site relies heavily on django.models to work right. If your needs aren’t met by them, admin doesn’t work.

Why don’t people like Django?

  • It’s too magical. Too many mysterious files
  • django.models is limited. Not everything is expressable as a 1:1 mapping with a db table. What if I want to store in other types of data stores?
  • (insert more reasons here!)

With polls added to the app

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
     'polls',
 )

What is the ROOT_URLCONF?

Look in settings.py:

ROOT_URLCONF = 'myproject.urls'

This setting is for a python module. In those, . implies a directory structure, so Django will look at myproject/urls.py. Magical?

What writes the error message when a choice is missing?

Look in views.py:

try:
    selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
    # Redisplay the poll voting form.
    return render_to_response('polls/detail.html', {
        'poll': p,
        'error_message': "You didn't select a choice.",
    }, context_instance=RequestContext(request))

What is triggered by http://127.0.0.1:8000/polls/23/results/ ?

Given:

urlpatterns = patterns('',
 (r'^polls/$', 'polls.views.index'),
 (r'^polls/(\d+)/$', 'polls.views.detail'),
 (r'^polls/(\d+)/results/$', 'polls.views.results'),
 (r'^polls/(\d+)/vote/$', 'polls.views.vote'),
)

We ignore the http://127.0.0.1:8000/ bit.

The rest polls/23/results/ fails to match first two, but does match r'^polls/(\d+)/results/$', which captures the 23.

Thus polls.views.results is called with the argument 23.

Why are request.POST values always strings?

  • Think about the interaction process with websites. You enter text, and it goes off for processing.
  • Strings are the universal currency of computing!
  • Even when something looks like an int, it is better not to guess (e.g. ZIP codes).
  • Explicit is better than Implicit is part of the Zen of Python . SNARK: Django isn’t always very explicit.