I keep hearing people saying they use Token auth because they think Django's
default session-based auth won't work with their Vue/React/whatever Single Page
Application (SPA).
This has always baffled me, beyond assuming people are
cargo culting something.
Also I've recently had interactions with someone I deeply respect, who also
seemed to feel Django's docs on handling authentication with a SPA were
lacking.
After writing my recent rant about token authentication, I realised there was
more to say on the subject.
Not all tokens are created equal, so I feel it's important for people to
understand the differences.
Here's a quick summary of some of the common token types, and their relative
strengths and weaknesses.
Recently a friend commented on how Django might do more to support SPA
applications, notably by having built-in support for authentication using JWTs.
This is not a new question, and recently I've been discussing with someone on
IRC about JWT support in Django that was not tied to
Django REST Framework.
I have frequently helped people on IRC having issues supporting token based
auth in their APIs. But all too often they can't explain why they're using
token auth or what problems it solve for them, just that they read somewhere it
was needed. (Or worse, their manager demanded it without justification.)
Note: This post is still a Work In Progress.
I am posting it now to help people with what I have, and seek feedback and
further input.
Recently a few people have been asking about managing dynamic numbers of
FormSets in
Django.
When we look at how Admin handles inlines we see Django can handle this
already.
Anyone who's been following my blog may have noticed it recently moved home,
and got a complete redesign.
This all happened because of my decisions to dogfood my own static site
generator.
A what, now?
Whilst working on my toy static site generator
gilbert, I decided I wanted it to use a
plugin pattern, so you could add new content types just by installing their
packages.
This would require some way for my code to automatically find all the related
packages, import them, and register their content type sub-classes.
But how?
One of my long time fascinations has been with data compression. I've read a
lot about it, tried to keep up with modern techniques, but never really written
much usable code.
Recently I decided, partly as an exercise in remaining fluent in C, I'd try to
re-implement one of the simplest algorithms I know. I used this method almost
20 years ago to compress payloads for a tiny embedded board which had 256kB RAM
and 128kB ROM.
The algorithm.
Some years ago, I adapted the work of a coworker and released it as
django-classy-settings
, a way to define Django settings using a class,
allowing a clean and easy way to derive local / production settings from a
common base, and opening the way to allowing composition, too.
Recently I was faced with a similar problem at my current job, though not using
Django this time.
Another big difference is my current job is using Python3.6 (and eager to move
to 3.7 ASAP), opening other opportunities.
In a previous post I wrote
a Vanilla JS function for parsing all the current cookies. Since then a couple
of things have happened:
- I realised it was not safe
- JS in browsers got better [and I got better at it]
It was not safe in as much as it parsed the cookie value once and retained the
value. If you were, for instance, using a SPA, Django might update the CSRF
token at any point, making your value stale. So instead, I've updated the
function to get just one value, and perform parsing on each call.
So, 4 years ago [already??] I wrote a post about a shortcut to getting "User
registration with verification email", using very little code by leveraging the
password reset machinery built into Django.
Since then, of course, Django has moved on... and recently, the auth views were
rewritten as class-based views, which changes the game entirely.
As a result, I've committed to providing here an updated version of the
previous post.
Those who've been reading my older posts may remember I showed how you could
use Enum and IntEnum as a cleaner way to declare const-type values for choices
lists in Django fields.
That solution never felt comfortable to me, because Enum values aren't simple
values.
So after some playing around, and a brief look over the enum.py in python 3.5,
I've come up with the following:
I've recently started teaching myself an interesting language I discovered on
the LLVM project page : Pony
Projects
First, I tried rewriting keyster - a
simple Key/Value store that talks over UDP.
So, I saw a post recently about Build an API under 30 lines of
code
using Flask.
I started wondering what it would take to do the same in Django.
The two main tools we're going go use are JsonResponse
and ModelForm
.
Whilst it is theoretically possible, I've yet to see a single server-side web
framework that is MVC.
"Oh, pshaw!", I hear you say, "But {framework of choice} says it is! So it
must be!"
Yeah, and MySQL says it's a good DBMS...
So, we've all needed a choices
list in Django at one time or another, right?
And from the docs we see the example code:
YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
)
I was recently helping someone who was trying to learn about building web
sites, and was trying to avoid learning too many things at once, so opted to
avoid JS libraries for now.
As the discussion progressed, they ran into Django's Cross Site Request
Forgery protection which
stumped them.
So, as I was about to link them to the part of the docs that shows how to add
the CSRF token from the cookie to your headers, I realised it all assumes
you're using jQuery.
Serialisers are increasingly important now that most web apps are just APIs for
the JavaScript to consume.
Serialisers help to reduce your living code objects into simpler types that can
be encoded in your serialisation format [typically JSON]. After all, JSON has
no date or time types, no classes, etc.
In the Django world, modern REST API libraries separate their Serialiser from
the views, and go to great lengths to make them easy to configure, simple to
use, and fast. They also support returning your "deflated" data into live code
objects.
This comes up a lot in #django ... and the solution is [as many are with
Django] much simpler than people assume.
Frequently I see people reach for formsets, in the mistaken conclusion that
formsets are for operating on related models. The sad part is that formsets
rely on the same functionality that the proper solution relies on, but the
seeker does not see it.
Somewhere people get the idea that for a single <form> submission, they
can only use a single Form class... but the formset should show that that's not
true; it uses multiple forms from the one submission.
We've all had to write a search form at some point. Beyond simple cases, you
reach for the big guns, like haystack, et al.
But what about when it's just something simple? What if you want to, for
instance, let people search your blog posts?
In django, that can be done simply with:
Django provides many decorators for use throughout your project. They can be
great time savers, and mastering them can help you DRY your code considerable.
However, they often confuse people as to how they work, or how to write their
own.
In this post I plan to walk through an example of building up a simple
decorator that tests if the user has a specific permission, and if not
returning a 403 Forbidden response.
Decorator basics.
Every so often (quite frequently, actually) you'll get someone in #django
begging for help trying to integrate some app that promises the world ... at
least, as far as it concerns user registration and profiles.
Update:
A couple of people pointed out the original version would end up requiring the user to enter their email twice.
I've now amended the code so the password_reset view's work is now done in the registration CreateView.
This makes the view a little more complicated, but the URLs and user workflow much simpler.
The thing is, now that we have custom User models, doing this is easier than
ever before - yes, even including email verification.
I was recently helping someone with the seemingly easy task of getting a list
of related sub-models. This was working with a "tree" structure, where the
base model had a ForeignKey to itself.
Whilst django-model-utils and django-polymorphic provide solid implementations
for this, I have derived my own solution and tuned it up.
This solution only works properly if there is only ever one sub-class for a
given base class instance. Otherwise, it may behave contrary to expectations.
Let the battle begin!
In Django, using the session is just so EASY! There it is on request, behaving
like a dict, just being all easy to use.
But sometimes, you're actually better off using cookies.
DRY fields
So, your app is growing nicely, but you find yourself repeating the same field definition in a bunch of models. The models themselves have nothing to do with each other, so an abstract base class isn't a fit, but at various points you want, say, prices to always be the same configuration of DecimalField, or titles to always allow the same size.
So, you could sub-class the fields to produce your own pre-configured fields, but sometimes you want to vary them a little... this price is nullable, that title has help_text, and so on.
Conventions, not Rules
As many newcomers to Python discover, a lot of things they've lived with as
rules in other languages [such as public/private members] ... and,
conversely, some things they're accustomed to as conventions are now rules
[like indenting].
Now, Django continues its history of embracing Pythonic ideals when it comes to
filenames. Many frameworks are very strict about what goes where ... in almost
all cases, Django couldn't care less.