Posts Tagged ‘django’

Unicode in Django, It’ll Getcha

Posted in Uncategorized on February 11th, 2010 by Nick – Be the first to comment

I’ve been having an insane time trying to squash a weird unicode bug in Beertraq. This was one of the first bugs that was found after starting the beta and it’s taken me this long to get it worked out. It all started with a cryptic-seeming error upon viewing the add-a-beer page:

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-9: ordinal not in range(128)

Real descriptive, right? Looking through the stack trace wasn’t much help either. It was a bunch of stuff pertaining to trying to render the template. One thing I did notice is that a brewer with a unicode name had recently gotten added and this error was only happening on the new beer form (which includes a ChoiceField of brewers), but the brewer was being displayed just fine on its own page.

After asking my friend and fellow Django-user Dan-o what he thought, he asked if I had __str__() and __unicode__() defined in my models. I had __str__() defined (generally a good idea) but not __unicode__(). I popped it in to my Brewer model as so:

class Brewer(models.Model):
  TYPE_CHOICES = (
    ('Macrobrewer', 'Macrobrewer'),
    ('Microbrewer', 'Microbrewer/Craft brewer'),
    ('Homebrewer', 'Homebrewer'),
    ('Unknown', 'Unknown'),
  )

  name = models.CharField("Brewer name", max_length=255)
  brewer_type = models.CharField("Type of brewer", max_length=25, choices=TYPE_CHOICES)
  city = models.CharField("Brewer's city", max_length=255, blank=True)
  approved = models.BooleanField(default=False)

  def __str__(self):
    return self.name

  def __unicode__(self):
    return self.name

  class Meta:
    ordering = ['name']

And guess what? My problems went away. I feel like an idiot for being foiled by something so simple that I overlooked. It makes sense too because __str__() is used quite a bit in forms where the model instance’s name needs to be magically generated. Without __unicode__() it would cause Django to barf on unicode names, just like it did on me.

Let this be a lesson to you. If you might EVER have ANY unicode text in your model instance’s names, for crap’s sake define __unicode__()!!

Beertraq Beta!

Posted in Uncategorized on December 5th, 2009 by Nick – Be the first to comment

I’m glad to announce that my recent pet project, Beertraq, is now in a (somewhat closed) beta stage! The basic idea is there and functioning, but the extra functionality isn’t done and it’s far from polished. Nonetheless, it’s time to take her for a test drive!

So what is Beertraq, you ask? It’s a way for you to keep track of which beers you’ve tasted, compare those with others, read beer reviews, and most importantly discover new beers to try. I originally got the idea from The Flying Saucer’s UFO Club, where members work toward a goal of drinking 200 different beers. Once they complete the task, they get their name on a plate which gets put on the wall of the bar. The cool part about the UFO Club is that it’s all computerized, using a magstripe card to login at a kiosk in the bar. You can also log in to their website to check your progress and read reviews on there. I figured that if The Flying Saucer can have that system for their bar, I could do the same for the world.

If you’re interested in becoming a BeerTraq beta user, send an email to beertraq (at) beertraq (dot) com with the email address you want to use for your account. All I ask is that you give feedback by filling out issue requests with bugs you find or suggestions you might have.

Intelligent Drink Dispenser – Software Design

Posted in Uncategorized on June 21st, 2009 by Nick – 1 Comment

The other major half of the Intelligent Drink Dispenser project was the software side of things. As with the hardware, there were some things we had to consider when beginning the design of things. What language should we use? Should this be a GUI application or web application? If we go with a GUI application, what operating system should we target?

We decided that since we only had a semester to get everything done, we needed a framework to take care of the more nitty-gritty stuff. We eventually decided to go with the Django web framework, which uses the Python programming language. Python is a language we all knew and Jon and I had used Django in the past. Also, since our ‘final product’ would be highly based on a client-server model, it makes sense to go with a web app since the server can be in a central location with many clients connecting to it.

The most important thing to us was the fact that Django abstracts the database into models for us. No having to mess around with raw SQL, we just run some queries and get our data from the models as if they’re just plain ol’ objects. After some thought, we came up with our models and their relationships:

Django Models

The development of the application was fairly straight-forward. It was just a standard Django app after all. The interesting part was interfacing with the hardware.

If you remember from my post talking about the hardware side, we used an FTDI UM232 USB-to-serial converter. Lucky for us, there’s a Linux kernel module which represents this device as a virtual serial port, which made our jobs a whole lot easier since there’s existing serial libraries for Python (like pyserial). We ended up just writing a couple of functions, one to read the RFID tag from the serial port, and one that takes in a Drink id and then communicates to the microcontroller to pour it. The microcontroller’s fairly dumb, just taking a number and turning that pin on, or turning all of the pins off if a non-valid character is sent, as you can see in the pourDrink function:

def pourDrink(id, serialPort=DEVICE):
  """Pours the drink given by the specified ID"""

  # Seconds per mL of the motors, found experimentally
  # These should be in the database or a config file instead of hardcoded...
  secondsPerML = []
  secondsPerML.append(9.858/350.0)  # Pump 0
  secondsPerML.append(9.858/350.0)  # Pump 1
  secondsPerML.append(6.385/210.0)  # Pump 2

  components = DrinkComponent.objects.filter(drink=id)

  for c in components:
    stock = IngredientStock.objects.filter(ingredient=c.ingredient)
    total = 0

    for s in stock:
      total += s.amount

    if total < c.amount:
      raise UnableToPour("Not enough " + c.ingredient.name + " to pour drink!")

  port = serial.Serial(serialPort, 2400)
  if not port.isOpen():
    raise UnableToPour("Unable to open serial port!")

  for c in components:
    stock = IngredientStock.objects.filter(ingredient=c.ingredient)
    leftToPour = c.amount

    startTime = time.time()

    for s in stock:
      port.write(str(s.slot))
      if leftToPour < s.amount:
        time.sleep(secondsPerML[s.slot]*leftToPour)
        s.amount = s.amount - leftToPour
        s.save()

        break
      else:
        time.sleep(secondsPerML[s.slot]*(s.amount - 30))
        leftToPour = leftToPour - s.amount - 30

        s.amount = 0
        s.save()

    print "Time to pour:" + str(time.time() - startTime)

  port.write("\n")
  port.close()

Not exactly the most precise in terms of pouring accuracy, but it gets the job done as a prototype. As for the rest of the code, there’s not too much else that’s very interesting. I may release the code at some point in the future.