<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Will Vincent</title>
    <description>The latest articles on DEV Community by Will Vincent (@wsvincent).</description>
    <link>https://dev.to/wsvincent</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F284931%2F37601a15-c230-4ca6-9de3-70ab2cb9a5df.png</url>
      <title>DEV Community: Will Vincent</title>
      <link>https://dev.to/wsvincent</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wsvincent"/>
    <language>en</language>
    <item>
      <title>Careless People by Sarah Wynn-Williams - Book Review</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Thu, 05 Jun 2025 14:10:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/careless-people-by-sarah-wynn-williams-book-review-1c3o</link>
      <guid>https://dev.to/wsvincent/careless-people-by-sarah-wynn-williams-book-review-1c3o</guid>
      <description>&lt;p&gt;&lt;a href="https://www.amazon.com/Careless-People-Cautionary-Power-Idealism/dp/1250391237?wsvincent-20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqfmfzing6kbgmzrjxmu.jpg" alt="Careless People Book Cover" width="800" height="1215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Careless People&lt;/em&gt; is a new memoir by Sarah Wynn-Williams, a former New Zealand diplomat who joined the company in 2011 and rose to become its global public policy director. She pitched herself to the still-nacent Washington D.C. office for over a year before finally securing a job. As she says in the book:&lt;/p&gt;

&lt;p&gt;"I know what I want this job to be. It's clear that in these next few years, Facebook and governments all over the world are going to be figuring out the rules of the road for these giant, globe-spanning internet companies. What they set in place will determine how social media is used for decades to come. It will affect elections, privacy, free speech, taxes, and so much else. I want to be part of that."&lt;/p&gt;

&lt;p&gt;As she quickly learns, Facebook--meaning Mark Zuckerberg--has no interest in policy or politics. In fact, it's a source of pride for him to focus only on engineering. Facebook's COO, on the other hand, Sheryl Sandberg, handles these things along with running the business and everything else. It feels odd to read these passages now, in 2025, where Facebook routinely influences elections and politics, to see that for quite a long time Facebook was aggressively indifferent to being involved in anything beyond tech.&lt;/p&gt;

&lt;p&gt;Sarah notes that at one point, someone on Facebook's small policy team asks how the company is meant to change the world.&lt;/p&gt;

&lt;p&gt;"They're shocked when the answer is...nothing really. For Mark and Sheryl, it's obvious. We run a website that connects people. That's what we believe in. We want more. We want it to be profitable and to grow. What else is there to say?&lt;/p&gt;

&lt;p&gt;There is no grand ideology here. No theory about what Facebook should be in the world. The company is just responding to stuff as it happens. We're managers, not world-builders."&lt;/p&gt;

&lt;p&gt;This indifference and narrow focus on growth at all costs more or less defines the company. And for Sarah, coming from the world of the U.N. and global law, it is quite shocking.&lt;/p&gt;

&lt;p&gt;Nonetheless, Sarah finds her niche, introducing global leaders to the Facebook team. Initially they have no interest in meeting Mark Zuckerberg, but in only a few short years most of them are currying his favor, looking for local investment and help being reelected. Unsurprisingly, Sarah relates that Facebook can and routinely does weight its algorithm to benefit certain people, most noteably any posts by Mark or Sheryl, but also world leaders as needed.&lt;/p&gt;

&lt;p&gt;For her part, Sarah is often flying around the world in the early days trying to open up countries to Facebook. This includes often dangerous situations, especially for a young woman. Trips to Mynamar to try to get the junta to allow Facebook. To central America. And so on. There is even a chapter titled "The Body" around efforts to visit South Korea, which had open arrest warrants for Facebook officials. Leadership wants to send a body in before the leadership team, to see how serious the country is about this. Sarah is told to go but finds a way out. Ulimately, it is one of the few other women on her team who goes. Not any of the men.&lt;/p&gt;

&lt;p&gt;And so on. Sarah acts generally as a consigliere to Mark or Sheryl at global gatherings. Arranging meetings with world leaders. Finding ways for informal one-on-ones. As such, she spends a lot of close time with both of them. Suffice it to say, neither comes across well.&lt;/p&gt;

&lt;p&gt;At one point, returning from a global trip, Sheryl invites Sarah, who is several months pregnant, to get some sleep and share the only bed on the plane with her. Sarah awkwardly declines and is seemingly frozen out thereafter.&lt;/p&gt;

&lt;p&gt;There is also the cruel irony that the company aggressively promoting Sheryl Sandberg's book, &lt;em&gt;Lean In&lt;/em&gt;, is, wait for it, not that kind to its female employees. This isn't unique to Facebook, though the company seems particularly cruel in how it treats people. During the birth of her second child, Sarah loses an enormous amount of blood and even goes into a comma for a period time.&lt;/p&gt;

&lt;p&gt;"I return to work in August 2016. My first day back, Joel decides to do a performance reviews, as he says "it's performance review season." A quick Google search confirms my suspicions that you are not supposed to be given a performance review of your maternity leave. In fact, I understand that pushing someone to work during their maternity leave is against the law. Nevertheless.&lt;/p&gt;

&lt;p&gt;"You weren't responsive enough," he says.&lt;/p&gt;

&lt;p&gt;"In my defense, I was in a coma for some of it."&lt;/p&gt;

&lt;p&gt;"It's not just me, Sarah. Some of your other colleauges found it challenging to engage with you."&lt;/p&gt;

&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;What are the takeaways from this book? It is a memoir so it's important to consider this is a first-person account, but it's a useful book for anyone new in their career to read as it provides insight into how leadership often thinks about things. Not all companies operate this way, but many do. Especially towards women.&lt;/p&gt;

&lt;p&gt;What resonates for me is the author's feeling of being trapped, aware that unethical things were being asked of her, done around her, but feeling like she couldn't stop them. Part of this was financial, as she was the chief breadwinner in her household and had children. Part of it was legal since her immigration status and that of her husband depended upon being employed. But one way or another, she felt like a frog in boiling water at the company, her idealism slowly but surely chipped away.&lt;/p&gt;

&lt;p&gt;In the end, after six years, Sarah is fired. As she notes, "It's less of a savage attack on my career and more of a quick euthanasia...My laptop is confiscated. I'm not allowed back to my desk to retrieve the personal items that had built up over the years at the company...I ask to say goodbye to my team and beloved assistant and I'm told no. Instead, I'm walked out of the building by a security guard."&lt;/p&gt;

</description>
      <category>books</category>
      <category>womenintech</category>
    </item>
    <item>
      <title>AI Thoughts in 2025</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Mon, 26 May 2025 13:35:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/ai-thoughts-in-2025-54j0</link>
      <guid>https://dev.to/wsvincent/ai-thoughts-in-2025-54j0</guid>
      <description>&lt;p&gt;Artificial Intelligence (AI) is a broad term describing the overall goal of creating machines that can perform tasks that typically require human intelligence. The term was first coined in 1955 by John McCarthy, a Dartmouth College computer scientist. Today, our everyday lives are drenched in AI, from large language models like ChatGPT to visual recognition features on phones and cameras, recommendation systems on Netflix and Spotify, Google Search, credit card fraud, self-driving cars, and more. It is literally everywhere.&lt;/p&gt;

&lt;p&gt;Within the larger bucket of AI are several major areas, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Machine Learning&lt;/strong&gt;: Systems that learn patterns from data on their own rather than being explicitly programmed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language Processing&lt;/strong&gt;: Programs that can understand, interpret, and generate human text and speech&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computer Vision&lt;/strong&gt;: Allows machines to interpret and understand visual information from images and videos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robotics&lt;/strong&gt;: Combining AI with physical systems to create machines that can act in the real world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until recently, AI relied heavily on expert systems and rule-based programming, where humans had to manually program the computers and provide guidance on how to make decisions. But in recent years, Machine Learning (ML) has taken over as the dominant AI technique because it can handle complex, unstructured data found in the real world, whether that is all the text on the internet, images, videos, or any other type of data. The more data you feed ML systems, the better they typically perform. This fact, combined with advances in processing power through more efficient computer chips and companies able to spend billions of dollars on data centers, means most major AI breakthroughs in the last decade--from AlphaGo beating the best Go player in the world, ChatGPT mimicking human conversations in a chatbot, and newer image and video generators--rely heavily on ML techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risks and Rewards
&lt;/h2&gt;

&lt;p&gt;But in addition to clear potential benefits, machine learning comes with a significant number of risks that are becoming increasingly apparent as these systems are more widely deployed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data and Bias Issues&lt;/strong&gt;: If the dataset given to an ML system is inherently biased, the resulting ML model will be biased, too. For example, many training sets for dermatology focus exclusively on white patients, meaning the model is trained to work well for them but not for patients with darker skin. Or suppose you train an ML model on historical data that contains discrimination. In that case, the model will perpetuate that, such as hiring systems that favor certain demographics, facial recognition systems that work poorly for people with dark skin, and so on. As ML models become more and more pervasive and start to replace humans, how accurate they are becomes important. The 2016 book, &lt;a href="https://en.wikipedia.org/wiki/Weapons_of_Math_Destruction" rel="noopener noreferrer"&gt;Weapons of Math Destruction&lt;/a&gt; goes in-depth on the societal impacts of algorithms, especially as many are used to perpetuate and even exacerbate preexisting inequality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Black Box Problem&lt;/strong&gt;: In many ML systems, especially the deep neural networks used to power LLMs like ChatGPT, the creators can't explain how the model reached specific decisions. Programmers provide an ML model with massive amounts of data, train it with enormous amounts of computer processing, and then evaluate if the end result seems to be accurate. But on the inside is a literal "black box." ML engineers can't recreate the ML models' thought process to understand why a certain decision was made. As these systems become ever more incorporated into daily life--and especially in critical areas such as medicine, science, policing, and finance--the risks of using programs we don't fully understand continue to grow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy and Surveillance&lt;/strong&gt;: ML enables governments and private businesses unprecedented surveillance options via facial recognition, behavior analysis, and data mining. Governments can monitor and control populations on a level never before deemed possible, while companies can engage in "algorithmic wage discrimination," such as nursing gig apps that offer different rates to a nurse based on their credit history. The lower a nurse's credit history--and, by extension, the more desperate they are for money--the lower the rate the app will offer. The hospital and the app pocket the difference in exploiting a person's financial situation. There are similar examples across a growing number of professions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job Loss&lt;/strong&gt;: As ML displaces more tasks, it threatens to displace workers faster than new jobs are created, leading to significant economic and political unrest and most likely exacerbating already record levels of inequality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Education&lt;/strong&gt;: ML models, especially LLMs, are already running rampant in education, where both students and teachers use them. Students use LLMs to write papers, and overworked teachers rely on them to grade large amounts of student work. There is a real risk that as people become more and more dependent on ML systems, they lose critical thinking skills, domain expertise, and the ability to step in should these ML systems start to fail in any way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not hyperbole to state that the current AI explosion is analogous to the Industrial Revolution in the late 19th century: back then, physical labor was mechanized, while today, ML is mental labor and the current knowledge economy. The Industrial Revolution didn't just change how things were made; it completely restructured the economy and politics, creating new classes or workers and concentrating power ever more in the hands of a wealthy elite.&lt;/p&gt;

&lt;p&gt;Both revolutions started with specific applications and then quickly cascaded across society. Steam power began in mining before transforming transportation, manufacturing, and agriculture. ML started in tech companies but is now actively reshaping healthcare, finance, transportation, and even creative industries.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;Machine Learning is on track to radically remake human society. Back in 1930, the English economist John Maynard Keynes wrote a famous essay, &lt;a href="http://www.econ.yale.edu/smith/econ116a/keynes1.pdf" rel="noopener noreferrer"&gt;Economic Possibilities for our Grandchildren&lt;/a&gt;, where he ruminated on the potential changes of future technological progress and economic growth over the next 100 years. He estimated that living standards would increase by 4-8 times, and people would only need to work about 15 hours per week to maintain a comfortable lifestyle. Keynes' main concern was what people would do with all this leisure time once their basic economic needs were met. He worried that humanity might face an existential crisis when work was no longer necessary for survival.&lt;/p&gt;

&lt;p&gt;From 1930 to 2020, in developed countries like the U.K. and the United States, real GDP per capita actually increased 6-7 times, so Keynes was remarkably accurate in his estimate. But he was wrong in his predictions about everyday life. Most people today are forced to work ever longer hours just to get by. Most of the economic gains over the last one hundred years--powered by increases in technology and productivity--have been concentrated in the hands of a few capital-owning elites rather than evenly distributed amongst the general population.&lt;/p&gt;

&lt;p&gt;The question now is what comes next? Will modern political systems adapt quickly enough to manage this transformation? If not, as seems likely, we will find ourselves living through a period of profound social upheaval where unprecedented job losses overlap with ever-more-powerful AI systems that operate beyond democratic control, shaping society according to the narrow wishes and whims of those who build and own them.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>PyCon US 2025 Recap</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Wed, 21 May 2025 16:59:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/pycon-us-2025-recap-2d09</link>
      <guid>https://dev.to/wsvincent/pycon-us-2025-recap-2d09</guid>
      <description>&lt;p&gt;I just attended &lt;a href="https://us.pycon.org/2025/" rel="noopener noreferrer"&gt;PyCon US&lt;/a&gt; this year in Pittsburgh as part of the &lt;a href="https://www.jetbrains.com/pycharm/" rel="noopener noreferrer"&gt;PyCharm&lt;/a&gt; crew. We had a booth in the Sponsors Hall, where I met many attendees. I was able to attend a few open spaces and squeeze in some sightseeing. This was my first time attending in person since 2019, so seeing what has changed over the last six years was interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;The two chairs of PyCon US, Elaine Wong and Jon Banafato, were &lt;a href="https://djangochat.com/episodes/pycon-us-2025-elaine-wong-jon-banafato" rel="noopener noreferrer"&gt;guests on the Django Chat podcast&lt;/a&gt; last month, so for anyone interested in a very in-depth look at the conference and what goes on behind the scenes, I recommend you take a listen!&lt;/p&gt;

&lt;p&gt;It also selfishly gave me a good sense of what to expect. PyCon US is a very big event, with somewhere around three thousand attendees, many talks, open spaces, and more. It can be a bit overwhelming the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thursday, May 15th
&lt;/h2&gt;

&lt;p&gt;I flew in from Boston on an early flight and was surprised to see an enormous T-Rex skeleton at the airport!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fity5vv6f9ca85nrm8d3x.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fity5vv6f9ca85nrm8d3x.jpeg" alt="T-Rex Sculpture in the Pittsburgh Airport" width="768" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;T-Rex Sculpture in the Pittsburgh Airport&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was an evening reception from 5 to 7 p.m., and before that, I needed to help set up the PyCharm booth. Since my flight was very early, I had most of the morning to explore the city.&lt;/p&gt;

&lt;p&gt;The first item on my list was the Duquesne Incline. Pittsburgh is very hilly and sits at the confluence of two major rivers, the Allegheny and Monongahela. These rivers form the Ohio River, which then snakes its way to the Mississippi River. This means that historically, if you controlled Pittsburgh, you controlled the interior of the United States, and as a result, Pittsburgh was very prominent in early wars between the French, British, and U.S. in the late 18th century.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x28ca02jdscxk7llegx.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x28ca02jdscxk7llegx.jpeg" alt="Duquesne Incline" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Duquesne Incline&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Look at the different colors of the two rivers! The Allegheny originates in the northeast, in relatively cleaner, forested regions of Pennsylvania and New York, so its water is often clearer and bluer/greener. The Monongahela comes from the south and tends to carry more sediment and pollutants, giving it a brownish or murkier appearance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubxap323gnwtwxn4quy2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubxap323gnwtwxn4quy2.jpeg" alt="Allegheny and Monongahela Rivers" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Allegheny and Monongahela rivers joining to form the Ohio River&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The conference was held in the very large &lt;a href="https://en.wikipedia.org/wiki/David_L._Lawrence_Convention_Center" rel="noopener noreferrer"&gt;David L. Lawrence Convention Center&lt;/a&gt;. I picked up my badge from registration and added some additional Django flair.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvn9ygs6ges5j669ima6x.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvn9ygs6ges5j669ima6x.jpeg" alt="PyCon Badge" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PyCon Badge&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There was a lot of traffic on the opening night as there were drinks and appetizers on the floor and, most importantly, no competing keynotes or other events!&lt;/p&gt;

&lt;h2&gt;
  
  
  Friday, May 16th
&lt;/h2&gt;

&lt;p&gt;I was on booth duty from 7:30 a.m. the following morning until 6:00 p.m. It was a very full day of doing demos and chatting with people. We also hosted a mid-morning book signing with &lt;a href="https://store.metasnake.com/" rel="noopener noreferrer"&gt;Matt Harrison&lt;/a&gt; and an afternoon one with &lt;a href="https://www.naomiceder.tech/pages/about/" rel="noopener noreferrer"&gt;Naomi Cedar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcoqrnwon7muj3hjxwpy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcoqrnwon7muj3hjxwpy.jpeg" alt="PyCharm Booth" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PyCharm Booth&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg5s1qpu3ciwcqlo6uyu.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhg5s1qpu3ciwcqlo6uyu.jpeg" alt="Sponsors Floor" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sponsors Floor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The primary topic of conversation for us was &lt;a href="https://www.jetbrains.com/junie/" rel="noopener noreferrer"&gt;Junie&lt;/a&gt;, the new coding agent that is part of PyCharm. Attendees were pretty evenly split between those who were well versed in agents and had detailed questions about ours vs. the competition, people who I'd label as "AI-curious" who hadn't used them, and a third group that couldn't use AI at work for privacy or security reasons but was trying them out for their personal usage.&lt;/p&gt;

&lt;p&gt;In the evening, I was planning to have a quiet night, but I got a last-minute invite from Eric Matthes (pictured later on this post) to attend the Pittsburgh Symphony for a performance including &lt;a href="https://pittsburghsymphony.org/production/92963/bronfman-plays-beethoven" rel="noopener noreferrer"&gt;Beethoven, Stravinsky, and Prokofiev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jw3lj5b4tqregfppzyi.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jw3lj5b4tqregfppzyi.jpeg" alt="Pittsburgh Symphony Hall" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pittsburgh Symphony Hall&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It was a fantastic performance, but it resulted in a very late night for me. So it goes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saturday, May 17th
&lt;/h2&gt;

&lt;p&gt;The next morning, I was on booth duty for most of the day. At 10:00am there was a book signing with Eric Matthes, author of the very popular &lt;a href="https://nostarch.com/python-crash-course-3rd-edition" rel="noopener noreferrer"&gt;Python Crash Course&lt;/a&gt;. One of the attendees was Jib Adegunloye, the lead engineer at MongoDB on their new Django backend. I had the pleasure of interviewing him &lt;a href="https://djangochat.com/episodes/official-django-mongodb-backend-jib-adegunloye" rel="noopener noreferrer"&gt;on the Django Chat podcast&lt;/a&gt; back in February.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxr1debtk8owvwnq195f.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgxr1debtk8owvwnq195f.jpeg" alt="Eric Matthes &amp;amp; Jib Adegunloye" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Eric Matthes &amp;amp; Jib Adegunloye&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At 11:00 a.m., I briefly escaped the booth to support my colleague &lt;a href="https://github.com/pauleveritt" rel="noopener noreferrer"&gt;Paul Everitt&lt;/a&gt;, who led an open space on &lt;a href="https://peps.python.org/pep-0750/" rel="noopener noreferrer"&gt;PEP 750—Template Strings&lt;/a&gt;, which was just accepted for Python 3.14. &lt;a href="https://us.pycon.org/2025/schedule/open-spaces/" rel="noopener noreferrer"&gt;Open spaces&lt;/a&gt; are a big deal at PyCon US and one of my favorite features. These are informal meetups on a wide variety of topics that you can just show up for.&lt;/p&gt;

&lt;p&gt;Paul is a co-author of &lt;code&gt;PEP 750&lt;/code&gt;, which introduces &lt;code&gt;t-strings,&lt;/code&gt; an enhanced version of &lt;code&gt;f-strings.&lt;/code&gt; While &lt;code&gt;f-strings&lt;/code&gt; evaluate to &lt;code&gt;str&lt;/code&gt; (a string), &lt;code&gt;t-strings&lt;/code&gt; evaluate to a new type, &lt;code&gt;Template&lt;/code&gt;, which provides a host of additional features. &lt;a href="https://davepeck.org/2025/04/11/pythons-new-t-strings/" rel="noopener noreferrer"&gt;See this article by Dave Peck&lt;/a&gt;, one of PEP-750s authors, for more information on t-strings.&lt;/p&gt;

&lt;p&gt;Also in attendance were two co-authors on the PEP, &lt;a href="https://davepeck.org/about/" rel="noopener noreferrer"&gt;Dave Peck&lt;/a&gt; and &lt;a href="https://github.com/koxudaxi" rel="noopener noreferrer"&gt;Koudai Aono&lt;/a&gt;, as well as &lt;a href="https://davidism.com/" rel="noopener noreferrer"&gt;David Lord&lt;/a&gt;, lead maintainer of Flask and Jinja (which t-strings might impact), and many other heavy hitters. Only at PyCons do you literally have almost all the decision makers for a major new Python feature sit in person in the same room.&lt;/p&gt;

&lt;p&gt;After the meeting, I raced back to the PyCharm booth to help Calvin Hendryx-Parker, CTO at &lt;a href="https://sixfeetup.com/" rel="noopener noreferrer"&gt;Six Feet Up&lt;/a&gt;, who presented a lunchtime talk on &lt;a href="https://www.youtube.com/watch?v=Ix68u1MM3FY&amp;amp;t=1298s" rel="noopener noreferrer"&gt;Battle of the Bots: Which AI Assistant Delivers?&lt;/a&gt;, covering Aider, Claude Code, Cursor, Goose, and Junie.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbi011pywe0w93mv6f8w.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbi011pywe0w93mv6f8w.jpeg" alt="Calvin Hendryx-Parker Talk" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Calvin Hendryx-Parker Talk&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And then, at 3:45pm, there was a book signing by me, of all people, and my book, &lt;a href="https://learndjango.com/courses/django-for-beginners/" rel="noopener noreferrer"&gt;Django for Beginners&lt;/a&gt;. I'm pleased to say we quickly ran through all 25 books on hand, and there were still quite a few people in line, so next year, we'll have to order more books!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sunday, May 18th
&lt;/h2&gt;

&lt;p&gt;At 7:00am sharp, I headed off on a run with my colleague Galina, the PyCharm Product Manager, who is also a competitive ultramarathon runner. There are some great running routes in Pittsburgh along the rivers and bridges. I am a casual runner at this point in my life, so the plan was that I'd run with her four or so miles and then turn around to head back into town at an equal distance. She continued on for a two-hour tempo run, while I got lost going back--at one point ending up 50 feet in the air along a railroad track that I thought was a shortcut but turned out not to be--and the overall return journey turned into a lot longer slow run/walk than expected. I didn't bring my phone, or I would have some pretty dramatic photos to show from this detour.&lt;/p&gt;

&lt;p&gt;After finally making it back to the hotel and showering, I was ready for a proper breakfast. I headed to Sally Ann's just down the street, which had excellent avocado toast and a cappuccino.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiojht454s4qufj0kwph.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiojht454s4qufj0kwph.jpeg" alt="Sally Ann's Breakfast" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sally Ann's Breakfast&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, it was off to the convention center for more open spaces on topics including Django simple deployments, high-performance Django, and AI evals. All three gave me a lot to think about.&lt;/p&gt;

&lt;p&gt;Given the long run/walk earlier, I was pretty well famished at this point, so I made it over to Bae Bae's Kitchen for a Bulgogi and egg seaweed burrito.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv357dsmggnj2552ovk22.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv357dsmggnj2552ovk22.jpeg" alt="Seaweed Burrito" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Seaweed Burrito&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, it was more socializing with friends and colleagues and a recap with the entire PyCharm team from 8 to 10 p.m. that evening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monday, May 19th
&lt;/h2&gt;

&lt;p&gt;I had an early flight back to Boston, so I was out the door by 7 a.m. and home in time to pick up my son from preschool. A short flight in the same time zone is a gift versus longer trips overseas.&lt;/p&gt;

&lt;p&gt;Overall, it was a jam-packed trip. I saw Pittsburgh for the first time, learned a lot, and interacted with hundreds of people about PyCharm and our new AI features. As there always is with PyCons, there is a lot to take away. If you have the opportunity, I strongly recommend attending one yourself in the future!&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>What's Happening in Developer Tools? (OpenAI Just Bought Windsurf for $3B)</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Wed, 07 May 2025 23:22:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/whats-happening-in-developer-tools-openai-just-bought-windsurf-for-3b-3k63</link>
      <guid>https://dev.to/wsvincent/whats-happening-in-developer-tools-openai-just-bought-windsurf-for-3b-3k63</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I work at JetBrains, a competitor in this space, and all comments are my own.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yesterday &lt;a href="https://www.reuters.com/business/openai-agrees-buy-windsurf-about-3-billion-bloomberg-news-reports-2025-05-06/" rel="noopener noreferrer"&gt;it was announced&lt;/a&gt; that OpenAI was buying Windsurf, an AI-first code editor, for $3 billion. This is a pretty amazing feat considering that Windsurf has only been Windsurf &lt;a href="https://windsurf.com/blog/windsurf-launch" rel="noopener noreferrer"&gt;since November 2024&lt;/a&gt;, a long seven months ago. Before that, it was Codeium, an AI-complete tool that plugged into existing IDEs like VS Code and JetBrains. And before that, way back in 2021, it was founded as Exafunction, which focused on optimizing GPU usage for Machine Learning workloads.&lt;/p&gt;

&lt;p&gt;A $3B acquisition is indeed extreme, considering Windsurf's annualized recurring revenue (ARR) is &lt;a href="https://techcrunch.com/2025/04/16/openai-is-reportedly-in-talks-to-buy-windsurf-for-3b-with-news-expected-later-this-week/" rel="noopener noreferrer"&gt;reportedly $40m&lt;/a&gt;, which makes it a 75x acquisition premium. For context, a typical premium for a mature Software-as-a-Service (SaaS) business is 3-7x, for high-growth, 8-15x, and for hypergrowth, 15-25x. When Microsoft bought GitHub in 2018, it was at a reported &lt;a href="https://www.cnbc.com/2018/06/05/github-interest-from-google-and-others-revenue-about-300-million.html" rel="noopener noreferrer"&gt;25x premium&lt;/a&gt;. Windsurf's 75x multiple is literally off the charts.&lt;/p&gt;

&lt;p&gt;And remember, this is revenue, not profit. Most of Windsurf's revenue is directly related to LLM usage, ie. collecting money from customers and using that to buy tokens from LLM providers like OpenAI or Anthropic.&lt;/p&gt;

&lt;p&gt;OpenAI just raised &lt;a href="https://techcrunch.com/2025/03/31/openai-raises-40b-at-300b-post-money-valuation/" rel="noopener noreferrer"&gt;$40B at a $300B valuation&lt;/a&gt;, meaning they acquired Windsurf for 1% of their current value. But at the same time, OpenAI reportedly &lt;a href="https://finance.yahoo.com/news/openai-thinks-revenue-more-triple-210900736.html" rel="noopener noreferrer"&gt;lost $5B in 2024&lt;/a&gt;, and their own coding agent, &lt;a href="https://github.com/openai/codex" rel="noopener noreferrer"&gt;codex&lt;/a&gt;, has had middling success. Clearly they were feeling pressure to "do something." It has been widely reported that they were interested in acquiring &lt;a href="https://www.cursor.com/en" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;, the leading startup AI-powered coding editor, yet the price was too high. Cursor was founded in 2022 and just raised a &lt;a href="https://pitchbook.com/news/articles/anysphere-cursor-ai-coding-doubling-valuation-every-8-weeks" rel="noopener noreferrer"&gt;$900m Series C round at a $9B valuation&lt;/a&gt; on the back of doubling its ARR from $100m to $200m over the last two months. Clearly, something is afoot!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Current Developer Tooling Ecosystem
&lt;/h2&gt;

&lt;p&gt;At the moment, the developer tooling ecosystem contains a dizzying mix of companies, products, and goals. Let's try to break it down and see where all these forces interact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F813qrsudgchz2ffmh5o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F813qrsudgchz2ffmh5o6.png" alt="Image of 2 Robots and a Road to the Future" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: LLM Models
&lt;/h2&gt;

&lt;p&gt;First, there are the LLM models powering the current craze: ChatGPT from OpenAI, Claude from Anthropic, Gemini from Google, and &lt;a href="https://llm-stats.com/" rel="noopener noreferrer"&gt;many more&lt;/a&gt;. Some of these models are proprietary, others like &lt;a href="https://www.deepseek.com/en" rel="noopener noreferrer"&gt;DeepSeek&lt;/a&gt; and &lt;a href="https://www.llama.com/" rel="noopener noreferrer"&gt;Facebook's Llama&lt;/a&gt; are "somewhat open," and others like &lt;a href="https://mistral.ai/" rel="noopener noreferrer"&gt;Mistral&lt;/a&gt; and &lt;a href="https://news.microsoft.com/source/features/ai/the-phi-3-small-language-models-with-big-potential/" rel="noopener noreferrer"&gt;Phi-3 from Microsoft&lt;/a&gt; are truly open.&lt;/p&gt;

&lt;p&gt;Amongst the general public, ChatGPT has the headstart and the branding, yet Claude by Anthropic is the clear leader amongst developers who are willing to pay real money for it. Thus, even as ChatGPT has been succeeding in growth, it has not managed to tap into what is currently the most lucrative part of the market. Claude's advantage means that it gets something even more valuable: data. When a developer uses a cloud LLM, they send their context (aka their coding files/projects/etc) to the LLM provider, who can evaluate how successful the responses were, retrain the model, and so on. This also means an LLM can slice and dice its customer base to find out what types of developers and companies use what.&lt;/p&gt;

&lt;p&gt;If LLMs eventually start adding ad-supported tiers—and I think it is inevitable that they will, given that &lt;a href="https://www.honest-broker.com/p/the-worlds-largest-search-doesnt" rel="noopener noreferrer"&gt;search is clearly broken&lt;/a&gt;-then they will want to harvest as much customer data as possible for targeting. It is likely that the current emphasis on result quality will face pressures around revenue, and so on. But that's a separate thread.&lt;/p&gt;

&lt;p&gt;The more immediate issue is that it is unclear currently whether the hundreds of billions of dollars invested into LLMs will result in truly proprietary models that can charge a premium or whether the space will be eventually commoditized. There are even newer smaller models focused just on a specific task; for example, JetBrains just open-sourced &lt;a href="https://blog.jetbrains.com/ai/2025/04/mellum-goes-open-source-a-purpose-built-llm-for-developers-now-on-hugging-face/" rel="noopener noreferrer"&gt;Mellum&lt;/a&gt;, its own coding LLM. &lt;/p&gt;

&lt;p&gt;The fact that &lt;a href="https://finance.yahoo.com/news/deepseek-tech-wipeout-erases-more-052250534.html" rel="noopener noreferrer"&gt;DeepSeek's launch&lt;/a&gt; in January led to a $1T (that's trillion, by the way, with a T) stock market loss speaks to fears that maybe all this investment in proprietary LLM models costing billions of dollars isn't an infinite pile of cash to collect. Perhaps only a few million dollars is needed. And what if your competitor gives away the model for free?&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Apps
&lt;/h2&gt;

&lt;p&gt;Then there are the apps. These days, almost every startup and company is "AI-powered," a deliberately broad term that deserves unpacking. But for this analysis, let's focus on text editors like Windsurf, that sell AI-powered coding editors to developers.&lt;/p&gt;

&lt;p&gt;Microsoft's &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; is a free code editor that relies on community plugins for support across various languages and frameworks. It also has an AI offering, &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;Copilot&lt;/a&gt;, that provides code completion and it just added its own agent. VSCode supports multiple LLMs, but initially, there seemed to be a preference for ChatGPT, in part given its early lead and no doubt influenced by the fact Microsoft &lt;a href="https://finance.yahoo.com/news/microsoft-invested-nearly-14-billion-000512844.html" rel="noopener noreferrer"&gt;was an early investor in it&lt;/a&gt;. However, that relationship seems to be fraying.&lt;/p&gt;

&lt;p&gt;Cursor and Windsurf are &lt;a href="https://github.com/microsoft/vscode" rel="noopener noreferrer"&gt;forks of VSCode&lt;/a&gt;, which means the developers copied the open-source VSCode code base and then modified it on their own to add AI and other features. That's why relatively small startup teams of recent college graduates could make such progress, taking an existing and relatively mature project and focusing on just the AI integration.&lt;/p&gt;

&lt;p&gt;Somewhat predictably, though, Microsoft has started to &lt;a href="https://ainativedev.io/news/microsofts-going-to-war" rel="noopener noreferrer"&gt;restrict access to the VSCode Marketplace&lt;/a&gt; and popular extensions. Presumably, Cursor and Windsurf have the resources to recreate and manage these things. Still, it is a lot less glamorous than focusing on the fun AI parts and will consume company attention and money. This is just the latest iteration of Microsoft's famous &lt;a href="https://en.wikipedia.org/wiki/Embrace,_extend,_and_extinguish" rel="noopener noreferrer"&gt;"Embrace, extend, and extinguish"&lt;/a&gt; strategy, first seen in the United States government's antitrust legal case against it in the 1990s:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Embrace&lt;/strong&gt; - Development of open source software and standards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extend&lt;/strong&gt; - Add features, creating inoperability problems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extinguish&lt;/strong&gt; - When extensions become de facto standards, marginalize competitors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are other AI agents and text editors out there, including &lt;a href="https://replit.com/" rel="noopener noreferrer"&gt;Replit&lt;/a&gt;, &lt;a href="https://zed.dev/" rel="noopener noreferrer"&gt;Zed&lt;/a&gt;, and many others, but if you say AI text editor at the moment, most people will think of Cursor/Windsurf/VSCode.&lt;/p&gt;

&lt;p&gt;A fourth option in this space is my employer, &lt;a href="https://www.jetbrains.com/" rel="noopener noreferrer"&gt;JetBrains&lt;/a&gt;, a privately held European company that has been around for over 20 years and creates popular free and paid tools for developers. JetBrains has been aggressively improving its own &lt;a href="https://www.jetbrains.com/ai/" rel="noopener noreferrer"&gt;AI offerings&lt;/a&gt;, including &lt;a href="https://www.jetbrains.com/ai-assistant/" rel="noopener noreferrer"&gt;AI Assistant&lt;/a&gt; that integrates chat mode with leading LLM models and its own coding agent, &lt;a href="https://www.jetbrains.com/junie/" rel="noopener noreferrer"&gt;Junie&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is worth pointing out that JetBrains does not have the same funding pressures as VC-backed startups. It does not have an expensive LLM model to maintain and market. It does not have a $2T market cap and other offerings like Microsoft. JetBrains is focused solely on developer tools, primarily text editors. &lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: The Future
&lt;/h2&gt;

&lt;p&gt;So where does this analysis of current models and apps leave us? Are we in a bubble or a new age where developer tools are worth tens of billions of dollars?&lt;/p&gt;

&lt;p&gt;One possibility is that the total market for developer tools has greatly expanded now that "vibe coders," aka non professional programmers who want to build software, can now do so with the help of AI. I think there is a definite limit to how much a non-technical person can build, but there's no question they can do a lot more than before and they are willing to pay for it.&lt;/p&gt;

&lt;p&gt;But even if the total market has grown and doesn't contract in the future, I'm still somewhat skeptical that the current pace is sustainable. After all, where will we be in just 2-3 years if OpenAI and Anthropic, both VC-backed and losing billions, have failed to either greatly improve their models to ChatGPT 5 levels and/or stop losing money? And what about Google, which has its own Gemini model but no coding editor to speak of? Given its current valuation, it seems the natural--and, indeed, the only--company capable of buying Cursor.&lt;/p&gt;

&lt;p&gt;But how much value is there in the app compared to the underlying LLM model? I'm partial to the hypothesis that smaller, potentially local, and maybe even "free" models will win out. That puts the emphasis back on the integration with the text editor.&lt;/p&gt;

&lt;p&gt;A final point is that AI certainly has a place in software development and will only grow in the future. But is it a total replacement or just a new tool developers must adopt? I agree with Tim O'Reilly here, who wrote a fantastic piece called &lt;a href="https://www.oreilly.com/radar/the-end-of-programming-as-we-know-it/" rel="noopener noreferrer"&gt;The End of Programming as We Know It&lt;/a&gt; that provides some historical context for the current hype, pointing out that there have been radical changes in the recent past, from desktop to internet programming, from compiled to interpreted languages, and so on.&lt;/p&gt;

&lt;p&gt;Marie-Alice Blete has a wonderful graphic illustration of the &lt;a href="https://malywut.github.io/ai-engineering-landscape/" rel="noopener noreferrer"&gt;current AI engineering landscape&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl2z46ohpk772v6hxv0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl2z46ohpk772v6hxv0t.png" alt="AI Engineering Landscape Image" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there is one person I personally look to for insight into what's coming, it is Simon Willison, who writes regularly and knowledgeably about these trends. In January, he posted an annual &lt;a href="https://simonwillison.net/2025/Jan/10/ai-predictions/" rel="noopener noreferrer"&gt;My AI/LLM predictions for the next 1, 3, and 6 years&lt;/a&gt; that provides a fantastic analysis of what might occur.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>openai</category>
      <category>llm</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Thoughts on Vibe Coding</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Tue, 06 May 2025 14:28:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/thoughts-on-vibe-coding-2pn5</link>
      <guid>https://dev.to/wsvincent/thoughts-on-vibe-coding-2pn5</guid>
      <description>&lt;p&gt;After reading yet another AI hype article--this one by Kevin Roose at the New York Times &lt;a href="https://www.nytimes.com/2025/02/27/technology/personaltech/vibecoding-ai-software-programming.html?unlocked_article_code=1.0U4.GoA9.S9IxqL6EzxZJ&amp;amp;smid=url-share" rel="noopener noreferrer"&gt;gift link here&lt;/a&gt;--I feel compelled to respond.&lt;/p&gt;

&lt;p&gt;Let's look at the title:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nytimes.com/2025/02/27/technology/personaltech/vibecoding-ai-software-programming.html?unlocked_article_code=1.0U4.GoA9.S9IxqL6EzxZJ&amp;amp;smid=url-share" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzj9z4qr3uonjax4qn3f1.png" alt="NYTimes Headline" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could easily swap out "Not a Coder" with just about any profession. Not a writer? Not a doctor? Not a lawyer? Not an engineer?&lt;/p&gt;

&lt;p&gt;The idea that you can whole swath replace an entire field or area of expertise is wrong on a number of levels. So here we go.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Current AI Is Not Intelligence
&lt;/h2&gt;

&lt;p&gt;All the evidence we have is that current AI does not appreciate actual intelligence. See Gary Marcus's prescient take in 2022, &lt;a href="https://nautil.us/deep-learning-is-hitting-a-wall-238440/" rel="noopener noreferrer"&gt;Deep Learning is Hitting a Wall&lt;/a&gt;, for more on this. What &lt;em&gt;has happened&lt;/em&gt; is that existing LLMs turn out to do really well with huge amounts of data and compute power.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. AI vs LLMs
&lt;/h2&gt;

&lt;p&gt;It's also important to note that AI and LLMs are not synonymous, even though it is common to see journalists and others in popular media conflate the two terms. "AI" is a very large field and applies to much more than just Large Language Models. For example, DeepMind's AlphaFold used deep learning to predict protein structures (see the &lt;a href="https://www.nature.com/articles/s41586-021-03819-2" rel="noopener noreferrer"&gt;Nature article&lt;/a&gt;) and this resulted in the 2024 Nobel Prize in Chemistry for members of the team.&lt;/p&gt;

&lt;p&gt;But that is not what LLMs do. Rather, they ingest large amounts of data--think downloading most of the internet such as Reddit and Wikipedia, not to mention copyrighted books--run them through algorithms, do fine-tuning, and the result is a probabilistic mathematical function that predicts the next word in a sequence. In other words, LLMs try to predict the next response to any user input. There is not currently any actual "intelligence" there.&lt;/p&gt;

&lt;p&gt;However, modern LLMs are powerful enough that they can seem intelligent and indeed do well on standard measures of intelligence, such as taking the SAT or answering math questions. Yet if I preloaded all SAT questions ever into a computer and then asked it to answer them, and it got the right answers, is that intelligence or just memorizing? It's not really intelligence.&lt;/p&gt;

&lt;p&gt;Similarly, LLMs are a long way away from actual AGI (Artificial General Intelligence), a theoretical form of AI that has or exceeds human reasoning.&lt;/p&gt;

&lt;p&gt;So AI is a real thing, a deep field with lots of applications, of which LLMs are just a subset, albeit the most popular one amongst the general public at the moment. Take a lot of data and run it through algorithms, and the result is something that tries to predict the right response.&lt;/p&gt;

&lt;p&gt;Andrej Karpathy's &lt;a href="https://youtu.be/zjkBMFhNj_g?si=QSFf6hCBWOd5YRwE" rel="noopener noreferrer"&gt;Intro to Large Language Models&lt;/a&gt; video is one of the best resources out there to actually explain how LLMs work, if you want to dive deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Vibe Coding
&lt;/h2&gt;

&lt;p&gt;Vibe coding means using an LLM in a modern text editor to generate all your code for you. Rather than actually code, you say things like, "Build me a website that helps choose lunch." And away the LLM will go, churning out code for you. From there, you can ask it to refine and use specific technologies or features.&lt;/p&gt;

&lt;p&gt;It is possible in &lt;em&gt;some&lt;/em&gt; contexts to have a working website this way, provided it is doing routine tasks and you don't have to really trust it. Why? Because the LLM has been trained on billions of lines of code by human programmers, so it is quite good at trying to predict how to do that. However, two major problems emerge.&lt;/p&gt;

&lt;p&gt;First, what happens when you want to do something that needs to be 100% correct? For example, building a website that handles payments in some way? Or manages user information that must be private? LLMs still wildly hallucinate and if you are not knowledgeable yourself, there is no way to tell when your code has deep-seated errors. Second, if you've used an LLM to write hundreds of lines of code you don't understand, there is no way to go in and meaningfully change things yourself. An LLM will want to rewrite and repredict most of it, not laser focus on a particular area. And if you don't know what the code is doing, how can you even tell the LLM where to start?&lt;/p&gt;

&lt;p&gt;This speaks to the larger truth that most of programming is reading and understanding existing code. It is not starting with a blank canvas and creating things from scratch. Programmers typically work in teams on complex codebases with millions of lines of code. If just one person puts in a serious mistake, it can cause the whole artifice to stop functioning correctly or, worse, to have hard-to-find bugs that result in big problems.&lt;/p&gt;

&lt;p&gt;If I were to ask 10 experienced developers today to build the same membership website that handles user accounts and payments, they would all do it slightly differently. Which way is right or wrong? If you have no programming knowledge yourself, it is hard to weigh in on decisions. Hard to evaluate any of them? If it's hard to do this even with experts, how can you expect a statistical function to do better on its own that you lack the capacity to evaluate? That's a long way of saying, someone somewhere needs to actually understand--or have the ability to understand--what is actually happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Using LLMs Today
&lt;/h2&gt;

&lt;p&gt;I've spent most of this post talking &lt;em&gt;against&lt;/em&gt; LLMs, but it's important to note that I personally use them daily, not as a replacement for my thinking or writing or programming, but as a drunken partner. By that, I mean LLMs are fantastic for generating ideas based on a topic. For example, "I want to build a membership website with payments and user accounts, what are 5 different ways I could architect it." This is useful and something I have done recently, because it provides an overview of existing approaches. From there I can dig deeper, asking questions about design decisions, and even asking for specific pieces of code. But the "drunken" part of my description is important: &lt;strong&gt;I don't trust the LLM&lt;/strong&gt;. And I shouldn't. It is a guessing partner that can help me be creative, &lt;em&gt;sometimes&lt;/em&gt; can find bugs or help with things, but it all has to be run through a human filter that has some domain knowledge.&lt;/p&gt;

&lt;p&gt;In this way, I think of LLMs as similar to Steve Jobs's description of computers as, "A bicycle for your mind." With them you can travel much further, but they don't replace your mind. And I suspect they never well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I'll end this piece with something I've been thinking a lot about recently. Let's assume an Artificial General Intelligence (AGI) is actually created that far exceeds human capabilities. How would we even know that? Even if it came to seemingly correct decisions, if we do not understand its reasoning--and with current LLM approaches it is impossible to derive how, exactly, the models reasoned on something--then what value does it have?&lt;/p&gt;

&lt;p&gt;We are already in a world awash with more facts and knowledge than ever before, and yet our everyday and political discourse has never been dumber. I highly doubt there is an actual AGI out there. Instead I think there are increasingly powerful tools that enable educated humans to be better (and learn more) about what they are trying to master.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final, Final Thoughts
&lt;/h2&gt;

&lt;p&gt;As a fun exercise, try using an LLM to write an article like the author's mentioned at the top of the page. If you prompt it with, "Write a New York Times article in the style of Kevin Roose that explores vibe coding and the idea that you don't have to be a programmer but can instead just use artificial intelligence." The result won't be as good as what he wrote, but it will be pretty close. And more importantly, how many readers will really be able to tell the difference between the two? Especially if they are just going to copy and paste the article into an LLM and ask for a short description of it, rather than read the whole thing themselves. 😛&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>Vibe Recap of DjangoCon Europe 2025</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Tue, 06 May 2025 14:08:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/vibe-recap-of-djangocon-europe-2025-571n</link>
      <guid>https://dev.to/wsvincent/vibe-recap-of-djangocon-europe-2025-571n</guid>
      <description>&lt;p&gt;&lt;a href="https://2025.djangocon.eu/" rel="noopener noreferrer"&gt;DjangoCon Europe 2025&lt;/a&gt; was in Dublin, Ireland, this year, and I was fortunate enough to attend, thanks to my employer, &lt;a href="https://www.jetbrains.com/" rel="noopener noreferrer"&gt;JetBrains&lt;/a&gt;. This is my second time attending a European DjangoCon, the first being in &lt;a href="https://2023.djangocon.eu/" rel="noopener noreferrer"&gt;2023 in Edinburgh, Scotland&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Compared to U.S. DjangoCons, the European version feels a bit more intimate. Rather than two separate tracks of talks (as in the U.S.), there was one room for the main talks and a smaller side room for workshops and other events, which meant that most people attended the same events.&lt;/p&gt;

&lt;p&gt;I recorded a &lt;a href="https://djangochat.com/episodes/djangocon-europe-2025-recap" rel="noopener noreferrer"&gt;Django Chat podcast&lt;/a&gt; on the conference if you prefer your info in audio format, but then you'll miss out on some of the pictures below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ireland Pre-Conference
&lt;/h2&gt;

&lt;p&gt;The week before coincided with my children's school vacation week, so we took our first overseas trip together, exploring the country's southwest corner, namely Killarney and Ennistymon. Unsurprisingly, Ireland is beautiful, wet, and very rural. I'd love to return and spend more time soaking it all in. Here are a few highlights:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwwf1f4haddybsjfm8iq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwwf1f4haddybsjfm8iq.jpeg" alt="Cliffs of Moher" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;The Cliffs of Moher&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6faxse5al68f2xgce7z.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6faxse5al68f2xgce7z.jpeg" alt="The Burren" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;The Burren&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijdsvnhusi65f38waxac.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijdsvnhusi65f38waxac.jpeg" alt="Inishmore" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Inishmore&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98bi5vk9uyeky94a19bl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98bi5vk9uyeky94a19bl.jpeg" alt="Irish Breakfast" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Typical Irish Breakfast&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmok4cmuqvtm005yv67k.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmok4cmuqvtm005yv67k.jpeg" alt="Fish and Chips" width="800" height="1066"&gt;&lt;/a&gt; &lt;em&gt;Typical Irish Dinner&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 0 (Tuesday)
&lt;/h2&gt;

&lt;p&gt;The night before the conference I met &lt;a href="https://noumenal.es/" rel="noopener noreferrer"&gt;Carlton Gibson&lt;/a&gt; at the airport and traveled down to the conference venue, the &lt;a href="https://www.talbothotelstillorgan.com/" rel="noopener noreferrer"&gt;Talbot Hotel Stillorgan&lt;/a&gt;. There is a very convenient &lt;a href="https://www.aircoach.ie/" rel="noopener noreferrer"&gt;Aircoach bus&lt;/a&gt; option, but given it was quite late and pouring rain, we opted to share a taxi instead.&lt;/p&gt;

&lt;p&gt;There were too many talks and workshops to give them all justice, so what follows is a series of highlights based on what I could attend in person.&lt;/p&gt;

&lt;p&gt;Eventually, all talks will be on YouTube. I will add a link to that playlist when it is live, but you can subscribe now to the &lt;a href="https://www.youtube.com/@DjangoConEurope" rel="noopener noreferrer"&gt;DjangoCon Europe YouTube account&lt;/a&gt; to be notified when they are live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 1 (Wednesday)
&lt;/h2&gt;

&lt;p&gt;The day started with a keynote from Django Fellow &lt;a href="https://github.com/sarahboyce" rel="noopener noreferrer"&gt;Sarah Boyce&lt;/a&gt; titled "Django needs you! (to do code review). " She discussed the current review process and why it takes so long, which is a source of frustration for everyone. I enjoyed her overview of the bottlenecks in the current system, as well as a lively question-and-answer session afterward about all things Django.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kxmr72q6wpubjvxvwea.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kxmr72q6wpubjvxvwea.jpeg" alt="Sarah Boyce" width="800" height="1066"&gt;&lt;/a&gt; &lt;em&gt;Sarah Boyce giving the opening keynote.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next up, &lt;a href="https://djangochat.com/episodes/e-commerce-jacob-rief-PfU7JFNf" rel="noopener noreferrer"&gt;Jacob Rief&lt;/a&gt; gave a great talk on "End-to-end testing Django applications using Pytest with Playwright," probably the most popular testing pattern I see these days, and he had a lot of examples and insight into why it's such a powerful combination. You don't &lt;em&gt;have&lt;/em&gt; to use Pytest--in fact, I don't use it on &lt;a href="https://learndjango.com" rel="noopener noreferrer"&gt;LearnDjango.com&lt;/a&gt;--but on an intermediate and advanced code base, it can be much faster than &lt;a href="https://docs.djangoproject.com/en/5.1/topics/testing/" rel="noopener noreferrer"&gt;Django's testing framework&lt;/a&gt; and comes with a ton of extra goodies around testing.&lt;/p&gt;

&lt;p&gt;Tim Bell was the following speaker and talked about his current work at &lt;a href="https://kraken.tech/" rel="noopener noreferrer"&gt;Kraken&lt;/a&gt;, converting integer fields to bigint using Django migrations at a massive scale.&lt;/p&gt;

&lt;p&gt;Before lunch, &lt;a href="https://adamj.eu/" rel="noopener noreferrer"&gt;Adam Johnson&lt;/a&gt; presented on writing indexes to improve your queries, another perennial topic for at-scale Django apps.&lt;/p&gt;

&lt;p&gt;During the afternoon, the workshop room had a Q&amp;amp;A with the &lt;a href="https://www.djangoproject.com/foundation/" rel="noopener noreferrer"&gt;Django Software Foundation Board&lt;/a&gt;. Four board members were present--Thibaud, Sarah, Tom, and Paolo--and there was a presentation on the current state of things, work in progress on various new initiatives, and then lively questions from the audience. The Django Board meets monthly and online, so conferences like this are one of the few opportunities for them to meet in person and with the broader Django community.&lt;/p&gt;

&lt;p&gt;In the evening, &lt;a href="https://django.social/" rel="noopener noreferrer"&gt;Django Social&lt;/a&gt; held an event in downtown Dublin, but I was fairly tired, so I took what &lt;a href="https://github.com/kojoidrissa" rel="noopener noreferrer"&gt;Kojo Idrissa&lt;/a&gt; has termed a &lt;a href="https://kojoidrissa.com/conferences/noramgt/2019/05/01/fail_recover_selfcare.html" rel="noopener noreferrer"&gt;self-care sprint&lt;/a&gt;. I spent a quiet night having dinner by myself and walked down to the water. In his words, "Self-care sprints make EVERY OTHER Sprint sustainable."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41v8b6vgf18r1g0vnv4f.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41v8b6vgf18r1g0vnv4f.jpeg" alt="Train" width="800" height="1066"&gt;&lt;/a&gt; &lt;em&gt;Commuter train running alongside a park and the sea with Dublin in the distance.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2 (Thursday)
&lt;/h2&gt;

&lt;p&gt;I felt much refreshed this morning, and several people even commented that I seemed more like myself than I was on the first day. So, self-care sprint for the win!&lt;/p&gt;

&lt;p&gt;The opening keynote was by &lt;a href="https://clytaemnestra.github.io/tech-blog/" rel="noopener noreferrer"&gt;Mia Bajić&lt;/a&gt; on "The Most Bizarre Software Bugs in History." It was a super engaging talk and one I highly recommend watching when the video comes out. It's not Django-specific but relates more generally to software bugs and how things can/do go wrong.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0lyww1iwwnisa3jcijy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo0lyww1iwwnisa3jcijy.jpeg" alt="Mia Bajić" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Mia Bajić presenting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next up was "How to get Foreign Keys horribly wrong in Django" by &lt;a href="https://hakibenita.com/" rel="noopener noreferrer"&gt;Haki Benita&lt;/a&gt;, and if I had to vote on the single most impressive technical talk I saw, it was this. He &lt;em&gt;really&lt;/em&gt; knows his stuff on databases and Django and the talk was more like a university lecture, mixing examples with audience interaction. Unsurprisingly, he also teaches online live training with O'Reilly, and I need to take some of his classes.&lt;/p&gt;

&lt;p&gt;After Haki's talk, my &lt;a href="https://djangochat.com" rel="noopener noreferrer"&gt;podcast co-host Carlton Gibson&lt;/a&gt; spoke on "How we make decisions in Django" because there is a lot of concern that Django's current decision-making process is no longer working. To quote his abstract of the talk, "New feature requests often hit a wall, as an endless discussion thread arises for even the smallest proposal. New contributors are frustrated. Established contributors are exhausted. It's not serving anyone." He provided an overview of how we got here and suggested several ways to improve things. The talk also dovetails with the work he and others are doing on the new &lt;a href="https://www.djangoproject.com/weblog/2024/dec/18/django-6x-steering-council-election-results/" rel="noopener noreferrer"&gt;Django Steering Council&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftunu7heaeubpngo0x9s9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftunu7heaeubpngo0x9s9.jpeg" alt="Carlton Gibson" width="800" height="1066"&gt;&lt;/a&gt; &lt;em&gt;Carlton Gibson presenting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After his talk, I had to find a quiet room and work on the slides for my own presentation. One downside of presenting is that you can't fully relax until your talk is over.&lt;/p&gt;

&lt;p&gt;After lunch, Carlton and I celebrated his talk and had a few drinks at the bar. While there, we met &lt;a href="https://pretalx.evolutio.pt/djangocon-europe-2025/talk/YHVBFJ/" rel="noopener noreferrer"&gt;Wouter Steenstra&lt;/a&gt; and colleagues from &lt;a href="https://monitdata.com/" rel="noopener noreferrer"&gt;Monit&lt;/a&gt; a Dutch platform for tracking and measuring parking data. He had just given his own talk, "100 Million Parking Transactions Per Year with Django," and so we had a hallway track meetup of sorts over beers.&lt;/p&gt;

&lt;p&gt;In the evening, there was a Speakers' Dinner at &lt;a href="https://www.eddierockets.ie/" rel="noopener noreferrer"&gt;Eddie Rocket's&lt;/a&gt;, an American diner-themed restaurant nearby. I always enjoy these evenings because it's a chance to meet other speakers and have a somewhat quieter discussion about things. After dinner, many people headed to a nearby bar to continue socializing but I had to retire early as I was presenting the following morning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6yjiqxgw1281uzdzpyx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6yjiqxgw1281uzdzpyx.jpg" alt="Speakers's Dinner après" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Speakers's Dinner après (photo courtesy of Paolo Melchiorre).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3 (Friday)
&lt;/h2&gt;

&lt;p&gt;I led off the morning by giving a keynote talk on &lt;a href="https://speakerdeck.com/wsvincent/django-for-data-science-djangocon-europe-2025-keynote" rel="noopener noreferrer"&gt;Django for Data Science&lt;/a&gt; that showed how to train a machine learning model from scratch in a Jupyter notebook and then deploy it using Django. Along the way, there are lots of points about data science generally and how it can/should integrate more closely with web development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16mvcz1c5x6owhu78mfs.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16mvcz1c5x6owhu78mfs.jpeg" alt="Will Vincent" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Will Vincent presenting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can try out the live version of the demo at &lt;a href="https://djangofordatascience.com" rel="noopener noreferrer"&gt;DjangoForDataScience.com&lt;/a&gt;. Here is the &lt;a href="https://github.com/wsvincent/iris_ml" rel="noopener noreferrer"&gt;Jupyter notebook repo&lt;/a&gt; and the &lt;a href="https://github.com/wsvincent/django_irisml" rel="noopener noreferrer"&gt;Django repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think Django is perfectly placed to be the default way  data scientists post their information and interact with users. After all, it's already in Python, comes with built-in batteries for most of what's needed--CRUD, auth, security--yet most data scientists find the web and Django in particular quite confusing.&lt;/p&gt;

&lt;p&gt;If I'm able to do an updated version of this talk, I'd like to dive more into two areas. First, more focus on the actual training of the model part using &lt;code&gt;scikit-learn&lt;/code&gt;. There are &lt;em&gt;a ton&lt;/em&gt; of built-in algorithms for supervised (labeled data) and unsupervised (unlabeled data) learning. Just as Django abstracts away much of the low-level coding required to build a web framework, so too does &lt;code&gt;scikit-learn&lt;/code&gt; abstract away a lot of difficulty coding required if you were to craft this algorithms from scratch yourself.&lt;/p&gt;

&lt;p&gt;The second area I'd dive deeper on is completing the feedback loop. Currently, we trained an ML model, presented it to users, and recorded the results. But in the real world, a data scientist would want to take those records and use them to retrain the model iteratively. Think of a recommendation engine for books as one example. In fact, my colleague Jodie Burchell has an excellent free course on this topic if you're interested, &lt;a href="https://youtu.be/Q7mS1VHm3Yw?si=mZngnEShBHiP-IIA" rel="noopener noreferrer"&gt;LLM Course – Build a Semantic Book Recommender (Python, OpenAI, LangChain, Gradio)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After my talk, it was time for &lt;a href="https://www.paulox.net/" rel="noopener noreferrer"&gt;Paolo Melchiorre&lt;/a&gt; to present on &lt;a href="https://djangonaut.space/" rel="noopener noreferrer"&gt;Djangonaut Space&lt;/a&gt;, an amazing program that has paired experienced Django contributors with newcomers.&lt;/p&gt;

&lt;p&gt;At the coffee break, many people came up to discuss data science with me. Several people in attendance were using Django and data science professionally, so I wanted to learn as much as I could from them about how these two domains are being combined in the real world.&lt;/p&gt;

&lt;p&gt;I want to mention that the food at the conference was excellent. The coffee breaks had coffee, decaf, tea, scones, and other small pastries. For lunch each day, there were sandwiches and other goodies. More importantly, the food was laid out near the main conference room, so everyone could seamlessly gather in between talks.&lt;/p&gt;

&lt;p&gt;Following the break, there was a talk on "Evolving Django: What We Learned by Integrating MongoDB" by Anaiya Raisinghani. MongoDB recently introduced &lt;a href="https://github.com/mongodb/django-mongodb-backend" rel="noopener noreferrer"&gt;official Django support&lt;/a&gt;, and we did a whole &lt;a href="https://djangochat.com/episodes/official-django-mongodb-backend-jib-adegunloye" rel="noopener noreferrer"&gt;podcast episode of Django Chat with Jib Adegunloye&lt;/a&gt;, the lead engineer on the effort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqazejupn9hleqytysbq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjqazejupn9hleqytysbq.jpeg" alt="Anaiya Raisinghani" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Anaiya Raisinghani presenting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At the same time, in the workshop room next door, there was a live recording of the &lt;a href="https://realpython.com/podcasts/rpp/" rel="noopener noreferrer"&gt;Real Python Podcast&lt;/a&gt; with audience participation. Hopefully, that episode will come out soon.&lt;/p&gt;

&lt;p&gt;The last morning's talk was on Feature Flags by &lt;a href="https://grahamknapp.com/blog/" rel="noopener noreferrer"&gt;Graham Knapp&lt;/a&gt;. Feature flags activate features for some users while hiding them for others. Graham had many good tips on how to use or misuse the flags.&lt;/p&gt;

&lt;p&gt;After this talk, I spent a while doing the "hallway track" and chatting with various people about what we'd seen so far, how each of us was using Django at work, and so on. Quite a few people used &lt;a href="https://www.jetbrains.com/pycharm/" rel="noopener noreferrer"&gt;PyCharm&lt;/a&gt; and had feedback on it and the recent AI releases.&lt;/p&gt;

&lt;p&gt;In the afternoon, Karen Jex gave a very in-depth yet accessible talk on database operations, focusing on what happens behind-the-scenes when you send a database query, how is data stored, retrieved, and modified. And more importantly, why should you care! You can see her &lt;a href="https://karenjex.blogspot.com/2025/05/anatomy-of-database-operation.html" rel="noopener noreferrer"&gt;slides and notes here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With a basic understanding of the way select, insert and update operations work, you can make sure your code and database play nicely together!&lt;/p&gt;

&lt;p&gt;It's a tough balancing act to see all the talks while taking time to chat with people in the hallway. I try to aim for 2/3 talks and 1/3 chatting during talks, but ultimately, we're at a conference to meet other people, so I will usually prioritize continuing a great conversation with someone over cutting it short to go see a talk.&lt;/p&gt;

&lt;p&gt;At the end of the talks, there was a moment of thanks to all the conference organizers. These are all volunteers who do an incredible amount of work to plan the event, run it day-to-day, select the talks, and so on. It's an incredible gift to our community that year after year people are willing to do this work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wetmv2klg61pgqh0pxz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wetmv2klg61pgqh0pxz.jpeg" alt="Conference organizers" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Conference organizers (photo courtesy of Adam Johnson).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the evening, there was a party at The Camden in downtown Dublin, so many of us hopped onto buses and headed there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2da83fjlh4fm5ocnbvc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2da83fjlh4fm5ocnbvc.jpg" alt="Bus to dinner" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Bus to dinner (photo courtesy of Paolo Melchiorre).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We stopped off at an excellent sushi restaurant along the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7sjfhmnzta9cc3jumgq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7sjfhmnzta9cc3jumgq.jpg" alt="Sushi dinner" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Sushi dinner (photo courtesy of Paolo Melchiorre).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before making it to the party itself, Adam Johnson discovered an &lt;a href="https://www.atlasobscura.com/places/aungier-street-lidl-archaelogy" rel="noopener noreferrer"&gt;ancient Viking Archaeology Site&lt;/a&gt; underneath a Lidl supermarket. So, of course, we had to check that out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfw4i1o6e7n1we12xwul.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnfw4i1o6e7n1we12xwul.jpeg" alt="Lidl Archaeology" width="800" height="600"&gt;&lt;/a&gt; &lt;em&gt;Archaeology site in a supermarket.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The party was at &lt;a href="https://www.thecamden.ie/" rel="noopener noreferrer"&gt;The Camden&lt;/a&gt;, and many people from the conference were able to attend. I enjoyed chatting with the folks from &lt;a href="https://www.hacksoft.io/" rel="noopener noreferrer"&gt;Hacksoft&lt;/a&gt;, among other conversations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ftt0yz4cud5csewdlvt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ftt0yz4cud5csewdlvt.jpg" alt="The Camden" width="800" height="533"&gt;&lt;/a&gt; &lt;em&gt;The Camden.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  DjangoTV
&lt;/h2&gt;

&lt;p&gt;At both DjangoCon Europe and DjangoCon US, talks are recorded and later released on YouTube. This is so helpful even if you can attend because it's not possible to see two talks at once, and it's better to be present and listen rather than furiously write down notes. But even so, it can be difficult to find all the amazing content put out by the community.&lt;/p&gt;

&lt;p&gt;To that end, &lt;a href="https://jefftriplett.com" rel="noopener noreferrer"&gt;Jeff Triplett&lt;/a&gt;, a current Django Board member and my partner on the &lt;a href="https://django-news.com" rel="noopener noreferrer"&gt;Django News newsletter&lt;/a&gt;, has a website called &lt;a href="https://djangotv.com/" rel="noopener noreferrer"&gt;Django TV&lt;/a&gt; that compiles conference talks from all the DjangoCons, Django events, and Wagtail conferences globally. I strongly recommend taking a look to uncover some gems you might have missed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://djangotv.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmv0luzst2swdhua3ehzf.png" alt="Image description" width="800" height="617"&gt;&lt;/a&gt; &lt;em&gt;DjangoTV Website.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I always come away from DjangoCon events feeling energized about the community and our beloved framework. It is an investment of time and money to attend (or speak at) these events, but they are so vital to the continued health of the ecosystem. And if anything, the second or third times you attend are even better because everything is so new the first time, and you are doing lots of "nice to meet yous" with people you follow online. But in the following years, you can jump right into conversations about things. And it puts a human face on our otherwise digital community interactions.&lt;/p&gt;

&lt;p&gt;Carlton Gibson and I both came away with a long list of people we'd like to chat with in the fall for Django Chat. I received lots of generally positive feedback on PyCharm and our new AI features, which I was happy to share with my colleagues on my return.&lt;/p&gt;

&lt;p&gt;When you work on a digital product like PyCharm, it's easy internally to focus on the feedback you see on the socials/Reddit/videos, and generally, people only take the time to write or say something if it is very negative. There's almost always something actionable within a complaint, but hearing that many developers are using PyCharm, enjoying it, and have small critiques is a more realistic representation of our user base, but you can only find that out through in-person interactions.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>techtalks</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Averaging Our Way to AGI</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Tue, 04 Mar 2025 18:52:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/averaging-our-way-to-agi-3lh6</link>
      <guid>https://dev.to/wsvincent/averaging-our-way-to-agi-3lh6</guid>
      <description>&lt;p&gt;I’ve been thinking a lot recently about &lt;a href="https://www.linkedin.com/posts/denis-o-b61a379a_ai-activity-7301519109698007040-4nVI/" rel="noopener noreferrer"&gt;this LinkedIn post&lt;/a&gt; (shout out to my colleague, &lt;a href="https://www.linkedin.com/in/michelle-frost-dev/" rel="noopener noreferrer"&gt;Michelle Frost&lt;/a&gt;, who first brought it to my attention), which makes the point that LLMs, initially built for translation and pattern matching, were then hyperscaled via Transformers and lots of money into the current leading example of AI intelligence amongst the general public.&lt;/p&gt;

&lt;p&gt;Are they truly a path to AGI (Artificial General Intelligence), a broad term used as a goal meaning an LLM that matches or exceeds human capabilities? Currently, we have ANIs (Artificial Narrow Intelligence) that can far exceed humans in closed systems, such as games like Chess or Go. However, true AGI is still in the future, even as companies like OpenAI publicly point to it as a goal for their products.&lt;/p&gt;

&lt;p&gt;Can the LLM approach ever reach AGI? I suspect no. The underlying architecture is designed to approximate, pattern match, and guess. It was initially built for language processing and translation. There is no deep inference of meaning or logic there, no matter how many hidden inputs the models create.&lt;/p&gt;

&lt;p&gt;The algorithms used to train LLMs have been around for quite a while. What was lacking until &lt;a href="https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)" rel="noopener noreferrer"&gt;Transformers&lt;/a&gt; came onto the scene in 2017 was the ability to massively scale them. ChatGPT was among the first to use Transformers and publicly release them to the general public. While there are other LLM models out there, we will focus on GPT’s history here to give a sense for how quickly these models have grown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief LLM History
&lt;/h2&gt;

&lt;p&gt;Let’s use GPT as a proxy for advancements in the field in general. We can track the rapid changes based on their model releases from 2018 to the present.&lt;/p&gt;

&lt;p&gt;GPT-1, released in 2018, had 117M parameters and was trained on &lt;a href="https://en.wikipedia.org/wiki/BookCorpus" rel="noopener noreferrer"&gt;BookCorpus&lt;/a&gt;, a dataset of 7,000 self-published books. A “parameter” is a numerical value the model learns during training. Broadly speaking, more parameters mean a model can store more complex patterns and perform better, although at a certain point (see future sections) efficiency matters more than just size.&lt;/p&gt;

&lt;p&gt;GPT-2 was released the following year, 2019, and had a large leap in parameters (1.5B) as well as training on a much larger dataset, &lt;a href="https://paperswithcode.com/dataset/webtext" rel="noopener noreferrer"&gt;WebText&lt;/a&gt;, containing 8 million documents and 40GB of text. The model had more fluid text responses but still struggled with accuracy and relevancy. This was the last GPT model that was open source; by GPT-3 the company shifted to proprietary closed models and datasets.&lt;/p&gt;

&lt;p&gt;GPT-3 (2020) was the big breakthrough: for the first time, a publicly-available LLM generated responses that felt vaguely natural, though it still suffered from hallucinations and errors in back-and-forth conversations. It featured 175B parameters, a much larger (though proprietary) dataset that ChatGPT itself estimates at ~570GB, and a larger “context window” (the number of tokens a model can process at once). Context windows become increasingly important since LLMs are inherently stateless--each request is independent of previous ones, similar to HTTP. On the web, we use cookies to remember “state,” such as whether a user is logged in to a website. In an LLM, a context window allows the model to process more information--vital for analyzing long documents--and maintaining a back-and-forth conversation history with the user.&lt;/p&gt;

&lt;p&gt;To highlight this point, if I am using an LLM to help with programming, it is very helpful if I can send the entire codebase to the LLM, which stores it in the context window, and therefore all future requests reference the same stored data.&lt;/p&gt;

&lt;p&gt;Three years passed before GPT-4 was released in 2023. The number of parameters was not publicly released, but it was likely over one trillion. Instead, the focus was on efficiency and smarter parameters rather than just more of them. GPT-4 demonstrated near-human-level performance in many exams such as the US bar (law) exam, GREs, AP courses, and so on. It was able to process text and images quite well and featured a much larger context window of 8,192 tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Competition
&lt;/h2&gt;

&lt;p&gt;Amidst these rapid improvements to GPT, a growing ecosystem of competing LLM models emerged. In 2023, several “open” models were released for the first time: Mistral, Falcon, and Meta’s Llama. Mistral and Falcon are available for commercial use, reveal their model weights (meaning anyone can use the models) and training code, but both have some restrictions on training data information. Llama has open weights, too, but restrictions for large companies. Llama also does not disclose its training code or training data.&lt;/p&gt;

&lt;p&gt;In the proprietary LLM space, many competitors popped up, most notably Anthropic, founded by former OpenAI engineers. Anthropic’s Claude model was first released in March 2023 with 9,000 context window tokens (more than GPT-4), and by September 2024 featured a 500,000 token context window, allowing for GitHub integration, and other advanced features. This made it arguably better than GPT for many coding tasks, as well as analyzing entire books, legal documents, financial reports, and so on, since all of the data could be fed directly into the context window for processing by the model. &lt;/p&gt;

&lt;p&gt;The prevailing thought at this time was that there were still-unlimited gains to be had by increasing the amount of computation and data in LLM models. As a result, billions of dollars of VC and corporate money went into this LLM arms race.&lt;/p&gt;

&lt;h2&gt;
  
  
  2025
&lt;/h2&gt;

&lt;p&gt;In January 2025 there was a “Sputnik moment” with the release of DeepSeek from a small Chinese company. DeepSeek roughly matched the performance of leading LLM models, including GPT 4, while open sourcing its model weights, training data, and allowing commercial use. The DeepSeek app was the most downloaded one on the Apple App Store the weekend it was released. But even more amazingly, DeepSeek claimed that training costs were only $6 million, rather than the billions used for competitors.&lt;/p&gt;

&lt;p&gt;We don’t know how accurate that $6 million figure truly is, but training costs were clearly far less. DeepSeek used a number of novel techniques including “knowledge distillation,” essentially training student models on larger teacher models, most notably Meta’s Llama and Alibaba’s Qwen.&lt;/p&gt;

&lt;p&gt;DeepSeek’s release of a cost-effective LLM model led to a $600B drop in market value for Nvidia, the company behind the GPUs used to train most models.&lt;/p&gt;

&lt;p&gt;The following month, February, GPT 4.5 was released, featuring a 30x cost increase over GPT 4, and so far, it seems, provides only marginal improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;The back-to-back releases of DeepSeek and then GPT 4.5 bring up the question of whether we are finally in an era of diminishing returns for LLMs. Has the previous approach of ever-more computation and data finally reached a limit? Gary Marcus famously predicted this back in 2022 with his piece, &lt;a href="https://nautil.us/deep-learning-is-hitting-a-wall-238440/" rel="noopener noreferrer"&gt;Deep Learning is Hitting a Wall&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;So what’s next? I suspect LLMs will continue to make marginal improvements, training costs will decrease, and we’ll see more and more open-source options available, as well as more and more LLMs trained on specific datasets and use cases, such as &lt;a href="https://blog.jetbrains.com/blog/2024/10/22/introducing-mellum-jetbrains-new-llm-built-for-developers/" rel="noopener noreferrer"&gt;JetBrains’ Mellum&lt;/a&gt;. Will open-source models that are good-enough win out over proprietary ones? Or will proprietary models continue to improve at a rate that justifies their growing price tag?&lt;/p&gt;

&lt;p&gt;I suspect we will also see improvements in the broader LLM ecosystem, such as an ever-increasing context window, which leads to a growing use case of industries where models can be applied.&lt;/p&gt;

&lt;p&gt;The larger issue of model inaccuracies and hallucinations persists. If a user asks a sufficiently niche question that the model wasn’t trained on, it will struggle to generate a good response. Likewise, if you ask questions after a model’s training data period, it will not handle them well. But there are techniques, such as Retrieval-Augmented Generation (RAG), that promise some solutions. RAG allows a model to interact with external data sources in real-time--for example by doing its own searches--to either supplement or double check its initial responses. &lt;/p&gt;

&lt;p&gt;And in the AI-assisted coding realm--where I work at &lt;a href="https://www.jetbrains.com/" rel="noopener noreferrer"&gt;JetBrains&lt;/a&gt;--things are really heating up with the rise of agents that can use AI to not just ask questions, but update code on its own. I don’t think this means the end of programmers, something I wrote about previously in &lt;a href="https://wsvincent.com/vibe-coding/" rel="noopener noreferrer"&gt;Thoughts on Vibe Coding&lt;/a&gt; and which Gary Marcus (again) wrote about more &lt;a href="https://substack.com/home/post/p-158228912" rel="noopener noreferrer"&gt;eloquently soon thereafter&lt;/a&gt;. But it is clear that programming tools are changing rapidly and likely most professional programmers will use LLMs to help write code going forward.&lt;/p&gt;

&lt;p&gt;But while LLMs have dominated the spotlight in the quest for AGI, it’s important to remember that they are not the only approach. There are other potential pathways such as reinforcement learning, neuro-symbolic systems, and hybrid models that combine multiple approaches. It is far to say that LLMs have demonstrated the power of scale, but given they are still--by architecture and definition--trying to average their way to the next response, they are not a straight path to true AGI.&lt;/p&gt;

&lt;p&gt;Will we ever get there? Personally, I have doubts. We still can’t even define intelligence in humans, let alone machines. Maybe there is some sort of &lt;a href="https://en.wikipedia.org/wiki/G%C3%B6del%27s_incompleteness_theorems" rel="noopener noreferrer"&gt;incompleteness theorem&lt;/a&gt; that AGI attempts will bump up into. Or not. I am keeping an open mind. But it is clear to me that LLMs are a game-changer but not the end of the game when it comes to AI surpassing humans.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Big thanks to my colleague, &lt;a href="https://www.linkedin.com/in/michelle-frost-dev/" rel="noopener noreferrer"&gt;Michelle Frost&lt;/a&gt;, for detailed feedback and suggestions on an earlier draft of this piece.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>chatgpt</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Does a Developer Advocate Do?</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Thu, 27 Feb 2025 14:14:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/what-does-a-developer-advocate-do-21co</link>
      <guid>https://dev.to/wsvincent/what-does-a-developer-advocate-do-21co</guid>
      <description>&lt;p&gt;I'm two months into my new job as a &lt;a href="https://blog.jetbrains.com/pycharm/2025/01/python-developer-advocate-will-vincent/" rel="noopener noreferrer"&gt;Python Developer Advocate&lt;/a&gt; at JetBrains and realize there is a lot of confusion in the general public about what exactly a Developer Advocate does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the Role
&lt;/h2&gt;

&lt;p&gt;Conversations with friends and family are typically along the lines of:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Them&lt;/strong&gt;: Congratulations on the new job! So what do you do?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: I'm a Developer Advocate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Them&lt;/strong&gt;: So what do you do day to day?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: It's a mixture of content, marketing, and community. I help developers learn and, where possible, feature our tools (primarily the &lt;a href="https://www.jetbrains.com/pycharm/" rel="noopener noreferrer"&gt;PyCharm IDE&lt;/a&gt; in my case).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Them&lt;/strong&gt;: So are you writing code or doing marketing?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: Both, but I'm not in marketing and I'm not a programmer per se.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Them&lt;/strong&gt;: Ok (eyes glaze over and move on to another topic)&lt;/p&gt;

&lt;h2&gt;
  
  
  The History of the Developer Advocate Role
&lt;/h2&gt;

&lt;p&gt;In fairness, the concept of a Developer Advocate is pretty foreign outside of the tech ecosystem. It is a role that sits between product, marketing, and community. The earliest forms of developer advocacy emerged in the 1980s, when companies like Microsoft, Apple, and IBM who had "Evangelists" promoting their platforms. In the 1990s, Microsoft had "Platform Evangelists" who helped developers build applications on top of the Windows operating system.&lt;/p&gt;

&lt;p&gt;But it is in the 2000s when the term "Developer Advocate" really picked up speed. Google is often credited with formalizing the role with employees who focus on developer experience (DX), APIs, and open web standards rather than just sales. Companies like Mozilla and Twitter also adopted Developer Advocacy positions to help engage better with developers building on their platforms.&lt;/p&gt;

&lt;p&gt;A big reason for the role is that developers &lt;strong&gt;do not like to be marketed to&lt;/strong&gt;. It is hard to sell products in traditional marketing ways to a group of superusers who are likely skeptical, full of questions, and want a domain expert to engage rather than just read or watch marketing materials.&lt;/p&gt;

&lt;p&gt;By the 2010s, Developer Advocacy had become a standard role in cloud, API-driven, and developer tools companies like AWS, Twilio, Stripe, GitHub, Docker, and JetBrains (my employer).&lt;/p&gt;

&lt;p&gt;These days, almost every developer-focused company--ie. selling products and services directly to developers--has Developer Advocates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Company-Level Developer Advocate Differences
&lt;/h2&gt;

&lt;p&gt;Part of the difficulty in defining what a Developer Advocate does is that the role varies widely depending on the company. It is always a hybrid of content, marketing, and community, but that balance varies depending on the company's goals. For example, DAs (Developer Advocates) at large companies like Google, Microsoft, or Amazon/AWS are often &lt;em&gt;product-centric&lt;/em&gt;, focused on advocating for specific cloud and developer products. That means deep dives into their APis, SDKs, and integration guides. DAs at other companies like Stripe or JetBrains, might be more &lt;em&gt;developer-centric&lt;/em&gt;, writing tutorials, making videos, building sample apps, and helping developers integrate the product into their workflow.&lt;/p&gt;

&lt;p&gt;It really depends upon the needs and size of the company itself. In an enterprise-focused company like SalesForce, Oracle, or IBM, a DA works closely with B2B customers, hosting webinars, training sessions, and working with sales teams. Whereas a startup-focused company would often have a DA do community-driven work, open source contributions, live streaming, and quick iteration on documentation and developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does JetBrains Do?
&lt;/h2&gt;

&lt;p&gt;My company, &lt;a href="https://www.jetbrains.com/" rel="noopener noreferrer"&gt;JetBrains&lt;/a&gt;, makes tools for developers, most notably IDEs (Integrated Development Environments), that make it much easier to write code in a variety of programming languages. It started off with one product, IntelliJ IDEA, which is an IDE for the Java and Kotlin programming languages. And soon developed multiple other products with a similar focus, including PyCharm, focused on the Python ecosystem.&lt;/p&gt;

&lt;p&gt;The company just celebrated its 25th birthday and is privately held, which makes it somewhat unusual in a tech landscape dominated by VC-funded startups and established public companies such as Microsoft and Google. We have around 2,000 employees, which makes us not a small company, but again orders of magnitude smaller than our competitors, who typically have trillion-dollar market caps. And as a final point of differentiation, the company is based in Europe, whereas most of the tech industry is in the United States. JetBrains was originally formed in Russia and later established its headquarters in Europe, where there are large offices in Prague, Munich, and Amsterdam, as well as small regional offices around the globe. There are also remote employees, such as myself and most of the ~30-person Developer Advocacy team.&lt;/p&gt;

&lt;h2&gt;
  
  
  IDE Landscape and AI
&lt;/h2&gt;

&lt;p&gt;The big change across all of technology, and especially developer tools, is AI. Everyday users have seen glimpses of its power through Large Language Models (LLMs) like ChatGPT, and developers are increasingly hooking into LLMs to power different products. For example, why pay a legal assistant to review thousands of documents when you can run them all through an LLM to pull out insights, find specific references, and so on? LLMs can also reason and increasingly find their way into medical contexts, where they can assist nurses and doctors reviewing patient information. And it turns out LLMs are quite good at writing code, which means every IDE out there is focused on integrating these capabilities into their product.&lt;/p&gt;

&lt;p&gt;The most recent Python developer survey, from 2023, showed the following distribution of IDE/Text Editors:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodj08gftdcbzufq3w8ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodj08gftdcbzufq3w8ez.png" alt="Python Developers Survey" width="800" height="975"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, VSCode and PyCharm dominate. The big difference between the two is that VSCode is free and relies on community-driven plugins for Python-specific support. In contrast, PyCharm is paid (there are free and Professional editions, but 68% of respondents use the Professional one) but has built-in support for Python and the broader ecosystem.&lt;/p&gt;

&lt;p&gt;VSCode is, therefore, the obvious competitor to PyCharm. It has a different value proposition and is backed by "an infinite competitor" in Microsoft, which makes buckets of money elsewhere and does not have to charge directly for VSCode. On the other hand, relying on community plugins has risks and the integration is often not as good as in a paid product, like PyCharm, which handles all of that for the developer.&lt;/p&gt;

&lt;p&gt;But the big, big change is AI. JetBrains has &lt;a href="https://www.jetbrains.com/ai/" rel="noopener noreferrer"&gt;AI Assistant&lt;/a&gt; whereas VSCode has &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;Copilot&lt;/a&gt;. And there are even newer coding agents, such as &lt;a href="https://www.jetbrains.com/junie/" rel="noopener noreferrer"&gt;Junie for JetBrains&lt;/a&gt; being released as we speak, that handle even more tasks directly for a programmer.&lt;/p&gt;

&lt;p&gt;And there a host of VC-funded startups focused on AI integration such as &lt;a href="https://www.cursor.com/en" rel="noopener noreferrer"&gt;Cursor&lt;/a&gt;, &lt;a href="https://codeium.com/windsurf" rel="noopener noreferrer"&gt;Windsurf&lt;/a&gt;, &lt;a href="https://zed.dev/" rel="noopener noreferrer"&gt;Zed&lt;/a&gt;, and many more.&lt;/p&gt;

&lt;p&gt;So it is an exciting time. It is clear that AI tools can and will help developers write code, but the details of that remain to be seen.&lt;/p&gt;

&lt;p&gt;A final point of interest is that the landscape for LLMs themselves is rapidly shifting. Simon Willison has &lt;a href="https://simonwillison.net/2024/Dec/31/llms-in-2024/" rel="noopener noreferrer"&gt;an excellent overview&lt;/a&gt; of things as they stood at the end of 2024. Among the main points, LLM prices are dropping, there are ever-more open-source models that can run on a local laptop, and the costs of training next-generation models are falling, as demonstrated by DeepSeek, which claimed to match leading performance benchmarks for a fraction of the cost.&lt;/p&gt;

&lt;p&gt;All of which is to say, will LLMs become a commodity soon? And if so, does that mean the integration of them is more important than the underlying LLM itself? We shall soon see.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Role at JetBrains
&lt;/h2&gt;

&lt;p&gt;So what do I actually do as a Python Developer Advocate at JetBrains? It's a mixture of things and the balance will change over time, but here are my current goals:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt;: Creating content is a big area, which means videos and guides on topics relevant to the commnunity, highlighting PyCharm-specific features where relevant. This is all in the works but something I'm very excited to release. I am giving a &lt;a href="https://pretalx.evolutio.pt/djangocon-europe-2025/talk/STZPLT/" rel="noopener noreferrer"&gt;keynote at DjangoCon Europe&lt;/a&gt; this year and hope to also do a talk at DjangoCon US in the fall. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community&lt;/strong&gt;: This is a squishy topic to define but basically means being out-and-about in the Python ecosystem, listening to developers and learning about their current needs. I will be attending a number of conferences this year, including PyCon US, EuroPython, and PyTorch, as well as the two DjangoCons noted above. I also continue to produce the &lt;a href="https://django-news.com/" rel="noopener noreferrer"&gt;Django News newsletter&lt;/a&gt; and &lt;a href="https://djangochat.com/" rel="noopener noreferrer"&gt;Django Chat podcast&lt;/a&gt;, which serve as community resources within the Django community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Source&lt;/strong&gt;: I'm excited at the prospect of contributing directly to Django, since JetBrains are big contributors in both dollars and time, to the Python community. There are open Django tickets to my name around documentation and user authentication that I plan to tackle this year. And I continue to maintain the &lt;a href="https://github.com/wsvincent/awesome-django" rel="noopener noreferrer"&gt;awesome-django repo&lt;/a&gt; and the &lt;a href="https://github.com/wsvincent/lithium" rel="noopener noreferrer"&gt;lithium&lt;/a&gt; Django starter project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product&lt;/strong&gt;: The PyCharm IDE is the primary product I support, so I have regular meetings with the product team there, evaluating new and proposed features, providing feedback, and learning about what's coming out soon so that I can create content around it. I also work directly with the PyCharm Product Manager, helping to escalate certain issues, sharing insights from the community, and so on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Marketing&lt;/strong&gt;: PyCharm has a dedicated marketing department and as a DA I'm marketing-adjacent, meaning I work closely with them on specific things. That can mean reading over blog posts and other materials produced by the team there, to ensure they are accurate and appropriate. Or creating videos for PyCharm marketing pages and YouTube Channels, and directly highlighting new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;So far I'm really enjoying my job at JetBrains. I have a great direct boss, helpful colleagues, and a wide variety of goals to tackle. I also appreciate working at a European company (a first for me), where everyone works quite hard but also values time to rest and recharge. That is somewhat new to me given my past experience at U.S. startups, but I know it is ultimately more productive for me personally and I think companies as a whole.&lt;/p&gt;

&lt;p&gt;It is also a very interesting time to be in the developer tools space, given the rapid changes brought about by AI. JetBrains is well-positioned, ultimately, given that the focus is on solely on providing best-in-class tools for developers. There are no other ulterior motives or products to sell. We may lack some of the resources of larger competitors, but I think that makes us focus more on the task at hand.&lt;/p&gt;

</description>
      <category>developer</category>
      <category>devrel</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Fixing Django FieldError at /admin/accounts/customuser/add/</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Sun, 23 Feb 2025 00:48:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/fixing-django-fielderror-at-adminaccountscustomuseradd-k9n</link>
      <guid>https://dev.to/wsvincent/fixing-django-fielderror-at-adminaccountscustomuseradd-k9n</guid>
      <description>&lt;p&gt;If you are a Django developer who wants to add a custom user model to your project, you've likely come across this error on Django versions 5.0 and above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FieldError at /admin/accounts/customuser/add/&lt;br&gt;
Unknown field(s) (usable_password) specified for CustomUser. Check fields/fieldsets/exclude attributes of class CustomUserAdmin.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevb26g1bgp7ku07xgck7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevb26g1bgp7ku07xgck7.png" alt="FieldError Message" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The issue is around &lt;code&gt;UserCreationForm.&lt;/code&gt; In Django versions up to 4.2, you could set your &lt;code&gt;accounts/forms.py&lt;/code&gt; file to add updated user creation and change forms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/forms.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserCreationForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserChangeForm&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserCreationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserCreationForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserChangeForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserChangeForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, as of Django 5.0, that leads to the above-mentioned &lt;code&gt;FieldError&lt;/code&gt;. The fix is straightforward to do, thankfully, which is to swap out &lt;code&gt;UserCreationForm&lt;/code&gt; for the newer &lt;a href="https://docs.djangoproject.com/en/5.1/topics/auth/default/#django.contrib.auth.forms.AdminUserCreationForm" rel="noopener noreferrer"&gt;AdminUserCreationForm&lt;/a&gt; instead, which includes the additional &lt;code&gt;usable_password&lt;/code&gt; field causing the initial issue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/forms.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib.auth.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AdminUserCreationForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserChangeForm&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserCreationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AdminUserCreationForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomUserChangeForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserChangeForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CustomUser&lt;/span&gt;
        &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the &lt;a href="https://code.djangoproject.com/ticket/35678" rel="noopener noreferrer"&gt;related ticket #35678&lt;/a&gt; and &lt;a href="https://forum.djangoproject.com/t/the-purpose-of-usercreationform/33836_/" rel="noopener noreferrer"&gt;forum discussion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For a complete guide on using a custom user model in Django, &lt;a href="https://learndjango.com/tutorials/django-custom-user-model" rel="noopener noreferrer"&gt;refer to this tutorial&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>authentication</category>
      <category>programming</category>
    </item>
    <item>
      <title>Django Redirects App Tutorial</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Thu, 05 Sep 2024 16:26:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/django-redirects-app-tutorial-o6a</link>
      <guid>https://dev.to/wsvincent/django-redirects-app-tutorial-o6a</guid>
      <description>&lt;p&gt;URL redirects are a fundamental part of maintaining a production website. There are many reasons &lt;em&gt;why&lt;/em&gt; you might want to redirect a user from one part of your website to another, but doing so correctly is important for a positive user experience and to maintain the maximium SEO (Search Engine Optimization) possible.&lt;/p&gt;

&lt;p&gt;Django ships with a built-in &lt;a href="https://docs.djangoproject.com/en/5.1/ref/contrib/redirects/" rel="noopener noreferrer"&gt;redirects app&lt;/a&gt; to help manage redirects, but the official documentation is not particularly friendly to newcomers, hence this tutorial.&lt;/p&gt;

&lt;p&gt;&lt;a id="set-up-django-redirects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up Django Redirects
&lt;/h2&gt;

&lt;p&gt;The Django redirects app works alongside the &lt;a href="https://docs.djangoproject.com/en/5.1/ref/contrib/sites/" rel="noopener noreferrer"&gt;sites framework&lt;/a&gt;, which is also built-in but not automatically installed. We, as Django developers, need a few pieces of setup to use both fully.&lt;/p&gt;

&lt;p&gt;To configure the Sites framework, add it to the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; configuration in &lt;code&gt;settings.py&lt;/code&gt; and set a &lt;a href="https://docs.djangoproject.com/en/5.1/ref/settings/#std-setting-SITE_ID" rel="noopener noreferrer"&gt;SITE_ID&lt;/a&gt;. It is customary to define a web application with only one site as &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sites&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;SITE_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For completeness, you should run a migration now to update your database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ python manage.py migrate
Operations to perform:
 Apply all migrations: admin, auth, contenttypes, sessions, sites
Running migrations:
 Applying sites.0001_initial... OK
 Applying sites.0002_alter_domain_unique... OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like the Sites framework, the redirects app is included in Django by default but requires some configuration. We will update &lt;code&gt;INSTALLED_APPS&lt;/code&gt;, &lt;code&gt;MIDDLEWARE&lt;/code&gt;, and again run a database migration. Note that when adding the middleware, it should be placed near the bottom to work properly since middleware is run from top to bottom for an HTTP request (and bottom to top for an HTTP response, but that is a topic for another day).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sites&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.redirects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;    &lt;span class="c1"&gt;# other local and 3rd party apps
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;MIDDLEWARE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.middleware.security.SecurityMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions.middleware.SessionMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.middleware.common.CommonMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.middleware.csrf.CsrfViewMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth.middleware.AuthenticationMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages.middleware.MessageMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.middleware.clickjacking.XFrameOptionsMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ... any other custom middleware ...
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.redirects.middleware.RedirectFallbackMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run migrations to create the necessary database tables for the redirects app to work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ python manage.py migrate
Operations to perform:
 Apply all migrations: admin, auth, contenttypes, redirects, sessions, sites
Running migrations:
 Applying redirects.0001_initial... OK
 Applying redirects.0002_alter_redirect_new_path_help_text... OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our set up is complete. Let's explore two different approaches for using it.&lt;/p&gt;

&lt;p&gt;&lt;a id="approach-1-admin-interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1: Admin Interface
&lt;/h2&gt;

&lt;p&gt;The Django admin is a user-friendly way to manage redirects without writing any code. It is ideal for quickly setting up a small number of redirects or for non-technical team members.&lt;/p&gt;

&lt;p&gt;Log into the admin: the Redirects and Sites sections should be visible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmgxaiizgff4vbubj4bz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmgxaiizgff4vbubj4bz.png" alt="Admin Homepage" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the "+Add" button next to Redirects. It brings up a form to select a Site, a "redirect from" path, and a "redirect to" path. As noted on the page, use an absolute path for the former and either an absolute path or full URL for the latter.&lt;/p&gt;

&lt;p&gt;Here is an example of adding a redirect from "example.com/old" to "example.com/new".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskbrn4xxiwienwrbi4bn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskbrn4xxiwienwrbi4bn.png" alt="Admin Redirects Add Page" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once saved you will be sent to the main Redirects page where you can see and edit all existing redirects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86xgj2zmmz3pggbir2t2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86xgj2zmmz3pggbir2t2.png" alt="Admin Redirects Main Page" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to change the "example.com" portion of the site, click on the Sites section, and you can update the Domain Name or Display Name. The Display Name is the human-readable name for the site, used in the admin and in templates for identification. The Domain Name is used for URL generation and validation, such as in a &lt;a href="https://learndjango.com/tutorials/django-sitemap-tutorial" rel="noopener noreferrer"&gt;sitemap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id="next-steps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;The redirects app uses permanent (301) redirects by default, which is typically what you want for SEO purposes. It is important to regularly review your redirects and monitor performance on a production website, as a large number of redirects can impact performance, and you might look into caching options if this is an issue. Also, remember to use relative URLs for new paths to ease the transition between local, staging, and production environments. A final tip is to add tests to confirm that redirects are working as expected.&lt;/p&gt;

&lt;p&gt;If you'd like additional tips on optimizing your Django website's SEO, check out the &lt;a href="https://learndjango.com/search/results/?q=seo" rel="noopener noreferrer"&gt;list of tutorials&lt;/a&gt; on this topic.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>redirects</category>
    </item>
    <item>
      <title>Getting Started with Django Tutorial</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Thu, 29 Aug 2024 02:12:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/getting-started-with-django-tutorial-2ak9</link>
      <guid>https://dev.to/wsvincent/getting-started-with-django-tutorial-2ak9</guid>
      <description>&lt;p&gt;This tutorial is designed for programmers new to the Django web framework, whether you are a beginner who wants to build web applications in Python for the first time or an experienced web developer looking for a complete overview of what Django offers.&lt;/p&gt;

&lt;p&gt;In comparison to &lt;a href="https://flask.palletsprojects.com/en/3.0.x/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt;, which adopts a microframework approach, Django is a "batteries-included" framework that includes by default most of what you need to build, test, and deploy powerful websites quickly. It has built-in solutions for user authentication (sign up, log in, log out), database connections and queries, logic, templates, security, and more. As the tagline says on the &lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django website&lt;/a&gt;, it is "The web framework for perfectionists with deadlines."&lt;/p&gt;

&lt;p&gt;This tutorial focuses on Django itself. If you'd like to compare the two most popular Python web frameworks, please refer to the article on &lt;a href="https://learndjango.com/tutorials/flask-vs-django" rel="noopener noreferrer"&gt;Flask vs Django&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Django?
&lt;/h2&gt;

&lt;p&gt;Django is a web framework written in the Python programming language that takes care of the difficult and routine parts of web development--authentication, database connection, CRUD (Create, Read, Update, Delete) operations, URL routing, forms, security, etc.--so that developers can concentrate on what makes a website unique without needing to reinvent the wheel.&lt;/p&gt;

&lt;p&gt;It was initially developed in the early 2000s at the Lawrence Journal-World newspaper in Lawrence, Kansas, and named after the famous jazz guitarist Django Reinhardt. First open-sourced in July 2005, Django grew rapidly thanks to an active community, regular updates, and widespread adoption that makes it one of the most popular web frameworks used by companies including Instagram, YouTube, Spotify, DropBox, Octopus Energy, and more.&lt;/p&gt;

&lt;p&gt;Django is run as a non-profit by the &lt;a href="https://www.djangoproject.com/foundation/" rel="noopener noreferrer"&gt;Django Software Foundation&lt;/a&gt; and features regular &lt;a href="https://www.djangoproject.com/community/local/" rel="noopener noreferrer"&gt;local meetups&lt;/a&gt;, an &lt;a href="https://forum.djangoproject.com/" rel="noopener noreferrer"&gt;online forum&lt;/a&gt;, and &lt;a href="https://www.djangoproject.com/download/" rel="noopener noreferrer"&gt;constant updates&lt;/a&gt; every month with a major new release every eight months. In short, Django is a mature and stable technology that is also actively maintained and improved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use The Django Web Framework?
&lt;/h2&gt;

&lt;p&gt;Django's "batteries-included" approach offers a wide range of features right out of the box, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ORM (Object-Relational Mapper)&lt;/strong&gt;: write Python rather than SQL to create and query database information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin Interface&lt;/strong&gt;: a visual way to interact with website content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL Routing&lt;/strong&gt;: clean, elegant URL schemas that are easy to maintain and reason about&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templating Engine&lt;/strong&gt;: a simple syntax for adding variables and logic to create dynamic HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forms&lt;/strong&gt;: a powerful form library that handles rendering forms in HTML and validating user-submitted data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: a full-featured and secure authentication system for user accounts, groups, permissions, and cookie-based user sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internationalization&lt;/strong&gt;: multilingual support plus locale-specific formatting of dates, time, numbers, and time zones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: protection against SQL injection, cross-site scripting, cross-site request forgery, clickjacking, and remote code execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: world-class documentation that is extensive and actively maintained by the community&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third Party Packages&lt;/strong&gt;: thousands of supplemental packages available to provide further functionality (see &lt;a href="https://djangopackages.org/" rel="noopener noreferrer"&gt;DjangoPackages.org&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular releases&lt;/strong&gt;: bugfixes every month and a major new release every eight months&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Written in Python&lt;/strong&gt;: an expressive language suitable for beginners and used in many areas of programming, including data science, AI/ML, scientific computing, web scraping, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the best part of Django is the community, which is welcoming and supportive to developers of all backgrounds and experience levels. There are regular meetups in major cities, annual conferences, online communities, and a forum to help fellow developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the Prerequisites for Django?
&lt;/h2&gt;

&lt;p&gt;The two major prerequisites are a basic understanding of the Python programming language and web development fundamentals. You should understand Python syntax, how to import and export modules, and be familiar with object-oriented concepts like classes and objects. The building blocks of web development &lt;em&gt;also include&lt;/em&gt; knowledge of HTML, CSS, some JavaScript, and how databases/SQL work together.&lt;/p&gt;

&lt;p&gt;You don't need to be an expert in Python or web development to start. The best way to learn is to have a project in mind and then learn as you go rather than trying to understand all these concepts abstractly without actually building something.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django Architecture
&lt;/h2&gt;

&lt;p&gt;Django follows a variant of the Model-View-Controller (MVC) architecture called the Model-View-Template (MVT) pattern that emphasizes separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Models&lt;/strong&gt; are the data structure layer that represents the database schema&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Views&lt;/strong&gt; are the business logic layer that receives a web request and returns a web response&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates&lt;/strong&gt; are the presentation layer that displays information to the user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All websites follow a client/server model where HTTP requests are sent from the web browser, processed by the website, and an HTTP request is returned. In Django, that sequence looks as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user makes an HTTP Request, for example.com&lt;/li&gt;
&lt;li&gt;A URLs processes it and assigns the correct View&lt;/li&gt;
&lt;li&gt;The View combines a Template and data from a Model/Database to create an HTTP Response&lt;/li&gt;
&lt;li&gt;The HTTP Response is returned to the user&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Under-the-hood things are slightly more complicated than that, but the general flow remains the same.&lt;/p&gt;

&lt;p&gt;An image of the request/response cycle is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk23e3hui31ps8t2kyudi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk23e3hui31ps8t2kyudi.jpg" alt="Django Architecture" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Django Project Structure
&lt;/h2&gt;

&lt;p&gt;Django doesn't force you to build web applications in a particular way. Still, there is a default structure that applies to most websites: a single Project has multiple Apps, each containing discrete functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Django Project
    -&amp;gt; App 1
    -&amp;gt; App 2
    -&amp;gt; App 3
    ...
    -&amp;gt; App X
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django ships with several built-in apps such as &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;sessions&lt;/code&gt;, &lt;code&gt;messages&lt;/code&gt;, &lt;code&gt;staticfiles&lt;/code&gt;, and more containing its "batteries." If you were to create a new Newspaper website with articles, you might make an &lt;code&gt;articles&lt;/code&gt; app with that functionality. If you added payments later on, that would reside in a separate &lt;code&gt;payments&lt;/code&gt; app. This structure helps developers reason about the code and means that even large Django codebases are relatively similar in structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Models
&lt;/h2&gt;

&lt;p&gt;Django's ORM (Object-Relational Mapper) means developers can define data models in Python and query them via a dynamic API, but you can still write SQL if needed. For example, this model defines an &lt;code&gt;Article&lt;/code&gt; table in a newspaper app that contains three fields: &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;pub_date&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pub_date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;title&lt;/code&gt; field is a character field (&lt;code&gt;CharField&lt;/code&gt;) with a maximum length of 100 characters; the &lt;code&gt;content&lt;/code&gt; field is a text field (&lt;code&gt;TextField&lt;/code&gt;) that can store any amount of text; and the &lt;code&gt;pub_date&lt;/code&gt; field is a date-time field (&lt;code&gt;DateTimeField&lt;/code&gt;) that stores a timestamp of when the article was published.&lt;/p&gt;

&lt;p&gt;Django provides support for &lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/fields/#field-types" rel="noopener noreferrer"&gt;many different field types&lt;/a&gt; as well as &lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/fields/#field-options" rel="noopener noreferrer"&gt;field options&lt;/a&gt; such as &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;blank&lt;/code&gt;, &lt;code&gt;primary_key&lt;/code&gt;, and &lt;code&gt;unique&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you've created your data models, Django provides a &lt;a href="https://docs.djangoproject.com/en/5.0/topics/db/queries/" rel="noopener noreferrer"&gt;database-abstraction API&lt;/a&gt; to create, retrieve, update, and delete objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  URLs
&lt;/h2&gt;

&lt;p&gt;A clean and elegant URL schema is essential for any high-quality web application. Django encourages beautiful URL design by creating a Python module called a URLconf. Similar to a table of contents for your app, it features precise mapping between URL patterns and your views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.views&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleListView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleDetailView&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;homepage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleListView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;article-list&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;articles/&amp;lt;int:pk&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleDetailView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;article-detail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, three views are imported for a home page, an article list page, and an article detail page. Then, we define three paths that can define thousands or even millions of different webpages of articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Views
&lt;/h2&gt;

&lt;p&gt;Views are the business logic layer that receives web requests and returns web responses. In Django, you can write your own &lt;a href="https://docs.djangoproject.com/en/5.0/topics/http/views/" rel="noopener noreferrer"&gt;function-based views&lt;/a&gt;, &lt;a href="https://docs.djangoproject.com/en/5.0/topics/class-based-views/" rel="noopener noreferrer"&gt;class-based views&lt;/a&gt;, or take advantage of &lt;a href="https://docs.djangoproject.com/en/5.0/topics/class-based-views/generic-display/" rel="noopener noreferrer"&gt;class-based generic views&lt;/a&gt; to handle common use cases such as displaying a template, a list of items, or a detail view of a single item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DetailView&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomePageView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;article_list.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleDetailView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DetailView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;article_detail.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet is all the code we need to use built-in views to display a template called &lt;code&gt;home.html&lt;/code&gt;, list all articles in a template called &lt;code&gt;article_list.html&lt;/code&gt;, and display a detail view of a single article in &lt;code&gt;article_detail.html&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Templates
&lt;/h2&gt;

&lt;p&gt;Django's templating engine strikes a balance between power and ease. A template is a text file, typically HTML, that contains variables replaced with values when the template is evaluated and &lt;a href="https://docs.djangoproject.com/en/5.0/ref/templates/builtins/" rel="noopener noreferrer"&gt;built-in tags and filters&lt;/a&gt; that control the logic of the template.  &lt;/p&gt;

&lt;p&gt;For example, a simple template file that displays all articles in the database would look as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- article_list.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;All Articles&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
{% for article in article_list %}
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;{{ article.title }} | {{ article.pub_date }}&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ article.content }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
{% endfor %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a template file to display a single article could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- article_detail.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;{{ article.title }} {{ article.pub_date }}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{ article.content }}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible to swap templating engines to use &lt;a href="https://jinja.palletsprojects.com/en/3.1.x/" rel="noopener noreferrer"&gt;Jijna&lt;/a&gt; if you prefer and it is easy to sprinkle in &lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;HTMX&lt;/a&gt; as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;p&gt;If you want to jump in and try Django for yourself, here are several free projects demonstrating how to build web applications with Django.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learndjango.com/tutorials/django-hello-world" rel="noopener noreferrer"&gt;Django Hello, World&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learndjango.com/tutorials/django-blog-tutorial" rel="noopener noreferrer"&gt;Django Blog Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learndjango.com/tutorials/django-login-and-logout-tutorial" rel="noopener noreferrer"&gt;Django User Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learndjango.com/tutorials/official-django-rest-framework-tutorial-beginners" rel="noopener noreferrer"&gt;Official Django REST Framework Tutorial - A Beginners Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learndjango.com/tutorials/django-stripe-tutorial" rel="noopener noreferrer"&gt;Django Stripe Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Courses
&lt;/h2&gt;

&lt;p&gt;If you'd like to become proficient in Django, premium courses cover multiple projects in far richer depth and provide a progressive introduction to Django concepts. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://djangoforbeginners.com" rel="noopener noreferrer"&gt;Django For Beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://djangoforapis.com" rel="noopener noreferrer"&gt;Django for APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://djangoforprofessionals.com" rel="noopener noreferrer"&gt;Django for Professionals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Django easy to learn?
&lt;/h3&gt;

&lt;p&gt;If you have a basic understanding of Python and web development concepts, yes. Django is written in Python and comes with many batteries included to make it fast to start and deploy websites quickly. As with all web frameworks, you will need some understanding of HTML, CSS, JavaScript, and databases to maximize its features.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are the differences between Flask and Django?
&lt;/h3&gt;

&lt;p&gt;Flask and Django are Python-based web frameworks but adopt very different approaches. Flask is a lightweight and flexible micro-framework, whereas Django is "batteries-included" and provides an extensive feature set by default. Flask is ideal for projects requiring maximum flexibility, while Django shines for traditional websites that value structure, excellent documentation, and a vibrant ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Django for the backend or frontend?
&lt;/h3&gt;

&lt;p&gt;Django is primarily used for backend web development: connecting to a database, adding logic, user authentication, creating APIs, URL routing, etc. It has a lightweight templating language for frontend use, but Django can also function as a backend API coupled with a frontend JavaScript framework like React, Vue, or Angular.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Django vs. Python?
&lt;/h3&gt;

&lt;p&gt;Python is a general-purpose computer programming language that emphasizes the readability of code, making it popular for both beginners and experienced programmers. It is used in data science, artificial intelligence, automation, and web development. Django is a web framework written in Python that handles common challenges in web development--connecting to a database, authentication, forms, security, URL routing, etc.--so developers don't have to reinvent the wheel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Django a programming language?
&lt;/h3&gt;

&lt;p&gt;No, Django is a web framework for creating applications or APIs written in the Python programming language. There are many common challenges in web development--connecting to a database, user authentication, URL routing, forms, security--and a framework like Django handles them all so a developer can focus on writing code specific to the project rather than reinventing the wheel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Django full-stack or not?
&lt;/h3&gt;

&lt;p&gt;Yes, Django provides all the backend and frontend web development tools, including database connections, URL routing, forms, and templates. It is generally considered a backend framework because developers can also swap in a dedicated JavaScript frontend library like Vue or React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I learn Django before Python?
&lt;/h3&gt;

&lt;p&gt;You should start with Python since Django is a Python-based web framework. Everything in Django is just Python. You don't need to master Python before attempting Django, but understanding basic syntax, variables, dictionaries, and object-oriented techniques like classes is recommended.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I ask a good programming question?
&lt;/h3&gt;

&lt;p&gt;Many beginners need help moving past following a tutorial or course to building their own projects. Whatever functionality you can imagine has already been implemented by others. The trick is finding an example online or asking a good question on a place like the &lt;a href="https://forum.djangoproject.com/" rel="noopener noreferrer"&gt;Django Forum&lt;/a&gt;. If you need help, try to be as specific as possible and make clear you have put in effort already. So, instead of saying, please help me build a blog!, you could say, I've already implemented authentication and models, but I'm stuck on a view displaying all posts, and here is the code I'm trying to use that I know is incorrect. A more experienced developer can quickly look at the code and make suggestions.&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
    </item>
    <item>
      <title>Flask vs Django in 2024: A Comprehensive Comparison of Python Web Frameworks</title>
      <dc:creator>Will Vincent</dc:creator>
      <pubDate>Thu, 29 Aug 2024 02:06:00 +0000</pubDate>
      <link>https://dev.to/wsvincent/flask-vs-django-in-2024-a-comprehensive-comparison-of-python-web-frameworks-4mhh</link>
      <guid>https://dev.to/wsvincent/flask-vs-django-in-2024-a-comprehensive-comparison-of-python-web-frameworks-4mhh</guid>
      <description>&lt;p&gt;Flask and Django are the two leading Python web frameworks and while they both help developers build websites quickly, they do so with vastly different approaches. In this article, we will look at what each framework does, how they work, and why developers choose one over the other. To demonstrate these differences we will build out three distinct projects from scratch—Hello World app, Personal website, and a To Do project—so you can see for yourself how they work and make the best decision for your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's a Web Framework?
&lt;/h2&gt;

&lt;p&gt;Database-driven websites have remarkably similar needs: URL routing, logic, connect to a database, render HTML templates, user authentication, and so on. In the early days of the World Wide Web, developers had to construct all these pieces themselves before they even started work on the website itself.&lt;/p&gt;

&lt;p&gt;Open-source web frameworks soon emerged that allowed groups of developers to collaborate on this challenge, sharing best practices, reviewing code, and generally not reinventing the wheel every time someone wanted to build a new website. There are web frameworks in every major programming language with notable examples including Ruby on Rails written in Ruby, Laravel written in PHP, Spring written in Java, and in Python the two frameworks we cover here: Flask and Django.&lt;/p&gt;

&lt;p&gt;If you're new to programming, it might be confusing to hear the term Python "framework" vs "library." Both refer to software but the difference is complexity: a library is focused on a specific problem, while a framework tackles a larger challenge and often incorporates many smaller libraries to do so. As we'll see, both Flask and Django rely on quite a few Python libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which is More Popular?
&lt;/h2&gt;

&lt;p&gt;If we look at &lt;a href="https://star-history.com/#django/django&amp;amp;pallets/flask&amp;amp;tiangolo/fastapi&amp;amp;Date" rel="noopener noreferrer"&gt;GitHub stars&lt;/a&gt;, Flask and Django are relatively neck and neck but we can see the explosive growth of &lt;a href="https://github.com/tiangolo/fastapi" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt;, which is now clearly established in the top 3 of Python web frameworks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbicvmtlszb6fddej9qka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbicvmtlszb6fddej9qka.png" alt="Star History Chart" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.jetbrains.com/lp/devecosystem-2023/python/#python_web_libs_two_years" rel="noopener noreferrer"&gt;2023 Python Developers Survey&lt;/a&gt; shows Django just ahead of Flask in 2023 but with FastAPI also gaining momentum.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc82f3vtdzdfepkw58bq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc82f3vtdzdfepkw58bq.png" alt="Python Developers Survey" width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://survey.stackoverflow.co/2023/#section-most-popular-technologies-web-frameworks-and-technologies" rel="noopener noreferrer"&gt;Stack Overflow's 2023 survey&lt;/a&gt; of developers across all programming languages Flask slightly ahead but followed almost immediately by Django and with FastAPI a little behind.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxawy2q1yv6ftwn7f1hj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxawy2q1yv6ftwn7f1hj.png" alt="Stack Overflow Developers Survey" width="800" height="1001"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These comparisons are interesting to view for trends but don't account for many things. For example, just because a web framework is popular, does that mean that real companies and professional developers are using it, or is it just something that beginners like to play around with?&lt;/p&gt;

&lt;p&gt;Regardless of the comparison metric, it is clear Flask and Django are currently the top two Python web frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jobs
&lt;/h2&gt;

&lt;p&gt;If you're looking for a job as a Python web developer, Django is the better choice. There are almost twice as many listings for &lt;a href="https://www.indeed.com/jobs?q=django+python&amp;amp;l=" rel="noopener noreferrer"&gt;Django developers&lt;/a&gt; as &lt;a href="https://www.indeed.com/jobs?q=flask+python&amp;amp;l=" rel="noopener noreferrer"&gt;for Flask&lt;/a&gt; on major job boards such as Indeed.com.&lt;/p&gt;

&lt;p&gt;However, this disparity is likely because Django is a much more specific choice than Flask. A startup or company can run almost all of their services just on Django whereas Flask is often used alongside other technologies given its lightweight footprint.&lt;/p&gt;

&lt;p&gt;The most employable approach is to truly master Python first and then add web development knowledge with either Django or Flask (ideally both!) on top.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community
&lt;/h2&gt;

&lt;p&gt;Django has the larger, more organized community of the two. There are over 1,800 committers to the Django codebase vs around 550 for Flask. On StackOverflow there are &lt;a href="https://stackoverflow.com/questions/tagged/django" rel="noopener noreferrer"&gt;~212,500 Django questions&lt;/a&gt; compared to &lt;a href="https://stackoverflow.com/questions/tagged/flask" rel="noopener noreferrer"&gt;~31,500 Flask questions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Django also has annual conferences in the &lt;a href="https://2024.djangocon.us" rel="noopener noreferrer"&gt;United States&lt;/a&gt;, &lt;a href="https://2024.djangocon.eu" rel="noopener noreferrer"&gt;Europe&lt;/a&gt;, and &lt;a href="https://2021.pycon.org.au/" rel="noopener noreferrer"&gt;Australia&lt;/a&gt;. Flask does not have a similar level of conferences, although there are active discussions for both frameworks at &lt;a href="https://us.pycon.org/2024/" rel="noopener noreferrer"&gt;PyCon&lt;/a&gt; events.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Flask?
&lt;/h2&gt;

&lt;p&gt;Flask is a micro-framework that is intentionally minimal and flexible by design, which clearly doesn't limit its utility. As we will see, this design decision comes with both strengths and weaknesses.&lt;/p&gt;

&lt;p&gt;Flask started out as an April Fool's joke in 2010 by Armin Ronacher and was inspired by the Sinatra Ruby framework. FLask was meant to be simple enough to fit in a single Python file and, despite its humorous origins, Flask quickly gained popularity due to its simplicity and flexibility.&lt;/p&gt;

&lt;p&gt;Flask itself has a quite small codebase and relies heavily on two major dependencies: &lt;a href="https://werkzeug.palletsprojects.com/en/3.0.x/" rel="noopener noreferrer"&gt;Werkzeug&lt;/a&gt; and &lt;a href="https://jinja.palletsprojects.com/en/3.1.x/" rel="noopener noreferrer"&gt;Jinja&lt;/a&gt;, both of which were initially created by Armin Ronacher.&lt;/p&gt;

&lt;p&gt;Werkzeug is a WSGI (Web Server Gateway Interface) toolkit that provides the core functionality for Flask. It handles HTTP requests, and responses, a URL routing system, a built-in development server, interactive debugger, test client, and middleware. Jinja is a templating engine used to generate dynamic HTML documents that comes with its own syntax for basic logic, variables, if/else loops, template inheritance, and more. &lt;/p&gt;

&lt;p&gt;Although Flask doesn't specify a specific structure, it is often used in a Model-View-Controller (MVC) pattern common to other web frameworks such as Ruby on Rails.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Interacts with the database and handles data logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: Renders HTML templates (usually) with data for the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller&lt;/strong&gt;: Processes user input, interacts with the Model, and selects the View to render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flask's micro-framework architecture means it performs a few tasks extremely well and relies on third-party libraries (and the developer) to implement the rest. This approach is well-suited to smaller web applications that don't require all the bells and whistles built into Django. On the other extreme, experienced programmers who demand complete control over their application often prefer Flask, though this means making more design decisions than they would with a full framework like Django.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Django?
&lt;/h2&gt;

&lt;p&gt;Django is a high-level Python web framework that encourages rapid development and clean, pragmatic design. It was created in at the Lawrence Journal-World newspaper and publicly released in 2005. "High-level" means that Django is designed to minimize the actual coding required during the web application process by providing built-in "batteries" for most use cases, including an ORM (Object-Relational Mapper), URL routing, template engine, form handling, authentication system, admin interface, and robust security features. In Flask, the developer must choose and implement these various features but with Django they are included out-of-the-box.&lt;/p&gt;

&lt;p&gt;Django is managed by the non-profit Django Software Foundation and has a large and dedicated community behind it working on new releases, extensive documentation, active online communities, and regular community-run conferences.&lt;/p&gt;

&lt;p&gt;Django follows a variant of the MVC architecture called the Model-View-Template (MVT) pattern that emphasizes separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt;: Handles data and business logic, including methods to interact with the data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: Handles business logic and interacts with the Model and Template. It also processes user requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates&lt;/strong&gt;: Render the user interface, usually as HTML using the Django templating language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fourth component, &lt;strong&gt;URLs&lt;/strong&gt;, is also included and used to handle URL routing, matching a user request to a specific View that then generates a response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flask: Hello, World
&lt;/h2&gt;

&lt;p&gt;Python should already be installed on your computer so all we need to do is create a virtual environment and install Flask.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Windows
$ python -m venv .venv
$ .venv\Scripts\Activate.ps1
(.venv) $ python -m pip install flask

# macOS/Linux
$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv) $ python -m pip install flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With your text editor, create a new file called &lt;code&gt;hello.py&lt;/code&gt;. Flask famously requires &lt;a href="https://flask.palletsprojects.com/en/3.0.x/quickstart/" rel="noopener noreferrer"&gt;only five lines&lt;/a&gt; for a Hello World web page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;p&amp;gt;Hello, World!&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code imports the &lt;code&gt;Flask&lt;/code&gt; class at the top and creates an instance called &lt;code&gt;app&lt;/code&gt; on the next line. The &lt;code&gt;route()&lt;/code&gt; decorator tells Flask what URL should trigger the function; here it is set to the homepage at &lt;code&gt;/&lt;/code&gt;. Then the function, &lt;code&gt;hello_world&lt;/code&gt;, returns an HTML string between paragraph &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags with our message.&lt;/p&gt;

&lt;p&gt;To run the code, use the &lt;code&gt;flask run&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv)
$ flask run
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you navigate to &lt;code&gt;127.0.0.1:5000&lt;/code&gt; in your web browser the message is visible. Flask uses port &lt;code&gt;5000&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9sufwszirdhm76fi0as.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9sufwszirdhm76fi0as.png" alt="Flask Hello World" width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is about as simple as can be and speaks to both Flask's roots as an attempt at a single-file way to create a web application and also an example of its inherent flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Django: Hello, World
&lt;/h2&gt;

&lt;p&gt;The Django docs don't provide a similar quickstart guide but we can accomplish a similar feat with only a few more lines of code. In fact, doing so has become a bit of a game among seasoned Django developers and there is an entire repo, &lt;a href="https://github.com/wsvincent/django-microframework" rel="noopener noreferrer"&gt;django-microframework&lt;/a&gt;, dedicated to these efforts. We will choose Option2, which is not the most concise, but is more easily understood than some of the other approaches.&lt;/p&gt;

&lt;p&gt;Navigate to a new directory, perhaps called &lt;code&gt;django&lt;/code&gt; on your Desktop, and create a virtual environment containing Django.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Windows
&amp;gt; cd onedrive\desktop\code
&amp;gt; mkdir django
&amp;gt; cd django
&amp;gt; python -m venv .venv
&amp;gt; .venv\Scripts\Activate.ps1
(.venv) &amp;gt; python -m pip install django

# macOS
% cd ~/desktop/code
% mkdir django
% cd django
% python3 -m venv .venv
% source .venv/bin/activate
(.venv) % python3 -m pip install django
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your text editor create a &lt;code&gt;hello_django.py&lt;/code&gt; file with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# hello_django.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.handlers.wsgi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WSGIHandler&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.management&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;execute_from_command_line&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;

&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ROOT_URLCONF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, Django!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WSGIHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;execute_from_command_line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Django is designed for larger web application and typically relies on a global &lt;code&gt;settings.py&lt;/code&gt; file for many configurations, however we can import what we need in a single file. The key points of reference are the &lt;code&gt;hello_world&lt;/code&gt; function that returns the string, "Hello, Django!" and the &lt;code&gt;urlpatterns&lt;/code&gt; defining our URL routes, namely at &lt;code&gt;""&lt;/code&gt;, meaning the empty string, so the homepage.&lt;/p&gt;

&lt;p&gt;Start up Django's built-in server using the &lt;code&gt;runserver&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) &amp;gt; python hello_django.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 17, 2024 - 13:48:54
Django version 5.0, using settings None
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to Django's standard port of 8000, &lt;a href="http://127.0.0.1:8000/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/&lt;/a&gt;, to see the "Hello, Django!" message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz1ctbadu0mb2n2ir8kh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz1ctbadu0mb2n2ir8kh.png" alt="Django welcome page" width="663" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Django required tweleve lines of code rather than Flask's five, but both these examples are intended as quickstart guides; they are not how you structure a real-world Flask or Django app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask Personal Website
&lt;/h3&gt;

&lt;p&gt;Now let's build a Personal Website with a home page and an about page. This will give a chance to introduce templates and repeat some of the patterns we saw around how routes are defined in Flask.&lt;/p&gt;

&lt;p&gt;Update the &lt;code&gt;app.py&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;home.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/about&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;about&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;about.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the &lt;code&gt;home&lt;/code&gt; and &lt;code&gt;about&lt;/code&gt; View functions now return a template. We're also using the &lt;code&gt;route()&lt;/code&gt; decorator again to define the URL path for each. We've also added &lt;code&gt;debug=True&lt;/code&gt; at the bottom so that the development server runs now in debug mode.&lt;/p&gt;

&lt;p&gt;The next step is creating our two templates. Flask will look for template files in a &lt;code&gt;templates&lt;/code&gt; directory so create that now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ mkdir templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within it add the two files with the following code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create templates in &lt;code&gt;templates/&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- templates/home.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Personal Website&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to My Website&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ url_for('about') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- templates/about.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my personal website.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ url_for('home') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file use the method &lt;a href="https://flask.palletsprojects.com/en/3.0.x/api/#flask.Flask.url_for" rel="noopener noreferrer"&gt;url_for&lt;/a&gt; to define links based on the view function name.&lt;/p&gt;

&lt;p&gt;Run the server again with &lt;code&gt;flask run&lt;/code&gt; and navigate to the homepage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkcncob4r57xgj74m0jn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkcncob4r57xgj74m0jn.png" alt="Flask Home Page" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click the "About Me" link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo1hvyi9pecdhe7qkvrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo1hvyi9pecdhe7qkvrd.png" alt="Flask About page" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a rudimentary example but you can start to see how templates and views interact in Flask. We still have only one main Python file powering the whole thing, but once we have many more pages and start to introduce logic, the single-file approach stops making sense and it's time to start organizing the Flask app in different ways. There are some common patterns used in the Flask community, however, it is ultimately up to the developer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Django: Personal Website
&lt;/h2&gt;

&lt;p&gt;Django is designed for full-bodied web applications so building a Personal Website is a chance to see this in action. We'll start by creating a project, which is the central hub for our website, using the &lt;code&gt;startproject&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ django-admin startproject django_project .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've named the project &lt;code&gt;django_project&lt;/code&gt; here. Adding the period, &lt;code&gt;.&lt;/code&gt;, means the new folder and files are installed in the current directory. If you don't have the period Django creates a new directory and &lt;em&gt;then&lt;/em&gt; adds the project folder and files there.&lt;/p&gt;

&lt;p&gt;This is what your directory should look like now. The &lt;code&gt;hello_django.py&lt;/code&gt; file remains and can either be left there or removed entirely: we will no longer use it. There is an entirely new &lt;code&gt;django_project&lt;/code&gt; folder containing several files and a &lt;code&gt;manage.py&lt;/code&gt; file used for running Django commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── django_project
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── hello_django.py
└── manage.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to create an app now using thes &lt;code&gt;startapp&lt;/code&gt; command which will be called &lt;code&gt;pages&lt;/code&gt;. A single Django project typically has multiple apps for different functionality. If we added user registration that code should be in its own app, same for payments, and so on. This is a way to help developers reason better about their code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ python manage.py startapp pages.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a &lt;code&gt;pages&lt;/code&gt; directory with the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── pages
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our first step is updating the &lt;code&gt;django_project/settings.py&lt;/code&gt; file to tell Django about our new app. This is a global settings file for the entire project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# django_project/settings.py
&lt;/span&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, update the &lt;code&gt;django_project/urls.py&lt;/code&gt; file. When a URL request comes in it will hit this file first and then be either processed or redirected to a specific app. In this case, we want to send requests to the &lt;code&gt;pages&lt;/code&gt; app. To do this we'll import &lt;code&gt;include&lt;/code&gt; and set a new path at &lt;code&gt;""&lt;/code&gt;, meaning the homepage. Django defaults to including the URL configuration for the built-in admin, a powerful visual way to interact with your database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# django_project/urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;
&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pages.urls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;  &lt;span class="c1"&gt;# new
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within the &lt;code&gt;pages&lt;/code&gt; app we need a view and a URLs file. Let's start with the view at &lt;code&gt;pages/views.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pages/views.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.shortcuts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;about&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;about.html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Django, views receive web requests and return web responses. The &lt;code&gt;request&lt;/code&gt; parameter is an object containing metadata about the request from the user. We'll define two function-based views here, &lt;code&gt;home&lt;/code&gt; and &lt;code&gt;about&lt;/code&gt;, that use the shortcut function &lt;code&gt;render&lt;/code&gt; to combine a template with an &lt;code&gt;HttpResponse&lt;/code&gt; object sent back to the user. The two templates are &lt;code&gt;home.html&lt;/code&gt; and &lt;code&gt;about.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the templates, we can create a &lt;code&gt;templates&lt;/code&gt; directory within &lt;code&gt;pages&lt;/code&gt;, then another directory with the app name, and finally our template files. This approach removes any concerns about confusing the Django template loader in larger projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ mkdir pages/templates
(.venv) $ mkdir pages/templates/pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in your text editor add two new files: &lt;code&gt;pages/templates/pages/home.html&lt;/code&gt; and &lt;code&gt;pages/templates/pages/about.html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- pages/templates/pages/home.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Personal Website&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to My Website&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'about' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- pages/templates/pages/about.html --&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;About Me&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is my personal website.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% url 'home' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is configuring the URLs for these two pages. To do this, create a &lt;code&gt;urls.py&lt;/code&gt; file within the &lt;code&gt;pages&lt;/code&gt; app with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pages/urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;home&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;about/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;about&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;about&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the top we import our views and then set a URL path for each. The syntax is defining the URL path, the view name, and optionally adding a URL &lt;code&gt;name&lt;/code&gt; that allows us to link to each path in our templates.&lt;/p&gt;

&lt;p&gt;Start up the Django local server with the &lt;code&gt;runserver&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(.venv) $ python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the homepage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7mcpekwl8u8d4p4vpy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7mcpekwl8u8d4p4vpy1.png" alt="Django Home Page" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the "About Me" to be redirected to the about page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u2zwie28f3a29jt8s39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u2zwie28f3a29jt8s39.png" alt="Django About Page" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see Django required more scaffolding than Flask, however this approach provides a consistent structure that is quite scaleable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detailed Comparison
&lt;/h2&gt;

&lt;p&gt;The true comparison of these web frameworks depends on your project's needs. Are you building a traditional web application that connects to a database, requires CRUD (Create-Read-Update-Delete) functionality, and user authentication? If yes, Django has built-in solutions for all of these needs. By comparison, Flask requires installing multiple third-party libraries: &lt;code&gt;Flask-SQLAlchemy&lt;/code&gt; to connect to the database, &lt;code&gt;Flask-Migrate&lt;/code&gt; to manage database migrations, &lt;code&gt;Flask-WTF&lt;/code&gt; and &lt;code&gt;WTForms&lt;/code&gt; for forms, &lt;code&gt;Flask-Login&lt;/code&gt; for user authentication, &lt;code&gt;FLask-Mail&lt;/code&gt; for email support, &lt;code&gt;Flask-Security&lt;/code&gt; for security features, &lt;code&gt;Flask-Admin&lt;/code&gt; for an admin interface to manage application data, &lt;code&gt;Flask-Caching&lt;/code&gt; for caching support, &lt;code&gt;Flask-BCrypt&lt;/code&gt; for password hashing and so on.&lt;/p&gt;

&lt;p&gt;The power of Django is that you don't have to worry about any of these things. They are included, tested, and supported by the community. For Flask, the third-party libraries are not as tightly integrated and require more manual installation by the developer. This affords greater flexibility but also requires more programmer expertise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Ultimately, you can't go wrong choosing Flask or Django for your web application needs. They both are mature, scaleable, and well-documented. This difference is in approach and the best way to determine what you prefer is to try each out by building more complex projects.&lt;/p&gt;

&lt;p&gt;If you're interested in learning more about Django, check out &lt;a href="https://djangoforbeginners" rel="noopener noreferrer"&gt;Django for Beginners&lt;/a&gt; for a guide to building six progressively more complex web applications including testing and deployment. For Flask, the &lt;a href="https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world" rel="noopener noreferrer"&gt;Flask Mega-Tutorial&lt;/a&gt; has a free online version. There are also two courses over at TestDriven.io worth recommending: &lt;a href="https://testdriven.io/courses/tdd-flask/?utm_source=will" rel="noopener noreferrer"&gt;TDD with Python, Flask and Docker&lt;/a&gt; and &lt;a href="https://testdriven.io/courses/auth-flask-react/?utm_source=will" rel="noopener noreferrer"&gt;Authentication with Flask, React, and Docker&lt;/a&gt;. If you prefer video, there are many Flask courses on Udemy but the best video course I've seen is &lt;a href="https://buildasaasappwithflask.com/ref-dfp" rel="noopener noreferrer"&gt;Build a SaaS App with Flask and Docker&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>django</category>
      <category>flask</category>
      <category>python</category>
      <category>web</category>
    </item>
  </channel>
</rss>
