<?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: Nicolás Andrés Cano Leal</title>
    <description>The latest articles on DEV Community by Nicolás Andrés Cano Leal (@nicolasandrescl).</description>
    <link>https://dev.to/nicolasandrescl</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%2F3277529%2F17913cbd-8300-4778-ac07-89102a7cf35e.jpg</url>
      <title>DEV Community: Nicolás Andrés Cano Leal</title>
      <link>https://dev.to/nicolasandrescl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicolasandrescl"/>
    <language>en</language>
    <item>
      <title>From Local Scripts to Global-Ready Backend: CI/CD, Testing &amp; Coverage in SparkTrace</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Wed, 13 Aug 2025 05:37:28 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/from-local-scripts-to-global-ready-backend-cicd-testing-coverage-in-sparktrace-3p32</link>
      <guid>https://dev.to/nicolasandrescl/from-local-scripts-to-global-ready-backend-cicd-testing-coverage-in-sparktrace-3p32</guid>
      <description>&lt;p&gt;Over the past few weeks, I’ve transformed my backend project SparkTrace into a reproducible, test-driven, and CI/CD-integrated system—ready for international technical interviews and scalable deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here’s a breakdown of the key milestones:
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🧠 Modular Architecture &amp;amp; Refactor
&lt;/h2&gt;

&lt;p&gt;Reorganized Django commands into a clean structure under productos/management/commands/&lt;/p&gt;

&lt;p&gt;Decoupled logic for API integration, CSV loading, and Spark job execution&lt;/p&gt;

&lt;p&gt;Refactored settings and .gitignore for cross-platform compatibility&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Automated Testing &amp;amp; Full Coverage
&lt;/h2&gt;

&lt;p&gt;Built a complete test suite with pytest and pytest-django&lt;/p&gt;

&lt;p&gt;Validated edge cases with JSON fixtures simulating real API responses&lt;/p&gt;

&lt;p&gt;Achieved 100% coverage in critical modules: CSV loader, API integration, custom exceptions&lt;/p&gt;

&lt;p&gt;Documented audit-ready testing strategy in bilingual README&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ CI/CD Integration with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Configured workflow to run tests and coverage on every push and pull request&lt;/p&gt;

&lt;p&gt;Managed secrets (SECRET_KEY, CODECOV_TOKEN) securely via GitHub&lt;/p&gt;

&lt;p&gt;Integrated Codecov for visual coverage reporting&lt;/p&gt;

&lt;p&gt;Added badges for test status and coverage to README&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Professional Presentation &amp;amp; Portfolio
&lt;/h2&gt;

&lt;p&gt;Updated bilingual README with technical branding&lt;/p&gt;

&lt;p&gt;Published progress on LinkedIn to showcase reproducibility and traceability&lt;/p&gt;

&lt;p&gt;Live portfolio available at nicolasandrescl.pythonanywhere.com&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 What’s Next?
&lt;/h2&gt;

&lt;p&gt;My goal is to lead backend projects with robust testing, API integration, and CI/CD pipelines that scale globally. SparkTrace is now a technical showcase for reproducibility, coverage, and auditability—ready for interviews, collaborations, and open-source contributions.&lt;/p&gt;

&lt;p&gt;🇪🇸 Versión en español&lt;/p&gt;

&lt;h2&gt;
  
  
  De scripts locales a backend listo para el mundo: CI/CD, testing y cobertura en SparkTrace
&lt;/h2&gt;

&lt;p&gt;Durante las últimas semanas, transformé mi proyecto backend SparkTrace en un sistema reproducible, orientado a testing y con integración CI/CD—preparado para entrevistas técnicas internacionales y despliegues escalables.&lt;/p&gt;

&lt;p&gt;Aquí el resumen de los hitos clave:&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Arquitectura modular y refactor
&lt;/h2&gt;

&lt;p&gt;Reorganicé los comandos Django en una estructura limpia bajo productos/management/commands/&lt;/p&gt;

&lt;p&gt;Desacoplé la lógica de integración API, carga CSV y ejecución de jobs Spark&lt;/p&gt;

&lt;p&gt;Refactoricé los settings y .gitignore para compatibilidad multiplataforma&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Testing automatizado y cobertura total
&lt;/h2&gt;

&lt;p&gt;Construí una suite completa con pytest y pytest-django&lt;/p&gt;

&lt;p&gt;Validé casos límite con fixtures JSON que simulan respuestas reales de API&lt;/p&gt;

&lt;p&gt;Alcancé cobertura del 100% en módulos críticos: cargador CSV, integración API, excepciones personalizadas&lt;/p&gt;

&lt;p&gt;Documenté la estrategia de testing lista para auditoría en README bilingüe&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%2F5tk4usqkve3x7m2unzy6.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%2F5tk4usqkve3x7m2unzy6.png" alt="tests" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Integración CI/CD con GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Configuré workflow para ejecutar tests y cobertura en cada push y pull request&lt;/p&gt;

&lt;p&gt;Gestioné secretos (SECRET_KEY, CODECOV_TOKEN) de forma segura vía GitHub&lt;/p&gt;

&lt;p&gt;Integré Codecov para reporte visual de cobertura&lt;/p&gt;

&lt;p&gt;Añadí badges de estado de tests y cobertura al README&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Presentación profesional y portafolio
&lt;/h2&gt;

&lt;p&gt;Actualicé README bilingüe con branding técnico&lt;/p&gt;

&lt;p&gt;Publiqué avances en LinkedIn destacando reproducibilidad y trazabilidad&lt;/p&gt;

&lt;p&gt;Portafolio en vivo disponible en nicolasandrescl.pythonanywhere.com&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 ¿Qué sigue?
&lt;/h2&gt;

&lt;p&gt;Mi objetivo es liderar proyectos backend con testing robusto, integración de APIs y pipelines CI/CD que escalen globalmente. SparkTrace es ahora una vitrina técnica de reproducibilidad, cobertura y auditoría—lista para entrevistas, colaboraciones y contribuciones open-source.&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%2Fo4cnqbu2rynaq5bds07k.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%2Fo4cnqbu2rynaq5bds07k.png" alt="test.yml" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pyspark</category>
      <category>drf</category>
      <category>cicd</category>
      <category>pytest</category>
    </item>
    <item>
      <title>A Fresh Launch: My Developer Portfolio Is Production Ready</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Wed, 23 Jul 2025 16:25:33 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/a-fresh-launch-my-developer-portfolio-is-production-ready-2cp3</link>
      <guid>https://dev.to/nicolasandrescl/a-fresh-launch-my-developer-portfolio-is-production-ready-2cp3</guid>
      <description>&lt;p&gt;After a comprehensive refactor across both backend and frontend, my personal portfolio is now fully modular, scalable, and ready to go live.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Backend: Django + DRF
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Migrated from monolithic to domain-based modular architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RESTful endpoints for projects, skills, and contact functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;API documentation with Swagger via drf_spectacular&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Direct email dispatch via custom contact endpoint&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistent routing under /api/, prepared for deployment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fsz9w8rjrhk0prg71tpsx.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%2Fsz9w8rjrhk0prg71tpsx.png" alt="Backend" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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%2F596riqaba9o3r3mf3qcf.png" alt="Backend" width="800" height="449"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🎨 Frontend: React + Vite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Refactored components for visual consistency (ProjectCard, ContactCard, FooterCard)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connected contact form to backend with dynamic user feedback&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added CV download functionality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unified styles and hover states with centralized index.css&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Interactive menu with Material UI icons for GitHub, LinkedIn, and Dev.to&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fbbnhjwxi1wtk9w227wgt.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%2Fbbnhjwxi1wtk9w227wgt.png" alt="Frontend" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📁 All code is available on GitHub via the dev branch, and will soon replace my current portfolio version.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📎 Live preview: &lt;a href="https://nicolasandrescl.pythonanywhere.com" rel="noopener noreferrer"&gt;https://nicolasandrescl.pythonanywhere.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&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%2Faa3hitd0bneoim1gcg1o.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%2Faa3hitd0bneoim1gcg1o.png" alt="Frontend" width="800" height="449"&gt;&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%2F06h8f3p0ljxvtoavc6oy.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%2F06h8f3p0ljxvtoavc6oy.png" alt="Frontend" width="800" height="449"&gt;&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%2Fj3ztbm43d5h0cknt1rvs.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%2Fj3ztbm43d5h0cknt1rvs.png" alt="Frontend" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
This project reflects not just code improvements, but an intentional evolution in architecture, documentation, and developer experience. It’s built to be shared, scaled, and showcased — and will be my new technical identity moving forward.&lt;/p&gt;

&lt;p&gt;🔖 Tags&lt;br&gt;
text&lt;/p&gt;

&lt;h1&gt;
  
  
  SoftwareEngineering #ReactDeveloper #BackendEngineer #DjangoREST #FrontendRefactor #APIDesign #ModularArchitecture #GitWorkflow #PortfolioLaunch #ProductionReady #OpenSource #LinkedInDev
&lt;/h1&gt;

</description>
      <category>softwareengineering</category>
      <category>react</category>
      <category>backend</category>
      <category>django</category>
    </item>
    <item>
      <title>Migrating My Portfolio from Django Templates to React + Vite + TailwindCSS</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Mon, 14 Jul 2025 01:00:37 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/migrating-my-portfolio-from-django-templates-to-react-vite-tailwindcss-3k6l</link>
      <guid>https://dev.to/nicolasandrescl/migrating-my-portfolio-from-django-templates-to-react-vite-tailwindcss-3k6l</guid>
      <description>&lt;p&gt;After years of building robust backend systems with Django, I’ve decided to give my personal portfolio a frontend makeover. The new version is built using React and Vite for a lightning-fast development experience, with TailwindCSS v4 (plus Shadcn/UI) for clean and flexible styling.&lt;/p&gt;

&lt;h2&gt;
  
  
  This transition reflects a shift not only in tech stack but in how I present my work as a Backend Developer — embracing modular architecture and focusing on user experience across devices.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🛠️ Core Stack and Setup
&lt;/h2&gt;

&lt;p&gt;React + Vite: Fast dev server, intuitive routing, and modular component design.&lt;/p&gt;

&lt;p&gt;Tailwind v4: Manually integrated via &lt;a class="mentioned-user" href="https://dev.to/tailwindcss"&gt;@tailwindcss&lt;/a&gt;/postcss to support Shadcn/UI.&lt;/p&gt;

&lt;p&gt;Shadcn/UI: Powerful UI components with headless accessibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Tailwind Setup Summary
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tailwindcss/postcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With config files:&lt;/p&gt;

&lt;p&gt;postcss.config.cjs using &lt;a class="mentioned-user" href="https://dev.to/tailwindcss"&gt;@tailwindcss&lt;/a&gt;/postcss&lt;/p&gt;

&lt;p&gt;Tailwind purging content from src/*&lt;em&gt;/&lt;/em&gt;.{js,ts,jsx,tsx}&lt;/p&gt;

&lt;p&gt;Global styles defined in index.css for consistent theming&lt;/p&gt;

&lt;h2&gt;
  
  
  📁 Component Highlights
&lt;/h2&gt;

&lt;p&gt;ProjectCard.jsx, ContactCard.jsx, SkillCard.jsx, TituloCard.jsx — each crafted with purpose to highlight key areas of my portfolio&lt;/p&gt;

&lt;p&gt;Responsive layout powered by Tailwind utility classes&lt;/p&gt;

&lt;p&gt;ESLint and Vite configuration for clean code and optimized builds&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Going Live Soon!
&lt;/h2&gt;

&lt;p&gt;The project will be deployed soon, but until then feel free to check out the current progress and explore my portfolio [insert your link here].&lt;/p&gt;

&lt;p&gt;Thanks for reading — if you’re working on frontend transitions or integrating Tailwind v4 in your own setup, let’s connect!&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%2Fgj3yvzcbfqmq5pon6kxd.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%2Fgj3yvzcbfqmq5pon6kxd.png" alt="Cambios Portafolio" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 #React #Vite #TailwindCSS #ShadcnUI #FrontendDev #PortfolioUpgrade #WebDevelopment #CleanArchitecture #Django #BackendToFrontend
&lt;/h2&gt;

</description>
      <category>react</category>
      <category>tailwindcss</category>
      <category>vite</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Building a Flask RESTful API: From Jinja2 Views to a Scalable Backend</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Wed, 02 Jul 2025 08:57:32 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/building-a-flask-restful-api-from-jinja2-views-to-a-scalable-backend-4jm9</link>
      <guid>https://dev.to/nicolasandrescl/building-a-flask-restful-api-from-jinja2-views-to-a-scalable-backend-4jm9</guid>
      <description>&lt;p&gt;In this post, I’ll walk you through how I transitioned my Flask project from a classic Jinja2-based web app to a modular, production-ready backend with a RESTful API, full test coverage, and Swagger documentation.&lt;/p&gt;

&lt;p&gt;🧠 Motivation: I wanted to go beyond basic templating and learn how to build backends that scale, integrate with frontend frameworks, and support proper testing and documentation.&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%2Fs6zjm0kbur7nqdw5hu09.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%2Fs6zjm0kbur7nqdw5hu09.png" alt="swagger (Flasgger)" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 Technologies Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Python 3.12&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flask with Blueprint architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQLite + SQLAlchemy ORM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flasgger (Swagger UI integration)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jinja2 for server-rendered views&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pytest for automated testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Postman for manual endpoint verification&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Git for version control&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 What I Built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🔄 A full RESTful API for task management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧩 Clean code structure with an app factory (create_app) and Blueprint registration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧪 Unit tests using Pytest with in-memory SQLite&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📘 Interactive API docs with Swagger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧼 Better endpoint handling using unique endpoint= values to resolve route conflicts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧠 JSON-based error responses and safe exception management&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F4au9kv6v7iux4fbharnd.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%2F4au9kv6v7iux4fbharnd.png" alt="Test Unitarios" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Swagger now correctly renders all documented endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All tests pass reliably across isolated app instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The backend is ready to be consumed by frontend frameworks like React.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All source code and documentation are publicly available via my portfolio.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔗 Check it out: nicolasandrescl.pythonanywhere.com 🧪 The code is already deployed as a static asset and will soon go live as a full API service.
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add JWT authentication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect a React frontend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enable pagination and filtering&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy to production with metrics&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you're learning Flask or building your first API, feel free to check out the repo and reach out—happy to collaborate and grow with the community!
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Python #Flask #RESTAPI #Swagger #Pytest #DeveloperJourney #WebDevelopment #Backend #SQLAlchemy #PortfolioProject
&lt;/h2&gt;

</description>
      <category>python</category>
      <category>flask</category>
      <category>restapi</category>
      <category>swagger</category>
    </item>
    <item>
      <title>🚀 Evolving My FastAPI Project: Modular Architecture, Testing &amp; MySQL Integration</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:55:28 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/evolving-my-fastapi-project-modular-architecture-testing-mysql-integration-g1</link>
      <guid>https://dev.to/nicolasandrescl/evolving-my-fastapi-project-modular-architecture-testing-mysql-integration-g1</guid>
      <description>&lt;p&gt;Over the past few hours, I've been deep into refactoring one of my FastAPI projects with a clear goal: make it production-ready and showcase it live through my portfolio at nicolasandrescl.pythonanywhere.com 💡&lt;/p&gt;




&lt;p&gt;Here’s what I accomplished:&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%2F4r2soffpjifntccim0yn.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%2F4r2soffpjifntccim0yn.png" alt="Fast Api" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ What Changed
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Refactored the entire project structure into clearly separated layers:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;routers/ for endpoints&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;repository/ for data access logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;schemas/ for Pydantic models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;models/ for SQLAlchemy models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;services/ for business logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;core/ for configuration and DB connections&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrated a MySQL database using SQLAlchemy and PyMySQL for full persistence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Switched to Pydantic v2, updating all .dict() references to .model_dump() to stay aligned with the latest standards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added error handling and validation, including custom messages and constraints (e.g. rejecting names under 3 characters).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wrote an integration test for user creation using pytest + TestClient, and installed httpx, email-validator, cryptography, and other missing dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Resolved merge conflicts cleanly and pushed the finalized version to GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updated the README.md with architecture overview, setup instructions, and feature highlights.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔧 What’s Next?
&lt;/h2&gt;

&lt;p&gt;I’m preparing to deploy the API backend publicly so that visitors to my portfolio can see it in action. The /user/ endpoint will be testable directly from Swagger UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live site: 🌐 nicolasandrescl.pythonanywhere.com Repo: 📁 github.com/NicolasAndresCL/FastAPI
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🛠️ Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;FastAPI, SQLAlchemy, PyMySQL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MySQL, Pydantic v2, Uvicorn&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pytest, TestClient, HTTPX&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧵 Let’s Connect
&lt;/h2&gt;

&lt;p&gt;If you're working on API design, backend structure, or transitioning to production, I'd love to exchange ideas!&lt;/p&gt;




&lt;h2&gt;
  
  
  FastAPI #BackendDevelopment #Python #SQLAlchemy #MySQL #TDD #CleanArchitecture #pytest #DevJourney #Pydantic #PythonBackend #PortfolioDev #APIDesign #OpenSource #PythonAnywhere
&lt;/h2&gt;

</description>
      <category>fastapi</category>
      <category>backenddevelopment</category>
      <category>python</category>
      <category>sqlalchemy</category>
    </item>
    <item>
      <title>🚀 My Developer Portfolio Is Live and Now Fully Responsive!</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Sat, 28 Jun 2025 01:05:15 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/my-developer-portfolio-is-live-and-now-fully-responsive-mb9</link>
      <guid>https://dev.to/nicolasandrescl/my-developer-portfolio-is-live-and-now-fully-responsive-mb9</guid>
      <description>&lt;p&gt;Bringing your work into production is thrilling—until something breaks and you don’t know why. That’s exactly what I faced while deploying my Django-based portfolio.&lt;/p&gt;

&lt;p&gt;Despite making all the right changes in my HTML and CSS, nothing was updating on the live site. Turns out, the answer was hidden in a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash
python manage.py collectstatic --noinput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  🎯 What I Built
&lt;/h1&gt;

&lt;p&gt;A full portfolio site running on PythonAnywhere, styled with custom CSS (nude color palette for minimalist elegance)&lt;/p&gt;

&lt;p&gt;Built with Django and Django REST Framework, showing off real API endpoints and dynamic content&lt;/p&gt;

&lt;p&gt;Responsive design using Flexbox, Grid, and media queries&lt;/p&gt;

&lt;p&gt;Deployment-ready, including secure admin access and custom favicon&lt;/p&gt;

&lt;h1&gt;
  
  
  📸 Key Win: Debugging in Production
&lt;/h1&gt;

&lt;p&gt;The image in my header was overlapping the page title on mobile. After reviewing my layout and adding all the right media queries… the issue persisted 😩 But the problem wasn’t layout—it was the old static files being served by Django. Once I re-ran collectstatic inside my virtual environment, everything fell into place.&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%2Fqp1z729k00pqem3mlaky.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%2Fqp1z729k00pqem3mlaky.jpeg" alt="Imagen de Error" width="720" height="1600"&gt;&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%2Fwx2yrnvjc9afnopq9gks.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%2Fwx2yrnvjc9afnopq9gks.jpeg" alt="Imagen Mejora" width="720" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🎨 See It for Yourself
&lt;/h1&gt;

&lt;p&gt;🌐 nicolasandrescl.pythonanywhere.com Feel free to check it out and explore my featured projects. Feedback is always welcome!&lt;/p&gt;




&lt;h1&gt;
  
  
  Django #Python #BackendDeveloper #WebDevelopment #ResponsiveDesign #PortfolioSite #ProductionDebugging #PythonAnywhere #DevJourney #OpenToWork
&lt;/h1&gt;

</description>
      <category>productiondebugging</category>
      <category>responsivedesign</category>
      <category>drf</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Successfully Deployed: My Django Portfolio is Now Live on PythonAnywhere</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Fri, 27 Jun 2025 19:08:01 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/successfully-deployed-my-django-portfolio-is-now-live-on-pythonanywhere-830</link>
      <guid>https://dev.to/nicolasandrescl/successfully-deployed-my-django-portfolio-is-now-live-on-pythonanywhere-830</guid>
      <description>&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%2Fl0tddxgljqniz878vk9n.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%2Fl0tddxgljqniz878vk9n.png" alt="Portafolio" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
After weeks of focused development, troubleshooting, and iteration, I’m proud to share that my Django-based portfolio project — MiPortafolioDjango — is now fully deployed and live in production!&lt;/p&gt;

&lt;p&gt;🔗 Check it out here: nicolasandrescl.pythonanywhere.com&lt;/p&gt;

&lt;p&gt;This deployment involved much more than pushing code — it was a comprehensive hands-on learning experience covering configuration management, static and media file handling, security, and debugging in a real-world production environment.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚙️ Key Improvements and Configurations
&lt;/h1&gt;

&lt;p&gt;I. Django Configuration (settings.py &amp;amp; wsgi.py)&lt;br&gt;
🔐 Secure Key Management with python-decouple&lt;/p&gt;

&lt;p&gt;Sensitive data like SECRET_KEY and EMAIL_HOST_PASSWORD were externalized using the python-decouple package.&lt;/p&gt;

&lt;p&gt;A .env file was created at the root of the project to store these secrets securely.&lt;/p&gt;

&lt;p&gt;The wsgi.py file was modified to explicitly load environment variables using pathlib.Path and config() from decouple.&lt;/p&gt;

&lt;h2&gt;
  
  
  📁 Static Files Configuration
&lt;/h2&gt;

&lt;p&gt;Set STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') in settings.py.&lt;/p&gt;

&lt;p&gt;Ran python manage.py collectstatic to collect and serve static files on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼 Media Files Configuration
&lt;/h2&gt;

&lt;p&gt;Configured MEDIA_URL and MEDIA_ROOT to handle uploaded files using Django’s ImageField.&lt;/p&gt;

&lt;p&gt;This enabled uploaded images to be visible through the admin and rendered on the frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 Production Settings
&lt;/h2&gt;

&lt;p&gt;ALLOWED_HOSTS was updated to include nicolasandrescl.pythonanywhere.com.&lt;/p&gt;

&lt;p&gt;Set DEBUG = False for security in production.&lt;/p&gt;

&lt;p&gt;Confirmed that portfolio_project/wsgi.py contains necessary .env loading logic to work independently of PythonAnywhere’s default.&lt;/p&gt;

&lt;h1&gt;
  
  
  II. Server Setup on PythonAnywhere
&lt;/h1&gt;

&lt;p&gt;✅ Repository Sync: Cleaned and re-pushed the latest repo to GitHub, then pulled it into PythonAnywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐍 Virtual Environment: Activated the virtualenv properly using workon MiPortafolioDjango_env.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🛠 Migrations &amp;amp; Superuser: Ran migrate and created a superuser for admin access.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🗂 Static &amp;amp; Media Files Web Config: Added /static/ and /media/ mappings in the Web &amp;gt; Static Files section.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🔁 App Reloads: Performed necessary web app reloads after every major change.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  🧠 Advanced Debugging: Inspected error.log and server.log for resolving tricky deployment issues.
&lt;/h2&gt;

&lt;p&gt;🐛 Critical Fixes Before Production Launch&lt;br&gt;
🔄 GitHub URL Redirection Bug&lt;/p&gt;

&lt;p&gt;Fixed a bug where all project cards linked to the same (wrong) GitHub repo.&lt;/p&gt;

&lt;p&gt;Root cause: hardcoded URLs in the HTML template.&lt;/p&gt;

&lt;p&gt;Solution: replaced with {{ project.github_link }} to dynamically fetch the correct link.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖼 Project Image Display Issues
&lt;/h2&gt;

&lt;p&gt;Solved the problem where project images didn’t render on the frontend.&lt;/p&gt;

&lt;p&gt;Verified correct use of ImageField and ensured MEDIA_URL and MEDIA_ROOT were properly configured.&lt;/p&gt;

&lt;p&gt;Now images uploaded via Django Admin appear seamlessly on the site.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧩 Conclusion
&lt;/h1&gt;

&lt;p&gt;This deployment marks a significant step forward in my journey as a backend developer. The process not only strengthened my understanding of Django and server-side deployment, but also gave me real DevOps exposure by working directly with environment variables, file systems, and web server configurations.&lt;/p&gt;

&lt;p&gt;🔍 Every issue resolved and each configuration tweaked is now a new skill in my toolkit.&lt;br&gt;
Check it out, and feel free to leave feedback!&lt;/p&gt;




&lt;h1&gt;
  
  
  Django #Python #Deployment #PythonAnywhere #BackendDevelopment #DevOps #PortfolioProject #WebDevelopment #DjangoTips #FullStackJourney #OpenToWork
&lt;/h1&gt;

</description>
      <category>django</category>
      <category>devops</category>
      <category>pythonanywhere</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Taking My Django Portfolio to Production – Key Milestones Achieved 🚀</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Thu, 26 Jun 2025 03:45:58 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/taking-my-django-portfolio-to-production-key-milestones-achieved-166f</link>
      <guid>https://dev.to/nicolasandrescl/taking-my-django-portfolio-to-production-key-milestones-achieved-166f</guid>
      <description>&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%2Frjrke2qfmacfk79c8ddq.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%2Frjrke2qfmacfk79c8ddq.png" alt="Image description" width="800" height="799"&gt;&lt;/a&gt;After weeks of development and iterations, I’m excited to share the latest progress on my personal portfolio, built with Django and Django REST Framework. Here's a breakdown of the key improvements I've implemented before deploying the project to production.&lt;/p&gt;




&lt;p&gt;🔐 1. Fully Functional Contact Form with Secure Email Integration&lt;br&gt;
One of the core features I prioritized was enabling visitors to contact me directly from the website. I implemented a working contact form that sends emails securely using a Google App Password, protecting my credentials while ensuring deliverability.&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%2F4q3w4nzlo0lviwm3w779.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%2F4q3w4nzlo0lviwm3w779.png" alt="Form" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🎨 2. Enhanced UI/UX – Visual and Structural Polish&lt;br&gt;
To make the user experience smoother and more visually coherent, I refined the CSS styling, improved background color contrast, and reorganized image placements. These changes make the navigation feel more intuitive and professional.&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%2Farurqde14hd7weasz53z.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%2Farurqde14hd7weasz53z.png" alt="estilo" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;📘 3. Embedded API Documentation (Swagger &amp;amp; ReDoc)&lt;br&gt;
Since the backend is powered by Django REST Framework, I integrated auto-generated API documentation using Swagger UI and ReDoc, accessible directly from the site’s main interface. This allows other developers to explore all endpoints with ease.&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%2Fxbwe4msnbcgmtjed63mm.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%2Fxbwe4msnbcgmtjed63mm.png" alt="swagger" width="800" height="449"&gt;&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%2Ftd6oa3lh3nmdwhne0ynj.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%2Ftd6oa3lh3nmdwhne0ynj.png" alt="swagger" width="800" height="449"&gt;&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%2Fdwtngb8289axyzebxa82.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%2Fdwtngb8289axyzebxa82.png" alt="redoc" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;⚙️ 4. Production-Ready Configuration&lt;br&gt;
I’ve fine-tuned the project settings for deployment:&lt;/p&gt;

&lt;p&gt;DEBUG=False to secure the environment&lt;/p&gt;

&lt;p&gt;Proper configuration of STATICFILES and MEDIA handling&lt;/p&gt;

&lt;p&gt;Optimized the settings.py file to separate development and production environments&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%2F45iwzbqonmjh0852o1u6.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%2F45iwzbqonmjh0852o1u6.png" alt="Debuf=False" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🚀 5. Preparing for Deployment on PythonAnywhere&lt;br&gt;
The final step is to host both frontend and backend on PythonAnywhere, which will allow seamless access and easier management under one domain. This transition is already in progress.&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%2Fq7aj239f5xryrolydzhe.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%2Fq7aj239f5xryrolydzhe.png" alt="project" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🔍 What’s Next?&lt;br&gt;
Soon, I’ll announce the complete deployment and share the final hosted version. Until then, you can preview the current progress and code here:&lt;br&gt;
👉 &lt;a href="https://nicolasandrescl.github.io" rel="noopener noreferrer"&gt;https://nicolasandrescl.github.io&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%2Fe10dep8ljazfhjp6khy7.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%2Fe10dep8ljazfhjp6khy7.png" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Thanks for following along in my journey! If you have feedback, ideas, or just want to connect — I’m always open to learning from the community.&lt;/p&gt;




&lt;p&gt;Tags:&lt;/p&gt;

&lt;h1&gt;
  
  
  Django #Python #Portfolio #WebDevelopment #APIDocumentation #SoftwareEngineering #PythonAnywhere #FullStack
&lt;/h1&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>swgger</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>🚀 Strengthening My Django Portfolio: Security, Contact Integration, and Optimization</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Wed, 25 Jun 2025 07:48:39 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/strengthening-my-django-portfolio-security-contact-integration-and-optimization-3f46</link>
      <guid>https://dev.to/nicolasandrescl/strengthening-my-django-portfolio-security-contact-integration-and-optimization-3f46</guid>
      <description>&lt;p&gt;🔐 1. API Security with Token Authentication&lt;br&gt;
One of the key updates was reinforcing the security of my Django REST API.&lt;/p&gt;

&lt;p&gt;I've implemented TokenAuthentication along with IsAuthenticatedOrReadOnly permissions. This means:&lt;/p&gt;

&lt;p&gt;Visitors can freely read and explore public endpoints.&lt;/p&gt;

&lt;p&gt;Only authenticated users (in this case, myself) with a valid token can perform write operations (POST, PUT, DELETE).&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;br&gt;
This approach ensures that my API remains accessible and transparent while protecting against unauthorized modifications. It's a great foundation for future scaling or integration with frontend 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%2Flhphbd5bsn9wz20dn6o4.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%2Flhphbd5bsn9wz20dn6o4.png" alt="ADMIN" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&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%2Flqw86o487gjkdu4em3lr.png" alt="SWAGGER UI" width="800" height="449"&gt;
&lt;/h2&gt;

&lt;p&gt;📬 2. Functional Contact Form&lt;br&gt;
I added a functional and stylish contact form to the main page of my portfolio.&lt;/p&gt;

&lt;p&gt;It uses Django’s form handling and CSRF protection, and sends messages securely via email or saves them to a database for future reference.&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;br&gt;
A direct and professional communication channel is essential for networking, job opportunities, and collaborations. This adds a serious layer of usability to my site.&lt;/p&gt;

&lt;h2&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%2Fcxstt0rbwf4snxc51ecl.png" alt="FORM" width="800" height="449"&gt;
&lt;/h2&gt;

&lt;p&gt;🧱 3. Optimized Static File Management&lt;br&gt;
Previously, my static files (like CSS and images) were scattered and unorganized.&lt;/p&gt;

&lt;p&gt;I restructured them using Django’s STATICFILES_DIRS and collectstatic system, keeping all assets organized inside the app directories and ensuring they’re properly served in production.&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;br&gt;
A clean static structure avoids conflicts, speeds up deployment, and improves maintainability of the project as it grows.&lt;/p&gt;

&lt;h2&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%2Fgr95qxs8ol3mhmgj2dtv.png" alt="FRONTEND" width="800" height="449"&gt;
&lt;/h2&gt;

&lt;p&gt;📝 4. Clean Git Commit History&lt;br&gt;
Every change has been tracked using clear and descriptive Git commits, following best practices like:&lt;/p&gt;

&lt;p&gt;Atomic commits&lt;/p&gt;

&lt;p&gt;Useful commit messages (add, fix, refactor, etc.)&lt;/p&gt;

&lt;p&gt;Grouped by functionality&lt;/p&gt;

&lt;p&gt;You can review the repository here 👉 GitHub Repo&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;br&gt;
A well-documented Git history reflects professionalism and helps collaborators (or future-me!) understand the project’s evolution.&lt;/p&gt;

&lt;h2&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%2Fsf48nkgqjwfge6hjerre.png" alt="COMMIT" width="800" height="449"&gt;
&lt;/h2&gt;

&lt;p&gt;✅ What’s Next?&lt;br&gt;
Production deployment on a custom domain.&lt;/p&gt;

&lt;p&gt;More automation using CI/CD.&lt;/p&gt;

&lt;p&gt;Deployment of a full-featured blog using Django CMS or a headless approach with DRF + React.&lt;/p&gt;

&lt;p&gt;Live site 👉 nicolasandrescl.github.io&lt;/p&gt;

&lt;p&gt;Thanks for reading, and feel free to connect or leave suggestions! 🙌&lt;br&gt;
Let’s keep learning and building 💪&lt;/p&gt;




&lt;h1&gt;
  
  
  django #python #webdev #portfolio #api #backend #devjournal #fullstack #restapi #programming
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>portfolio</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>🚀 Migrating from SQLite3 to MySQL in My Django REST API – Step by Step</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Mon, 23 Jun 2025 08:14:13 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/migrating-from-sqlite3-to-mysql-in-my-django-rest-api-step-by-step-34pl</link>
      <guid>https://dev.to/nicolasandrescl/migrating-from-sqlite3-to-mysql-in-my-django-rest-api-step-by-step-34pl</guid>
      <description>&lt;p&gt;🛠️ Step-by-step Migration Process&lt;br&gt;
✅ 1. Install MySQL Driver&lt;br&gt;
Inside my virtual environment:&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 mysqlclient
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Alternatively, you can use pymysql if you face issues with mysqlclient.)&lt;/p&gt;




&lt;p&gt;✅ 2. Create a New MySQL Database&lt;br&gt;
Using MySQL Workbench or CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE myproject_db CHARACTER SET UTF8MB4;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;✅ 3. Update settings.py&lt;br&gt;
I replaced the default SQLite configuration with MySQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject_db',
        'USER': 'root',
        'PASSWORD': 'your_password',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

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

&lt;/div&gt;






&lt;p&gt;✅ 4. Apply Migrations&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate

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

&lt;/div&gt;






&lt;p&gt;✅ 5. Create a New Superuser&lt;br&gt;
Since the database is clean, I recreated the admin user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py createsuperuser

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

&lt;/div&gt;






&lt;p&gt;✅ 6. Test Functionality&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All API endpoints were tested via Postman.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Admin panel access was verified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Existing unit tests were re-run to confirm stability.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fnvv7xctwjc5mfszavhe0.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%2Fnvv7xctwjc5mfszavhe0.png" alt="MySQL" width="800" height="449"&gt;&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%2Fawsnhjt8ftthfhfq25ll.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%2Fawsnhjt8ftthfhfq25ll.png" alt="Admin Customers" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;✅ 7. Optional: Migrate data from SQLite to MySQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python manage.py dumpdata &amp;gt; data.json
# after switching DB
python manage.py loaddata data.json

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

&lt;/div&gt;






&lt;p&gt;🔗 My Work Online&lt;br&gt;
🔹 Portfolio: &lt;a href="https://nicolasandrescl.github.io/" rel="noopener noreferrer"&gt;https://nicolasandrescl.github.io/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 GitHub Repo: &lt;a href="https://github.com/NicolasAndresCL/API_con_DRF" rel="noopener noreferrer"&gt;https://github.com/NicolasAndresCL/API_con_DRF&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;💬 Final Thoughts&lt;br&gt;
This migration helped me take my backend to the next level. Whether it's for performance, structure, or readiness for deployment, using MySQL brings me closer to a professional production setup.&lt;/p&gt;

&lt;p&gt;Would love to hear your thoughts – which DB do you prefer for your Django projects?&lt;/p&gt;

</description>
      <category>djangorestframework</category>
      <category>mysql</category>
      <category>api</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Mastering Full-Stack Authentication with Django REST Framework and React ⚙️🔐</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Sat, 21 Jun 2025 01:24:35 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/mastering-full-stack-authentication-with-django-rest-framework-and-react-4k30</link>
      <guid>https://dev.to/nicolasandrescl/mastering-full-stack-authentication-with-django-rest-framework-and-react-4k30</guid>
      <description>&lt;p&gt;&lt;em&gt;From a blank screen to a fully functional login flow — this has been one of the most rewarding challenges in my personal project.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🚀 Introduction&lt;br&gt;
Not long ago, I tackled one of the most classic challenges in modern full-stack development: implementing user authentication.&lt;br&gt;
With Django REST Framework (DRF) powering the backend and React + Vite on the frontend, the journey was packed with misconfigured routes, unexpected 405 errors, and the occasional blank screen.&lt;/p&gt;

&lt;p&gt;In this post, I’ll share my experience, the bugs I faced, what I learned, and how I eventually solved everything.&lt;/p&gt;

&lt;p&gt;🔍 The Problem: Unexpected Errors and Misleading Routes&lt;br&gt;
After setting up the login form and connecting React to the API, I ran into this all-too-familiar message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;405 Method Not Allowed  
Unexpected non-whitespace character after JSON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eventually, I discovered I was sending credentials to the wrong endpoint (/api/schema/swagger-ui/) instead of the actual auth route (/api/token/).&lt;br&gt;
A small mistake… but it caused a lot of frustration.&lt;/p&gt;

&lt;p&gt;✍️ Lesson Learned&lt;br&gt;
Double-check your routes, HTTP methods, and urls.py configurations. And never underestimate console errors — they’re often trying to help you.&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%2Fjsk65wq7l1ejtu8xk8ev.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%2Fjsk65wq7l1ejtu8xk8ev.png" alt="Login" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧩 The Fix: Connecting the Dots, Managing State, and Redirecting&lt;br&gt;
Once I got the token successfully, I stored it in localStorage and used React Router’s useNavigate() to redirect the user to the customer dashboard.&lt;/p&gt;

&lt;p&gt;Along the way, I cleaned up and modularized the frontend:&lt;/p&gt;

&lt;p&gt;Split key views (Login, Dashboard) into src/pages/&lt;/p&gt;

&lt;p&gt;Used CSS Modules for component-scoped styling&lt;/p&gt;

&lt;p&gt;Added loading indicators and error handling to the login form&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%2F39h1e0aidjb1ohpbc62v.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%2F39h1e0aidjb1ohpbc62v.png" alt="Deshboard" width="800" height="449"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (response.ok) {
  localStorage.setItem('authToken', data.token);
  navigate('/customers');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result: a smoother user experience and more maintainable code.&lt;/p&gt;

&lt;p&gt;🛠️ Extras: React + CSS Modules&lt;br&gt;
Beyond authentication, I also worked on the dashboard layout and organized my styles into .module.css files per page. This approach:&lt;/p&gt;

&lt;p&gt;Makes teamwork easier&lt;/p&gt;

&lt;p&gt;Prevents global style conflicts&lt;/p&gt;

&lt;p&gt;Sets the stage for future scalability&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%2F1p4gv892ep0o58vgulhk.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%2F1p4gv892ep0o58vgulhk.png" alt="Deshboard" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎯 Next Steps&lt;br&gt;
Implement protected routes for authenticated users&lt;/p&gt;

&lt;p&gt;Centralize authentication state management&lt;/p&gt;

&lt;p&gt;Continue building CRUD functionality for Customers, Orders, and Products&lt;/p&gt;

&lt;p&gt;🎉 Conclusion&lt;br&gt;
Every bug taught me something new. This experience not only improved my logic and debugging skills, but also refined my approach to clean code and user-centered design.&lt;/p&gt;

&lt;p&gt;👉 You can follow the full project here: nicolasandrescl.github.io&lt;/p&gt;

&lt;p&gt;Have you faced similar authentication struggles in your full-stack projects? I’d love to hear your thoughts in the comments!&lt;/p&gt;

</description>
      <category>fullstack</category>
      <category>react</category>
      <category>djangorestframework</category>
      <category>authentication</category>
    </item>
    <item>
      <title>"From 'NOT NULL constraint failed' to Success: Debugging My Django DRF Order Creation API"</title>
      <dc:creator>Nicolás Andrés Cano Leal</dc:creator>
      <pubDate>Thu, 19 Jun 2025 23:58:02 +0000</pubDate>
      <link>https://dev.to/nicolasandrescl/from-not-null-constraint-failed-to-success-debugging-my-django-drf-order-creation-api-3gn2</link>
      <guid>https://dev.to/nicolasandrescl/from-not-null-constraint-failed-to-success-debugging-my-django-drf-order-creation-api-3gn2</guid>
      <description>&lt;h2&gt;
  
  
  My Journey to a Robust E-commerce Order API
&lt;/h2&gt;

&lt;p&gt;Hey Dev.to community! 👋&lt;/p&gt;

&lt;p&gt;Today marks a significant milestone in my ongoing journey to build a robust e-commerce API using &lt;strong&gt;Django REST Framework (DRF)&lt;/strong&gt;. As a passionate #Python and #Django developer, I've been diving deep into backend development, and today's session was all about strengthening the foundation of my &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;products&lt;/code&gt;, and &lt;code&gt;customers&lt;/code&gt; applications.&lt;/p&gt;

&lt;p&gt;The core focus? &lt;strong&gt;Extensive Unit Testing&lt;/strong&gt; and refining API serialization to handle complex data relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: A Mysterious &lt;code&gt;IntegrityError&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;While testing my order creation endpoint via Swagger, I ran into a seemingly cryptic error in the console:&lt;/p&gt;

&lt;p&gt;sqlite3.IntegrityError: NOT NULL constraint failed: orders_order.total_amount&lt;/p&gt;

&lt;p&gt;This traceback clearly pointed to my &lt;code&gt;Order&lt;/code&gt; model's &lt;code&gt;total_amount&lt;/code&gt; field. The database was refusing to save an &lt;code&gt;Order&lt;/code&gt; because &lt;code&gt;total_amount&lt;/code&gt; was &lt;code&gt;NULL&lt;/code&gt;, but my model definition (implicitly) required a non-null value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Internal Server Error: /api/orders/

Traceback (most recent call last):

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute

    return self.cursor.execute(sql, params)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\sqlite3\base.py", line 329, in execute

    return super().execute(query, params)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

sqlite3.IntegrityError: NOT NULL constraint failed: orders_order.total_amount



The above exception was the direct cause of the following exception:



Traceback (most recent call last):

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner

    response = get_response(request)

               ^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response

    response = wrapped_callback(request, *callback_args, **callback_kwargs)

               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\views\decorators\csrf.py", line 65, in _view_wrapper

    return view_func(request, *args, **kwargs)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\viewsets.py", line 124, in view

    return self.dispatch(request, *args, **kwargs)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\views.py", line 509, in dispatch

    response = self.handle_exception(exc)

               ^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\views.py", line 469, in handle_exception

    self.raise_uncaught_exception(exc)

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception

    raise exc

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\views.py", line 506, in dispatch

    response = handler(request, *args, **kwargs)

               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\mixins.py", line 19, in create

    self.perform_create(serializer)

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\mixins.py", line 24, in perform_create

    serializer.save()

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\rest_framework\serializers.py", line 208, in save

    self.instance = self.create(validated_data)

                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\orders\serializers.py", line 26, in create

    order = Order.objects.create(**validated_data)

            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\manager.py", line 87, in manager_method

    return getattr(self.get_queryset(), name)(*args, **kwargs)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\query.py", line 679, in create

    obj.save(force_insert=True, using=self.db)

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\base.py", line 822, in save

    self.save_base(

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\base.py", line 909, in save_base

    updated = self._save_table(

              ^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\base.py", line 1071, in _save_table

    results = self._do_insert(

              ^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\base.py", line 1112, in _do_insert

    return manager._insert(

           ^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\manager.py", line 87, in manager_method

    return getattr(self.get_queryset(), name)(*args, **kwargs)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\query.py", line 1847, in _insert

    return query.get_compiler(using=using).execute_sql(returning_fields)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\models\sql\compiler.py", line 1823, in execute_sql

    cursor.execute(sql, params)

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 122, in execute

    return super().execute(sql, params)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 79, in execute

    return self._execute_with_wrappers(

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 92, in _execute_with_wrappers

    return executor(sql, params, many, context)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 100, in _execute

    with self.db.wrap_database_errors:

         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\utils.py", line 91, in __exit__

    raise dj_exc_value.with_traceback(traceback) from exc_value

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute

    return self.cursor.execute(sql, params)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\Nicol\Aprendizaje\Udemy\Python\DjangoRestFramework\env\Lib\site-packages\django\db\backends\sqlite3\base.py", line 329, in execute

    return super().execute(query, params)

           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

django.db.utils.IntegrityError: NOT NULL constraint failed: orders_order.total_amount

[19/Jun/2025 02:06:41] "POST /api/orders/ HTTP/1.1" 500 32475

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Diagnosis: Where Model Tests Meet API Logic
&lt;/h3&gt;

&lt;p&gt;Interestingly, my dedicated unit tests for the &lt;code&gt;Product&lt;/code&gt; and &lt;code&gt;Customer&lt;/code&gt; models were passing perfectly. This confirmed that my models were correctly defined and behaved as expected in isolation.&lt;/p&gt;

&lt;p&gt;For example, for the &lt;code&gt;Product&lt;/code&gt; model, my tests covered creation, default values, &lt;code&gt;__str__&lt;/code&gt; representation, updates (including &lt;code&gt;auto_now&lt;/code&gt; fields like &lt;code&gt;updated_at&lt;/code&gt; which required a small &lt;code&gt;time.sleep&lt;/code&gt; for accurate testing!), and deletion.&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%2F12n8fgo8nkdbnxlprf8h.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%2F12n8fgo8nkdbnxlprf8h.png" alt="Test Customers" width="800" height="449"&gt;&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%2F1ipnigmz8fb0yxkddzp8.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%2F1ipnigmz8fb0yxkddzp8.png" alt="Se Agrego Signals.py" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This led me to understand that the issue wasn't within the model itself, but rather in how the &lt;strong&gt;DRF serializer&lt;/strong&gt; was processing the incoming API request data before saving it to the database. The &lt;code&gt;total_amount&lt;/code&gt; is a calculated field (derived from order items), and my API wasn't providing an initial value.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Smart Serialization and Initializing Values
&lt;/h3&gt;

&lt;p&gt;To resolve the &lt;code&gt;NOT NULL&lt;/code&gt; constraint violation and streamline the API's behavior, I implemented key changes in my &lt;code&gt;orders/serializers.py&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Making Calculated Fields Read-Only
&lt;/h4&gt;

&lt;p&gt;Fields like &lt;code&gt;order_date&lt;/code&gt;, &lt;code&gt;total_amount&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt; (for initial creation), and &lt;code&gt;price_at_order&lt;/code&gt; are typically generated or calculated by the backend, not provided by the client. Marking them as &lt;code&gt;read_only_fields&lt;/code&gt; in the serializer's &lt;code&gt;Meta&lt;/code&gt; class tells DRF to ignore them during input (deserialization) but include them in the output (serialization).&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;# orders/serializers.py (snippet)
&lt;/span&gt;
&lt;span class="c1"&gt;# ... (other imports) ...
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderItemSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&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;OrderItem&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;id&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;product&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;product_id&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;quantity&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;price_at_order&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;read_only_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;price_at_order&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Client shouldn't provide this, it's calculated.
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serializers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelSerializer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&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;Order&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;id&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;customer&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;order_date&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;total_amount&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;status&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;items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# These fields are either auto-generated or have a default,
&lt;/span&gt;        &lt;span class="c1"&gt;# so they should not be provided by the client on creation.
&lt;/span&gt;        &lt;span class="n"&gt;read_only_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;order_date&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;total_amount&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;status&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;h3&gt;
  
  
  2. Ensuring Initial total_amount During Order Creation
&lt;/h3&gt;

&lt;p&gt;Even after making total_amount read-only, the database still required a non-null value during the Order object's instantiation. I explicitly passed a default of 0.00 when creating the Order in the serializer's create method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# orders/serializers.py (inside OrderSerializer's create method)

import decimal # Make sure this is at the top of your file!

class OrderSerializer(...):
    # ...
    def create(self, validated_data):
        items_data = validated_data.pop('items') # Crucial: Extract nested items data

        # Initialize total_amount to 0.00 to satisfy the NOT NULL constraint.
        # This is particularly important if the model itself doesn't have a default.
        order = Order.objects.create(total_amount=decimal.Decimal('0.00'), **validated_data) 

        for item_data in items_data:
            product_instance = item_data.pop('product_id') 
            OrderItem.objects.create(
                order=order, 
                product=product_instance, 
                **item_data
            )

        # Note: I removed an explicit call to order.calculate_total_amount() here.
        # My Django signals (post_save/post_delete on OrderItem) are already configured
        # to automatically update the Order's total when its items are saved or deleted.
        # This keeps the serializer lean and relies on the model's self-maintaining logic.

        return order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Handling Nested Relationships for Read/Write
&lt;/h3&gt;

&lt;p&gt;For OrderItems, I used a powerful DRF pattern:&lt;/p&gt;

&lt;p&gt;For Reading (GET requests): I use product = ProductSerializer(read_only=True) to show detailed product information nested within the OrderItem.&lt;br&gt;
For Writing (POST/PUT requests): I use product_id = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(), write_only=True) to expect just the product's ID from the client, simplifying the input payload.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# orders/serializers.py (inside OrderItemSerializer)
# Assuming ProductSerializer is correctly imported from products.serializers
from products.serializers import ProductSerializer 

class OrderItemSerializer(serializers.ModelSerializer):
    product = ProductSerializer(read_only=True) # Full product details on read
    product_id = serializers.PrimaryKeyRelatedField( # Product ID on write
        queryset=Product.objects.all(), 
        write_only=True
    )
    # ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Sweet Taste of Success!
&lt;/h3&gt;

&lt;p&gt;After implementing these changes and restarting my server, the API calls from Swagger were finally successful!&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%2Fn06l2bj2cz9wrqh13fc9.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%2Fn06l2bj2cz9wrqh13fc9.png" alt="Swagger" width="800" height="449"&gt;&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%2F9yx7pwa09vza3khny91t.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%2F9yx7pwa09vza3khny91t.png" alt="Swagger" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  My console now shows:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[19/Jun/2025 02:57:30] "POST /api/orders/ HTTP/1.1" 201 378
[19/Jun/2025 02:57:59] "GET /api/orders/ HTTP/1.1" 200 742
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  This journey reinforced the immense value of:
&lt;/h3&gt;

&lt;p&gt;Thorough Unit Testing: Pinpointing where the issue truly lies (model vs. serializer).&lt;br&gt;
Understanding DRF's Mechanics: Especially read_only_fields and custom create/update methods for nested writes.&lt;br&gt;
Data Integrity: Ensuring fields meet database constraints.&lt;br&gt;
Django Signals: Leveraging them for automated calculations and maintaining data consistency.&lt;br&gt;
I'm incredibly grateful for the guidance received throughout this process. Every debugged error is a massive learning opportunity!&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeking Opportunities!
&lt;/h3&gt;

&lt;p&gt;I'm actively looking for junior to mid-level #Python / #Django / #BackendDeveloper roles. If you're building exciting projects and need someone passionate about clean, tested, and robust code, I'd love to connect!&lt;/p&gt;

&lt;h3&gt;
  
  
  Feel free to reach out and check out my work:
&lt;/h3&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/NicolasAndresCL/API_con_DRF" rel="noopener noreferrer"&gt;https://github.com/NicolasAndresCL/API_con_DRF&lt;/a&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/nicolas-andres-cano-leal" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/nicolas-andres-cano-leal/&lt;/a&gt;&lt;br&gt;
Thanks for reading! What are your go-to strategies for handling calculated fields in DRF, or debugging IntegrityErrors? Share your thoughts in the comments!&lt;/p&gt;

</description>
      <category>python</category>
      <category>testing</category>
      <category>api</category>
      <category>djangorestframework</category>
    </item>
  </channel>
</rss>
