Planet Python
eGenix.com: Python Meeting Düsseldorf - 2024-10-02
The following text is in German, since we're announcing a regional user group meeting in Düsseldorf, Germany.
Das nächste Python Meeting Düsseldorf findet an folgendem Termin statt:
02.10.2024, 18:00 Uhr
Raum 1, 2.OG im Bürgerhaus Stadtteilzentrum Bilk
Düsseldorfer Arcaden, Bachstr. 145, 40217 Düsseldorf
- Detlef Lannert:
pyinfra als Alternative zu Ansible - Marc-André Lemburg:
Rapid web app development with Panel - Detlef Lannert:
Low-cost-Objekte als Alternativen zu Dictionaries? - Charlie Clark:
Editieren von ZIP Dateien mit Python
Wir treffen uns um 18:00 Uhr im Bürgerhaus in den Düsseldorfer Arcaden.
Das Bürgerhaus teilt sich den Eingang mit dem Schwimmbad und befindet
sich an der Seite der Tiefgarageneinfahrt der Düsseldorfer Arcaden.
Über dem Eingang steht ein großes "Schwimm’ in Bilk" Logo. Hinter der Tür
direkt links zu den zwei Aufzügen, dann in den 2. Stock hochfahren. Der
Eingang zum Raum 1 liegt direkt links, wenn man aus dem Aufzug kommt.
>>> Eingang in Google Street View
Das Python Meeting Düsseldorf ist eine regelmäßige Veranstaltung in Düsseldorf, die sich an Python Begeisterte aus der Region wendet.
Einen guten Überblick über die Vorträge bietet unser PyDDF YouTube-Kanal, auf dem wir Videos der Vorträge nach den Meetings veröffentlichen.Veranstaltet wird das Meeting von der eGenix.com GmbH, Langenfeld, in Zusammenarbeit mit Clark Consulting & Research, Düsseldorf:
Das Python Meeting Düsseldorf nutzt eine Mischung aus (Lightning) Talks und offener Diskussion.
Vorträge können vorher angemeldet werden, oder auch spontan während des Treffens eingebracht werden. Ein Beamer mit HDMI und FullHD Auflösung steht zur Verfügung.(Lightning) Talk Anmeldung bitte formlos per EMail an info@pyddf.de
KostenbeteiligungDas Python Meeting Düsseldorf wird von Python Nutzern für Python Nutzer veranstaltet.
Da Tagungsraum, Beamer, Internet und Getränke Kosten produzieren, bitten wir die Teilnehmer um einen Beitrag in Höhe von EUR 10,00 inkl. 19% Mwst. Schüler und Studenten zahlen EUR 5,00 inkl. 19% Mwst.
Wir möchten alle Teilnehmer bitten, den Betrag in bar mitzubringen.
AnmeldungDa wir nur 25 Personen in dem angemieteten Raum empfangen können, möchten wir bitten, sich vorher anzumelden.
Meeting Anmeldung bitte per Meetup
Weitere Informationen finden Sie auf der Webseite des Meetings:
https://pyddf.de/
Viel Spaß !
Marc-Andre Lemburg, eGenix.com
Zato Blog: Enterprise Python: Integrating with Salesforce
Salesforce connections are one of the newest additions to Zato 3.2, allowing you to look up and manage Salesforce records and other business data. To showcase it, the article will create a sample Salesforce marketing campaign in a way that does not require the usage of anything else except for basic REST APIs combined with plain Python objects, such as dicts.
If you have not done it already, you can download Zato here.
Basic workflowThe scope of our works will be:
- Creating Salesforce credentials for our integration project
- Defining a Salesforce connection in Zato
- Authoring a service that will map input data to the format that Salesforce expects
- Creating a Zato REST channel that will be invoked through curl during tests
- Testing the integration
To be able to create as connection to Salesforce in the next step, we need a few credentials. There is a full article about how to prepare them and this section is the gist of it.
In runtime, based on this information, Zato will obtain the necessary authentication and authorization tokens itself, which means that you will only focus on the business side of the integrations, not on the low-level aspects of it.
The process of obtaining the credentials needs to be coordinated with an administrator of your organization. To assist in that, the screenshots below explain where to find them.
The credentials are:
- Username and password
- Consumer key
- Consumer secret
The username and password are simply the same credentials that can be used to log in to Salesforce:
Consumer key and secret are properties of a connected app - this is a term that Salesforce uses for API clients that invoke its services. If you are already an experienced Salesforce REST API user, you may know the key and secret under their aliases of "client_id" and "client_secret" - these are the same objects.
Note that when a connected app already exists and you would like to retrieve the key and secret, they will be available under the "View" menu option for the app, not under "Edit" or "Manage".
Defining a Salesforce connection in ZatoWith all the credentials in place, we can create a new Salesforce connection in Zato Dashboard, as below.
Authoring an integration service in PythonAbove, we created a connection definition that lets Zato obtain session tokens and establish connections to Salesforce. Now, we can create an API service that will make use of such connections.
In the example below, we are using the POST REST method to invoke an endpoint that creates new Salesforce campaigns. In your own integrations, you can invoke any other Salesforce endpoint, using any REST method as needed, by following the same pattern, which is, create a model with input fields, build a Python dict for the request to Salesforce, invoke it and map all the required from the response from Salesforce to that which your own service returns to its own callers.
Note that we use a datamodel-based SimpleIO definition for the service. Among other things, although we are not going to do it here, this would let us offer definitions for this and other services.
# -*- coding: utf-8 -*- # stdlib from dataclasses import dataclass # Zato from zato.server.service import Model, Service # ########################################################################### if 0: from zato.server.connection.salesforce import SalesforceClient # ########################################################################### @dataclass(init=False) class CreateCampaignRequest(Model): name: str segment: str # ########################################################################### @dataclass(init=False) class CreateCampaignResponse(Model): campaign_id: str # ########################################################################### class CreateCampaign(Service): class SimpleIO: input = CreateCampaignRequest output = CreateCampaignResponse def handle(self): # This is our input data input = self.request.input # type: CreateCampaignRequest # Salesforce REST API endpoint to invoke - note that Zato # will add a prefix to it containing the API version. path = '/sobjects/Campaign/' # Build the request to Salesforce based on what we received request = { 'Name': input.name, 'Segment__c': input.segment, } # .. create a reference to our connection definition .. salesforce = self.cloud.salesforce['My Salesforce Connection'] # .. obtain a client to Salesforce .. with salesforce.conn.client() as client: # type: SalesforceClient # .. create the campaign now .. sf_response = client.post(path, request) # .. build our response object .. response = CreateCampaignResponse() response.campaign_id = sf_response['id'] # .. and return its ID to our caller. self.response.payload = response # ########################################################################### Creating a REST channelNote that we assign HTTP Basic Auth credentials to the channel. In this manner, it is possible for clients of this REST channel to authenticate using a method that they are already familiar which simplifies everyone's work - it is Zato that deals with how to authenticate against Salesforce whereas your API clients use the ubiquitous HTTP Basic Auth method.
Testing
The last step is to invoke the newly created channel:
$ curl http://api:password@localhost:17010/api/campaign/create -d '{"name":"Hello", "segment":"123"}' {"campaign_id":"8901Z3VHXDTebEJWs"} $That is everything - you have just integrated with Salesforce and exposed a REST channel for external applications to integrate with!
More resources➤ Python API integration tutorial
➤ What is an integration platform?
➤ Python Integration platform as a Service (iPaaS)
➤ What is an Enterprise Service Bus (ESB)? What is SOA?
Quansight Labs Blog: Numpy QuadDType: Quadruple Precision for Everyone
Quansight Labs Blog: Polars Plugins: let's make them easier to use
Python⇒Speed: Beyond multi-core parallelism: faster Mandelbrot with SIMD
What do you do when computation is too expensive?
Recently I’ve had a brilliant business idea: Mandelbrot-as-a-Service! Instead of companies calculating their own fractals, I will do it for them, freshly calculated in the cloud, with no work on their part. And by using cloud computing, I will be able to scale to the no-doubt vast number of customers who will be paying for my ingenious new service.
I have two goals:
- Speeding up results: The faster I can return fractals, the happier my customers will be.
- Reducing costs: If I can pay my cloud provider less for computing, my profits will go up!
Unfortunately, since I will only be selling freshly calculated and warm-from-the-CPU Mandelbrots, I can’t rely on caching.
What would you do in this situation?
One obvious approach is parallelism: threading or multiprocessing. This will speed up results, so it’s definitely worth doing, but it won’t reduce my costs. If we use 10 cores instead of 1 core, the service will return results ten times faster, but we’ll have to pay approximately 10× as much, since we’ll be using 10× larger instances.
However, if we can figure out how to speed up calculations on a single core, this will contribute to both our goals. We’ll both get faster results, compounded by any multi-core processing, and reduce compute costs.
In this article we will:
- Quickly go over a standard Mandelbrot implementation, written in Rust.
- Discuss why it can be tricky to optimize the Mandelbrot algorithm on a single CPU core.
- Demonstrate how you can in fact do so, by using masked SIMD operations.
- Trivially add on multi-core parallelism, using Rust’s Rayon library.
- PROFIT!
Mike C. Fletcher: Interesting Memory Leak with Python 3.12 for PyOpenGL-accelerate
So I'm currently trying to figure out why the PyOpenGL 3.12 test suite is failing. There's a particular test that looks for VBO memory leakage and it looks loosely like this:
for i in range(100):
create_a_vbo_and_delete_it()
calculate_total_process_memory()
assert_no_leak()
which shouldn't ever lose more than a few bytes (limit is set to 200 for this test, but it doesn't lose even one normally). This passes fine on python2.7 through 3.11, but on 3.12 the first 75 iterations leak nothing, then on the 76th iteration (always the 76th) iteration there is a substantial memory leak (100s of KB) and then memory usage goes flat again.
My first guess is that there's something in the 3.12 JIT compiler that looks for e.g. 75 iterations, then does lots of analysis and caching and uses the 100s of KBs of RAM to track the behaviour. I can "fix" the test by reducing the iterations below 75, but that doesn't really address the underlying issue of the test, which is that it's using whole-system memory as a proxy for "did this local function leak RAM". Guess I need to find a better "does some RAM leak" test.
Update: always 75th iteration observation is *only* when run with just the single test. When run in the main test suite, the JIT seems to kick in much earlier (likely because of other tests exercising the same paths). That means it's likely to start failing as more tests are added, which reinforces the need to find a better test method.
The Python Coding Blog: The Python Coding Stack’s New Look
The Python Coding Stack has a new look. Here it is:
The Stack has been growing steadily as a standalone publication, separate from The Python Coding Book and The Python Coding Place, and now it has its own identity.
It offers a very different and unique perspective on Python programming, often with a narrative style.
If you’ve not read articles on The Stack yet, have a look at some of the most recent ones, or the top 5.
The post The Python Coding Stack’s New Look appeared first on The Python Coding Book.
Ned Batchelder: Changelog philosophy
I playfully quipped about changelogs, and Sumana Harihareswara thoughtfully responded with Changelogs and Release Notes. I agree with her on some things, and disagree on others.
My point with the meme was that people should put effort into a hand-crafted description of what has changed in each release of their product. It should be focused on what users need to know, and not include internal changes, which can be found in the git commits or pull requests. It’s easy to publish a list of commits or pull requests and call it a changelog, but it’s not that helpful to your users trying to understand what has changed for them. That was the point of the meme.
But Sumana raised the stakes, explaining why projects should produce two hand-crafted descriptions. The first is a changelog which mentions every non-trivial change. The second are release notes which should be user-focused with more details.
I liked the reasons Sumana gave:
- Release notes can include project-level information that doesn’t correspond to a particular change in a release. Maybe you started a new discussion forum, or there’s a shift in maintainer attention, plans for upcoming work, and so on.
- If the release notes are user-focused, then the changelog can be more comprehensive, giving people a fuller picture of the work that goes into producing the project. This can pull back the curtain, helping people understand the inner workings of the project and perhaps find a way to help out.
My problem with separating the changelog and release notes is that I have limited energy to produce them, and perhaps more importantly, people have limited attention to read them. For my projects, I opt instead for a middle ground: my changelogs lean more toward Sumana’s ideal of release notes. They are hand-written, focused on what users of the project need to know, and do not include things like build changes and refactorings.
For large projects like Python and Linux, there are many maintainers and many types of information, so it makes sense to have multiple views of “what’s changed.” For single-maintainer projects, it feels like too much. I applaud people who can do it, but I don’t think I can, and I won’t expect it from others.
Ultimately, each project has to decide for themselves how to balance the effort and the benefit. They know their audience(s), and what resources they have to do the work. Open source is already difficult, the last thing I want to do is add a giant SHOULD to a project.
There’s an inexact nested ratio at work in projects: Most users (say 90%) will only consume, you will never hear from them. You hear from the remaining 10%, but only 10% of those will do something you consider a contribution. For widely used projects like coverage.py, I think the ratio might be more like 1% of 1% instead of 10% of 10%. How does this affect your communication approach? You could look at it two ways: either write for the audience you have (focus on the 90%), or write for the audience you want (focus on the 10%).
In my changelogs now, for fixes I try to describe the bad thing that used to happen and any important changes in behavior. For features, I link to the new docs. I include links to issues and pull requests, and I name the contributors who helped.
So I guess my approach is to write changelogs for the 90%. But I like Sumana’s idea of making the full picture of maintainence more visible to people, so I’m thinking about how to add that without changing the essential character of my changelog. Perhaps something at the end summarizing the changes that aren’t yet mentioned, with a link to the git history? I’m not sure I can automate collecting that information, but I’ll have to play with it.
Real Python: Quiz: Syntactic Sugar: Why Python Is Sweet and Pythonic
Test your understanding of Python’s most common pieces of syntactic sugar and how they make your code more Pythonic and readable.
Take this quiz after reading our Syntactic Sugar: Why Python is Sweet and Pythonic tutorial.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Real Python: Quiz: Python 3.13: Cool New Features for You to Try
In this quiz, you’ll test your understanding of Python 3.13: Cool New Features for You to Try. By working through this quiz, you’ll review the key updates and improvements in this version of Python.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Kushal Das: Updated blog theme after many years
One of the major reason of using static blogging for me is to less worry about how the site will look like. Instead the focus was to just write (which of course I did not do well this year). I did not change my blog's theme for many many years.
But, I noticed Oskar Wickström created a monospace based site and kindly released it under MIT license. I liked the theme, so decided to start using it. I still don't know HTML/CSS but managed to change the template for my website.
You can let me know over mastodon what do you think :)
Zero to Mastery: Python Monthly Newsletter 💻🐍
Python Morsels: The string split method in Python
Strings can be split by a substring separator. Usually the string split is called without any arguments, which splits on any whitespace.
Table of contents
- Breaking apart a string by a separator
- Splitting a specific number of times
- Splitting from the end of a string
- The string split method versus regular expressions
If you need to break a string into smaller strings based on a separator, you can use the string split method:
>>> time = "1:19:48" >>> time.split(":") ['1', '19', '48']The separator you split by can be any string. It doesn't need to be just one character:
>>> graph = "A->B->C->D" >>> graph.split("->") ['A', 'B', 'C', 'D']Note that it's a little bit unusual to call the string split method on a single space character:
>>> langston = "Does it dry up\nlike a raisin in the sun?\n" >>> langston.split(" ") ['Does', 'it', 'dry', 'up\nlike', 'a', 'raisin', 'in', 'the', 'sun?\n']It's usually preferable to call split without any arguments at all:
>>> langston = "Does it dry up\nlike a raisin in the sun?\n" >>> langston.split() ['Does', 'it', 'dry', 'up', 'like', 'a', 'raisin', 'in', 'the', 'sun?']Calling the split with no arguments will split on any consecutive whitespace characters. So we're even splitting on a new line here in between up and like (up\nlike).
Also note that the split method without any arguments removes leading and trailing whitespace (note that the last element in the list is sun? rather than sun?\n).
There's one more split feature that's often overlooked: maxsplit.
Splitting a specific number of timesWhen calling split with a …
Read the full article: https://www.pythonmorsels.com/string-split-method/Carl Trachte: DAG Hamilton Graph Presented as SVG in Blogger
Through the kindness of the DAG Hamilton project team, I was able to secure an official svg version of the DAG Hamilton logo. It looks significantly better than the one I had generated with an online image to svg converter and is much smaller and easy to work with (4 kilobytes versus 200 kb). The DAG Hamilton graphviz graph now shows up in Blogger; it is unlikely to show up on the planet(python) feed. Blogger is not liking the code and svg I have included (complaints of malformed html). In the interest of preserving the rendering of the graph(s), I am constraining the text here to a few paragraphs
The first graph has the code provided. This graph is from a previous post.
The second graph represents the DAG Hamilton workflow for the production of the first graph. This is in keeping with the "Eat your own dogfood" mantra. I happen to like the DAG Hamilton dogfood as I've mentioned in previous posts. It allows me to visualize my workflows and track complexity and areas for improvement in the code.
The third one I did with a scaled down version of the code presented (no logos). I hand pasted the DAG Hamilton official logo into the third one. It is not subtle (the logo is huge), but it provides an idea of what one can do creatively with the logo or any svg element. Also, it shows the DAG Hamilton workflow for the graph with the respective two logos.
All the code is a work in progress. Ideally I would like to keep reducing this to the most simple svg implementation possible to get it to show up or "work." Realistically, I'm afraid to sneeze for fear Blogger will protest. For now, I'm leaving good enough alone. Links and thoughts on svg (there is at least one python library (orsinium-labs/svg.py) out there that is way more elegant in its treatment of the medium than my rough regular expressions / text processing) will have to wait for another post.
Thanks for stopping by.
run.py code
""" Hamilton wrapper. """ # run.py import sys import pprint from hamilton import driver import dag_hamilton_to_blogger as dhtb dr = driver.Builder().with_modules(dhtb).build() dr.display_all_functions('dhtb.svg', deduplicate_inputs=True, keep_dot=True, orient='BR') results = dr.execute(['defluffed_lines', 'scale_and_translation', 'logo_positions', 'captured_values', 'scaled_elements', 'translated_elements', 'hamilton_logo_data', 'scale_and_translation_hamilton_logo', 'fauxcompany_logo_data', 'scale_and_translation_fauxcompany_logo', 'svg_ready_doc', 'written_svg'], inputs={'svg_file':'web_scraping_functions_highlighted.svg', 'outputfile':'test_output.svg', 'hamiltonlogofile':'hamilton_official_stripped.svg', 'hamiltonlogo_coords':{'min_x':-0.001, 'max_x':4353.846, 'min_y':-0.0006, 'max_y':4177.257}, 'fauxcompanylogofile':'fauxcompanylogo_stripped_down.svg', 'fauxcompanylogo_coords':{'min_x':11.542786063261742, 'max_x':705.10684, 'min_y':4.9643821, 'max_y':74.47416391682819}})Main DAG Hamilton functions (dag_hamilton_to_blogger.py)
# python 3.12 """ Make DAG Hamilton graph show up in Blogger. """ import re import sys import pprint import math import copy import reusedfunctions as rf VIEWBOX_PAT = (r'[ ]viewBox[=]["][-]?[0-9]+[.]?[0-9]*[ ][-]?[0-9]+[.]?[0-9]*[ ]' r'([0-9]+[.]?[0-9]*)[ ]([0-9]+[.]?[0-9]*)') # 5 coordinates. POLYGON_PAT = (r'[]polygon' r'.*([ ]points[=]["])([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)["]') # 4 coordinates instead of 5. POLYGON_PAT_4 = (r'[]polygon' r'.*([ ]points[=]["])([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)[ ]' r'([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)["]') # x, y TEXTPAT = (r']text[ ].*' r'([ ]font[-]size[=])' r'["]([0-9]+[.]?[0-9]*)["]') # initial bezier curve notation PATHPAT = (r'[]path[ ].*' r'([ ]d[=]["]M)([-]?[0-9]+[.]?[0-9]*)[,]' r'([-]?[0-9]+[.]?[0-9]*)C') X_SIZE = 600 NEW_FIRST_LINE = '') IMAGE_FLAG = '') # 4 coords (arrow head). POLYGON_STR_4 = (r' points="{0:.3f},{1:.3f} {2:.3f},{3:.3f} ' r'{4:.3f},{5:.3f} {6:.3f},{7:.3f}"/>') PATH_START_STR = r' d="M{0:.3f},{1:.3f}C' PATH_STR_SEGMENT = ' {0:.3f},{1:.3f}' PATH_STR = r' {0:s}"/>' TEXT_STR = r' x="{0:.3f}" y="{1:.3f}"' TEXT_STR_FONT = r' font-size="{0:.3f}"' HAMILTON_LOGO_DIMENSIONS_PAT = (r'.*width[=]["]([0-9]+[.]?[0-9]*)px["][ ]' r'height[=]["]([0-9]+[.]?[0-9]*)px["][>]') FAUXCOMPANY_LOGO_DIMENSIONS_PAT = (r'[ ]width[=]["]([0-9]+[.]?[0-9]*)["][ ]' r'height[=]["]([0-9]+[.]?[0-9]*)["][ ][>]') # The official Hamilton logo splits the path into multiple # lines with the last one having the absolute location # ("C") of a bezier curve. HAMILTON_CHANGE_LINE_PAT = r'.*C[-]?[0-9]+[.]?[0-9]*' HAMILTON_TRANSFORM_FMT = (' transform="scale({scale:f}) ' 'translate({translate_x:f},{translate_y:f})" />') # One line of paths in Inkscape generated file. FAUXCOMPANY_CHANGE_LINE_PAT = r'.*d[=]["]m[ ]' # Inkscape put the closing tag /> on the following line. FAUXCOMPANY_TRANSFORM_FMT = (' transform="scale({scale:f}) ' 'translate({translate_x:f},{translate_y:f})"') # * - get rid of first 6 lines. # * - get rid of any line starting with: # # "Terri Oda: Best practices in practice: Black, the Python code formatter
I’m starting a little mini-series about some of the “best practices” I’ve tried out in my real-life open source software development. These can be specific tools, checklists, workflows, whatever. Some of these have been great, some of them have been not so great, but I’ve learned a lot. I wanted to talk a bit about the usability and assumptions made in various tools and procedures, especially relative to the wider conversations we need to have about open source maintainer burnout, mentoring new contributors, and improving the security and quality of software.
So let’s start with a tool that I love: Black.
Black’s tagline is “the uncompromising Python code formatter” and it pretty much is what it says on the tin: it can be used to automatically format Python code, and it’s reasonably opinionated about how it’s done with very few options to change. It starts with pep8 compliance (that’s the python style guide for those of you don’t need to memorize such things) and takes it further. I’m not going to talk about the design decisions they made but the black style guide is actually an interesting read if you’re into this kind of thing.
I’m probably a bit more excited about style guides than the average person because I spent several years reading and marking student code, including being a teaching assistant for a course on Perl, a language that is famously hard to read. (Though I’ve got to tell you, the first year undergraduates’ Java programs were absolutely worse to read than Perl.) And then in case mounds of beginner code wasn’t enough of a challenge, I also was involved in a fairly well-known open source project (GNU Mailman) with a decade of code to its name even when I joined so I was learning a lot about the experience of integrating code from many contributors into a single code base. Both of these are… kind of exhausting? I was young enough to not be completely set in my ways, but especially with the beginner Java code, it became really clear that debugging was harder when the formatting was adding a layer of obfuscation to the code. I’d have loved to have an autoformatter for Java because so many students could find their bugs easier once I showed them how to fix their indents or braces.
And then I spent years as an open source project maintainer rather than just a contributor, so it was my job to enforce style as part of code reviews. And… I kind of hated that part of it? It’s frustrating to have the same conversation with people over and over about style and be constantly leaving the same code review comments, and then on top of that sometimes people don’t *agree* with the style and want to argue about it, or people can’t be bothered to come back and fix it themselves so I either have to leave a potentially good bug fix on the floor or I have to fix it myself. Formatting code elegantly can be fun once in a while, but doing it over and over and over and over quickly got old for me.
So when I first heard about Black, I knew it was a thing I wanted for my projects.
Now when someone submits a thing to my code base, Black runs alongside the other tests, and they get feedback right away if their code doesn’t meet our coding standards. It hardly any time to run so sometimes people get feedback very fast. Many new contributors even notice failing required test and go do some reading and fix it before I even see it, and for those that don’t fix issues before I get there I get a much easier conversation that amounts to “run black on your files and update the pull request.” I don’t have to explain what they got wrong and why it matters — they don’t even need to understand what happens when the auto-formatter runs. It just cleans things up and we move on with life.
I feel like the workflow might actually be better if Black was run in our continuous integration system and automatically updated the submitted code, but there’s some challenges there around security and permissions that we haven’t gotten around to solving. And honestly, it’s kind of nice to have an easy low-stress “train the new contributors to use the tools we use” or “share a link to the contributors doc” opening conversation, so I haven’t been as motivated as I might be to fix things. I could probably have a bot leave those comments and maybe one of those days we’ll do that, but I’m going to have to look at the code for code review anyhow so I usually just add it in to the code review comments.
The other thing that Black itself calls out in their docs is that by conforming to a standard auto-format, we really reduce the differences between existing code and new code. It’s pretty obvious when the first attempt has a pile of random extra lines and is failing the Black check. We get a number of contributors using different integrated development environments (IDEs) that are pretty opinionated themselves, and it’s been freeing to not to deal with whitespace nonsense in pull requests or have people try to tell me on the glory if their IDE of choice when I ask them to fix it. Some python IDEs actually support Black so sometimes I can just tell them to flip a switch or whatever and then they never have to think about it again either. Win for us all!
So here’s the highlights about why I use Black:
As a contributor:
- Black lets me not think about style; it’s easy to fix before I put together a pull request or patch.
- It saves me from the often confusing messages you get from other style checkers.
- Because I got into the habit of running it before I even run my code or tests, it serves as a quick mistake checkers.
- Some of the style choices, like forcing trailing commas in lists, make editing existing code easier and I suspect increase code quality overall because certain types of bug are more obvious.
As a an open source maintainer:
- Black lets me not think about style.
- It makes basic code quality conversations easier. I used to have a *lot* of conversations about style and people get really passionate about it, but it wasted a lot of time when the end result was usually going to be “conform to our style if you want to contribute to this project”
- Fixing bad style is fast, either for the contributor or for me as needed.
- It makes code review easier because there aren’t obfuscating style issues.
- It allows for very quick feedback for users even if all our maintainers are busy. Since I regularly work with people in other time zones, this can potentially save days of back and forth before code can be used.
- It provides a gateway for users to learn about code quality tools. I work with a lot of new contributors through Google Summer of Code and Hacktoberfest, so they may have no existing framework for professional development. But also even a lot of experienced devs haven’t used tools like Black before!
- It provides a starting point for mentoring users about pre-commit checks, continuous integration tests, and how to run things locally. We’ve got other starting points but Black is fast and easy and it helps reduce resistance to the harder ones.
- It reduces “bike shedding” about style. Bikeshedding can be a real contributor to burnout of both maintainers and contributors, and this reduces one place where I’ve seen it occur regularly.
- It decreases the cognitive overhead of reading and maintainin a full code base which includes a bunch of code from different contributors or even from the same contributor years later. If you’ve spent any time with code that’s been around for decades, you know what I’m talking about.
- In short: it helps me reduce maintainer burnout for me and my co-maintainers.
So yeah, that’s Black. It improves my experience as an open source maintainer and as a mentor for new contributors. I love it, and maybe you would too? I highly recommend trying it out on your own code and new projects. (and it’s good for existing projects, even big established ones, but choosing to apply it to an existing code base gets into bikeshedding territory so proceed with caution!)
It’s only for Python, but if you have similar auto-formatters for other languages that you love, let me know! I’d love to have some to recommend to my colleagues at work who focus on other languages.
comments
Real Python: The Real Python Podcast – Episode #222: Using Virtual Environments in Docker & Comparing Python Dev Tools
Should you use a Python virtual environment in a Docker container? What are the advantages of using the same development practices locally and inside a container? Christopher Trudeau is back on the show this week, bringing another batch of PyCoder's Weekly articles and projects.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Python GUIs: Introduction to the QGraphics framework — Creating vector interfaces using the QGraphics View framework
The Qt Graphics View Framework allows you to develop fast and efficient 2D vector graphic scenes. Scenes can contain millions of items, each with their own features and behaviors. By using the Graphics View via PySide6 you get access to this highly performant graphics layer in Python. Whether you're integrating vector graphics views into an existing PySide6 application, or simply want a powerful vector graphics interface for Python, Qt's Graphics View is what you're looking for.
Some common uses of the Graphics View include data visualization, mapping applications, 2D design tools, modern data dashboards and even 2D games.
In this tutorial we'll take our first steps looking at the Qt Graphics View framework, building a scene with some simple vector items. This will allow us to familiarize ourselves with the API and coordinate system, which we'll use later to build more complex examples.
Table of Contents- The Graphics View Framework
- A simple scene
- Another way to create objects.
- Building a more complex scene
- Adding graphics views to Qt layouts
The Graphics View framework consists of 3 main parts QGraphicsView, QGraphicsScene, and QGraphicsItem, each with different responsibilities.
The framework can be interpreted using the Model-View paradigm, with the QGraphicsScene as the Model and the QGraphicsView as the View. Each scene can have multiple views. The QGraphicsItems within the scene can be considered as items within the model, holding the visual data that the scene combines to define the complete image.
QGraphicsScene is the central component that glues everything together. It acts as a whiteboard on which all items are drawn (circles, rectangles, lines, pixmaps, etc). The QGraphicsView has the responsibility of rendering a given scene -- or part of it, with some transformation (scaling, rotating, shearing) -- to display it to the user. The view is a standard Qt widget and can be placed inside any Qt layout.
QGraphicsScene provides some important functionalities out of the box, so we can use them to develop advanced applications without struggling with low-level details. For example --
- Collision Detection, detect a graphics item is collided with another item.
- Item Selection, gives us the ability to deal with multiple items at the same time, for example, the user can select multiple items, and when pressing delete, a function asks the scene to give the list for all selected items, and then delete them.
- Items discovery, the scene can tell us what items are present (or part of them) at a specific point or inside some defined region, for example, if the user adds an item that intersects with a forbidden area, the program will detect them and give them another (mostly red) color.
- Events Propagation, the scene receives the events and then propagates them to items.
To define a QGraphicsScene you define it's boundaries or sceneRect which defines the x & y origins and dimensions of the scene. If you don't provide a sceneRect it will default to the minimum bounding rectangle for all child items -- updating as items are added, moved or removed. This is flexible but less efficient.
Items in the scene are represented by QGraphicsItem objects. These are the basic building block of any 2D scene, representing a shape, pixmap or SVG image to be displayed in the scene. Each item has a relative position inside the sceneRect and can have different transformation effects (scale, translate, rotate, shear).
Finally, the QGraphicsView is the renderer of the scene, taking the scene and displaying it -- either wholly or in part -- to the user. The view itself can have transformations (scale, translate, rotate and shear) applied to modify the display without affecting the underlying scene. By default the view will forward mouse and keyboard events to the scene allowing for user interaction. This can be disabled by calling view.setInteractive(False).
A simple sceneLet's start by creating a simple scene. The following code creates QGraphicsScene, defining a 400 x 200 scene, and then displays it in a QGraphicsView.
python import sys from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QApplication app = QApplication(sys.argv) # Defining a scene rect of 400x200, with it's origin at 0,0. # If we don't set this on creation, we can set it later with .setSceneRect scene = QGraphicsScene(0, 0, 400, 200) view = QGraphicsView(scene) view.show() app.exec()If you run this example you'll see an empty window.
The empty graphics scene, shown in a QGraphicsView window.
Not very exciting yet -- but this is our QGraphicsView displaying our empty scene.
As mentioned earlier, QGraphicsView is a widget. In Qt any widgets without a parent display as windows. This is why our QGraphicsView appears as a window on the desktop.
Adding itemsLet's start adding some items to the scene. There are a number of built-in graphics items which you can customize and add to your scene. In the example below we use QGraphicsRectItem which draws a rectangle. We create the item passing in it's dimensions, and then set it's position pen and brush before adding it to the scene.
python import sys from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsRectItem, QApplication from PySide6.QtGui import QBrush, QPen from PySide6.QtCore import Qt app = QApplication(sys.argv) # Defining a scene rect of 400x200, with it's origin at 0,0. # If we don't set this on creation, we can set it later with .setSceneRect scene = QGraphicsScene(0, 0, 400, 200) # Draw a rectangle item, setting the dimensions. rect = QGraphicsRectItem(0, 0, 200, 50) # Set the origin (position) of the rectangle in the scene. rect.setPos(50, 20) # Define the brush (fill). brush = QBrush(Qt.red) rect.setBrush(brush) # Define the pen (line) pen = QPen(Qt.cyan) pen.setWidth(10) rect.setPen(pen) scene.addItem(rect) view = QGraphicsView(scene) view.show() app.exec()Running the above you'll see a single, rather ugly colored, rectangle in the scene.
A single rectangle in the scene
Adding more items is simply a case of creating the objects, customizing them and then adding them to the scene. In the example below we add an circle, using QGraphicsEllipseItem -- a circle is just an ellipse with equal height and width.
python import sys from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsRectItem, QGraphicsEllipseItem, QApplication from PySide6.QtGui import QBrush, QPen from PySide6.QtCore import Qt app = QApplication(sys.argv) # Defining a scene rect of 400x200, with it's origin at 0,0. # If we don't set this on creation, we can set it later with .setSceneRect scene = QGraphicsScene(0, 0, 400, 200) # Draw a rectangle item, setting the dimensions. rect = QGraphicsRectItem(0, 0, 200, 50) # Set the origin (position) of the rectangle in the scene. rect.setPos(50, 20) # Define the brush (fill). brush = QBrush(Qt.red) rect.setBrush(brush) # Define the pen (line) pen = QPen(Qt.cyan) pen.setWidth(10) rect.setPen(pen) ellipse = QGraphicsEllipseItem(0, 0, 100, 100) ellipse.setPos(75, 30) brush = QBrush(Qt.blue) ellipse.setBrush(brush) pen = QPen(Qt.green) pen.setWidth(5) ellipse.setPen(pen) # Add the items to the scene. Items are stacked in the order they are added. scene.addItem(ellipse) scene.addItem(rect) view = QGraphicsView(scene) view.show() app.exec()The above code will give the following result.
A scene with two items
The order you add items affects the stacking order in the scene -- items added later will always appear on top of items added first. However, if you need more control you can set the stacking order using .setZValue.
python ellipse.setZValue(500) rect.setZValue(200)Now the circle (ellipse) appears above the rectangle.
Using Zvalue to order items in the scene
Try experimenting with setting the Z value of the two items -- you can set it before or after the items are in the scene, and can change it at any time.
Z in this context refers to the Z coordinate. The X & Y coordinates are the horizontal and vertical position in the scene respectively. The Z coordinate determines the relative position of items toward the front and back of the scene -- coming "out" of the screen towards the viewer.
There are also the convenience methods .stackBefore() and .stackAfter() which allow you to stack your QGraphicsItem behind, or in front of another item in the scene.
python ellipse.stackAfter(rect) Making items moveableOur two QGraphicsItem objects are currently fixed in position where we place them, but they don't have to be! As already mentioned Qt's Graphics View framework allows items to respond to user input, for example allowing them to be dragged and dropped around the scene at will. Simple functionality like is actually already built in, you just need to enable it on each QGraphicsItem. To do that we need to set the flag QGraphicsItem.GraphicsItemFlags.ItemIsMoveable on the item.
The full list of graphics item flags is available here.
python import sys from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsItem, QGraphicsRectItem, QGraphicsEllipseItem, QApplication from PySide6.QtGui import QBrush, QPen from PySide6.QtCore import Qt app = QApplication(sys.argv) # Defining a scene rect of 400x200, with it's origin at 0,0. # If we don't set this on creation, we can set it later with .setSceneRect scene = QGraphicsScene(0, 0, 400, 200) # Draw a rectangle item, setting the dimensions. rect = QGraphicsRectItem(0, 0, 200, 50) # Set the origin (position) of the rectangle in the scene. rect.setPos(50, 20) # Define the brush (fill). brush = QBrush(Qt.red) rect.setBrush(brush) # Define the pen (line) pen = QPen(Qt.cyan) pen.setWidth(10) rect.setPen(pen) ellipse = QGraphicsEllipseItem(0, 0, 100, 100) ellipse.setPos(75, 30) brush = QBrush(Qt.blue) ellipse.setBrush(brush) pen = QPen(Qt.green) pen.setWidth(5) ellipse.setPen(pen) # Add the items to the scene. Items are stacked in the order they are added. scene.addItem(ellipse) scene.addItem(rect) ellipse.setFlag(QGraphicsItem.ItemIsMovable) view = QGraphicsView(scene) view.show() app.exec()In the above example we've set ItemIsMovable on the ellipse only. You can drag the ellipse around the scene -- including behind the rectangle -- but the rectangle itself will remain locked in place. Experiment with adding more items and configuring the moveable status.
If you want an item to be selectable you can enable this by setting the ItemIsSelectable flag, for example here using .setFlags() to set multiple flags at the same time.
python ellipse.setFlags(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)If you click on the ellipse you'll now see it surrounded by a dashed line to indicate that it is selected. We'll look at how to use item selection in more detail in a later tutorial.
A selected item in the scene, highlighted with dashed lines
Another way to create objects.So far we've been creating items by creating the objects and then adding them to the scene. But you can also create an object in the scene directly by calling one of the helper methods on the scene itself, e.g. scene.addEllipse(). This creates the object and returns it so you can modify it as before.
python import sys from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsRectItem, QApplication from PySide6.QtGui import QBrush, QPen from PySide6.QtCore import Qt app = QApplication(sys.argv) scene = QGraphicsScene(0, 0, 400, 200) rect = scene.addRect(0, 0, 200, 50) rect.setPos(50, 20) # Define the brush (fill). brush = QBrush(Qt.red) rect.setBrush(brush) # Define the pen (line) pen = QPen(Qt.cyan) pen.setWidth(10) rect.setPen(pen) view = QGraphicsView(scene) view.show() app.exec()Feel free to use whichever form you find most comfortable in your code.
You can only use this approach for the built-in QGraphicsItem object types.
Building a more complex sceneSo far we've built a simple scene using the basic QGraphicsRectItem and QGraphicsEllipseItem shapes. Now let's use some other QGraphicsItem objects to build a more complex scene, including lines, text and QPixmap (images).
python from PySide6.QtCore import QPointF, Qt from PySide6.QtWidgets import QGraphicsRectItem, QGraphicsScene, QGraphicsView, QApplication from PySide6.QtGui import QBrush, QPainter, QPen, QPixmap, QPolygonF import sys app = QApplication(sys.argv) scene = QGraphicsScene(0, 0, 400, 200) rectitem = QGraphicsRectItem(0, 0, 360, 20) rectitem.setPos(20, 20) rectitem.setBrush(QBrush(Qt.red)) rectitem.setPen(QPen(Qt.cyan)) scene.addItem(rectitem) textitem = scene.addText("QGraphics is fun!") textitem.setPos(100, 100) scene.addPolygon( QPolygonF( [ QPointF(30, 60), QPointF(270, 40), QPointF(400, 200), QPointF(20, 150), ]), QPen(Qt.darkGreen), ) pixmap = QPixmap("cat.jpg") pixmapitem = scene.addPixmap(pixmap) pixmapitem.setPos(250, 70) view = QGraphicsView(scene) view.setRenderHint(QPainter.Antialiasing) view.show() app.exec()If you run the example above you'll see the following scene.
Scene with multiple items including a rectangle, polygon, text and a pixmap.
Let's step through the code looking at the interesting bits.
Polygons are defined using a series of QPointF objects which give the coordinates relative to the items position. So, for example if you create a polygon object with a point at 30, 20 and then move this polygon object X & Y coordinates 50, 40 then the point will be displayed at 80, 60 in the scene.
Points inside an item are always relative to the item itself, and item coordinates are always relative to the scene -- or the item's parent, if it has one. We'll take a closer look at the Graphics View coordinate system in the next tutorial.
To add an image to the scene we can open it from a file using QPixmap(). This creates a QPixmap object, which can then in turn add to the scene using scene.addPixmap(pixmap). This returns a QGraphicsPixmapItem which is the QGraphicsItem type for the pixmap -- a wrapper than handles displaying the pixmap in the scene. You can use this object to perform any changes to item in the scene.
The multiple layers of objects can get confusing, so it's important to choose sensible variable names which make clear the distinction between, e.g. the pixmap itself and the pixmap item that contains it.
Finally, we set the flag RenderHint,Antialiasing on the view to smooth the edges of diagonal lines. You almost always want to enable this on your views as otherwise any rotated objects will look very ugly indeed. Below is our scene without antialiasing enabled, you can see the jagged lines on the polygon.
Scene with antialiasing disabled.
Antialiasing has a (small) performance impact however, so if you are building scenes with millions of rotated items it may in some cases make sense to turn it off.
Adding graphics views to Qt layoutsThe QGraphicsView is subclassed from QWidget, meaning it can be placed in layouts just like any other widget. In the following example we add the view to a simple interface, with buttons which perform a basic effect on the view -- raising and lowering selected item's ZValue. This has the effect of allowing us to move items in front and behind other objects.
The full code is given below.
python import sys from PySide6.QtCore import Qt from PySide6.QtGui import QBrush, QPainter, QPen from PySide6.QtWidgets import ( QApplication, QGraphicsEllipseItem, QGraphicsItem, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QHBoxLayout, QPushButton, QSlider, QVBoxLayout, QWidget, ) class Window(QWidget): def __init__(self): super().__init__() # Defining a scene rect of 400x200, with it's origin at 0,0. # If we don't set this on creation, we can set it later with .setSceneRect self.scene = QGraphicsScene(0, 0, 400, 200) # Draw a rectangle item, setting the dimensions. rect = QGraphicsRectItem(0, 0, 200, 50) rect.setPos(50, 20) brush = QBrush(Qt.red) rect.setBrush(brush) # Define the pen (line) pen = QPen(Qt.cyan) pen.setWidth(10) rect.setPen(pen) ellipse = QGraphicsEllipseItem(0, 0, 100, 100) ellipse.setPos(75, 30) brush = QBrush(Qt.blue) ellipse.setBrush(brush) pen = QPen(Qt.green) pen.setWidth(5) ellipse.setPen(pen) # Add the items to the scene. Items are stacked in the order they are added. self.scene.addItem(ellipse) self.scene.addItem(rect) # Set all items as moveable and selectable. for item in self.scene.items(): item.setFlag(QGraphicsItem.ItemIsMovable) item.setFlag(QGraphicsItem.ItemIsSelectable) # Define our layout. vbox = QVBoxLayout() up = QPushButton("Up") up.clicked.connect(self.up) vbox.addWidget(up) down = QPushButton("Down") down.clicked.connect(self.down) vbox.addWidget(down) rotate = QSlider() rotate.setRange(0, 360) rotate.valueChanged.connect(self.rotate) vbox.addWidget(rotate) view = QGraphicsView(self.scene) view.setRenderHint(QPainter.Antialiasing) hbox = QHBoxLayout(self) hbox.addLayout(vbox) hbox.addWidget(view) self.setLayout(hbox) def up(self): """ Iterate all selected items in the view, moving them forward. """ items = self.scene.selectedItems() for item in items: z = item.zValue() item.setZValue(z + 1) def down(self): """ Iterate all selected items in the view, moving them backward. """ items = self.scene.selectedItems() for item in items: z = item.zValue() item.setZValue(z - 1) def rotate(self, value): """ Rotate the object by the received number of degrees """ items = self.scene.selectedItems() for item in items: item.setRotation(value) app = QApplication(sys.argv) w = Window() w.show() app.exec()If you run this, you will get a window like that shown below. By selecting an item in the graphics view and then clicking either the "Up" or "Down" button you can move items up and down within the scene -- behind and in front of one another. The items are all moveable, so you can drag them around too. Clicking on the slider will rotate the currently selected items by the set number of degrees.
A graphics scene with some custom controls
The raising and lowering is handled by our custom methods up and down, which work by iterating over the currently selected items in the scene -- retrieved using scene.selectedItems() and then getting the items z value and increasing or decreasing it respectively.
python def up(self): """ Iterate all selected items in the view, moving them forward. """ items = self.scene.selectedItems() for item in items: z = item.zValue() item.setZValue(z + 1)While rotation is handled using the item.setRotation method. This receives the current angle from the QSlider and again, applies it to any currently selected items in the scene.
python def rotate(self, value): """ Rotate the object by the received number of degrees. """ items = self.scene.selectedItems() for item in items: item.setRotation(value)Take a look at the QGraphicsItem documentation for some other properties you can control with widgets and try extending the interface to allow you to change them dynamically.
Hopefully this quick introduction to the Qt Graphics View framework has given you some ideas of what you can do with it. In the next tutorials we'll look at how events and user interaction can be handled on items and how to create custom & compound items for your own scenes.
Matt Layman: Postgres to SQLite - Building SaaS #204
PyCharm: Django Project Ideas
Ready to get started on your Django project? Whether you want to build a personal project, improve your portfolio, or just experiment with a new technology, Django provides the perfect foundation.
We’ve compiled a list of Django project ideas that will help you expand your competence, whether you’re new to the framework or looking to advance your existing skills.
In this guide, we’ll explore a range of Django project ideas to help you get hands-on experience, ranging from simple apps to more advanced, full-stack applications.
When should I use Django?Known as the “web framework for perfectionists with deadlines”, Django is a great choice for building robust, production-ready websites, apps, or services.
It’s an open-source and highly versatile Python web framework that can be used for everything from blogs and social media platforms to e-commerce sites, content management systems, and fitness trackers.
First released in 2005, Django continues to receive regular updates and enjoys a considerable following. Its “batteries included” design means you get what you need to build a full-stack web app right out of the box. You can also pair Django with a front-end JavaScript framework for projects that demand richly interactive user interfaces.
- Learn more about Django in our blog, including its key components and benefits.
- Still trying to figure out whether Django is the right framework for you? Read our comparison of Django and Flask – the two most popular Python web frameworks.
Working on a real-world project is one of the best ways to get to grips with Django. You can start with something simple and extend it as you learn more about the framework. In the process, you’ll develop your skills and build a portfolio of work showcasing your abilities.
Stuck for ideas? Previous projects (both professional and personal), forums, dev meetups and hackathons, as well as platforms like GitHub, can all provide sources of inspiration.
GitHub is also useful for hosting and collaborating on open-source projects – this is where the source code or design documents are made publicly available for anyone to access, modify, and distribute. You can use and build upon various software, making them a great jumping-off point for a Django project.
Some GitHub open-source Django projects include:
- Django packages: a directory of reusable apps, sites, tools, and more for your Django projects.
- Django project: source code for djangoproject.com.
- Django social: code for a social network or community site built using Django.
Are you unfamiliar with a particular area, such as routing or database design? You could choose to design a project that addresses this knowledge gap while learning Django simultaneously.
Django project ideas for beginnersIf this is your first time building with Django, look no further. We’ve compiled a list of project ideas that are ideal for anyone using Django for the first time. These will help you find your feet as you explore what Django offers.
Before you start, reading this Django tutorial for beginners is useful. It walks through building a simple but non-trivial project by starting with a single file. The tutorial is an excellent starting point for anyone new to Django, as it introduces core concepts and helps you build a functional project from the ground up.
Once you’re familiar with Django’s principal elements and are comfortable building within the framework, you can get going with these more dynamic yet straightforward projects.
Air temperature appThis tutorial will walk you through creating a simple Django app using PyCharm that displays the current air temperature at your location. The app also allows users to explore weather conditions at random locations to add interactivity.
By following this guide, you’ll learn to:
- Set up a Django project.
- Develop models, views, and templates.
- Make and process API calls.
- Connect to and populate databases.
This hands-on task will give you practical experience with core Django concepts and show how PyCharm can help you develop more efficiently while working with Django. It’s a great place to begin building web applications and sets you up for further starter projects.
Follow the step-by-step tutorial BlogRequired tech stack:
- Django admin: for managing blog posts.
- Django templates: for rendering HTML pages.
- TinyMCE or CKEditor (optional): for rich text editing.
Building your own blogging platform with Django is a great way to cover the basics of create, read, update, and delete (CRUD), setting up routes, and serving a site locally. To keep things simple, use the Django Admin site to add and update blog posts. To explore further, extend the basic blog functionality by implementing tags and filters, adding a search option, or enabling comments.
We highly recommend the Django Girls Tutorial for beginners, which takes you through creating a small blog.
To-do list appRequired tech stack:
- Django templates: for rendering the UI.
- Single-page applications (SPA)/JavaScript: for updating the status of pages and components without reloading the page.
A simple task list with an option to check items off when complete is an excellent way to learn the basics of developing with Django. You’ll need a UI to add tasks and update their status and a simple database to record each entry. You can also add the ability to record due dates or set priorities.
Recipe organizerRequired tech stack:
- Django templates: for rendering the frontend.
- Django ORM: for database interactions.
- JavaScript (optional): for additional security.
Familiarize yourself with Django’s ORM (object-relational mapper) and database support by building an app to keep track of your favorite recipes. Add a web-based frontend with options to filter recipes by category, ingredients, and user ratings so you can easily browse for inspiration.
Quiz appRequired tech stack:
- Django templates: for rendering the UI.
- Django ORM: for managing the question bank and user scores.
- JavaScript: for interactive quiz elements.
Create a quiz app or website to familiarize yourself with each layer of Django’s architecture. Build a question bank, give players a simple UI to select their answer, and calculate the score. Enhance the functionality by sorting questions into categories and adding options to choose topics or change the number of questions asked. You could also add a leaderboard to celebrate your highest scorers.
Authentication systemRequired tech stack:
- Django built-in authentication: for handling login, registration, and password resetting.
- Email service: for email validation and password reset (e.g. SMTP server).
Login systems are a feature of most websites and apps. Fortunately, adding authentication and authorization to a web app is easier with Django’s built-in authentication system. Creating one as a practice project helps familiarize yourself with the functionality and provides a reusable pattern for future projects. Don’t forget to include key features such as email validation and a password reset option.
URL shortenerRequired tech stack:
- Django templates: for the frontend.
- Django ORM: for storing URLs.
- Bitly API (optional): if using an external shortening service.
You can approach this project in a couple of ways, depending on your interests. One option is to build a simple app that sends requests to an existing URL-shortening service, such as Bitly’s API. Alternatively, create your own service by generating shortened URLs, storing the URLs in a database, and defining routing logic to match incoming requests to the appropriate URL. Add a simple frontend so you can generate new shortened URLs on demand.
Expense trackerRequired tech stack:
- Django templates: for the UI.
- Django ORM: for managing expense data.
- Chart.js or D3.js: for visualizing expense trends.
Expense management apps provide an opportunity to define different data models for expenses, such as invoices, payroll, and cash expenditures. As well as creating forms for users to enter the costs, you might have existing data to import. Consider creating graphs to show expense trends in each category.
Simple social networkRequired tech stack:
- Django templates: for rendering the UI.
- Django ORM: for managing user data and posts.
- Media storage: for images and videos (e.g. Amazon S3 or local storage).
- JavaScript: For interactive elements.
Use Django to create your version of Instagram or Facebook and learn about user account management, security, and privacy along the way. Users will need to be able to manage connections, share images and videos, and view each other’s posts.
Personal portfolioRequired tech stack:
- Django templates: for the frontend.
- Django ORM: for managing project data.
- Deployment tools: for deploying the website (e.g. Heroku, AWS, or DigitalOcean).
Sharing personal projects on your website enables you to showcase your skills as a developer. Create an engaging website for users to browse your work and view the source code. This project will also allow you to try deploying Django to a production web server.
Learn how to build a personal portfolio using Django with this helpful guide.
Event calendarRequired tech stack:
- Django templates: for rendering the frontend.
- JavaScript libraries: for interactive calendar functionalities (e.g. FullCalendar).
- Django ORM: for storing event data.
An enjoyable beginner project with a frontend focus, building an event calendar gives you a reason to work with Django’s built-in templates or Jinja2. You can also combine Django with JavaScript libraries to make your calendar interactive.
Survey toolRequired tech stack:
- Django templates: for the frontend.
- Django forms: for creating and submitting surveys.
- Django ORM: for storing survey data.
- Chart.js or D3.js: for visualizing survey results.
An online survey tool requires UIs for building and responding to surveys, storage of the responses, and logic to aggregate answers. This project is an ideal opportunity to try out Django forms. If you want to extend it, add user authentication and/or visualizations for the survey data.
Advanced Django projectsIf you’re familiar with Django or looking for more advanced project ideas, the following suggestions are for you. Get ideas to help you use more of Django’s rich capabilities and grow your developer skills.
Multi-user classifieds siteBuild a site where multiple users can post classified ads. You’ll need to create pages for listing, creating, and editing ads. Since the site supports multiple users, you’ll also need to create and manage user accounts, manage permissions so only the ad owner can edit their ads, and create paginated ad listings to avoid overloading the browser.
For the full experience, include a self-sign-up page and password reset management. For additional practice, consider adding an API to the site and/or using a frontend library like HTMX or Vue.js to make your pages more dynamic.
The book “Django In Action” guides you through building a musicians’ classified ad site called RiffMates. It also covers deeper topics such as testing, management commands, and Django power tools.
Chat appBuilding a messaging app is an excellent way to explore real-time two-way communication using WebSockets and Django Channels.
You’ll also need to create and manage user accounts, add contacts, and view message history. You can model the functionality on existing chat platforms like WhatsApp, X, or Telegram. Adding support for audio messages helps to extend your project further.
This tutorial on Django Channels will help you create your chat app, going beyond the basics for a more comprehensive application. For an extra challenge, consider incorporating WebRTC and webcam video chat.
E-commerce storeBuilding an online retail site is a sizable project that demonstrates various skills. In addition to a database of products and a website that lets customers browse and search, you’ll need to handle user accounts, shopping carts, payments, and order updates.
There is plenty to consider, from generating product image thumbnails to managing abandoned checkout processes. This project will help you understand advanced Django features like signals, middleware, and caching.
Medical records systemThis project requires you to consider user authentication and authorization to ensure only those with the correct permissions can view a patient’s records.
When defining your templates, ensure you present the data reverse chronologically (most recent first). You will also need to provide forms for authorized users to add new patients and update patients’ records.
You may even connect to another system to import test results and associate them with the right patient, integrating third-party APIs for extended functionality.
Financial dashboardDashboards make fantastic projects for combining Django with a frontend JavaScript framework. You can pull in data from an API or add an option to import data manually from .csv files. For real-time data, use Django Channels.
Leverage Django to manipulate the data in different ways and JavaScript to create visually appealing UIs. This project can also integrate with data visualization libraries such as D3.js or Chart.js for dynamic, interactive charts.
Property management systemBuilding a system to keep track of rented properties, record rent payments, and manage maintenance tasks and inspections is ideal for Django.
This project gives you a chance to work with multiple data sources, implement complex business logic, and handle common functionality such as user authentication and notifications. Consider using the Django REST framework to create APIs that mobile apps or other systems can consume.
Interactive dashboardsDeveloping an interactive dashboard with Django is perfect for visualizing data from various sources. It also allows you to handle large datasets, perform real-time data updates, and integrate frontend visualization libraries with Django.
Use libraries like Plotly or Bokeh to create dynamic charts and graphs. Implement data filtering, time range selection, and report exporting. Add user authentication to provide personalized dashboards based on roles and permissions.
Stock exchange analysisBuild a stock market analysis platform using Django, a project that combines data science, machine learning, and the Django REST framework. It also offers more practical experience in handling lots of real-time data.
Import historical stock prices, run technical analyses, and generate predictions using machine learning. Create RESTful APIs for data retrieval and analysis results, and integrate external APIs for real-time market data. Implement visualization tools to display trends, predictions, and alerts.
Processing large volumes of dataUse Django with Celery and Redis to process large datasets. This project will involve setting up task queues with Celery and managing them with Redis, helping you understand task scheduling and big data processing.
Implement features to handle server failures and ensure data integrity throughout the pipeline. Demonstrate how to scale the system by running Redis in cluster mode and balancing loads across multiple servers. Create dashboards to monitor task progress and performance metrics.
Generative AI RAG-based applicationDjango projects are a great way to gain practical experience working with language models. This project involves natural language processing and AI, helping to deepen your understanding.
Build a Django application for advanced AI-driven solutions using retrieval-augmented generation (RAG) techniques. Integrate pre-trained language models like GPT-3 or GPT-4 with a retrieval system to fetch relevant documents. Develop features for generating contextual responses, automated content creation, and personalized recommendations. Implement a feedback loop to continuously improve the system’s accuracy.
AIOps for server scalingTake on this assignment to help enhance your skills in AI, cloud computing, and automation.
Develop an AI-based system for predicting traffic and scaling servers automatically. Use machine learning models to analyze historical traffic data and forecast future loads. Integrate this system with cloud platforms like AWS or GCP to automatically provision and de-provision servers based on the predictions. Implement features for monitoring system performance, generating alerts, and providing dashboards for administrators.
Customized dashboard for MLOps pipelineCreate a dashboard to manage and monitor machine learning pipelines, integrating tools like TensorFlow or PyTorch with Django.
Allow users to track experiments, visualize training progress, and compare model performance. Implement features for managing datasets, configuring training parameters, and deploying models to production. Provide tools for monitoring model drift and triggering re-training when necessary.
By the end of the project, you should understand the end-to-end machine learning lifecycle and how to operationalize ML models using Django.
Location-based food recommendationLevel up your skills in recommendation systems, geolocation services, and user personalization. This task involves using machine learning algorithms to recommend food options based on user location and preferences.
Integrate with mapping services like Google Maps or OpenStreetMap to provide location-based search and routing. Implement user profiles to store preferences, dietary restrictions, and past interactions. Use collaborative filtering or content-based filtering techniques to generate recommendations. Provide a user-friendly interface to browse and rate food options.
Langchain-based projectsBuild applications utilizing Langchain for advanced natural language processing tasks.
Create use cases such as automated summarization, question answering, or text generation. Integrate with Django to provide a web-based interface for users to interact with the system. Implement features for fine-tuning models on specific domains, evaluating model performance, and giving real-time predictions.
Building these apps will help you explore the capabilities of state-of-the-art language models and how to integrate them with web applications.
Birthday message reminderDeveloping a birthday message reminder is a fantastic project for helping to understand chatbot development and automating workflows with Django. You will implement a system using ChatGPT to generate unique birthday messages and send them to employees via Slack.
Integrate with Slack’s API to send or direct messages to the appropriate channels. Use Django’s scheduling features to automate the message-sending process. Allow administrators to configure message templates, personalize messages based on employee data, and track message delivery.
Cloud server managementDeveloping cloud servers is an ideal way to build your skills in cloud computing, infrastructure as code, and DevOps practices. You could begin by creating and managing cloud servers using Django and Pulumi.
Allow users to provision and configure infrastructure as code, including virtual machines, databases, and networking resources. Implement features for monitoring resource usage, scaling infrastructure based on demand, and generating cost reports. Provide a web-based interface for administrators to manage cloud resources and view infrastructure status.
Ready to get started?We hope these project ideas have provided some inspiration to help you start building web apps with Django. Whatever your experience level, using an IDE optimized for your chosen language and framework makes software development more accessible and enjoyable.
PyCharm Professional is a Python IDE with built-in support for Django, Flask, FastAPI, and more. Intelligent coding assistance, streamlined navigation, and powerful debugging are just some of the features that PyCharm offers to help you code faster and smarter.
Using PyCharm, you will also benefit from:
- Advanced database management (including PostgreSQL, SQLite, Redis, and more).
- Frontend support for various languages and frameworks (such as JavaScript, React, Node.js, Tailwind CSS, and more).
- A built-in HTTP Client – essential for developing Django web applications.
- The Endpoints tool window – to visualize and navigate through your application’s endpoints.
Use PyCharm’s full-stack development features and database tools to help you build powerful Django projects.
Get started with PyCharm now More tutorials and guides