Django community: RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Renewing Let's Encrypt Certificates with NGINX Unit
Recently, I moved the DjangoTricks website and started PyBazaar on servers with Nginx Unit. One thing that was left undone was SSL certificate renewals. Let's Encrypt has special certbot parameters for renewing certificates for websites on Apache or Nginx servers, but they don't work out of the box with the Nginx Unit. In this blog post, I will tell you how to do that. The certificate bundle Nginx Unit doesn't use the fullchain.pem and privkey.pem generated by certbot directly from the location where they were generated. Instead, one has to create a bundle (like bundle1.pem) by concatenating them and then uploading it to the Nginx Unit configuration endpoint. The bash script For that, I created a bash script: #!/usr/bin/env bash SECONDS=0 CRON_LOG_FILE=/var/webapps/pybazaar/logs/renew_certificate.log echo "=== Renewing Letsencrypt Certificate ===" > ${CRON_LOG_FILE} date >> ${CRON_LOG_FILE} echo "Renewing certificate..." >> ${CRON_LOG_FILE} certbot --renew-by-default certonly -n --webroot -w /var/www/letsencrypt/ -m hello@pybazaar.com --agree-tos --no-verify-ssl -d pybazaar.com -d www.pybazaar.com echo "Creating bundle..." >> ${CRON_LOG_FILE} cat /etc/letsencrypt/live/pybazaar.com/fullchain.pem /etc/letsencrypt/live/pybazaar.com/privkey.pem > /var/webapps/pybazaar/unit-config/bundle1.pem echo "Temporarily switching the Unit configuration to a dummy one..." >> ${CRON_LOG_FILE} curl -X PUT --data-binary @/var/webapps/pybazaar/unit-config/unit-config-pre.json --unix-socket /var/run/control.unit.sock http://localhost/config echo "Deleting old certificate from Nginx Unit..." >> ${CRON_LOG_FILE} curl -X DELETE --unix-socket /var/run/control.unit.sock http://localhost/certificates/certbot1 echo "Installing … -
Self-Hosted Open Source - Michael Kennedy
TalkPython to Me Podcast and CoursesHTMX + Django: Modern Python Web Apps, Hold the JavaScript CourseUmamilistmonkOpen Source Software Products for Every Business FunctionElestHigh Availability Percentage CalculationPostHogbtopSponsorMailtrap.io -
Generating Fake Django Model Instances with Factory Boy
As you might know, I am developing PyBazaar, a Python Developer Marketplace. For a project of that scope, I need to create hundreds or thousands of data entries to ensure that everything works as expected. Factory Boy is a tool that allows me to create model instances in batches, and this blog post is about it. The benefits of using Factory Boy By creating a bunch of fake entries, I can achieve the following: Work on list and detail representation and styling. Work on and try functionality like filters, sorting, and pagination. Check and improve performance with loads of data entries. Create dummy data for unit or functional tests. Factory Boy seemed like a pretty complex package, so I want to simplify things and introduce you to all the necessary parts for creating a fake model instances. Model preparation At PyBazaar, I have users with profiles, job offers, and resources that can be faked in batch. The related categories are predefined and don't need to be faked. To make it possible to distinguish between real and fake entries, I added a new boolean field is_fake to all those models that I can create in batch: # For testing and debugging … -
How to Use ModelAdmin with Wagtail CMS v6+
The powerful ModelAdmin feature of Wagtail CMS has been removed as of Wagtail v6. The Wagtail team now encourages the use of SnippetViewSet, which includes advanced features like bulk actions. Here is an official migration guide from ModelAdmin to Snippets. However, if you have extensive custom code … Read now -
Django: An admin extension to prevent state leaking between requests
Here’s a small protection I added to a project a few years ago. I was considering it again since I saw a similar potential bug in a Django middleware. Long live the ModelAdmin instances Django’s admin site is configured by the ModelAdmin class. You register this per model: from django.contrib import admin from example.models import Book @admin.register(Book) class BookAdmin(admin.ModelAdmin): fields = [ "title", "special", ] The @admin.register() decorator calls the AdminSite.register() method, which creates an instance of the ModelAdmin class (which can also be auto-generated): class AdminSite: ... def register(self, model_or_iterable, admin_class=None, **options): ... for model in model_or_iterable: ... # Ignore the registration if the model has been # swapped out. if not model._meta.swapped: ... # Instantiate the admin class to save in the registry self._registry[model] = admin_class(model, self) So, ModelAdmin instances are created once at import time and reused between all requests. That means it’s not safe to use ModelAdmin instance variables to store state because they can affect later requests. (And if you run your project with a threaded WSGI server or ASGI server, ModelAdmin instance variables may be read by concurrent requests!) This may be a surprising revelation if you have come from PHP, which has a … -
Django News - Djangonaut Space 2024 Session 2 - Apr 26th 2024
News Djangonauts Space Session 2 Applications Open! Applications are now open for the next 8-week group mentoring program, where individuals will work self-paced in a semi-structured learning environment. If you want to work with Jeff on Django Packages, he is mentoring a team this session. djangonaut.space Django Developers Survey 2023 Results The results of the Django Developers Survey 2023, which is a collaborative effort between the Django Software Foundation and PyCharm, are in! jetbrains.com 10th anniversary of Django Girls Survey Speaking of surveys, Django Girls and JetBrains have teamed up to celebrate the 10th anniversary of Django Girls with a survey that is complete with prizes. jetbrains.com Updates to Django Today 'Updates to Django' is presented by Raffaella Suardini from Djangonaut Space! Last week we had 9 pull requests merged into Django by 9 different contributors - including 3 first-time contributors! Congratulations to Mohammad Kazemi, Jason K Hall and Eyal Cherevatsky for having their first commits merged into Django - welcome on board! Coming in Django 5.0.5, a bug fix with GeneratedField, preventing crashes when applying migrations, especially those involving the argument db_index=true. Application for Djangonaut Space Open 🚀 I'm thrilled to announce that the second session of Djangonaut Space … -
South: migraciones inversas
Una vez que pruebas las migraciones de bases de datos es muy complicado adaptarse a trabajar sin ellas. Cuando empezamos un proyecto Django uno de los primeros "requisitos" es instalar South para que haga todo este sucio trabajo. Y no todo es bonito... normalmente estás obligado a ejecutar la migración para probar si funciona o no. Y si no funciona, sigues obligado a corregirla y volver a correr otra migración para arreglar la anterior que no funcionaba. Y este proceso puede repetirse varias veces a lo largo del desarrollo de un proyecto, con lo que al final acabas con un número muy alto de migraciones, de las cuales cierta cantidad son parches ínfimos para arreglar cualquier pequeño fallo. Y si a todo esto le sumamos un equipo de trabajo, un repositorio de versiones y todo el flujo de trabajo que conlleva, puede ser una fuente importante de conflictos. South schemamigration --auto --update Imagino que a petición de la gente, en South han pensado en ello y han implementado una sencilla funcionalidad que resuelve todo este entuerto y hace más llevadero tanto el probar los cambios como la resolución de esos pequeños fallos que puedan surgir sin llenar de paja nuestro … -
Django and memcache: clear cache keys
Let's play Django with Memcached. As the great framework Django is, it's so easy to activate any kind of cache in your project. Memcached is one of the options, but you can also work with DatabaseCache, FileBasedCache, LocMemCache, MemcachedCache, DummyCache (a kind of non-cache very useful for devel/test enviroments) or - of course - your own CustomCache if you want. Activating cache It's too easy to activate the cache feature, it's enough to set the preferences in settings, install python-memcached in your enviroment (in case you will use MemcachedCache), and not much more to do. A couple of examples: 1. Basic FileBasedCache settings: # settings.py CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache', } } 2. MemcachedCache settings: # settings.py CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } 3. Depending on the enviroment you can use MemcachedCache and DummyCache: # settings.devel.py CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', } } # settings.production.py CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } Setting the places where cache will act Now that we have our project with a configured kind of cache, we must to say where and when to activate it. There are multiple ways to do it … -
Django: CACHE KEY_PREFIX
Una rápida para acabar el día, después de ponerme a leer la documentación de django.contrib.sitemaps y ver, por enésima vez, que reinventar la rueda es MAL, quise jugar otro poco con Memcached, porque tenía un issue bastante curioso. Con instancias distintas del mismo software (Django) ejecutando varias páginas, todas contra Memcached, las caches se iban solapando de una forma muy divertida. Por ejemplo en la página index (/), la que primero cargaba y guardaba sus datos en memcache, sobreescribía a las demás y todas ofrecían el mismo contenido. Lo mismo con el resto de páginas con url coincidente. Viendo el comportamiento la solución era sencilla, implementar KEY_PREFIX y que cada instsancia tuviera su propia "despensa de datos". Lo que en principio parecía trivial al final se convirtió en varias pruebas porque la documentación no está del todo clara (al menos para mí). Después de varias pruebas, la configuración que ha funcionado adecuadamente ha sido la siguiente, en el archivo settings.py de cada instancia: CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', 'KEY_PREFIX': 'your-custom-prefix_', } } Con cambiar la variable de configuración KEY_PREFIX dentro de la sección CACHES es suficiente, pero fuera de aquí no funcionará, como tampoco lo harán CACHE_PREFIX, … -
DjangoCMS, ventajas e inconvenientes
DjangoCMS es un proyecto que cada día se está volviendo más interesante. Se trata de un gestor de contenidos moderno con un montón de funcionalidades y características programado - obviamente - en Django. Hace menos de 1 mes, el 9 de abril para ser más exactos, ha salido la esperada versión 3.0 y, aunque todavía no la he probado, pinta bastante interesante. Sí he trabajado en varios proyectos con la "antigua" versión 2.4.3 estable y tengo que decir que las sensaciones en general son bastante buenas, aunque como todo, con matices. Es un proyecto relativamente sencillo de instalar y de configurar, cuenta con un montón de características atractivas como la edición live, una completa colección de plugins que permiten extender la funcionalidad del software para casi cualquier cosa y una sencilla personalización a través de placeholders en plantillas o la posibilidad de crear tus propios custom plugins de una manera fácil y rápida. En el otro lado de la balanza tenemos que la documentación no es todo lo completa que debiera, a veces se pega con South, o que es bastante laborioso hacer una contribución al proyecto (curiosamente, una de las operaciones mejor documentadas). En definitiva, si os apetece jugar un rato … -
Django deploy: problems with limited hosting
Some months ago I had to deal with a Symfony2 project in a shared hosting (Spanish article) and now the big next deal is a similar task with Django. The project is almost done and I have the hosting credentials, once I'm in I noticed that there is no chance to configure anything (Apache, WSGI or whatever) so I was a bit lost. Thanks to my Ailalelo's mates (they had lot of experience with this kind of situations) I found the proper configuration. Hosting is django-ready, but the version they're running (1.4.2) is not the best choice, I want to install 1.6.x, the one I have used to develop the project. The other big requirement is virtualenv+pip to retrieve the packages I'm using. Mainly I've solved it with two files, project.cgi and .htaccess. project.cgi The hosting structure is like many others, I have access to a homedir with the following directories: myhome/ logs/ tmp/ www/ cgi-bin/ index.html Before to say Apache what to do with our project, let's install virtualenv and all the requirements, my choice is to put the environment out of the www/ directory: myhome/ env/ logs/ tmp/ www/ cgi-bin/ project/ index.html $ virtualenv env $ . env/bin/activate $ pip install -r www/project/requirements/production.txt Seems to be that apache's mod_cgi will process all the files you put in the cgi-bin directory, … -
Python: Diffing unit tests to keep a copy-pasted code in sync
Copy-paste-tweaking library code feels like a dirty but inevitable programming practice. Often driven by deadlines or other constraints, it seems all projects end up with something copy-pasted in and tweaked for one specific use case. When we find ourselves doing this, it’s essential to consider the long-term maintenance of those copies. After all, “software engineering is programming integrated over time” (see previously). We want to add a defence that alerts us to any relevant upstream changes. But since that is hard to do robustly, it is often omitted. One approach is to maintain a fork, but that is heavy-handed and requires per-release maintenance. In this post, we’ll cover an alternative I recently tried, using a unit test. This test asserts that the diff between the upstream code and our project’s copy-pasted version is constant. The test fails if either version changes, smoothing upgrades and ensuring we consider any further tweaks. A Djangoey example I recently worked on a Django project that heavily extends Django’s admin site. Most of these extensions were done as usual, extending classes or templates as required. However, one case needed a copy-paste-tweak of the upstream “fieldset” template used to render form fields. That tweak looks something … -
Python: Make line number paths with inspect
Many terminals and text editors support what I’ll call “line number paths” of the form <filename>:<lineno>. Opening that path, whether by clicking or passing to a CLI, opens the given file at that line. Python’s inspect module has a couple of functions that can be combined to make such paths, for a given class or function. Here’s the recipe: from inspect import getsourcefile, getsourcelines print(f"{getsourcefile(obj)}:{getsourcelines(obj)[1]}") getsourcefile() returns the file the object is defined in. getsourcelines() returns a tuple, containing the list of source code lines and the first line number, hence the [1] to select just the line number. For example, to make a path for a function in Django: In [1]: from django.utils.html import format_html In [2]: from inspect import getsourcefile, getsourcelines ...: print(f"{getsourcefile(obj)}:{getsourcelines(obj)[1]}") /.../.venv/site-packages/django/utils/html.py:95 I have found this recipe handy a couple of times for batch edits. For example, I recently upgraded django-import-export on a project. Due to an upstream change, I needed to check every subclass of django-import-export’s ModelResource class in the project. I could have searched the code for all such classes, but that can be complicated due to inheritance. Instead, I used class.__subclasses__() to find all subclasses and made “line number paths” for each: In … -
Workbench, the Django-based agency software
Workbench, the Django-based agency softwareI get the impression that there’s a lot of interesting but unknown software in Django land. I don’t know if there’s any interest in some of the packages I have been working on; if not this blog post is for myself only. (Hi)story time As people may know I work at Feinheit, an agency which specializes in digital communication services for SMEs, campaigns for referendums, and website and webapp development. At the time of writing we are a team of about 20-25 communication experts, graphic designers, programmers and project managers. We have many different clients and are working on many different projects at the same time and are billing by the hour1. Last year my own work has been billed to more than 50 different customers. In the early days we used a shared file server with spreadsheet files to track our working hours. Luckily we didn’t often overwrite the edits others made but that was definitely something which happened from time to time. We knew of another agency who had the same problems and used a FileMaker-based software. Their solution had several problems, among them the fact that it became hard to evolve and that … -
Django: Pinpoint upstream changes with Git
Django’s release notes are extensive and describe nearly all changes. Still, when upgrading between Django versions, you may encounter behaviour changes that are hard to relate to any particular release note. To understand whether a change is expected or a regression, you can use Django’s Git repository to search the commits between versions. I often do this when upgrading client projects, at least the larger ones. In this post, we’ll cover Django’s branching structure, determining and searching through those commits, a worked example, and advanced behavioural searching with git bisect. Django’s branching structure Most open source projects use a single main branch, tagged for release when appropriate. However, because Django maintains support for multiple feature versions simultaneously, its branching structure is more complicated. Here’s an example: * main | | * stable/5.0.x | | ⋮ ⋮ |/ | * ⋮ * * stable/4.2.x | | ⋮ ⋮ |/ | * ⋮ There’s a main branch, representing the future version of Django, and stable/<version>.x branches representing released versions (at least, released in alpha). When it is time for an alpha release of a new version, a new stable/<version>.x branch is created from main. Commits are always merged to main. Then, they … -
Django News - [Resend of #228] PyPI Expanding Trusted Publisher Support - Apr 22nd 2024
Introduction Hi everyone, We apologize to anyone who didn't receive the Django News Newsletter Issue #228 last Friday and to anyone who just received a duplicate edition. Issue #229 is a re-send of what everything should have received last Friday. Last week, our newsletter provider had a hiccup, and we estimate that less than 10% of our subscribers received their weekly Friday edition of Django News. We felt terrible that you didn't receive it and that two conference CFPs will have ended before our next newsletter goes out. We decided our best bet was to re-send everyone an updated Monday edition of Django News and apologize again for Friday's mishap. Please note that Wagtail Space US's CFP ends today, April 22nd (hours left), and DjangoCon US's CFP ends Wednesday, April 24th (less than two days left). Jeff and Will Django Newsletter News Don't Miss Out: Last Call for DjangoCon US 2024 Talk Proposals! Have you submitted your talk or tutorial for DjangoCon US 2024, in beautiful Durham, North Carolina, USA? This is your last call to submit a talk or tutorial. The CFP deadline is April 24, 2024, at 12 PM EDT. djangocon.us PyPI: Expanding Trusted Publisher Support PyPI added … -
Django News - PyPI Expanding Trusted Publisher Support - Apr 19th 2024
News Don't Miss Out: Last Call for DjangoCon US 2024 Talk Proposals! Have you submitted your talk or tutorial for DjangoCon US 2024, in beautiful Durham, North Carolina, USA? This is your last call to submit a talk or tutorial. The CFP deadline is April 24, 2024, at 12 PM EDT. djangocon.us PyPI: Expanding Trusted Publisher Support PyPI added GitLab CI/CD, Google Cloud, and ActiveState as Trusted Publishing providers. pypi.org Django Software Foundation DSF Board meeting minutes for April 11, 2024 Here are the DSF Board's meeting minutes for April 11, 2024. djangoproject.com Updates to Django Today 'Updates to Django' is presented by Raffaella Suardini from Djangonaut Space! Last week we had 10 pull requests merged into Django by 5 different contributors - including 1 first-time contributor! Congratulations to Aleksander Milinkevich for having their first commits merged into Django - welcome on board! Coming in Django 5.0.5 (expected May 6th): Resolved a compatibility issue with Python 3.11.9+ and 3.12.3+ when validating email max line lengths with content decoded using the surrogateescape error handling scheme. Resolved a bug in Django 5.0 that makes Model.save() crash when creating a model instance with a GeneratedField and specifying a primary key. Django Newsletter Wagtail … -
Importing Content - Building SaaS #189
In this episode, I built the import view that is needed to allow users to add their own journal entries to JourneyInbox. After completing that, I handled the pull requests from dependabot, then I worked on some quality of life to do better handling with beta user trials. -
Why Django and why not Flask?
Why would someone pick Django over Flask? That’s the question that I got on stream and here is my answer. -
Importing Content - Building SaaS with Python and Django #189
In this episode, I built the import view that is needed to allow users to add their own journal entries to JourneyInbox. After completing that, I handled the pull requests from dependabot, then I worked on some quality of life to do better handling with beta user trials. -
Why Django and why not Flask?
Why would someone pick Django over Flask? That’s the question that I got on stream and here is my answer. -
Octopus Energy - Çağıl Uluşahin Sönmez
Django Software Foundation BoardOctopus EnergyLocal Django CommunitiesDjango London Meetup GroupDjangoCon US 2021: How We Built a Mobile Application Backend with Django in 10 WeeksEuroPython 2023: The coding conventions that make our lives easier Support the ShowLearnDjango.comButtonDjango News newsletter -
Building forms with the Django admin
Building forms with the Django admin The title of this post was shamelessly copied from Jeff Triplett’s post on Mastodon. Why? Many websites need a simple way of embedding forms, for example as a contact form or for simple surveys to collect some data or inputs from visitors. Django’s forms library makes building such forms straightforward but changing those forms requires programming skills and programmer time. Both of them may not be readily available. More importantly, sometimes it’s just nice to give more tools to web publishers. The simple way to build something like this is to use a form builder such as Google Forms, Typeform, Paperform or anything of the sort. Those options work nicely. The downsides are that embedded forms using those services load slowly, look differently, cost a lot or collect a lot of data on users, or all of those options. Because of that there’s still a place for building such functionality locally. If I wanted to use PHP and WordPress I could just use WPForms and call it a day. Since I do not actually want that this blog post is a bit longer. The early days: form-designer One of the first Django-based third party … -
Django News - Open Source Week - Apr 12th 2024
News Python 3.11.9, 3.12.3, and 3.13.0a6 released! This week we saw new Python 3.11.9, 3.12.3, and 3.13.0a6 releases. Django Newsletter PyPI: Malware Distribution and Domain Abuse Domain names used in a malware attack, and how PyPI handled it. pypi.org Updates to Django Today 'Updates to Django' is presented by Velda Kiara from Djangonaut Space! Last week we had 9 pull requests merged into Django by 8 different contributors - including 3 first-time contributors! Congratulations to Lang Tran, us77ipis, and devin13cox for having their first commits merged into Django - welcome on board! Django 5.0.4 has been released which includes the bug fixes: Fixed a crash in Django 5.0 on table aliases and lookups on a GenerateField of the aliased table Fixed a bug in Django 5.0 that caused a migration crash when adding a GeneratedField relying on the __contains or __icontains lookups or using a Value containing a "%". If you're currently on Django 5.0.3, I recommend upgrading to 5.0.4 to benefit from these improvements. We would also like to extend a special recognition to Mariusz Felisiak for being a fellow for the past 5 years. In his final year, his contributions include: Triaged: 602 issues Reviewed/committed: 555 PRs Authored: … -
Weeknotes (2024 week 14)
Weeknotes (2024 week 14)I’m having a bit of a slow week with the easter weekend and a wisdom tooth extraction. I’m recovering quite quickly it seems and I’m glad about it. This weeknotes entry is short and quick. I’m trying to get back into the habit of writing them after a mediocre start this year. 20th Anniversary Celebration of Young Greens Switzerland I have attended the celebration of Young Greens Switzerland. I have been a founding member and have been active for close to ten years. A lot of time has passed since then. It has been great to reminisce about old times with friends and, more importantly, to see how the torch is carried on. Releases blacknoise 0.0.5: blacknoise is an ASGI app for static file serving inspired by whitenoise. It only supports a very limited subset of whitenoise’s functionality, but it supports async. html-sanitizer 2.4.1: The lxml library moved the HTML cleaner into its own package, lxml-html-clean; this release adds support for that. I didn’t know that the HTML cleaner is viewed as being problematic by the lxml maintainers. I’m having another look at nh3 and will maybe switch html-sanitizer’s guts from lxml to nh3 in the future. …