HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythondjangoMinor

Simple Django website with no authentication. For auth/testing tutorial -- Model, model-tests, urls.py, and settings.py only

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
websiteauthsimpledjangosettingswithtestsauthenticationtutorialtesting

Problem

I am writing a simple Django project which has no authentication at all. It's going to be used as the basis of a tutorial I'm writing, on the full authentication lifecycle (create account, login, change/reset password, delete account, etc.), where testing will be emphasized at every step. Beyond testing, the goal of this tutorial is to create as little of a website as possible, before moving onto the authentication parts.

This first question-post contains only the model, its tests, the urls, and settings. After these are improved, I'll follow up with a single view and its tests.

These are the only two views:

The "main" page which is publicly viewable, but shows extra information when logged in. This screenshot demonstrates being logged in (the login functionality doesn't exist yet, but a few days ago I manually logged a user in with authenticate and then login, and the cookie is still in my browser).

It shows some aggregate information, compares their information to the aggregate, and provides a link to their profile page.

Displays all their available information, aside from password, and links back to the main page.

I've built a few demo Django websites, nothing production. However, testing is completely new to me (both in Python and Django). While comments on anything and everything would be appreciated, I'm mostly interested in improving the tests and ensuring the Django code is Django-y. In particular, I'm wondering if there might be a more standard/concise way to do the "unit-test-required blocks" (<!--UNITRQD: start...) as you'll see in the templates (in a follow up post).

I come from backend (non-GUI) Java. I've learned both Python and Django in the past few months, hand in hand, at the same time.

pylint has been run on everything, and all tests pass.

Model

Beyond the User object, the only extra piece of information in the model is their birth year, which is in a UserProfile model.

models.py

```
"""Defines a single extra user-profile

Solution

def _validate_birth_year(value):
    """Validator for , ensuring the
        selected year is between  and
        , inclusive.
        Raises:
            ValidationError: When the selected year is invalid.
        See:
            https://docs.djangoproject.com/en/1.7/ref/validators/
    """
    intval = -1
    try:
        intval = int(str(value).strip())
    except TypeError:
        raise ValidationError(u'"{0}" is not an integer'.format(value))

    if  intval  MAX_BIRTH_YEAR:
        message = (u'{0} is an invalid birth year.'
                   u'Must be between {1} and {2}, inclusive')
        raise ValidationError(message.format(
            value, MIN_BIRTH_YEAR, MAX_BIRTH_YEAR))
    #It's all good.


Range checks are better done with the following syntax:

if min <= value and value <= max


This makes it more readable.

You are checking whether it's not in range. So I'd wrap it like this:

if !(MIN_BIRTH_YEAR <= intval and intval <= MAX_BIRTH_YEAR)


But we're not quite there yet. Why are we comparing intval with MIN_BIRTH_YEAR? The values have no relation to each other. So let's rename intval to birthyear.

birthyear = -1
    try:
        birthyear = int(str(value).strip())
    except TypeError:
        raise ValidationError(u'"{0}" is not an integer'.format(value))

    if  not (MIN_BIRTH_YEAR <= birthyear <= MAX_BIRTH_YEAR):
        message = (u'{0} is an invalid birth year.'
                   u'Must be between {1} and {2}, inclusive')
        raise ValidationError(message.format(
            value, MIN_BIRTH_YEAR, MAX_BIRTH_YEAR))

Code Snippets

def _validate_birth_year(value):
    """Validator for <link to UserProfile.birth_year>, ensuring the
        selected year is between <link to OLDEST_EVER_AGE> and
        <link to MAX_BIRTH_YEAR>, inclusive.
        Raises:
            ValidationError: When the selected year is invalid.
        See:
            https://docs.djangoproject.com/en/1.7/ref/validators/
    """
    intval = -1
    try:
        intval = int(str(value).strip())
    except TypeError:
        raise ValidationError(u'"{0}" is not an integer'.format(value))

    if  intval < MIN_BIRTH_YEAR  or  intval > MAX_BIRTH_YEAR:
        message = (u'{0} is an invalid birth year.'
                   u'Must be between {1} and {2}, inclusive')
        raise ValidationError(message.format(
            value, MIN_BIRTH_YEAR, MAX_BIRTH_YEAR))
    #It's all good.
if min <= value and value <= max
if !(MIN_BIRTH_YEAR <= intval and intval <= MAX_BIRTH_YEAR)
birthyear = -1
    try:
        birthyear = int(str(value).strip())
    except TypeError:
        raise ValidationError(u'"{0}" is not an integer'.format(value))

    if  not (MIN_BIRTH_YEAR <= birthyear <= MAX_BIRTH_YEAR):
        message = (u'{0} is an invalid birth year.'
                   u'Must be between {1} and {2}, inclusive')
        raise ValidationError(message.format(
            value, MIN_BIRTH_YEAR, MAX_BIRTH_YEAR))

Context

StackExchange Code Review Q#66766, answer score: 3

Revisions (0)

No revisions yet.