Django community: Community blog posts RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Why you should use the Django admin: 9 tips
This writing is inspired by a comment on Reddit concerning my recent post: “The problem is that everyone I speak to seems to think the opposite - that the admin is super-limited, inflexible and hard to customize.” — andybak on Reddit I’m about to break this prejudice right now. The Django admin is a really brilliant piece of software, which can significantly speed up your development. Here are some tips about the Django admin, which I’ve found to be quite useful. -
Automatic Maintenance Page for Nginx+Django app
If you've used Django with Nginx, you are probably familiar with how to configure the Nginx process group to reverse proxy to a second Gunicorn or uWSGI Django process group. (The proxy_pass Nginx parameter passes traffic through Nginx to Django.)One benefit of this approach is that if your Django process crashes or if you are preforming an upgrade and take Django offline, Nginx can still be available to serve static content and offer some sort of "the system is down" message to users. With just a few lines of configuration, Nginx can be set to automatically display a splash page in the above scenarios.If the Django process running behind the reverse proxy becomes unavailable, a 502 error will be emitted by Nginx. By default, that 502 will be returned to the browser as an ugly error message. However, Nginx can be configured to catch that 502 error and respond with custom behavior. Specifically, if a 502 is raised by Nginx, Nginx can check for a custom html error page document and serve up that document if it exists. If that document does not exist, Nginx can just return the default ugly 502 error message. The Nginx configuration below executes this … -
Row Level Security in Postgres and Django
Postgres keeps introducing new things that pique my attention. One of the latest ones of these is [Row Level Permissions](http://www.postgresql.org/docs/devel/static/ddl-rowsecurity.html), which essentially hides rows that a given database user cannot view. There's a bit more to it than that, a good writeup is at [Postgres 9.5 feature highlight: Row-Level Security and Policies](http://michael.otacoo.com/postgresql-2/postgres-9-5-feature-highlight-row-level-security/). However, it's worth noting that the way Django connects to a database uses a single database user. Indeed, if your users table is in your database, then you'll need some way to connect to it to authenticate. I haven't come up with a nice way to use the Postgres users for authentication within Django just yet. I did have an idea about a workflow that may just work. * Single Postgres User is used for authentication (Login User). * Every Django user gets an associated Postgres User (Session User), that may not log in. * This Session User is automatically created using a Postgres trigger, whenever the Django users table is updated. * After authentication, a `SET SESSION ROLE` (or `SET SESSION AUTHORIZATION`) statement is used to change to the correct Session User for the remainder of the session. Then, we can implement the Postgres Row Level Security … -
reverse, lazy and resolve - Django url-resolvers
Working with urls is a core part of web development. The url-resolver utilities django provides makes working with them just that much easier. Look at using `reverse`, `reverse_lazy`, and `resolve` utility functions to write better idiomatic django.Watch Now... -
Headsupper.io
tl;dr Headsupper.io is a free GitHub webhook service that emails people when commits have the configurable keyword "headsup" in it. Introduction Headsupper.io is great for when you have a GitHub project with multiple people working on it and when you make a commit you want to notify other people by email. Basically, you set up a GitHub Webhook, on pushes, to push to https://headsupper.io and then it'll parse the incoming push and its commits and look for certain things in the commit message. By default, it'll look for the word "headsup". For example, a git commit message might look like this: fixes #123 - more juice in the Saab headsup! will require updating Or you can use the multi-line approach where the first line is short and sweat and after the break a bit more elaborate: bug 1234567 - tea kettle upgrade 2.1 Headsup: Next time you git pull from master, remember to run peep install on the requirements.txt file since this commit introduces a bunch of crazt dependency changes. Git commits that come through that don't have any match on this word will simply be ignored by Headsupper. How you use it Maybe paradoxically, you need to authenticate with … -
Headsupper.io
tl;dr Headsupper.io is a free GitHub webhook service that emails people when commits have the configurable keyword "headsup" in it. Introduction Headsupper.io is great for when you have a GitHub project with multiple people working on it and when you make a commit you want to notify other people by email. Basically, you set up a GitHub Webhook, on pushes, to push to https://headsupper.io and then it'll parse the incoming push and its commits and look for certain things in the commit message. By default, it'll look for the word "headsup". For example, a git commit message might look like this: fixes #123 - more juice in the Saab headsup! will require updating Or you can use the multi-line approach where the first line is short and sweat and after the break a bit more elaborate: bug 1234567 - tea kettle upgrade 2.1 Headsup: Next time you git pull from master, remember to run peep install on the requirements.txt file since this commit introduces a bunch of crazt dependency changes. Git commits that come through that don't have any match on this word will simply be ignored by Headsupper. How you use it Maybe paradoxically, you need to authenticate with … -
Django forms and making datetime inputs localized
tl;dr To change from one timezone aware datetime to another, turn it into a naive datetime and then use pytz's localize() method to convert it back to the timezone you want it to be. Introduction Suppose you have a Django form where you allow people to enter a date, e.g. 2015-06-04 13:00. You have to save it timezone aware, because you have settings.USE_TZ on and it's just many times to store things in timezone aware dates. By default, if you have settings.USE_TZ and no timezone information is in the string that the django.form.fields.DateTimeField parses, it will use settings.TIME_ZONE and that timezone might be different from what it really should be. For example, in my case, I have an app where you can upload a CSV file full of information about events. These events belong to a venue which I have in the database. Every venue has a timezone, e.g. Europe/Berlin or US/Pacific. So if someone uploads a CSV file for the Berlin location 2015-06-04 13:00 means 13:00 o'clock in Berlin. I don't care where the server is hosted and what its settings.TIME_ZONE is. I need to make that input timezone aware specifically for Berlin/Europe. Examples Suppose you have settings.TIME_ZONE == … -
Django forms and making datetime inputs localized
tl;dr To change from one timezone aware datetime to another, turn it into a naive datetime and then use pytz's localize() method to convert it back to the timezone you want it to be. Introduction Suppose you have a Django form where you allow people to enter a date, e.g. 2015-06-04 13:00. You have to save it timezone aware, because you have settings.USE_TZ on and it's just many times to store things in timezone aware dates. By default, if you have settings.USE_TZ and no timezone information is in the string that the django.form.fields.DateTimeField parses, it will use settings.TIME_ZONE and that timezone might be different from what it really should be. For example, in my case, I have an app where you can upload a CSV file full of information about events. These events belong to a venue which I have in the database. Every venue has a timezone, e.g. Europe/Berlin or US/Pacific. So if someone uploads a CSV file for the Berlin location 2015-06-04 13:00 means 13:00 o'clock in Berlin. I don't care where the server is hosted and what its settings.TIME_ZONE is. I need to make that input timezone aware specifically for Berlin/Europe. Examples Suppose you have settings.TIME_ZONE == … -
Django Abstract Base Class - Model Inheritance
Model inheritance is a very useful and powerful feature of django, but used incorrectly it can cause a lot of confusion. Lets go ahead and take a look at some of those. Have you ever been looking through other peoples code and seen a model class Meta with abstract = True? That is the first type of inheritance we are going to look at, abstract base models. There is also multi-table inheritance, proxy models, and multiple inheritance available. Abstract Base Classes In this post we are going to focus on Abstract base classes. This is the easiest type of model inheritance to really understand because it works very much like normal inheritance. In OOP when you inherit from another object you get all of its members plus your own. You can modify those members or leave them the same. Abstract base classes are the same. Here are two example classes class Customer(models.Model): name = models.CharField(max_length=100) email = models.EmailField(max_length=100) address = models.CharField(max_length=100) purchase_history = models.ForeignKey('cart.Invoice') class Staff(models.Model): name = models.CharField(max_length=100) email = models.EmailField(max_length=100) address = models.CharField(max_length=100) bio = models.TextField() position = models.CharField(max_length=20) As you can see these two models are legitimate models with fields, but they do have common elements. In … -
Cyber Monday: 50% off Django book and videos
Are you looking for a good gift for a current or future Django developer? Check out Caktus technical director Mark Lavin's work for O'Reilly: Lightweight Django (book co-written with Julia Elman) Intermediate Django: Build modern, scalable, and maintainable web applications (videos). Both are now 50% off at the O'Reilly site with the discount code CYBER15. -
Comics v2.2.0 released with Django 1.5 support
Version 2.2.0 of my comics aggregator is now released. It features a general upgrade of dependencies, including the move from Django 1.4 to Django 1.5, and a lot of updates to comic crawlers. The Django upgrade was completed months ago and it’s been running my Comics instance since, so it’s about time to get it released before Django 1.6 arrives in a month or two. Regarding the crawler updates, it’s a bit sad to see that many of the crawlers have been broken for months without me or anybody else noticing, but it’s hard to catch some content lacking in the middle of a firehose of similar content. I guess I’ll have to make it a monthly task to look through the crawler status page of my Comics instance and do patch releases with updated crawlers. Check out the project docs for more information about Comics and this release in particular. -
Comics v2.3.0 released with better mobile support
Version 2.3.0 of my comics aggregator is now released. As always, dependencies have been updated, including the routine Django upgrade from Django 1.5 to 1.6, just in time for the upcoming 1.7 release. The largest change this time around is the move from Bootstrap 2 to 3, which includes a refreshed, flatter design and lots of tweaking to make Comics both look good and work nicely on mobile devices, something it didn’t use to do. The dependency overview at requires.io has been a great motivation for doing some maintenance work on Comics. The only dependency left outdated is django-registration, as 1.0 moves to class-based views, which requires some larger changes to my customizations. Thus, the upgrade of django-registration has been deferred together with the related upgrade of my vendorized copy of django-invitation. Most, if not all, of the other dependencies seems to support Python 3 now, though some lack the right Trove classifiers in their PyPI registration, so they are not correctly labeled by requires.io. I found an open pull request for cssmin and a recent commit for django-compressor adding the missing Trove classifiers. I’ve also done my part to improve the Python 3 metadata by sending a pull request … -
Sorting querysets with NULLs in Django
One thing which I’ve found surprisingly hard to do in Django over the years is sort a list of items on a database column when that column might have NULLs in it. The problem is that the default Postgres behaviour is to give NULL a higher sort value than everything else, so when sorting in descending order, all the NULLs appear at the top. This is particularly strange if, say, you want a list of items sorted by most recently updated, and the ones at the top are the ones that have never had an update. If we were writing the SQL directly, we could just add NULLS LAST to the ORDER BY clause, but that would be a really rubbish reason to drop down to raw SQL mode in Django. Fortunately, Django 1.8 has introduced a new feature: Func() expressions. These expressions let you run SQL-level functions like LOWER(), SUM() etc. and annotate your queryset with a new column containing the result. I didn’t want to run a database function, but what I discovered was that it is really easy to subclass and make your own Func() expression, giving you access to a template for generating SQL! The base … -
Moya Template Language
Moya's template language is a spiritual successor to Django, and Jinja templates. It borrows a number of constructs from both, and adds a few of its own. There is a slight difference in the syntax in that variables are substituted with ${variable} rather than {{ variable }}, but tags still use the familiar {% tag %} syntax. Template languages are generally quite extensible, so there is probably nothing that Moya template can do that Django / Jinja can't (via a plugin or extension), but there are a few things which are I think are more elegant in Moya's templates language (and built-in). I'm going to talk about a few of them in this post. The Attrib Tag How often have you written code like this? <div id="{{ article_id }}" class="{% if type %}{{ type }}{% endif %}{% if active %} active{% endif %}{% if highlight %} highlight{% endif %}"> {{ content }} </div> This code renders a div with an id attribute and a few optional classes. It is easy to follow, but verbose. It's also a little error prone to write; we have to be careful about the whitespace between the classes, or we could end up generating the … -
Fixing SSL certificate chains
This blog post applies when the following two cases are true: Your browser does not complain about your https site. Everything seems fine. Some other tool does complain about not finding your certificate or not finding intermediate certificates. What is the problem? So: your browser doesn't complain. Let's see a screenshot: Examples of the errors you can see Some examples of complaining tools. First curl: $ curl https://api.letsgxxxxxxx curl: (60) SSL certificate problem: Invalid certificate chain More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option. curl has the right error message: Invalid certificate chain. Let us look at wget: $ wget https://api.letsgxxxxxx --2015-11-23 10:54:28-- https://api.letsgxxxxx Resolving api.letsgxxxxxx... 87.233.157.170 Connecting to … -
How To Create Installable Django Packages
What I mean by an "installable Django package": a reusable component that can be shared across Django projects, allowing us to combine our own efforts with others. Some examples include: django-test-plus django-crispy-forms dj-stripe dj-spam Ever want to quickly create a similarly installable Django package to submit to PyPI and Django Packages? One that goes beyond the basics described in the Django tutorial? Specifically, a package that includes: Test runner so you don't need a example/test project (Although those can be useful). The important configuration in place: Travis, editorconfig, gitignore, etc. The important documentation in place: Readme, License, Read the Docs-ready Sphinx docs, etc. Static files ready to go. A base DTL/Jinja2 template ready to go. All those other fiddly bits not included in django-admin.py startapp that are hard to remember. Well, here's how I do it. Introducing cookiecutter-djangopackage First, get Cookiecutter. Trust me, it's awesome: $ pip install cookiecutter Now run it against this repo: $ cookiecutter https://github.com/pydanny/cookiecutter-djangopackage.git You'll be prompted to enter some values. Enter them. Then an installable Django package will be built for you. Warning: app_name must be a valid Python module name or you will have issues on imports. Enter the new package (in my case, … -
How To Create Installable, Reusable Django Packages
What I mean by an "installable Django package": a reusable component that can be shared across Django projects, allowing us to combine our own efforts with others. Some examples include: django-test-plus django-crispy-forms dj-stripe dj-spam Ever want to quickly create a similarly installable Django package to submit to PyPI and Django Packages? One that goes beyond the basics described in the Django tutorial? Specifically, a package that includes: Test runner so you don't need a example/test project (Although those can be useful). The important configuration in place: Travis, editorconfig, gitignore, etc. The important documentation in place: Readme, License, Read the Docs-ready Sphinx docs, etc. Static files ready to go. A base DTL/Jinja2 template ready to go. All those other fiddly bits not included in django-admin.py startapp that are hard to remember. Well, here's how I do it. Introducing cookiecutter-djangopackage cookiecutter-djangopackage is a Cookiecutter template for creating reusable Django packages. Using it is easy: First, get Cookiecutter. Trust me, it's awesome: $ pip install cookiecutter Now run it against this repo: $ cookiecutter https://github.com/pydanny/cookiecutter-djangopackage.git You'll be prompted to enter some values. Enter them. Then an installable Django package will be built for you. Warning: app_name must be a valid Python module name … -
How To Create Installable, Reusable Django Packages
name : Django Package Ecosystem: cookiecutter-djangopackage align : center alt : Django Package Ecosystem: cookiecutter-djangopackage target : https://www.pydanny.com/how-to-create-installable-django-packages.html What I mean by an \"installable Django package\": a reusable component that can be shared across Django projects, allowing us to combine our own efforts with others. Some examples include: django-test-plus django-crispy-forms dj-stripe dj-spam Ever want to quickly create a similarly installable Django package to submit to PyPI and Django Packages? One that goes beyond the basics described in the Django tutorial? Specifically, a package that includes: Test runner so you don't need a example/test project (Although those can be useful). The important configuration in place: Travis, editorconfig, gitignore, etc. The important documentation in place: Readme, License, Read the Docs-ready Sphinx docs, etc. Static files ready to go. A base DTL/Jinja2 template ready to go. All those other fiddly bits not included in django-admin.py startapp that are hard to remember. Well, here's how I do it. Introducing cookiecutter-djangopackage cookiecutter-djangopackage is a Cookiecutter template for creating reusable Django packages. Using it is easy: First, get Cookiecutter. Trust me, it's awesome: $ pip install cookiecutter Now run it against this repo: $ cookiecutter https://github.com/pydanny/cookiecutter-djangopackage.git You'll be prompted to enter some values. Enter them. Then … -
Installing Wagtail
Wagtail has become a very popular CMS in the last year. Start with this video to see how to get it up and running for your project, and get content on the homepage.Watch Now... -
Introducing Moya Techblog, a Blogging Engine for Coders and Photographers
I've had a blog on my vanity domain for nearly a decade now. For the last 6 years, it has been powered by Django Techblog, which I wrote out of my frustration with syntax highlighting plugins in Wordpress. Techblog has happily served my blog those 6 years, with only minor hiccups when I half-heartedly ported the code to the latest Django. There was nothing terribly wrong with Django Techblog; it had multiple blogs, tags, search etc., but there were some annoyances that I didn't have the motivation to do much about. The custom markup system I used was clever, but I would often forget the syntax! The support for images was rudimentary and the single-threaded comment system wouldn't notify me of replies. So fast forward 6 years and the time is right to build a new blog system to fix the old niggles. This time around I had same requirements for syntax highlighting in both posts and comments, with a new requirement to be able to manage and display photographs, while supporting the same multi-blog and feed URLs. Moya Tech Blog The new blog engine running my blog is Moya Tech Blog. Posts and comments use markdown (by default), which … -
Nginx proxying to nginx: getting gzip compression to work
At work we use gunicorn as our wsgi runner. Like many, gunicorn advises you to run the nginx webserver in front of it. So on every server we have one or more websites with gunicorn. And an nginx in front. Nginx takes care, of course, of serving the static files like css and javascript. Some gzipping of the results is a very, very good idea: server { listen 80; server_name my.great.site; ... gzip on; gzip_proxied any; gzip_types text/css text/javascript text/xml text/plain application/javascript application/x-javascript application/json; .... } Two notes: The default is to only gzip html output. We also want javascript and json. So you need to configure gzip_types. (I copy-pasted this from one of my config files, apparently I needed three different javascript mimetypes... Perhaps some further research could strip that number down.) gzip_proxied any tells nginx that gzipping is fine even for proxied requests. Proxied requests? Yes, because we have a lot of servers and all external traffic first hits our main nginx proxy. So: we have one central server with nginx that proxies requests to the actual servers. So: nginx behind nginx: server { listen 443; server_name my.great.site; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect … -
Looking for an experienced Python Developer
My client, WildFoundry, is looking for an experienced Python developer to join us. We work in the field of IoT, and you will get to work with a variety of really cool technologies. Here's the job description: Job Description WildFoundry is seeking a senior Python web application developer on a 8 month contract to help us in the development of the dataplicity Internet-of-Things platform (dataplicity.com). You would be expected to work from your home or own office most of the time and very high quality candidates based in Slovakia, Poland and the United Kingdom will be considered. This is an unbeatable opportunity to work from home, earn excellent rates and join in with fast growing projects. Our web application runs on a combination of Python and django, and we’re really pushing the boundaries of what we can do with both of them. You will be challenged. You’ll be playing with everything from Amazon and Linode services to embedded PCs, and a bunch of new web technologies. You’ll be writing daemons, UI for django apps, code for embedded systems, websockets. We are seeking a top calibre developer well regarded in the community. If you’ve contributed code to OSS apps or have … -
A real Python "wat"
A few weeks ago I went through and explained the various items in a list of “Python wats” — behaviors of Python which seemingly made no sense. Calling them “wats” is a bit of a stretch in most cases, though, because most of them were simply consequences of fairly reasonable design decisions in how Python or its standard libraries work, but presented in ways which obscured what was actually going on. Lest I be accused of ... Read full entry -
A real Python "wat"
A few weeks ago I went through and explained the various items in a list of “Python wats” — behaviors of Python which seemingly made no sense. Calling them “wats” is a bit of a stretch in most cases, though, because most of them were simply consequences of fairly reasonable design decisions in how Python or its standard libraries work, but presented in ways which obscured what was actually going on. Lest I be accused of ... Read full entry -
Buildout 2.5.0 has much nicer version conflict reporting
We use buildout for all our django projects. Nothing wrong with pip, but buildout has extension possibilities build-in (for creating directories, installing user crontabs, local development checkouts and many more) that are quite helpful. And it works better when you need to use system packages (gdal, mapnik, etc). One area where buildout could use some improvement was the version conflict reporting. Let's say you have pinned django to 1.6.6 (old project that I'll upgrade to 1.8 this week) and you add the django debug toolbar. This is the error you get: The constraint, 1.6.6, is not consistent with the requirement, 'Django>=1.7'. While: Updating django. Error: Bad constraint 1.6.6 Django>=1.7 First things first. An easy one is to improve the wording of the message: While: Installing django. Error: The requirement ('Django>=1.7') is not allowed by your [versions] constraint (1.6.6) Now... so there is some package that requires at least django 1.7. But which one? Buildout did not tell you. Which would mean you'd have to grep in all your requirements' sub-requirements for which package actually requires the offending "django>=1.7"... I've now added some internal logging that stores which package required which dependency. After an error occurs, the list is searched for …