Django community: RSS
This page, updated regularly, aggregates Community blog posts from the Django community.
-
Testing Django with Cypress, how nice!
When I discovered Cypress in 2017 my life as a developer changed. I was not afraid to write functional tests anymore, and since then I applied this tool to any web framework I worked with. In particular, I've been working almost exclusively with Django these days, and even if JavaScript does not fare so well in Python developers circle, when it comes to testing a Django/JavaScript project my tool of choice is always Cypress. In this post I share a couple of recipes for testing Django with Cypress, with a focus on the authentication flow. Testing Django login with Cypress As suggested in the Cypress documentation, you may want to test the authentication flow of a web application no more than once with the UI. This means you create a single test somewhere, where you check your login page: describe("Login", () => { before(() => { cy.fixture("users.json").as("mockedUsers"); }); it("Can login through the UI", function () { cy.visit("/login/"); cy.get("input[name='username']").type(this.mockedUsers[0].fields.email); cy.get("input[name='password']").type("dummy_password"); cy.get("form").submit(); cy.getCookie("sessionid").should("exist"); }); }); As for the fixtures, you can use the same data from Django dumpdata, aply saved in cypress/fixtures/fixture_name.json. Testing Django login without the UI So far so good for the first login test. What if you now need … -
RobotFramework, Chromedriver and Docker
One of my team implemented [RobotFramework](https://robotframework.org) support for automated browser testing of our platform a while ago. At the time, we were using [Codeship](https://codeship.com) Basic, and I built a [helper](https://schinckel.net/2020/05/27/django-and-robot-framework/) to run a robot test suite within a tox environment. It was all good, because `chromedriver` and all it's dependencies were already installed. But time passes, and we needed to move to Codeship Pro. Which has some neater features, but required me to build docker images for everything. We already use docker for deployment, but I didn't really want to build a bunch of distinct images just for testing that re-implemented the same stuff that we have in our deployment images. Even just appending new stuff to them means that things could turn out to be a pain in the arse to manage. And getting chromedriver installed into a docker image is not neat. I did find a [docker image that just has an instance of chromedriver](https://github.com/RobCherry/docker-chromedriver/blob/master/Dockerfile), and exposes that. But getting that to work with robot was still a bunch of work. After much experimentation, I was able to get the connections between everything to work. First, we need to have the chromedriver container running: {% highlight bash %} … -
RobotFramework, Chromedriver and Docker
One of my team implemented [RobotFramework](https://robotframework.org) support for automated browser testing of our platform a while ago. At the time, we were using [Codeship](https://codeship.com) Basic, and I built a [helper](https://schinckel.net/2020/05/27/django-and-robot-framework/) to run a robot test suite within a tox environment. It was all good, because `chromedriver` and all it's dependencies were already installed. But time passes, and we needed to move to Codeship Pro. Which has some neater features, but required me to build docker images for everything. We already use docker for deployment, but I didn't really want to build a bunch of distinct images just for testing that re-implemented the same stuff that we have in our deployment images. Even just appending new stuff to them means that things could turn out to be a pain in the arse to manage. And getting chromedriver installed into a docker image is not neat. I did find a [docker image that just has an instance of chromedriver](https://github.com/RobCherry/docker-chromedriver/blob/master/Dockerfile), and exposes that. But getting that to work with robot was still a bunch of work. After much experimentation, I was able to get the connections between everything to work. First, we need to have the chromedriver container running: {% highlight bash %} … -
Update value only if present
We have a bunch of integrations with external systems, and in most of these cases we are unable to use Oauth, or other mechanisms that don't require us to store a username password pair. So, we have to store that information (encrypted, because we need to use the value, rather than just being able to store a hashed value to compare an incoming value with). Because this data is sensitive, we do not want to show this value to the user, but we do need to allow them to change it. As such, we end up with a form that usually contains a username and a password field, and sometimes a URL field: {% highlight python %} class ConfigForm(forms.ModelForm): class Meta: model = ExternalSystem fields = ('username', 'password', 'url') {% endhighlight %} But this would show the password to the user. We don't want to do that, but we do want to allow them to include a new password if it has changed. In the past, I've done this on a per-form basis by overridding the `clean_password` method: {% highlight python %} class ConfigForm(forms.ModelForm): class Meta: model = ExternalSystem fields = ('username', 'password', 'url') def clean_password(self): return self.cleaned_data.get('password') or self.instance.password … -
Update value only if present
We have a bunch of integrations with external systems, and in most of these cases we are unable to use Oauth, or other mechanisms that don't require us to store a username password pair. So, we have to store that information (encrypted, because we need to use the value, rather than just being able to store a hashed value to compare an incoming value with). Because this data is sensitive, we do not want to show this value to the user, but we do need to allow them to change it. As such, we end up with a form that usually contains a username and a password field, and sometimes a URL field: {% highlight python %} class ConfigForm(forms.ModelForm): class Meta: model = ExternalSystem fields = ('username', 'password', 'url') {% endhighlight %} But this would show the password to the user. We don't want to do that, but we do want to allow them to include a new password if it has changed. In the past, I've done this on a per-form basis by overridding the `clean_password` method: {% highlight python %} class ConfigForm(forms.ModelForm): class Meta: model = ExternalSystem fields = ('username', 'password', 'url') def clean_password(self): return self.cleaned_data.get('password') or self.instance.password … -
Django News - Wagtail in the news - Dec 18th 2020
News Announcing the Location for PyCon US 2022/2023 PyCon US 2022 and 2023 will be in Salt Lake City, Utah. blogspot.com Wagtail 2.11.3 release notes Wagtail 2.11.3 includes four bug fixes and one upgrade consideration to look at before you upgrade. wagtail.io Events Wagtail Documentation Sprint We're running a two-day sprint, focused on Wagtail's documentation, and we'd love you to come. It will be on January 7th and 8th 2021 and will take place in Torchbox's offices in the UK (depending on what's safe by then), as well as remotely. google.com Articles Django Session-based Auth for Single Page Apps A look at how to authenticate Single-Page Applications (SPAs) with Django session-based authentication. Suitable for a frontend built with React/Vue/Angular/etc. testdriven.io Introducing django-version-checks by Adam Johnson Notes on the recently released django-version-checks package and why it came to be. adamj.eu 12 Days of Performance by REVSYS An oldie but a goodie. revsys.com Understanding Django: Middleware Do You Go? Another in Matt Layman's series on Understand Django, this is a deep look at middleware. mattlayman.com Useful Flake8 Plugins for Python Linting This is a nice introduction to Flake8 and many useful plugins. dev.to Design Articles Pattern Lab goes Django Torchbox recently released … -
Empty States - Building SaaS #83
In this episode, I returned to the onboarding flow and start to polish some of the extra pages. We filled the pages with special copy and a call to action to each page to help customers be successful. I started with the pages that displays the school years. We added a chunk of template from the onboarding process that asks the user to create a school year. I modified the template chunk to make it fit in the context of the page. -
Why is the Django Framework Suitable for Web Development?
Choosing a web development framework is challenging. But for most companies, the Django web framework is a popular choice. It is versatile, powerful, and supports Machine Learning development. A Django web development company builds scalable applications for enterprises of all shapes and sizes. The Django framework architecture... The post Why is the Django Framework Suitable for Web Development? appeared first on BoTree Technologies. -
Middleware Do You Go?
In the previous Understand Django article, we covered the built-in auth system. That article gave you a chance to see the User model, ways to login users with Django’s authentication tools, and the features that make the authorization controls work. In that topic, middleware came up as an integral component. Now we’re going to learn more about middleware and its function within a Django project. From Browser To DjangoURLs Lead The WayViews On ViewsTemplates For User InterfacesUser Interaction With FormsStore Data With ModelsAdminister All The ThingsAnatomy Of An ApplicationUser AuthenticationMiddleware Do You Go? -
Django Session-based Auth for Single Page Apps
This article looks at how to add session-based authentication to a Single-Page Application (SPA) powered by Django and React. -
Wagtail modeladmin and a dynamic panels list
Wagtail has the modeladmin module in contrib which allows you to edit any Django model through the Wagtail admin interface. Unfortunately it's not very flexible, the code calls the get_edit_handler method on the admin class and the panels property of the model can only be a list. In one project I have a base model that many other models are derived from and wanted to build the panels dynamically. The code below shows how I did it. I chose to break the Wagtail convention and defined the admin fields on the admin class, but I get the additional fields from the model itself. It's somewhat messy, but it's my mess. Raw from wagtail.admin.edit_handlers import FieldPanel from wagtail.admin.edit_handlers import MultiFieldPanel from wagtail.admin.edit_handlers import ObjectList from wagtail.contrib.modeladmin.options import ModelAdmin class DynamicPanelMixin: def get_edit_handler(self, instance, request): return ObjectList(self._get_panels(instance)) def _get_panels(self, instance): return [ *self._get_head_panels(instance), MultiFieldPanel( self._get_multi_panels(instance), heading="Collapsed", classname="collapsible collapsed", ), ] def _get_head_panels(self, instance): panels = [ FieldPanel("foo"), ] return panels + getattr(instance, "head_panels", []) def _get_multi_panels(self, instance): panels = [ FieldPanel("bar"), ] return panels + getattr(instance, "multi_panels", []) # class MyModelAdmin(DynamicPanelMixin, ModelAdmin): # pass -
Introducing django-version-checks
It can be tricky to ensure all the environments that your project runs on use the same versions of Python, PostgreSQL, and other external dependencies. Often development, CI, and cloud environments have different configuration systems, making them hard to keep in sync. And coordinating between all your team members to upgrade their local environments can be complicated, as upgrade emails or instant messages get forgotten if they are away on holiday, working on other projects, etc. And using the wrong versions of external dependencies can lead to hard-to-debug errors, wasting time to find such a simple fix. I’ve solved this problem several times on different projects over the years with custom Django system checks. These can tell you early in Django’s startup process the environment has the incorrect versions. Today I’ve released a package containing configurable versions of such checks, django-version-checks. You activate the checks by specifying the allowed versions in PEP 440 specifiers, the same format that pip uses.s For example, imagine you are using the cutting-edge versions of Python and MariaDB. To ensure all environments use these versions, or compatible bug fix releases, you can install django-version-checks and add this to your settings file: VERSION_CHECKS = { "mysql": … -
Django News - Issue 53 - Dec 11th 2020
News 2021 DSF Board Election Results Thank you to our outgoing DSF Board Members: Frank Wiles (President), James Bennett (Secretary), and Sayantika Banik. We appreciate your years of service to the community. The 2021 returning Board of Directors are Anna Makarudze (Vice President/President-elect), William Vincent (Treasurer), Kátia Nakamura, and Aaron Bassett. New board members are Žan Anderle, Mfon Eti-mfon, and Chaim Kirby. djangoproject.com Wagtail 3rd Party Packages A new dedicated home for Wagtail 3rd party packages. Learn more in the official blog post documenting the move. wagtail.io Python 3.9.1 is now available, together with 3.10.0a3 and 3.8.7rc1 Python 3.9.1 is the first version of Python to support macOS 11 Big Sur natively on Apple Silicon. blogspot.com Python Software Foundation News: Announcing the PSF Diversity and Inclusion Work Group blogspot.com Events PyCascades Grant application opens! If you would like to attend the conference but do not have the funds to purchase a ticket, the application deadline is December 19, 2020 (AoE). pycascades.com Articles Exhaustiveness Checking with Mypy by Haki Benita Haki Benita walks us through exhaustiveness checking with mypy. hakibenita.com How To Set Up Tailwind CSS In Django On Heroku A step-by-step guide to configuring Tailwind on a Heroku-hosted Django app. … -
Introducing django-linear-migrations
If you’ve used Django migrations for a while, you may be familiar with this message: $ python manage.py migrate CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0002_longer_titles, 0002_author_nicknames). To fix them run 'python manage.py makemigrations --merge' This appears when the migration history for one of your apps branched to have two “leaf nodes”, that is, two final migrations. The simplest example has our first initial migration, then two conflicting second migrations: +--> 0002_author_nicknames / 0001_initial +--| \ +--> 0002_longer_titles This happens quite naturally when developing two features for same app, both with migrations. The solution Django suggests is to create a merge migration with makemigrations --merge. This creates another migration in our history that depends on the last two: +--> 0002_author_nicknames +-+ / \ 0001_initial +--| |--> 0003_merge \ / +--> 0002_longer_titles +----+ This merge migration tells Django “it’s fine to run both branches of migrations and end up here”. This is a simple solution, and avoids modification of the exisiting migrations. But it has a number of drawbacks. First, it’s a fix after the fact. You need to encounter the “Conflicting migrations detected” error before you step in and create the merge migration. This is … -
Customer Feedback - Building SaaS #82
In this episode, I worked on feedback from my primary customer. We fixed a couple of issues that she reported, then moved on to more of the onboarding flow. Before getting to the code, we chatted about ways to learn to code. I linked to a popular book, Automate the Boring Stuff with Python, and some good web tutorials for learning Django. The first bit of customer feedback that I worked on was to add a back link from a course details to get a user back to the grade level that holds the course. -
Jazzband - Matthias Kestenholz
Matthias’s Personal SiteJazzband on GitHubfeincms may still be relevantOfficial Django MerchandiseFeinheitMatthias on Githubfeincms3Official Django merchandiseSupport the ShowThis podcast is a labor of love and does not have any ads or sponsors. To support the show, consider purchasing or recommending a book from LearnDjango.com or signing up for the free weekly Django News newsletter. -
Maps with Django (part 1): GeoDjango, SpatiaLite and Leaflet
A quickstart guide to create a web map with the Python-based web framework Django using its module GeoDjango, the SQLite database with its spatial extension SpaliaLite and Leaflet, a JavaScript library for interactive maps. -
Exhaustiveness Checking with Mypy
Mypy is an optional static type checker for Python. It's been around since 2012 and is gaining traction even since. One of the main benefits of using a type checker is getting errors at "compile time" rather than at run time. Exhaustiveness checking is a common feature of type checkers, and a very useful one! In this article I'm going to show you how you can get mypy to perform exhaustiveness checking! Playing cards are also useful for explaining enumeration types...Photo by Daniel Rykhev Table of Contents Exhaustiveness Checking Enumeration types Type Narrowing in Mypy The Future Bonus: Exhaustiveness Checking in Django Exhaustiveness Checking Say you have a system to manage orders. To represent the status of an order, you have the following enum: import enum class OrderStatus(enum.Enum): Ready = 'ready' Shipped = 'shipped' You also have the following code to process an Order: def handle_order(status: OrderStatus) -> None: if status is OrderStatus.Ready: print('ship order') elif status is OrderStatus.Shipped: print('charge order') When the order is ready, you ship it; and when it's shipped, you charge it. A few months go by and your system becomes big. So big in fact, that you can no longer ship orders immediately, and you … -
A Vue.js workflow for Django
Pairing JavaScript tooling like Vue CLI and create-react-app with traditional frameworks like Django is notoriously hard. There isn't a "right way" to do this stuff, but thanks to Vue.js configurability you can at least choose where to put the resulting bundle. In the following notes I present a Vue.js workflow for Django which I found out working well for most use cases. Configuring Vue.js Suppose you have a Django app named billing, and you want to make the frontend of this app a single-page. You also want to serve this single-page from within Django's umbrella to use Django built-in authentication. First off, we generate a Vue project inside the app with Vue CLI, let's say in repo-root/billing/billing_spa Then, we set up vue.config.js, in the same Vue project folder, with the following configuration: const path = require("path"); const outputDir = path.resolve(__dirname, "../static", "billing"); module.exports = { publicPath: process.env.VUE_APP_STATIC_URL, outputDir, indexPath: path.resolve( outputDir, "../../templates/", "billing", "index.html" ) }; With this configuration we say to Vue: put static assets inside billing/static/billing put the index.html inside billing/templates/billing Django is highly configurable in regard to static files and template structure, but this setup respects Django expectations on where to find static files and templates. Your … -
How To Set Up Tailwind CSS In Django On Heroku
How can you set up Tailwind CSS for your Django app on Heroku? In this article, we’ll see how I did exactly that recently. I have a side project that uses Tailwind CSS. To get started quickly, I used the version from a Content Delivery Network (CDN) as Tailwind describes in the documentation. This worked fine initially while I got my project started, but the CDN version is huge (around 3MB). -
Django News - 🎂 Django News Newsletter turns one-year-old! - Dec 4th 2020
Introduction Django News Newsletter feedback This newsletter turns one year old this week. We (Jeff & Will) would like feedback on what you like and what could be improved for year #2. Please take a moment to respond on either the Django Forum or the Google Form. djangoproject.com News Django bugfix release: 3.1.4 The 🥧 release is out with 7 different bugfixes. djangoproject.com Pip 20.3 Release (heads-up for potential disruption) The pip we have been warning you about for six months is out and you will more than likely run into a few issues. python.org Help share the future of Django Girls Django Girls is looking for advisory board members for 2021. djangogirls.org Rebuilding the PSF - Q4 2020 Fundraiser The Python Software Foundation is running its Q4 fundraiser and is raising money to offset any potential 2021 revenue shortfalls. python.org Events Announcing PyCon US 2021 PyCon US goes virtual again for 2021. blogspot.com Articles Don't Panic: Kubernetes and Docker tl;dr Docker will still run in your Kubernetes cluster. kubernetes.io Django Best Practices: Referencing the User Model There are 3 different ways to access the built-in User model. This post covers each method with recommendations on the best approach. learndjango.com … -
Finishing Onboarding - Building SaaS #81
In this episode, I completed the last form that completes the last step on my Django app’s onboarding process. We built up the view, wrote the tests, and worked through the templates changes. I started with a discussion of what the onboarding flow does and what was left. I needed to make a form that creates a task for a course. For the first chunk of code, we added some tests to cover all the scenarios that are important for the view. -
Django: Change or translate the app name in the admin menu
Let’s say I have a Django app users. The admin menu shows this as category Users. That’s ok, but if the website users speak another language I want this name translated. Also I’m not necessarily using Users as name in the admin menu as section name, but can use something more descriptive. Website Users, as example. -
Finding Performance Issues In Python Web Apps with Sentry
Introduction Earlier, we have seen couple of articles here on finding performance issues1 and how to go about optimizing them2. In this article, lets see how to use Sentry Performance to find bottlenecks in Python web applications. The Pitfalls A common pitfall while identifying performance issues is to do profiling in development environment. Performance in development environment will be quite different from production environment due to difference in system requirements, database size, network latency etc. In some cases, performance issues could be happening only for certain users and in specific scenarios. Replicating production performance on development machine will be costly. To avoid these, we can use APM tool to monitor performance in production. Sentry Performance Sentry is widely used Open source error tracking tool. Recently, it has introduced Performance to track performance also. Sentry doesn't need any agent running on the host machine to track performance. Enabling performance monitoring is just a single line change in Sentry3 setup. import sentry_sdk sentry_sdk.init( dsn="dummy_dsn", # Trace half the requests traces_sample_rate=0.5, ) Tracing performance will have additional overhead4 on the web application response time. Depending on the traffic, server capacity, acceptable overhead, we can decide what percentage of the requests we need to … -
Exhaustiveness Checking with Mypy
Mypy is an optional static type checker for Python. It's been around since 2012 and is gaining traction even since. One of the main benefits of using a type checker is getting errors at "compile time" rather than at run time. Exhaustiveness checking is a common feature of type checkers, and a very useful one! In this article I'm going to show you how you can get mypy to perform exhaustiveness checking! Playing cards are also useful for explaining enumeration types...Photo by Daniel Rykhev Table of Contents Exhaustiveness Checking Enumeration types Type Narrowing in Mypy The Future Bonus: Exhaustiveness Checking in Django Exhaustiveness Checking Say you have a system to manage orders. To represent the status of an order, you have the following enum: import enum class OrderStatus(enum.Enum): Ready = 'ready' Shipped = 'shipped' You also have the following code to process an Order: def handle_order(status: OrderStatus) -> None: if status is OrderStatus.Ready: print('ship order') elif status is OrderStatus.Shipped: print('charge order') When the order is ready, you ship it; and when it's shipped, you charge it. A few months go by and your system becomes big. So big in fact, that you can no longer ship orders immediately, and you …