Why Django Sucks, and How we Can Fix it

52
Why Django Sucks And how we can fix it

Transcript of Why Django Sucks, and How we Can Fix it

Page 1: Why Django Sucks, and How we Can Fix it

Why Django Sucks

A n d h o w w e c a n f i x i t

Page 2: Why Django Sucks, and How we Can Fix it

My Qualifications

Started using Django in 2006

Not a core developer

Early active involvement in Django apps

Helped out with the initial form of Pinax

Co-host of DjangoDose

Day job: mochigames.com

Page 3: Why Django Sucks, and How we Can Fix it

What Sucks?

Apps

Generic Foreign Keys

Memory usage and performance

Settings

Exclusionary establishment

Bad batteries

Page 4: Why Django Sucks, and How we Can Fix it

Apps

It’s a mess

Page 5: Why Django Sucks, and How we Can Fix it

My typical app discovery lifecycle“I need to let users upload avatars.”

“Cool! Looks like there’s an app called django-avatar.”

“Now I want to add an extra domain-specific field to each avatar.”

:(

Fork

Page 6: Why Django Sucks, and How we Can Fix it

The model problem

Apps which provide models are inflexible

Providing abstract model classes introduces configuration headache

Page 7: Why Django Sucks, and How we Can Fix it

Primary Key Assumptions

Everyone basically assumes PositiveIntegerField primary keys.

UUID primary keys have lots of advantages.

Especially for the user table.

To achieve this, you have to fork pretty much everything.

Page 8: Why Django Sucks, and How we Can Fix it

Field naming

{{ entry.body }}, {{ item.description }}

{{ post.content }}, {{ comment.comment }}

Different field names have emerged for the same “kind” of attribute.

To reuse template code, we’re forced to monkeypatch model code.

Page 9: Why Django Sucks, and How we Can Fix it

Classes to the rescue?

Wildly differing ideas on how to implement class-based views.

Little to no consensus on this front.

Where do you put customized view subclasses?

Trades complexity and configuration for flexibility.

Page 10: Why Django Sucks, and How we Can Fix it

Put customizations where?

Seriously, where do we put customized view subclasses?

Convention is in urls.py, but that will quickly become overloaded.

Create a new app? Now we have an extra level of indirection, making code less clear.

Page 11: Why Django Sucks, and How we Can Fix it

TODO: Tests & docs

Seriously, most apps suck.

P.S. I’m guilty of this too.

Page 12: Why Django Sucks, and How we Can Fix it

Base Problem

The app as the sole level of abstraction is too broad.

Page 13: Why Django Sucks, and How we Can Fix it

Generic Foreign Keys

Wrong solution

Page 14: Why Django Sucks, and How we Can Fix it

Generic Foreign Keys

Good for flexibility

Bad for configuration

Used way too much as configuration

Favorites, Ratings, Voting, Messages, etc.

These things should usually have concrete foreign keys.

Page 15: Why Django Sucks, and How we Can Fix it

Memory & Performance

Going the wrong way

Page 16: Why Django Sucks, and How we Can Fix it

Case Study: Blog App (Of Course)

Disclaimer: Lies, damn lies, and benchmarks.

Illustrative only, take my numbers with a grain of salt.

Kept everything the same except for the Django version. Completely the same code.

Page 17: Why Django Sucks, and How we Can Fix it

Memory

180

182.75

185.5

188.25

191

1.0 1.1 1.2

Memory (MB)

Page 18: Why Django Sucks, and How we Can Fix it

Performance

0

20

40

60

80

1.0 1.1 1.2

Requests/Second

Page 19: Why Django Sucks, and How we Can Fix it

In Effect

It’s gotten slower in every release since 1.0.

Every release has a larger memory footprint than the last one.

Page 20: Why Django Sucks, and How we Can Fix it

Monolithic Settings

Page 21: Why Django Sucks, and How we Can Fix it

Monolithic Settings

Can’t change it on a per-request basis in a thread-safe way

Makes multi-tenancy nearly impossible

Causes headaches for deployment

Prevents composition of Django projects

It’s essentially a global, which is something Django tends to shy away from*

Page 22: Why Django Sucks, and How we Can Fix it

Others get this right

Flask has an App object.

CherryPy has an Application object.

web.py has an application object.

Werkzeug encourages a make_app function.

Page 23: Why Django Sucks, and How we Can Fix it

Exclusionary Establishment

People feel un-welcome

Page 24: Why Django Sucks, and How we Can Fix it

Exclusionary Establishment

People have made real-life friends through the community. Being tight-knit is good!

But it’s bad if you feel you can’t join in.

Why would someone think the establishment is exclusionary?

Page 25: Why Django Sucks, and How we Can Fix it

django.contrib isn’t

No application ever created by a non-core-developer has ever been added to django.contrib.

It’s not really “contrib”, is it?

This sends a signal to the community.

Page 26: Why Django Sucks, and How we Can Fix it

django-core

Did you know that there’s a private mailing list just for the Django core developers?

Why does this exist?

What kinds of discussions go on in there?

Shouldn’t Django-related discussions happen out in the open?

This sends a signal to the community.

Page 27: Why Django Sucks, and How we Can Fix it

Case Study:Alex Gaynor

How is he still not a core developer?

He’s been contributing to Django in every way he can for over 3 years.

This sends a signal to the community.

Page 28: Why Django Sucks, and How we Can Fix it

Case study: truncatechars

It’s a tiny feature that’s been requested many, many times, by many different people.

It’s properly gone through all the right steps.

Every time someone brings it up again, it gets snarky responses from core team. Stays in Design Decision Needed.

This sends a signal to the community.

Page 29: Why Django Sucks, and How we Can Fix it

Badteries

Page 30: Why Django Sucks, and How we Can Fix it

Badteries: Auth

django.contrib.auth is unbelievably inflexible.

first_name, last_name is culturally limited.

Admin is coupled to user (is_staff.)

Integer primary key

get_profile() is inelegant and inefficient.

No way to use secure cookie instead of session.

Page 31: Why Django Sucks, and How we Can Fix it

Badteries: Webdesign

Web designers care about a lot more than just lorem ipsum.

Page 32: Why Django Sucks, and How we Can Fix it

Badteries: Databrowse

Despite what the docs say, it’s not very new anymore (3 years old.)

Doesn’t support pagination.

Why is this even in Django?

Page 33: Why Django Sucks, and How we Can Fix it

OK I’ll stop hatin’

I say these things because I care :)

Page 34: Why Django Sucks, and How we Can Fix it

How can we make it better?

Introduce focused abstraction layers

Late-binding configuration option

Monitor performance and memory changes

Rip off Flask

Kill contrib

Add more core developers

Move to a DVCS

Page 35: Why Django Sucks, and How we Can Fix it

Must apps suck?

This is the toughest one.

Page 36: Why Django Sucks, and How we Can Fix it

Must apps suck?

If the app as the sole level of abstraction is too broad...

Then we need to make abstractions with a narrower focus.

These narrower abstractions could be built on top of the current app abstraction.

Page 37: Why Django Sucks, and How we Can Fix it

Idea: Use models, don’t expose them

class Message(models.Model): from_user = models.ForeignKey(User) to_user = models.ForeignKey(User) msg = models.CharField(max_length=128)

Page 38: Why Django Sucks, and How we Can Fix it

Idea: Use models, don’t expose them

class Message(object):

def create(self, from_user, to_user, msg, **kw): # ...

def inbox(self, user, start=0, stop=20): # ...

def outbox(self, user, start=0, stop=20): # ...

Page 39: Why Django Sucks, and How we Can Fix it

Idea: Use models, don’t expose them

Now we can pass extra keywords to create().

We can swap out the model to include extra fields, etc.

We can swap out the implementation to use a different storage layer.

We can expose it over the network as a service layer.

Page 40: Why Django Sucks, and How we Can Fix it

FeinCMS

http://bit.ly/feincms

Example of a more focused abstraction, built on top of existing abstractions.

Page.create_content_type(RichTextContent)

Page.register_templates(...)

Page.register_extensions('navigation', 'titles')

Page 41: Why Django Sucks, and How we Can Fix it

Late Binding FKs

In models.py:

class Favorite(models.Model): item = LazyForeignKey(‘fave’) user = ForeignKey(User) date = DateTimeField(default=utcnow)

In settings.py:

LAZY_FKS = {‘fave’: ‘pages.models.Page’}

Page 42: Why Django Sucks, and How we Can Fix it

Late Binding FKs

This way we don’t need to use GenericFK

Still get the flexibility of attaching to whichever content object we want

Disadvantage: more configuration necessary, but it’s not too onerous.

Any app that Django provides should use these, to set the example.

Page 43: Why Django Sucks, and How we Can Fix it

Performance / Memory

Set up a performance and memory “test suite”, graphed over time, show it prominently.

Great start: http://github.com/jacobian/djangobench

Every patch already requires docs, tests, code.

Now it should require docs, tests, code, impact justification.

Page 44: Why Django Sucks, and How we Can Fix it

Performance / Memory

Provide mechanisms to shut of unused Django machinery

USE_I18N is a good example

USE_MAIL, USE_VALIDATION, and more?

Page 45: Why Django Sucks, and How we Can Fix it

Monolithic Settings

Flask (http://bit.ly/flask) gets this really, really right.

Let’s just rip it off wholesale.

You create an app object instance, and configure that object instance.

Page 46: Why Django Sucks, and How we Can Fix it

Flask

>>> app = Flask(__name__)>>> app.config['DEBUG'] = True>>> app.config.from_object('myapp.dev_settings')>>> app.config.from_envvar('SETTINGS')

# SAME INTERPRETER! MULTITENANCY!

>>> app2 = Flask(__name__)>>> app2.config['DEBUG'] = False>>> app2.config.from_object('myapp.prod_settings')

Page 47: Why Django Sucks, and How we Can Fix it

Kill Contrib

pip is good now.

Users are likely going to use pip on their first sit-down anyway (e.g. South)

If it doesn’t make sense to split it out, then call it like it really is: a core app.

Core apps: Sessions, Auth (not Admin, split that out)

Page 48: Why Django Sucks, and How we Can Fix it

Kill Contrib

We could release updates to the admin without releasing Django!

Each app could have different committers.

It would foster innovation in the community.

Might have to start “blessing” apps officially.

Page 49: Why Django Sucks, and How we Can Fix it

Add more core devs

“So, my recommendation (which surely is a turn-around of my *own* attitude in the past) is to give out more commit privileges sooner.”- Guido van Rossum

http://mail.python.org/pipermail/python-dev/2010-July/102306.html

Page 50: Why Django Sucks, and How we Can Fix it

Add more Core Devs

We have releases now, vast majority of people don’t run off of trunk.

Trunk can break sometimes and it’s not the end of the world.

Django’s bigger problem now isn’t quality control, it’s lack of participation.

Solution for this is to loosen the reigns a bit, and to add more core developers.

Can name 5 developers off the top of my head who should be considered.

Page 51: Why Django Sucks, and How we Can Fix it

Switch to Git/GitHub

Commit bit would be less important.

Much easier to do experimental branches.

Easier for people to stay up to date on what’s going on.

Frankly, marketing.

Page 52: Why Django Sucks, and How we Can Fix it

Throw Tomatoes Now

Questions?

Comments?