Make a deck of cards with Django

Learn you Django by making a deck of cards out of internets.

For the impatient, source code is here

Start the project

1
2
$ django-admin startproject django_cards
$ cd django_cards

create a virtual environment and activate it

1
2
3
4
5
6
7
$ virtualenv venv
New python executable in venv/bin/python2.7
Also creating executable in venv/bin/python
Installing setuptools, pip...done.
$ . venv/bin/activate
(venv) $

venv is a convention. It creates a new environment for our project where we’ll install django and other packages. A virtual environment is like a virtual machine with way less overhead. Add venv to .gitignore for version control.

Install django and generate a requirements.txt file. This is where all the packages that our app requires will be defined. It’s like a gemfile in ruby or package.json in node.

1
2
$ pip install django
$ pip freeze > requirements.txt

This creates our project directory. Now we create a new app called cards where we will have all of our application logic.

1
$ django-admin.py startapp cards

cards is now an app we’ll use within the django_cards project. In django_cards/settings.py add cards to our installed apps:

1
2
3
4
5
6
7
8
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cards',
)

Create a card model in cards/models.py. This will define the columns in our

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.db import models
class Card(models.Model):
SPADE = 0
CLUB = 1
DIAMOND = 2
HEART = 3
SUITS = (
(SPADE, "spade"),
(CLUB, "club"),
(DIAMOND, "diamond"),
(HEART, "heart")
)
suit = models.PositiveSmallIntegerField(choices=SUITS)
rank = models.CharField(max_length=5)

Add to a new file cards/utils.py:

1
2
3
4
5
6
7
8
9
10
from models import Card
def create_deck():
"""
Create a list of playing cards in our database
"""
suits = [0, 1, 2, 3]
ranks = ['two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'jack', 'queen', 'king', 'ace']
cards = [Card(suit=suit, rank=rank) for rank in ranks for suit in suits]
Card.objects.bulk_create(cards)

Now we’re going to set up our database. Make the migrations and migrate the database. We’re also going to run the create deck function.

1
2
3
4
5
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py shell
>> from cards.utils import create_deck
>> create_deck()

Next we’ll set up routing. In the project directory (django_cards) add a new route:

1
url(r'^$', 'cards.views.home', name='home'),

This regex matches our index route and will use the view as defined in the views.py file of our card app. The last parameter gives our route a name.

Define the home view:

1
2
3
4
5
6
7
from models import Card
def home(request):
data = {
'cards': Card.objects.all()
}
return render(request, 'cards.html', data)

This provides all the card data to our template. Inside of the cards directory add a templates/cards.html. This will be our homepage. Django automatically knows to search for cards.html inside of a templates directory.

Add a basic loop to templates/cards.html:

1
2
3
4
5
<div>
{% for card in cards %}
<p>Suit: {{ card.suit }}, Rank: {{ card.rank }}</p>
{% endfor %}
</div>

Then run the server and see the card data displayed on localhost:8000

1
$ python manage.py runserver

We’ll make our template a bit more snazzy:

1
2
3
4
5
6
7
8
9
10
We have {{ cards | length }} cards!
{% for card in cards %}
<div>
<p>
Capitalized Suit: {{ card.get_suit_display | capfirst }} <br>
Uppercased Rank: {{ card.rank | upper }}
</p>
</div>
{% endfor %}

We now use get_FIELD_display to show the suit name. This is a bit magical to me, had to investigate on SO.

In future tutorials we will build up actual functionality to play cards. Keep an eye on the SOURCE code for this tutorial!