<?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: Augusto Domingos</title>
    <description>The latest articles on DEV Community by Augusto Domingos (@aghastygd).</description>
    <link>https://dev.to/aghastygd</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%2F1267934%2F68afff2e-23b9-4567-bbd3-1ad10ecf9f8f.png</url>
      <title>DEV Community: Augusto Domingos</title>
      <link>https://dev.to/aghastygd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aghastygd"/>
    <language>en</language>
    <item>
      <title>Metaprogramming and the Limits of Static Analysis</title>
      <dc:creator>Augusto Domingos</dc:creator>
      <pubDate>Sun, 25 Jan 2026 08:01:25 +0000</pubDate>
      <link>https://dev.to/aghastygd/metaprogramming-and-the-limits-of-static-analysis-4dbk</link>
      <guid>https://dev.to/aghastygd/metaprogramming-and-the-limits-of-static-analysis-4dbk</guid>
      <description>&lt;p&gt;About a year ago, I started &lt;strong&gt;Lazy Ninja&lt;/strong&gt; with a clear goal: eliminate boilerplate in Django APIs.&lt;/p&gt;

&lt;p&gt;The idea was simple in theory: automatically generate CRUD routes, validation, serialization, and documentation directly from Django models. Less repetition, fewer files to maintain, and a smoother developer experience.&lt;/p&gt;

&lt;p&gt;I was involved early in the development of &lt;strong&gt;Arkos.js&lt;/strong&gt;, a project built on top of &lt;strong&gt;Prisma&lt;/strong&gt; and designed around a &lt;strong&gt;schema-first, code-generated&lt;/strong&gt; approach. That experience strongly influenced how I initially thought about tooling and type safety.&lt;/p&gt;

&lt;p&gt;While building Lazy Ninja, however, I ran into a problem that had little to do with framework design and everything to do with &lt;strong&gt;how far static analysis can really go&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real tension
&lt;/h2&gt;

&lt;p&gt;The core issue is not Python versus any other language.&lt;/p&gt;

&lt;p&gt;It is the tension between &lt;strong&gt;static analysis&lt;/strong&gt; and &lt;strong&gt;runtime-driven systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lazy Ninja relies heavily on metaprogramming and runtime introspection. In practice, it needs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Inspect Django models at runtime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discover fields via reflection (&lt;code&gt;_meta.get_fields()&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate Pydantic schemas dynamically&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create API routes automatically&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a runtime perspective, this is safe and predictable. Django guarantees the existence of model fields, primary keys, and relationships.&lt;/p&gt;

&lt;p&gt;From a static analysis perspective, however, things start to break down.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why static analysis struggles with runtime-driven design
&lt;/h2&gt;

&lt;p&gt;Static type checkers such as &lt;strong&gt;Pylance&lt;/strong&gt; and &lt;strong&gt;mypy&lt;/strong&gt; analyze code &lt;em&gt;without executing it&lt;/em&gt;. They operate under a fundamental constraint: they can only reason about information that exists &lt;strong&gt;before runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a system builds part of its structure dynamically, static analysis simply cannot observe that process.&lt;/p&gt;

&lt;p&gt;A minimal example:&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="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_user_model&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# type unknown to the checker 
&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="c1"&gt;# attribute may not exist (statically)  
&lt;/span&gt;
&lt;span class="c1"&gt;# At runtime, Django guarantees that User has an email field
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a bug in the type checker.&lt;br&gt;&lt;br&gt;
It is a limitation of static analysis itself.&lt;/p&gt;

&lt;p&gt;The contract exists — but it exists &lt;strong&gt;only at runtime&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  A more realistic example from metaprogramming
&lt;/h2&gt;

&lt;p&gt;Consider a simplified version of how Lazy Ninja inspects models:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_fields&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&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;_meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_fields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_relation&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At runtime, this works flawlessly.&lt;br&gt;&lt;br&gt;
Django’s model system ensures &lt;code&gt;_meta&lt;/code&gt; is present and fully populated.&lt;/p&gt;

&lt;p&gt;From the type checker’s point of view:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;_meta&lt;/code&gt; is dynamic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;get_fields()&lt;/code&gt; returns heterogeneous field types&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The structure is opaque&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is warnings — even though the behavior is correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  The temptation to “fight” the type checker
&lt;/h2&gt;

&lt;p&gt;Early on, it’s tempting to try to make the type checker happy at all costs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Overusing &lt;code&gt;cast()&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding fake base classes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing overly generic &lt;code&gt;Any&lt;/code&gt; annotations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hiding logic behind layers of indirection&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, this often makes the code &lt;strong&gt;harder to read&lt;/strong&gt; and &lt;strong&gt;less honest&lt;/strong&gt; about what is happening.&lt;/p&gt;

&lt;p&gt;At some point, I realized the better question was not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I silence the type checker?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But rather:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Where exactly does static analysis stop being useful?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  When static analysis works extremely well
&lt;/h2&gt;

&lt;p&gt;Static analysis shines when the data contract is known &lt;strong&gt;before execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Schema-first systems that generate code ahead of time give static analyzers full visibility into models, fields, and relationships. This is why tools like &lt;strong&gt;Prisma Client Python&lt;/strong&gt; can offer strong type safety in Python: the client is generated from a schema, not inferred from runtime behavior.&lt;/p&gt;

&lt;p&gt;In those systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Autocomplete works perfectly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IDEs understand relationships&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Many bugs are caught before execution&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reinforces an important idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The limitation is not the language, but &lt;em&gt;when&lt;/em&gt; the contract exists.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why Lazy Ninja does not adopt a schema-first approach
&lt;/h2&gt;

&lt;p&gt;I seriously considered a schema-first model.&lt;/p&gt;

&lt;p&gt;However, Lazy Ninja is intentionally built &lt;strong&gt;on top of Django&lt;/strong&gt;, not just as a database access layer.&lt;/p&gt;

&lt;p&gt;Django provides much more than an ORM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A mature model system tightly integrated with the framework&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrations and schema evolution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The admin panel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Signals, authentication, permissions, and a large ecosystem&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adopting a separate schema and code-generation pipeline would mean stepping outside Django’s model system and duplicating responsibilities that Django already handles well.&lt;/p&gt;

&lt;p&gt;Lazy Ninja’s goal is not to replace Django’s data layer, but to &lt;strong&gt;amplify it&lt;/strong&gt; — even if that means accepting the limits of static analysis in exchange for runtime flexibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Making the trade-offs explicit
&lt;/h2&gt;

&lt;p&gt;Rather than pretending full static guarantees were possible, I chose to make the boundaries explicit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategic &lt;code&gt;type: ignore&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;  &lt;span class="c1"&gt;# type: ignore[attr-defined]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, Django guarantees that every model instance has a primary key.&lt;br&gt;&lt;br&gt;
The &lt;code&gt;type: ignore&lt;/code&gt; is local and intentional.&lt;/p&gt;




&lt;h3&gt;
  
  
  Safe attribute access with &lt;code&gt;getattr&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;last_login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows optional fields without breaking at runtime and without lying to the type system.&lt;/p&gt;




&lt;h3&gt;
  
  
  Conditional logic with &lt;code&gt;hasattr&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;  &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;is_staff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially useful for compatibility across Django versions or custom user models.&lt;/p&gt;




&lt;h3&gt;
  
  
  Encapsulating ambiguity with type guards
&lt;/h3&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypeGuard&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_django_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TypeGuard&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_meta&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;This keeps dynamic checks localized and improves readability.&lt;/p&gt;




&lt;h2&gt;
  
  
  The outcome
&lt;/h2&gt;

&lt;p&gt;This approach led to a predictable result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Zero runtime errors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some IDE warnings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A codebase that is honest about its constraints&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, it avoided the illusion of safety that comes from forcing static guarantees where they cannot truly exist.&lt;/p&gt;




&lt;h2&gt;
  
  
  The main lesson
&lt;/h2&gt;

&lt;p&gt;Static analysis is not a universal solution.&lt;/p&gt;

&lt;p&gt;It has real limits when applied to systems designed around runtime introspection and metaprogramming. Lazy Ninja does not fight type checkers — it operates beyond what they can fully model.&lt;/p&gt;

&lt;p&gt;The real challenge is being explicit about where static guarantees end and runtime guarantees begin, and designing systems that respect that boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final reflection
&lt;/h2&gt;

&lt;p&gt;Building Lazy Ninja ended up being less about generating routes and more about understanding the architectural limits of static analysis in highly dynamic systems.&lt;/p&gt;

&lt;p&gt;If you’ve built frameworks, ORMs, or tooling that relies heavily on metaprogramming, you’ve likely faced the same trade-offs — regardless of language.&lt;/p&gt;

&lt;p&gt;Lazy Ninja is available on &lt;a href="https://github.com/AghastyGD/lazy-ninja" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and you can experiment with it directly in your Django projects.&lt;/p&gt;

</description>
      <category>api</category>
      <category>django</category>
      <category>python</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Integração do Cloudinary ao seu projeto Django gratuitamente</title>
      <dc:creator>Augusto Domingos</dc:creator>
      <pubDate>Tue, 16 Jul 2024 11:53:27 +0000</pubDate>
      <link>https://dev.to/aghastygd/integracao-do-cloudinary-ao-seu-projeto-django-gratuitamente-8pm</link>
      <guid>https://dev.to/aghastygd/integracao-do-cloudinary-ao-seu-projeto-django-gratuitamente-8pm</guid>
      <description>&lt;p&gt;No &lt;a href="https://dev.to/aghastygd/hospede-seu-site-django-com-arquivos-estaticos-na-vercel-gratuitamente-novo-metodo-339p"&gt;tutorial passado&lt;/a&gt;, você aprendeu a hospedar um site Django de maneira gratuita no Vercel. Mas o que acontece se o seu site precisar fazer upload de arquivos, como fotos ou vídeos? Normalmente, você teria um diretório de mídia no seu projeto para armazenar e renderizar esses arquivos, pois não é uma boa prática armazenar fotos ou vídeos diretamente no banco de dados. &lt;/p&gt;

&lt;p&gt;No entanto, a Vercel não permite escrita na plataforma. Como resolver isso? É aí que entra o Cloudinary, um serviço de upload de imagens e vídeos com um plano gratuito oferecendo 25 GB de storage, ideal para o seu projeto que necessita de armazenamento de mídias.&lt;/p&gt;

&lt;p&gt;Neste tutorial, você aprenderá a integrar o Cloudinary ao seu projeto Django, aproveitando a SDK que esta plataforma oferece para Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando Cloudinary no seu projeto Django
&lt;/h2&gt;

&lt;p&gt;Para seguir com esse tutorial, basta ter um projeto Django funcionando, seja ele já hospedado na Vercel ou não, pois o método é o mesmo.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 1:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A primeira coisa é instalar a SDK do Cloudinary no seu ambiente de desenvolvimento usando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;cloudinary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dica:&lt;/strong&gt; Se for na Vercel, basta adicionar &lt;code&gt;cloudinary&lt;/code&gt; no &lt;code&gt;requirements.txt&lt;/code&gt; do seu projeto e fazer o build (redeploy) novamente. Caso esteja controlando versões com o Git, o commit dessa alteração já vai automaticamente buildar na plataforma Vercel e estará instalando a biblioteca usando o nosso &lt;a href="https://dev.to/aghastygd/hospede-seu-site-django-com-arquivos-estaticos-na-vercel-gratuitamente-novo-metodo-339p#:~:text=mais%20um%20arquivo-,build.sh,-com%20o%20seguinte"&gt;script bash&lt;/a&gt; que criamos anteriormente.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 2:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;No seu &lt;code&gt;settings.py&lt;/code&gt;, importe o &lt;code&gt;cloudinary&lt;/code&gt; e adicione a seguinte configuração:&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;import&lt;/span&gt; &lt;span class="n"&gt;cloudinary&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloudinary.uploader&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cloudinary.api&lt;/span&gt;

&lt;span class="n"&gt;cloudinary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;cloud_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOUD_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOUD_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;api_secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOUD_SECRET_KEY&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;h4&gt;
  
  
  &lt;strong&gt;Passo 3:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;No seu &lt;code&gt;models.py&lt;/code&gt; faça o seguinte import:&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;cloudinary.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CloudinaryField&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E no campo de imagem em qualquer modelo seu que faz upload de imagens, use o &lt;code&gt;CloudinaryField&lt;/code&gt; além de &lt;code&gt;models.ImageField&lt;/code&gt; (padrão do Django), veja o exemplo de um modelo &lt;code&gt;Post&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&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;description&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;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CloudinaryField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# nesta linha
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 4:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Agora você vai configurar váriaveis de ambiente que chamaste no segundo passo.&lt;br&gt;
Para isso, crie um arquivo &lt;code&gt;.env&lt;/code&gt; no diretório raíz do seu projeto com as seguintes variáveis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight make"&gt;&lt;code&gt;&lt;span class="nv"&gt;CLOUD_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;seu cloud_name
&lt;span class="nv"&gt;CLOUD_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sua api_key
&lt;span class="nv"&gt;CLOUD_SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sua secret_key

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Dica:&lt;/strong&gt; Se estiver usando a Vercel, você pode adicionar variáveis de ambiente diretamente nas configurações do projeto na dashboard da plataforma. Além de criar um arquivo &lt;code&gt;.env&lt;/code&gt; localmente, acesse a dashboard da Vercel e adicione as variáveis com os respectivos valores no seu projeto.&lt;/p&gt;

&lt;p&gt;Falando em valores, você precisará pegar eles na sua conta do Cloudinary, para isso, acesse o &lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;site oficial&lt;/a&gt;, e crie uma conta se não tiver uma.&lt;br&gt;
Tendo acesso à Dashboard da sua conta, clique em &lt;strong&gt;"Go to API Key"&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0df0hm6i83k455o38e8i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0df0hm6i83k455o38e8i.jpg" alt="dashboard do cloudinary" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na próxima tela, clique em &lt;strong&gt;"Generate API KEY"&lt;/strong&gt; para obter suas chaves de acesso:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmd3i9yd641gtgo1ecoc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmd3i9yd641gtgo1ecoc.jpg" alt="gerar uma api key" width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com isso, você terá os valores necessários para preencher seu arquivo &lt;code&gt;.env&lt;/code&gt;: &lt;code&gt;CLOUD_NAME&lt;/code&gt;, &lt;code&gt;CLOUD_API_KEY&lt;/code&gt; e &lt;code&gt;CLOUD_SECRET_KEY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Neste tutorial, estamos usando o &lt;code&gt;os.getenv&lt;/code&gt; para acessar as váriaveis, e para funcionar, precisamos da biblioteca &lt;code&gt;python-dotenv&lt;/code&gt;. Então, caso não tenha essa biblioteca no seu ambiente, faça a instalação com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E no princípio do &lt;code&gt;settings.py&lt;/code&gt; do seu projeto, faça a importação dela para permitir o uso:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tudo pronto! Você configurou o Cloudinary no seu projeto, permitindo o upload e host de imagens diretamente na plataforma. Parabéns por ter concluído! &lt;br&gt;
Agora, para exibir essas imagens no seu projeto, você pode configurar suas views e templates para renderizar as URLs das imagens em suas páginas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links Utéis:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Projeto usado para configuração de Cloudinary nesse tutorial:&lt;/strong&gt; &lt;a href="https://github.com/AghastyGD/django-cloudinary-demo.git" rel="noopener noreferrer"&gt;https://github.com/AghastyGD/django-cloudinary-demo.git&lt;/a&gt; - Inclusive, neste repositório adicionei &lt;code&gt;views&lt;/code&gt; e &lt;code&gt;templates&lt;/code&gt; de exemplo para demonstrar uma imagem hospedada no Cloudinary. Você pode usá-lo como referência.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentação do Cloudinary para uso com Python:&lt;/strong&gt; &lt;a href="https://cloudinary.com/documentation/django_integration" rel="noopener noreferrer"&gt;https://cloudinary.com/documentation/django_integration&lt;/a&gt; - Recomendo a leitura, pois oferece diversas funcionalidades adicionais, como compressão de imagens, transformações e muito mais.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se precisar de mais ajuda ou tiver dúvidas, deixe um comentário. Te vejo na próxima vez 👋.&lt;/p&gt;

</description>
      <category>cloudstorage</category>
      <category>django</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>Hospede seu site Django com arquivos estáticos na Vercel gratuitamente (Novo Método)</title>
      <dc:creator>Augusto Domingos</dc:creator>
      <pubDate>Fri, 12 Jul 2024 18:24:17 +0000</pubDate>
      <link>https://dev.to/aghastygd/hospede-seu-site-django-com-arquivos-estaticos-na-vercel-gratuitamente-novo-metodo-339p</link>
      <guid>https://dev.to/aghastygd/hospede-seu-site-django-com-arquivos-estaticos-na-vercel-gratuitamente-novo-metodo-339p</guid>
      <description>&lt;p&gt;Hospedar um site Django completo pode ser um desafio, especialmente ao optar por plataformas gratuitas. No entanto, com a Vercel, você pode configurar seu site para ser hospedado sem custo algum 💸 , e com os arquivos estáticos funcionando corretamente utilizando esse novo método sem erros 🤩.&lt;br&gt;
Neste tutorial, você será guiado por todo o processo, desde a preparação do ambiente até o deploy final.&lt;/p&gt;
&lt;h4&gt;
  
  
  Requisitos:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Ter um projeto Django funcional na sua máquina&lt;/li&gt;
&lt;li&gt;Ter Python instalado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atendendo esses requisitos, você já pode continuar o tutorial abaixo:&lt;/p&gt;
&lt;h2&gt;
  
  
  Preparando o ambiente
&lt;/h2&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 1:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Abra o arquivo &lt;code&gt;wsgi.py&lt;/code&gt; do seu projeto, normalmente localizado dentro do seu diretorio "project_name" e adicione a seguinte linha no final:&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;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.wsgi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_wsgi_application&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&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_SETTINGS_MODULE&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;nomedoseuprojeto.settings&lt;/span&gt;&lt;span class="sh"&gt;'&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="nf"&gt;get_wsgi_application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# esta linha
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 2:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Navegue até a pasta raiz do seu projeto e crie o arquivo &lt;code&gt;vercel.json&lt;/code&gt; com o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"builds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nomedoseuprojeto/wsgi.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@vercel/python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"maxLambdaSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15mb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python3.9"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/(.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nomedoseuprojeto/wsgi.py"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Substitua "nomedoseuprojeto" pelo nome do diretório onde está localizado o arquivo &lt;code&gt;wsgi.py&lt;/code&gt; do seu projeto Django&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Explicação (pode pular se quiser):&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;O arquivo &lt;code&gt;vercel.json&lt;/code&gt; configura como seu projeto será construído e roteado na plataforma Vercel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;version&lt;/strong&gt;: Define a versão da configuração da Vercel (geralmente 1 ou 2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;builds&lt;/strong&gt;: Especifica como seu projeto será construído.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;src&lt;/strong&gt;: Caminho para o arquivo &lt;code&gt;wsgi.py&lt;/code&gt; do seu projeto Django.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;use&lt;/strong&gt;: Usa o ambiente Python da Vercel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;config&lt;/strong&gt;: Configurações específicas para Python, como tamanho máximo do pacote e versão.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;routes&lt;/strong&gt;: Define como as solicitações HTTP são roteadas.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;src&lt;/strong&gt;: Todas as solicitações HTTP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;dest&lt;/strong&gt;: Encaminha para &lt;code&gt;wsgi.py&lt;/code&gt; do seu projeto.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Agora com o vercel.json criado corretamente, no próximo passo você irá adicionar um script bash para executar comandos de terminal na plataforma Vercel.&lt;/p&gt;

&lt;h4&gt;
  
  
  Passo 3:
&lt;/h4&gt;

&lt;p&gt;Na pasta raíz do seu projeto, crie mais um arquivo &lt;code&gt;build.sh&lt;/code&gt; com o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# build.sh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Starting build script"&lt;/span&gt;

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# make migrations&lt;/span&gt;
python3 manage.py makemigrations
python3 manage.py migrate

&lt;span class="c"&gt;# collectstatic&lt;/span&gt;
python3 manage.py collectstatic

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Build script completed"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 4&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;Gere um requirements.txt de todas as dependências do seu projeto, e adicione &lt;code&gt;whitenoise&lt;/code&gt; na lista, conforme o exemplo abaixo:&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;# outras dependências...
&lt;/span&gt;&lt;span class="n"&gt;Django&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="n"&gt;whitenoise&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mf"&gt;6.7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No momento da escrita deste post, a versão atual do WhiteNoise é a 6.7.0. Sinta-se à vontade para usar uma versão mais recente no seu caso.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Explicação&lt;/strong&gt;:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WhiteNoise&lt;/strong&gt; é uma biblioteca Python que ajuda a servir arquivos estáticos em aplicações web de maneira eficiente. É frequentemente usado com Django para simplificar a configuração e melhorar o desempenho no serviço de arquivos estáticos como CSS, JavaScript e imagens, muito útil para hospedagem em plataformas cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Passo 5&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;Adicione o middleware do whitenoise no &lt;code&gt;settings.py&lt;/code&gt; do seu projeto:&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="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;whitenoise.middleware.WhiteNoiseMiddleware&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Adicione esta linha
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure a localização dos seus arquivos estáticos:&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="n"&gt;STATIC_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;static/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;static/&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;E se preferir, adicione também a seguinte configuração para ativar a compressão e armazenamento em cache, garantindo melhor performance na sua aplicação:&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="n"&gt;STATICFILES_STORAGE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;whitenoise.storage.CompressedManifestStaticFilesStorage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fazendo Deploy na Vercel
&lt;/h2&gt;

&lt;p&gt;Agora que você preparou o ambiente, está pronto para fazer o deploy do seu projeto na Vercel. Siga os passos abaixo para completar o processo:&lt;/p&gt;

&lt;p&gt;1 - &lt;strong&gt;Crie uma conta na plataforma &lt;a href="//vercel.com"&gt;Vercel&lt;/a&gt;&lt;/strong&gt; se ainda não tiver&lt;br&gt;
2 - &lt;strong&gt;Importe o repositório git do seu projeto:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofxm3mrj6r05597cgktq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofxm3mrj6r05597cgktq.png" alt="Image description" width="706" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3 - &lt;strong&gt;Configure as variáveis de ambiente se o seu projeto precisar de alguma e depois clique em "Deploy"&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyuy3y220fb5xnloijo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffyuy3y220fb5xnloijo3.png" alt="Image description" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4 - &lt;strong&gt;Aguarde o processo:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5evm86nak4qd03wcvjny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5evm86nak4qd03wcvjny.png" alt="Image description" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5 - &lt;strong&gt;Finalmente, após a conclusão do processo, você deve ver uma tela semelhante a esta:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw00kf5n9swjuc3cfgeom.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw00kf5n9swjuc3cfgeom.png" alt="Image description" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E booyah! Você conseguiu hospedar o seu projeto Django com arquivos estáticos na Vercel! Parabéns pelo feito, é um grande passo!&lt;/p&gt;

&lt;p&gt;Prepare-se para futuras jornadas, pois, uma vez que a Vercel é serverless, você não poderá realizar tarefas de escrita diretamente na Vercel, como upload de imagens e vídeos. No entanto, não se preocupe, Em um artigo futuro, você aprenderá como fazer isso gratuitamente utilizando a API de outra plataforma gratuita que serve arquivos de mídia, sem custos. 💸🫡&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Se o seu projeto Django estiver utilizando o banco de dados SQLite, que é geralmente gerado em todos os projetos Django, não será possível realizar gravações diretamente na Vercel. Para isso, será necessário utilizar um servidor de banco de dados. A Vercel oferece uma instância gratuita de PostgreSQL que pode ser configurada no seu projeto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links Utéis
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Código-fonte do Projeto usado para deploy neste tutorial:&lt;/strong&gt; &lt;a href="https://github.com/AghastyGD/ai-interview-django/tree/deploy" rel="noopener noreferrer"&gt;https://github.com/AghastyGD/ai-interview-django/tree/deploy&lt;/a&gt; (acesse a branch deploy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentação do Whitenoise&lt;/strong&gt;: &lt;a href="https://whitenoise.readthedocs.io/en/stable/django.html" rel="noopener noreferrer"&gt;https://whitenoise.readthedocs.io/en/stable/django.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Volte sempre! ❤️ Dúvidas? deixe nos comentários!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>vercel</category>
      <category>django</category>
      <category>python</category>
    </item>
  </channel>
</rss>
