Ultimate beginner’s Django cheat sheet.

Here are some code snippets which might be helpful for people who are new to Django and may want to quickly go through basic concepts. This code covers up to tutorial 4 of the series provided on the official Django documentation: Tutorial 1. You may look this link too for detailed explainations. Here we cover basic topics like views, urls, models, SQLite integration, template system, django command line tool etc. You may copy these snippets in some code editor like sublime text to read it easily.

# create a new django project
django-admin startproject mysite

# run the server
python manage.py runserver
or
python manage.py runserver 8080  # run in different port instead of default.

# create new app in project
python manage.py startapp polls


#to create new view, open the file polls/views.py and put the following Python code in it:
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")


# now we have to map a url to above view.
# In the polls/urls.py file include the following code:
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),    # path(regex, function inside views file, name associated with function)
]


# now since polls app will be in extension of mysite, so we have to register its regex in mysite/urls.py:
from django.urls import include, path
from django.contrib import admin

urlpatterns = [
    path('polls/', include('polls.urls')),    # use include function to extend urls of polls app over mysite.
    path('admin/', admin.site.urls),
]


# creating models:
# models are essentially database layouts, used for object relational mapping between classes and their respective items in database.
from django.db import models

class Question(models.Model):          # this class will map to a table 'polls_question' with rows question_text and pub_date.
    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)



# now to include polls app in our project, we need to add a reference to the configuration class of this app in settings.py INSTALLED_APPS.
# this class is in polls/apps.py
INSTALLED_APPS = [
    'polls.apps.PollsConfig',   # reference to PollsConfig class inside polls/apps.py
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]    
# now run command:
python manage.py makemigrations polls
# this command tells django that changes have been made in models, and django storesa these changes in a migration.

# now to see what sql commands will run due to your model, use command:
python manage.py sqlmigrate polls 0001    # note that this command will NOT actually run the sql commands, it just shows the sql commands.

# now to run the migration stored earlier, use command:
python manage.py migrate

# django provides a shell which can be used as an API. To invoke the Python shell, use this command:
python manage.py shell



# Some sample shell commands and their outputs:
		>>> from polls.models import Question, Choice   # Import the model classes we just wrote.

		# No questions are in the system yet.
		>>> Question.objects.all()
		<QuerySet []>

		# Create a new Question.
		# Support for time zones is enabled in the default settings file, so
		# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
		# instead of datetime.datetime.now() and it will do the right thing.
		>>> from django.utils import timezone
		>>> q = Question(question_text="Whats new?", pub_date=timezone.now())

		# Save the object into the database. You have to call save() explicitly.
		>>> q.save()

		# Now it has an ID.
		>>> q.id
		1

		# Access model field values via Python attributes.
		>>> q.question_text
		"What's new?"
		>>> q.pub_date
		datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

		# Change values by changing the attributes, then calling save().
		>>> q.question_text = "Whats up?"
		>>> q.save()

		# objects.all() displays all the questions in the database.
		>>> Question.objects.all()
		<QuerySet [<Question: Question object (1)>]>


# now we can customize the above output for command in line 114 to make it more readable.
# for that create new __str__ methods inside classes Question and Choice of the file models.py
class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text        		

		# now if you again run above command, we get output:
		<QuerySet [<Question: Whats up?>]>


# you can also use custom methods in these classes:
from django.utils import timezone
import datetime
...
class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)      # returns True if publish date is not older than yesterday.

# Now again run shell commands:
		...
		>>> q = Question.objects.get(pk=1)
		>>> q.was_published_recently()
		True

# creating choices of questions using shell:
		>>> q = Question.objects.get(pk=1)

		# Display any choices from the related object set -- none so far.
		>>> q.choice_set.all()
		<QuerySet []>

		# Create three choices.
		>>> 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)

		# Choice objects have API access to their related Question objects.
		>>> c.question
		<Question: Whats up?>

		# And vice versa: Question objects get access to Choice objects.
		>>> q.choice_set.all()
		<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
		# The API automatically follows relationships as far as you need.
		# Use double underscores to separate relationships.
		# This works as many levels deep as you want; there's no limit.
		# Find all Choices for any question whose pub_date is in this year
		# (reusing the 'current_year' variable we created above).
		>>> Choice.objects.filter(question__pub_date__year=current_year)
		<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

		# Let's delete one of the choices. Use delete() for that.
		>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
		>>> c.delete()		# deletes choice 3 of the question with pk=1

# use command exit() to leave shell.

#create a django admin account:
python manage.py createsuperuser

# use the submitted credentials to login to http://127.0.0.1:8000/admin/


# Now to make our Question class editable by django admin, register it in polls/admin.py
from django.contrib import admin
from .models import Question

# Register your models here.
admin.site.register(Question)



# to add new views to polls app, type these methods in polls/views.py
...
...
def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

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)


# now register the urls of these views in polls/urls.py
...
...
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
		
# to define templates for methods in views.py, create directory 'templates' in polls directory. 
# now in templates directory, create another subdirectory polls. inside polls, create index.html
# so now in file polls/templates/polls/index.html, write following code:
		{% if latest_question_list %}          # in template, to use programming statements, enclose them in {% ... %}  
		    <ul>
		    {% for question in latest_question_list %}
		        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a> </li> # enclose programming variables in {{...}}
		    {% endfor %}    # for has endfor in templates.
		    </ul>
		{% else %}
		    <p>No polls available. </p>
		{% endif %}    # if has endif in templates.

# now modify index method in polls/views.py:
...
from .models import Question
from django.shortcuts import render

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]    # get last 5 published question objects in a list.
    context = {
    	# this dictionary contains list of variables used inside html file mapped to their python counterparts.
    	# ex: 'latest_question_list' is used in html in line 226, it comes from python variable latest_question_list in line 242.
        'latest_question_list': latest_question_list    
    }
    return HttpResponse(render(request, 'polls/index.html', context))    # pass request, template file location and context to render.
	

# returning 404 error if object doesnot exist:
from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})


# to remove hardcoded urls from template files, use their definitions as used in urls.py file:
        <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>    
# this looks urlpattern with name='detail' in urls.py and replaces <question_id> with question.id 
# this way, you can directly change urls from a central location when required without having to edit each template.


# to namespace urls for each app, so that they don't get mixed up, add app_name to urls.py:
app_name = 'polls'
# now add reference of app_name to urls:
		<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>


# creating form in detail.html:
<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}    # used to prevent cross site request forgeries.
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" /># forloop.counter gives number of times loop has run.
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

# defining vote function in views.py:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse

from .models import Choice, Question
# ...
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])    # POST[] returns id of selected choice as captured by form.
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))   # takes url as single argument to redirect.
        # reverse function is used to avoid hardcoding urls and referencing them by their name in urls.py.

Leave a Reply

Your email address will not be published. Required fields are marked *