Skip to content

Instantly share code, notes, and snippets.

@chadgh
Last active August 29, 2015 14:16
Show Gist options
  • Save chadgh/2fffa4a8f57c09edbb51 to your computer and use it in GitHub Desktop.
Save chadgh/2fffa4a8f57c09edbb51 to your computer and use it in GitHub Desktop.
Trello to Django

What?!?!

Sometimes it is easier to design and talk about models in a more abstract easy to change way. After that design phase is finished, it is nice to have something to take your designs and give you boilerplate code. This does that for Django when models are specified in a specific style in Trello. An example board https://trello.com/b/iPHi7eQz/my-django-models.

Assumptions

  • py-trello==0.1.6 is installed
    • py-trello has a bug that is easily fixed, edit the env/lib/python2.X/site-packages/trello/__init__.py line 577. Change it from self.due = json_obj.get('due', '')[:10] to if json_obj.get('due', ''): self.due = json_obj.get('due', '')[:10]
  • Environment variables are set; TRELLO_KEY, TRELLO_SECRET, TRELLO_TOKEN

Trello Syntax

  • Each list that starts with "Model:" will be turned into a Django model. All other syntax is based on the cards in those lists.
  • All cards are created as attributes/fields in the Django model, unless they have a label 'ignored'.
  • The name of the card is the name of the field in the model.
  • For relationships the name of the card should be the field name followed by a '>' followed by the name of the model that is linked. Adding a 'link' label also is important. Ex. author > Author
  • Card descriptions should contain the Django model field name (CharField, TextField, etc).
  • If you want to set other attributes on the Django field specify them in the description of the card as well after the field type followed by colon, and colon separated. Ex. CharField:max_length=255:default='blah'
  • The default field is CharField(max_length=255).
  • For relationships, the description of the card works the same way, but the first property after the type should be the related_name of the relationship. Ex ForeignKey:books. Other properties can then be specified after that, colon separated.
  • If you want to specify choices for a field, create a checklist in trello for that card, call it 'choices' and specify the choices as checklist items.
  • You can also use a label called 'optional', to specify optional fields. This will set null=True and blank=True for fields with this label.
#!/usr/bin/env python
import sys
from os import environ
from trello import TrelloClient
def slug(text):
return text.strip().replace(' ', '_').lower()
def make_model(li_model):
model_name = li_model.name.split(':')[1]
model = ["class {}(models.Model):".format(model_name)]
model.append(' """Django model representing a {}"""'.format(model_name))
for card in li_model.list_cards():
card.fetch()
labels = [l['name'] for l in card.labels]
optional = 'optional' in labels
if 'ignore' in labels:
continue
model_type = 'models.CharField'
args = ['max_length=255']
name = card.name
link_model = None
if '>' in card.name:
name, link_model = [n.strip() for n in card.name.split('>')]
if card.description:
args = []
info = card.description.split(':')
model_type = 'models.{}'.format(info.pop(0))
if 'link' in labels:
args = [link_model, 'related_name="{}"'.format(info.pop(0))]
for arg in info:
args.append(arg)
if optional:
args.append('null=True')
args.append('blank=True')
if card.checklists:
for checklist in card.checklists:
if checklist.name == 'choices':
choices = ['("{}", "{}")'
.format(slug(i['name']), i['name'])
for i in checklist.items]
args.append('choices=({})'.format(', '.join(choices)))
model_args = ', '.join(args)
model.append(' {} = {}({})'.format(name, model_type, model_args))
return "\n".join(model)
if __name__ == '__main__':
trell = TrelloClient(environ['TRELLO_KEY'],
environ['TRELLO_SECRET'],
environ['TRELLO_TOKEN'])
board_id = sys.argv[1]
board = trell.get_board(board_id)
model_lists = [l for l in board.open_lists() if l.name.startswith('Model:')]
output = ["from django.db import models"]
for li in model_lists:
output.append(make_model(li))
print "\n\n\n".join(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment