Table of Contents

Django

https://docs.djangoproject.com/en/5.1/contents

(venv) % python -m pip install Django
 
>>> import django
>>> print(django.get_version())
4.2.1
 
(venv) % python -m django --version
4.2.1

Creating a project

% django-admin startproject django_blue

The development server

(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
 
System check identified no issues (0 silenced).
 
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
August 28, 2024 - 15:13:33
Django version 5.1, using settings 'django_blue.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Creating the app

% python manage.py startapp polls

Write your first view

polls/views.py
from django.http import HttpResponse
 
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
polls/urls.py
from django.http import HttpResponse
 
def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
django_blue/urls.py
from django.contrib import admin
from django.urls import include, path
 
urlpatterns = [
    path('admin/', admin.site.urls),
    path("polls/", include("polls.urls")),
]
$ python manage.py runserver

Migrations

(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Creating models

polls/models.py
from django.db import models
 
 
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField("date published")
 
 
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
django_blue/settings.py
INSTALLED_APPS = [
    ...
    "polls.apps.PollsConfig",
]
(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    + Create model Question
    + Create model Choice
 
(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

Django Shell

(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py shell
Python 3.11.6 (main, Oct  2 2023, 13:45:54) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet []>
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
>>> q.save()
>>> q.id
1
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2024, 8, 29, 7, 24, 30, 119985, tzinfo=datetime.timezone.utc)
>>> q.question_text = "What's up?"
>>> q.save()
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
polls/models.py
import datetime
from django.db import models
from django.utils import timezone
 
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField("date published")
 
    def __str__(self):
        return self.question_text    
 
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
 
class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
 
    def __str__(self):
        return self.choice_text    
(django5.1) tungnt@MacBook-Pro-cua-Nguyen-2 django_blue % python manage.py shell
Python 3.11.6 (main, Oct  2 2023, 13:45:54) [Clang 15.0.0 (clang-1500.0.40.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 
>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith="What")
<QuerySet [<Question: What's up?>]>
>>> 
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
>>> 
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
    raise self.model.DoesNotExist(
polls.models.Question.DoesNotExist: Question matching query does not exist.
>>> Question.objects.get(pk=1)
<Question: What's up?>
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
>>> q = Question.objects.get(pk=1)
>>> q.choice_set.all()
<QuerySet []>
>>> q.choice_set.create(choice_text="Not much", votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text="The sky", votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text="Just hacking again", votes=0)
>>> c.question
<Question: What's up?>
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
>>> c.delete()
(1, {'polls.Choice': 1})

Django Admin

https://docs.djangoproject.com/en/5.1/intro/tutorial02/

% python manage.py createsuperuser
polls/admin.py
from django.contrib import admin
from .models import Question
 
admin.site.register(Question)

Django Views

https://docs.djangoproject.com/en/5.1/intro/tutorial03/

polls/views.py
from django.shortcuts import get_object_or_404, render
from django.template import loader
from django.http import HttpResponse
from django.http import Http404
 
from .models import Question
 
def index(request):
    latest_question_list = Question.objects.order_by("-pub_date")[:5]
    template = loader.get_template("polls/index.html")
    context = {
        "latest_question_list": latest_question_list,
    }
    #return HttpResponse(template.render(context, request))
    return render(request, "polls/index.html", context)
 
def detail(request, question_id):
    #try:
    #    question = Question.objects.get(pk=question_id)
    #except Question.DoesNotExist:
    #    raise Http404("Question does not exist")
 
    question = get_object_or_404(Question, pk=question_id)
 
    return render(request, "polls/detail.html", {"question": question})
 
 
def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)
 
 
def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)     
polls/urls.py
from django.urls import path
 
from . import views
 
app_name = "polls"
 
urlpatterns = [
    # ex: /polls/
    path("", views.index, name="index"),
    # ex: /polls/{id}/
    path("<int:question_id>/", views.detail, name="detail"),
    # ex: /polls/{id}/results/
    path("<int:question_id>/results/", views.results, name="results"),
    # ex: /polls/{id}/vote/
    path("<int:question_id>/vote/", views.vote, name="vote"),
]
polls/templates/polls/index.html
{% if latest_question_list %}
<ul>
    {% for question in latest_question_list %}
    <!--<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>-->
    <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
polls/templates/polls/detail.html
<h1>{{ question.question_text }}</h1>
<ul>
    {% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
    {% endfor %}
</ul>

Django Form

https://docs.djangoproject.com/en/5.1/intro/tutorial04/