Categories
Django Python

Programmatically Adding Users to Groups in Django

I recently needed to add a large number of users to a permission group in Django. I had a hard time finding a way to do this in the documentation, so I thought I’d share my solution.

from django.contrib.auth.models import Group, User
 
g = Group.objects.get(name='My Group Name')
users = User.objects.all()
for u in users:
    g.user_set.add(u)

Easy as pie. I originally attempted to do this from the perspective of a user, but as it turns out, doing it from the group perspective is much easier.

Categories
Django Python

Copying Django Model Objects

Django’s ORM is top notch. It provides facilities to do almost anything you can think of with a database, and if it doesn’t, it still lets you execute arbitrary SQL to your hearts content. I’ve been developing Django for close to 2 years now, and still discover facets of it that I never knew existed. For instance, I had a need to duplicate a row in a table, but give it a different primary key. After a quick Google search, I discovered that Django allows you to do the following to copy instantiated model objects.

my_model = MyModel.objects.get(pk=4)
my_model.id = None
my_model.save()

There are a few caveats with doing things this way.

  • Unique Constraints – If you have any unique constraints on the model, the save will not pass validation and fail.
  • ManyToMany Fields – If you need new copies of ManyToMany field values, you’ll need to handle this yourself.

That being said, in many cases duplicating a model instance is as easy as changing it’s ID and saving.

Categories
Django Python

Update All PIP Packages

Revisiting an old Python + Django project made me realize that I needed to upgrade it’s PIP packages. Unfortunately, PIP doesn’t provide a way out of the box to update all of your installed packages at once. To update all of the PIP packages at once, use the following script.

import pip
from subprocess import call
 
for dist in pip.get_installed_distributions():
    call("pip install --upgrade " + dist.project_name, shell=True)

For more detail, check out this question on Stack Overflow.

Categories
Other

28 Questions

Over the past few years I’ve tried my hand at launching a couple of different start ups. Over this time period, I’ve collected a set of questions from many different sources (HN, YCombinator, TechStars, etc) that I ask myself before proceeding. They help be decided if this is a real or manufactured problem, if it can be profitable, and if people will buy what I’m selling. My latest project idea is the only idea I’ve had that passes all of these questions to my satisfaction. How do yours hold up?

  1. What are you going to build?
  2. What is the actual problem?
  3. How will you sell your product/service?
  4. What are some potential obstacles?
  5. What are some existing options that solve this problem? How are you different?
  6. Who needs what you’re making?
  7. How do you know that they need it?
  8. How is the problem being solved now? Is it being solved now?
  9. Why isn’t this being done your way already?
  10. How will customers find out about you?
  11. What resistance will they have to trying your product?
  12. What are some key things about your project that outsiders don’t understand?
  13. Who will your first paying customer be?
  14. How might you expand if your initial idea succeeds?
  15. Why did you choose to work on this idea?
  16. Six months from now, what will be you biggest problem?
  17. What are the hard parts of this idea?
  18. Who would you hire/add to your team?
  19. What is the next step in product evolution?
  20. How does your product work?
  21. How big is the opportunity? [market]
  22. How do you know customers need what you’re making?
  23. What domain expertise do you have? Why should you be the one to do this?
  24. What part of your project will you build first? (could be business connections, hardware, software, etc)
  25. How much money could you make per year?
  26. How will you make money?
  27. What have you built in the past?
  28. How would you spend $5,000, how would you use it?
Categories
Django Python

Installing Local Flavor with Django 1.5

I just started a new project using the latest release candidate of Django 1.5. One thing that I needed was the local flavor add-on so I could get a list of US states. This functionality used to be rolled into the main codebase, but it was rightfully removed in Django 1.5. To install the US local flavor package, just use PIP.

pip install https://github.com/django/django-localflavor-us/zipball/master

Now you should be able to import anything you need from the package in the usual manner, except from the new package instead of the old one.

from django_localflavor_us.us_states import STATE_CHOICES

For more information, check out the How To Migrate section of the local flavor docs on the Django documentation site.

Categories
Django Python

Extending Django’s Model.save() Method

I’m currently working on a project where I have a model named ‘Instructor’ with a few fields:

  • first_name – CharField
  • last_name – CharField
  • departments – Many-toMany

I found out at some point that I’d really like a field called “full_name”, which is “first_name” and “last_name” concatenated together. I didn’t want to have to fill the field in though, I wanted it to happen automatically. To accomplish this, I extended Django’s Model.save() method after I added the ‘full_name’ column to my model.

class Instructor(models.Model):
    first_name = models.CharField(max_length=150)
    last_name = models.CharField(max_length=150)
    departments = models.ManyToManyField(Department)
    full_name = models.CharField(max_length=180, blank=True)
 
    def save( self, *args, **kw ):
        self.full_name = '{0} {1}'.format( self.first_name, self.last_name )
        super( Instructor, self ).save( *args, **kw )

And that’s it! Now every time I create a new instructor with ‘first_name’ and ‘last_name’, it automatically populates the ‘full_name’ field for me.

Categories
Django Python

Deploying Django with Fabric

Fabric is a Python library and command-line tool for streamlining the use of SSH to deployment and sys-admin tasks. In the Django community Fabric has been picked up as the de facto standard for deploying apps, which is a place that it deserves. One thing I noticed though was that there wasn’t a lot of good examples for getting it to place nice with VirtualEnv.

Getting Started

The first thing you need is to make sure that you have Fabric installed.

pip install fabric

Once that’s done, open a file called fabfile.py and add the following imports:

from __future__ import with_statement
from fabric.api import *

Role Defs

Fabric has two functions that get used very frequently: local & run. The local() command will execute whatever you pass into in your local environment. The run() command will execute whatever you put into it in a remote environment defined in your roledefs.

A roledef defines a what a server is. For instance, if you have a nice fleshed out dev-staging-live type of environment:

evn.roledefs = {
	'dev' : ['dev.re-cycledair.wploadtest.xyz'],
	'staging' : ['staging.re-cycledair.wploadtest.xyz'],
	'live' : ['re-cycledair.wploadtest.xyz']
}

Once your roledefs are defined, you can run code on those specific servers by using the @roles decorator.

@roles("dev")
def ls_on_dev:
	run("ls") # Runs 'ls' on dev.re-cycledair.wploadtest.xyz
 
@roles("staging")
def ls_on_staging:
	run("ls") # Runs 'ls' on staging.re-cycledair.wploadtest.xyz

At this point, you want to run one of your new Fabric functions, from the directory where your fabfile is run:

fab ls_on_staging

Deployment

Now that you’ve got a handle on the trivial examples, lets make things a little more useful. We’re going to deploy to our ‘staging’ server.

@roles("staging")
def deploy_staging(tag=False):
	code_dir = '/path/to/remote/directory'
	with cd(code_dir):
		run("git fetch")
		if tag:
			run("git checkout %s" % tag)
		else:
			run("git checkout master")
			run("git pull origin master")
		with prefix('source /path/to/virtual/environment/bin/activate'):
			run("pip install -r requirements.txt")
			run("python manage.py syncdb")
			run("python manage.py migrate")
			run("python manage.py collectstatic --noinput")
			run("touch path/to/wsgi.py"

All this code is pretty self-explanatory. The @roles decorator has run execute in the context of “staging”. The run commands are just regular commands you would execute at the terminal if you were manually deploying. The only potential “gotch-ya” is the with prefix call. That basically says “execute the following statements in the context of my virtual environment”. To make everthing go:

fab deploy_staging

will deploy the head of the master branch and

fab deploy_staging:tag=1.0.0

will deploy the 1.0.0 tag.

Done

If all goes well, you can now deploy your app in seconds! If it takes longer then that, you might need to set up your ssh keys you so can login to your server without getting prompted for usernames and password.

Categories
Django Python

Deploying Django 1.4 to Heroku

Note: It is assumed that your are keeping track of your changes using Git. If you aren’t, you’ll need to be to deploy to Heroku.

If there is one thing that scares beginners away from Django, its the idea of deployment. For a PHP programmer, deployment can be as simple as FTP’ing some files to a server, and boom, deployed. This isn’t to say that PHP deployment is simple. If you have to do it from scratch (get apache running, get your db installed, get PHP installed and configured, etc, etc) it can still be very complex, but many hosting companies take care of this for you. It’s almost like you never even have to think about it, which isn’t always the case for Django. That doesn’t mean its a bad thing, just…different.

So where do we start? Heroku is as good a place as any.

Heroku


Heroku is a cloud service for easy deployment of web applications. Initially it was Ruby only, but has been working hard to become a deployment service for many languages including Java, Python, and Node.js. Deploying to Heroku assumes a few things:

  1. You are familiar with Git and use it to track your code changes.
  2. You are at least passingly familiar with PostgreSQL, because that’s what you will being using. (You can use other storage devices, but PostgreSQL is the default and easiest to setup.
  3. You use PIP to manage your project’s requirements. If you aren’t doing this, you need to be. (seriously, it’s worth the effort)

Now that we have that out of the way, let’s get started. Before we can proceed further, you’ll need to get a Heroku account set up. For our testing purposes, a free account should be plenty.

  1. Go to Heroku.com and set up an account.
  2. Go to https://toolbelt.herokuapp.com and download the Herok toolbelt. Follow the directions on this page up to the “login” section.

That’s all for setting up Heroku for now. Next, we’re going to move on to configure Django so it can be deployed.

Django

Django gives you the flexibility to use almost any database under the sun. I generally develop using MySQL, but Heroku uses Postgres. As long as you haven’t been hand-tailoring queries, this shouldn’t provide any problem whatsoever. To make your project compatible with Heroku, you need to install the psycopg2 library.

pip install psycopg2

Now that you have the Postgres library installed, when your app is pushed to Heroku, Heroku will append some code to the end of your settings.py file that will point your install to the correct database.

Speaking of settings.py, you’ll also need to get your template and media paths set up correctly. To do that, add the following to the top of your settings.py and then set your paths to look like this:

import os.path
root = os.path.dirname(__file__).replace('\\','/')
 
MEDIA_ROOT = root + '/../media/'
STATIC_ROOT = root + '/../static/'
TEMPLATE_DIRS = (
    root +'/../templates',
)

We use this calculate root variable because it’s kind of a pain to know the path of your install on Heroku. This way it doesn’t matter where you deploy your app to, it should just work. Another thing to consider is static files. Heroku can be made to serve them, but having the same domain that is serving your site serve your static files is bad practice.

Wrapping it up

Now that Django is configured for Heroku deployment, all that’s left is to deploy it! The first thing we need to do is create a requirements file so that Heroku knows what packages to install. At the top level of your project, run the following:

pip freeze > requirements.txt

Great, now if you look at the generated file you can see what software Heroku is going to install for you. Next up, we’re going to create an app on Heroku (assuming you set up the Heroku tool belt correctly). In the top level directory of your project, run the following.

heroku create --stack cedar

This added your new Heroku app as a remote on your local Git repository. All you do to deploy is:

git push heroku master

Which should give you some output that looks like:

Counting objects: 10, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (10/10), 3.59 KiB, done.
Total 10 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Python/Django app detected
-----> Preparing Python interpreter (2.7.2)
-----> Creating Virtualenv version 1.7
       New python executable in .heroku/venv/bin/python2.7
       Also creating executable in .heroku/venv/bin/python
       Installing distribute........done.
       Installing pip...............done.
       Running virtualenv with interpreter /usr/local/bin/python2.7
-----> Activating virtualenv
-----> Installing dependencies using Pip version 1.0.2
       Downloading/unpacking Django==1.4 (from -r requirements.txt (line 1))
       ...
       Successfully installed Django psycopg2
       Cleaning up...
-----> Injecting Django settings...
       Injecting code into ./hellodjango/settings.py to read from DATABASE_URL
-----> Discovering process types
       Procfile declares types         -> (none)
       Default types for Python/Django -> web
-----> Compiled slug size is 9.3MB
-----> Launching... done, v4
       http://simple-spring-9999.herokuapp.com deployed to Heroku

To git@heroku.com:afternoon-sword-29.git
* [new branch]      master -> master

On the line immediately after “—–> Launching… done,…”, the url of your project is displayed. Before you go to it though, you need to run syncdb on Heroku. The Heroku toolbelt makes this pretty easy:

heroku run python manage.py syncdb

Conclusion

That’s all there is to it. If you get stuck, feel free to leave a comment. Heroku also has a great guide for getting up and running and explains some more features of the Heroku tool belt. That can be found here.