Archive for the ‘ Code ’ Category

BHS Shirt Sales with Django

This is a project I’ve been working on for the past week or so. It’s live now, and I wanted to share the codebase. This post is more or less exactly the README from the GitHub repo bhs_sales, so head there if you want to get right to it.

Intro

The BHS Class of 2014 needs some money for prom. We came up with the idea of selling senior shirts as a fundraiser, but the process for organizing an order for ~300 people is incredibly complex and comes with the headaches of having to lend money to make an order, collecting money afterward, over-ordering, etc.

This is our solution: a Stripe-based marketplace to preorder shirts. This lets us record the name/size/selection of everyone who wants a shirt, and then aggregate that data later. Payments are processed through Stripe.

Technical Stuff

This is a Django project. It currently only has one application, “shirts.” Data is stored by default in SQLite, but that can be changed easily. Database migrations are handled through South.

I have included some deployment scripts, namely:

  • Makefile
    • Provides automated deployment, but will require changing of paths
  • hup_bhssales
    • Used in my git post-receive hook to restart the server process automatically when I push new changes to production
  • bin/gunicorn_start
    • The script called by supervisord to start gunicorn — will also require changing of paths for custom deployment

Supervisor keeps a gunicorn instance running with a socket in /tmp. I have set up nginx to proxy_pass to that socket, more or less just like any other Django project.

Architecture

There are only two models. 1. StoreItem contains a name/description/summary/price of a certain item 2. Order contains the name of the customer, a timestamp, the purchase price (in case the price in the future changes), and the Stripe ID of the charge. The Stripe ID is optional — I’ve allowed a separate “in person” payment type.

When the order form is submitted, /charge will use the Stripe Checkout token to attempt to make the charge through Stripe. If it’s successful, an Order instance will be saved and the user redirected to a confirmation page. A public list of all orders is included.

The sizes are stored as a constant in shirts/models.py. I’m not sure this is the best way to do it.

Configuration

I have included my Dev configuration. I manage configurations using django-configurations. You’ll notice the end of settings.py tries to import all from local_settings.py. You’ll need to create a local_settings.py in the same format as settings.py, containing a:

class Production(Configuration):

Put your live Stripe keys in that configuration, without committing it to Git.

Also, run this in a venv. A requirements.txt is included.

Weekend Project: Web-controlled Christmas Lights with Node.js, Arduino, and Raspberry Pi

Christmas Lights

This is my Node.js “hello world.” It’s a weekend project that allows you to control GE Color Effects lights over the internet through the use of a Raspberry Pi (running nginx and a Node.js application) connected to an Arduino. Like I say in the video, I think it may be possible to control the data line of these lights directly from the Raspberry Pi’s GPIO pins, but I already wrote an Arduino library to handle that and it works nicely.

Tech Stuff

The setup is fairly simple. The Raspberry Pi runs a frontend with my webserver of choice, nginx. It serves up a static page on / and proxies to my Node.js application on /api. Post data sent to /api is decoded by the Node application and matched with a hex value (assuming the color sent was valid). This hex value is then packed into the two-byte serial format I developed for my Arduino library, and sent over serial to the Arduino. Internally the Arduino uses a data structure called a circular buffer. Circular buffers are especially cool for this usage, because when I ‘push’ a light onto the string of lights, every single light needs to be updated (as each color is ‘moving’ down the line). With a circular buffer, the data structure remains a constant size, and all that’s required to update it is to write a new value at the ‘head’ location and then increment the location of the head. More specifics about how this works can be found in the linked Wikipedia article as well as the source code for the aforementioned Arduino library.

I had a lot of fun with this project. One thing I really like about Node.js is how simple it makes creating APIs that can do Really Cool Things. Using just the JavaScript environment available in my web browser, I can package the color data in the format Node needs it, and let Node handle the rest. Node.js is not for everything, but the ease of communication between browser and application makes it a joy to work with.

Do It Yourself

Get a Raspberry Pi set up with Node.js installed, and an Arduino with the sketch linked below flashed to it. To flash the Arduino, you need the GEColorEffects library as a dependency.  Connection to the lights themselves is outside of the scope of this post, but more info can be found in darco’s original post. Clone the nodejs-christmas-lights git repository onto the Raspberry Pi. Ensure that the Arduino manifests as a serial port (usually /dev/ttyACM0) on the RPi, and chmod it to be accessible by your user. A simple ‘chmod 777 /dev/ttyACM0’ should do, since (hopefully…) your Raspberry Pi isn’t a production box.

Set up nginx on your Raspberry Pi, and put the contents of the nodejs-christmas-lights repository’s www folder in your webroot. Again, this is more or less outside the scope of this post, but the following config should act as a starting point. Important to note is that the /api path must forward to the host/port of your Node.js application.

server {
    listen 80;
    server_name lights;

    root /var/www/vhosts/lights/htdocs;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location /api {
        proxy_pass http://localhost:8080;
    }
}

If all is set up correctly, navigate to the Raspberry Pi in your browser, choose a color, and hit the ‘Go!’ button.

Resources

Feel free to ask questions in the comments. If you do something cool with this code, I’d love to hear about it!

Publishing Data to Redis with Django Signals

Just something I found and thought was kind of cool. I’m currently working on a project that uses Django for its frontend, but eventually passes the user to a JavaScript frontend that talks to the Node.js / Redis backend with Socket.IO. I needed a way to store data in Redis whenever a specific Django model was saved. I looked up ‘Django + redis’ beforehand, but the existing projects seem to be mostly cache-oriented, and as far as I know Django doesn’t have a standard adapter for Redis. No worries — it’s all Python!

Django signals let you execute functions whenever a signal is emitted, but specifically in my case, when a model is saved. You can put your signals code anywhere, but I like to make a ‘signals.py’ in the app directory and then just add the line ‘import signals’ to the app’s __init__.py. I subscribed to the Django model saved and model deleted signals with functions that connect to Redis and add some of the relevant data to a hash. Hashes in Redis are very much like dicts in Python, and Andy McCurdy’s redis-py library allows you to pass dicts directly to the hmset function.

Here’s the relevant code (adapted for the example) in signals.py:

import redis
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from yourapp.models import YourModel

@receiver(post_save, sender=YourModel, dispatch_uid="yourmodel_create")
def addYourModelToRedis(sender, instance, **kwargs):
	r = redis.StrictRedis(host='localhost', port=6379, db=0)
	yourmodel_dict = {
		'uid': instance.user.id,
		'number1': instance.number_1,
		'number2': instance.number_2,
		'status': instance.status
	}
	r.hmset('yourmodel:' + instance.uniqueKey, yourmodel_dict)

@receiver(post_delete, sender=YourModel, dispatch_uid="yourmodel_delete")
def removeYourModelFromRedis(sender, instance, **kwargs):
	r = redis.StrictRedis(host='localhost', port=6379, db=0)
	r.delete('yourmodel:' + instance.uniqueKey)

The “dispatch_uid” parameter passed to the receiver decorator is intended to keep the signal from being acted upon more than once per save/deletion of a model. All the Django documentation says is to use a unique string; they don’t recommend that you use a specific format and it doesn’t seem to matter as long as it’s unique. Another thing to note is that the ‘instance’ parameter for my handler functions is specific to the post_save and post_delete signals. In general signal handlers are expected to take “sender” and “**kwargs.” However it’s safe to extract the ‘instance’ variable from **kwargs in the function definition when only being used for these specific signals. More information about signals and handling signals can be found in the Django documentation.