<?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: Arjun Adhikari</title>
    <description>The latest articles on DEV Community by Arjun Adhikari (@thearjun).</description>
    <link>https://dev.to/thearjun</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%2F213635%2F30ff8d09-0196-45ba-ad40-4ebd34eaafea.JPG</url>
      <title>DEV Community: Arjun Adhikari</title>
      <link>https://dev.to/thearjun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thearjun"/>
    <language>en</language>
    <item>
      <title>Lost in a Forest of Tabs? Here’s Your Friendly Guide Out!</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Thu, 29 May 2025 14:41:41 +0000</pubDate>
      <link>https://dev.to/thearjun/lost-in-a-forest-of-tabs-heres-your-friendly-guide-out-4f71</link>
      <guid>https://dev.to/thearjun/lost-in-a-forest-of-tabs-heres-your-friendly-guide-out-4f71</guid>
      <description>&lt;p&gt;Picture this: you’re on your computer, looking up something really interesting. Maybe you're learning about dinosaurs, planning a trip, or trying to fix something around the house. You open one internet page, then another, then another. Soon, the top of your screen is packed with so many little tabs, it looks like a crowded bus!&lt;/p&gt;

&lt;p&gt;You find a great picture on one tab, an important fact on another, and a cool video on a third. Then, the phone rings, or someone calls your name. You step away for a bit.&lt;/p&gt;

&lt;p&gt;When you come back, you stare at the screen. Oh no! Which tab had that amazing dinosaur picture? Where was that important fact? It’s all a muddle. You click one tab, then another, feeling a bit grumpy and lost. It’s like trying to find your favorite toy in a messy room.&lt;/p&gt;

&lt;p&gt;If this sounds like you, don’t worry! So many of us feel this way. But what if there was a magic button to tidy up all those tabs for you?&lt;/p&gt;

&lt;h3&gt;
  
  
  Meet Your New Helper: The Tab Sorter!
&lt;/h3&gt;

&lt;p&gt;There's a super simple tool for your Chrome internet browser called &lt;strong&gt;Tab Sorter&lt;/strong&gt;. Think of it as a helpful little robot that lives in your computer. Its main job is to neatly line up all your open tabs, like books on a shelf.&lt;/p&gt;

&lt;p&gt;And the best part? It does this with just &lt;strong&gt;one click&lt;/strong&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Little Helper is a Big Deal
&lt;/h3&gt;

&lt;p&gt;When you have too many tabs open, it’s not just messy; it can make your brain feel tired. It’s hard to focus when you’re always hunting for the right page. Tab Sorter helps to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;See Clearly:&lt;/strong&gt; Suddenly, all your tabs are lined up by their website names (like all the "&lt;a href="https://www.google.com/search?q=google.com" rel="noopener noreferrer"&gt;https://www.google.com/search?q=google.com&lt;/a&gt;" pages together, all the "youtube.com" pages together). It’s like sorting your crayons by color!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find Things Fast:&lt;/strong&gt; Need to get back to that recipe on "&lt;a href="https://www.google.com/search?q=supercookingsite.com" rel="noopener noreferrer"&gt;https://www.google.com/search?q=supercookingsite.com&lt;/a&gt;"? Now you can spot it much quicker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stay on Your Page:&lt;/strong&gt; When you click the sort button, you won’t suddenly jump to a different page. You’ll stay right where you were, but everything else will be neatly organized.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feel Calm:&lt;/strong&gt; A tidy screen means a calmer mind. You can get back to your fun research or important work without the "where did it go?!" frustration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s like having a friend who quickly straightens up your desk while you’re still working, so you can find everything easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Welcome Tab Sorter to Your Chrome (It’s Like a Mini Treasure Hunt!)
&lt;/h3&gt;

&lt;p&gt;Getting this helper is easy. You just need to tell Chrome it’s okay to use tools that aren't from its main store, using something called "Developer Mode." It sounds fancy, but it's just like flipping a special switch.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Get the Tool's Files:&lt;/strong&gt; First, you need to download the Tab Sorter files. You can find them on a website called GitHub (ask a grown-up or a tech-savvy friend if you need help finding the "Download ZIP" button for "theArjun/tab-sorter"). Once downloaded, you’ll have a zipped folder. You need to "unzip" it (most computers can do this by right-clicking the folder and choosing "Extract All" or "Unzip"). Remember where you save the unzipped folder!&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Open Chrome's Special Page:&lt;/strong&gt; In Chrome, type this into the address bar at the top (where you type website names): &lt;code&gt;chrome://extensions/&lt;/code&gt; and press Enter.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Flip the Special Switch:&lt;/strong&gt; On this new page, look for a switch that says "Developer mode." It’s usually in a corner. Click it to turn it &lt;strong&gt;ON&lt;/strong&gt;. Some new buttons will appear.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Tell Chrome Where Your Tool Is:&lt;/strong&gt; Click the button that says "Load unpacked." A window will pop up, asking you to find the tool’s files.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Show Chrome the Folder:&lt;/strong&gt; Find the Tab Sorter folder you unzipped earlier (the one with files like &lt;code&gt;manifest.json&lt;/code&gt; inside) and select it. Click "Open" or "Select Folder."&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;All Set!&lt;/strong&gt; You should now see the Tab Sorter icon (it might be a simple square or puzzle piece at first) in your Chrome toolbar, usually near the top right. It's ready to help!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;(The person who made this tool says you might need to add your own pictures for the icon if you want it to look a certain way. These would be tiny picture files named icon16.png, icon32.png, and so on, placed in an "icons" folder inside the Tab Sorter folder.)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Your New Tab Helper: Easy Peasy!
&lt;/h3&gt;

&lt;p&gt;This is the simplest part of the story:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Are your tabs looking like a wild jungle?&lt;/li&gt;
&lt;li&gt; Just &lt;strong&gt;click the Tab Sorter icon&lt;/strong&gt; in your Chrome toolbar.&lt;/li&gt;
&lt;li&gt; Poof! Like magic, all your tabs in that window will line up neatly, from A to Z based on their website address. You’ll still be looking at the same page you were on, but now everything is tidy!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What Makes it Work? (The Simple Version)
&lt;/h3&gt;

&lt;p&gt;Inside that folder you downloaded, there are a few instruction files. One called &lt;code&gt;manifest.json&lt;/code&gt; is like a label that tells Chrome what the tool is. Another, &lt;code&gt;background.js&lt;/code&gt;, has the main instructions that tell Chrome how to sort your tabs. It also needs permission to look at your tabs so it can sort them, which is perfectly normal for a tab helper.&lt;/p&gt;

&lt;h3&gt;
  
  
  No More Tab Troubles!
&lt;/h3&gt;

&lt;p&gt;Imagine going back to your computer after a break. Instead of a confusing jumble, you see all your tabs neatly arranged. You easily spot the dinosaur page, the important fact, and the cool video. You smile, take a deep breath, and dive back into your exciting discoveries, feeling clear and calm.&lt;/p&gt;

&lt;p&gt;That's what Tab Sorter can do for you. It’s a small change that makes a big difference, especially when you're trying to learn, explore, or create. Give it a try, and say goodbye to that lost-in-a-forest-of-tabs feeling!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The 5 Levels of Machine Learning Projects: From Kaggle to Cutting-Edge AI</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Tue, 27 May 2025 02:57:06 +0000</pubDate>
      <link>https://dev.to/thearjun/the-5-levels-of-machine-learning-projects-from-kaggle-to-cutting-edge-ai-4eaf</link>
      <guid>https://dev.to/thearjun/the-5-levels-of-machine-learning-projects-from-kaggle-to-cutting-edge-ai-4eaf</guid>
      <description>&lt;p&gt;Have you ever wondered what truly distinguishes an entry-level machine learning project from the sophisticated AI systems powering tech giants like Google and Amazon? The gap might seem immense, but there's a clear, progressive path that most successful ML practitioners follow.&lt;/p&gt;

&lt;p&gt;This guide maps out the &lt;strong&gt;five distinct levels of machine learning projects&lt;/strong&gt;, showing you exactly where you stand on this journey and the specific skills you need to advance. Understanding these levels is crucial, as many aspiring machine learning engineers get stuck building the wrong types of projects that never lead to their desired roles. We'll also cover what level of project is expected for various positions, from entry-level to research-focused roles at leading AI companies.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 1: The Jupyter Notebook Explorer
&lt;/h3&gt;

&lt;p&gt;Every machine learning journey begins here. At Level 1, you're working with &lt;strong&gt;clean, structured datasets&lt;/strong&gt; primarily within a Jupyter notebook on your local machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you're doing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Downloading pre-cleaned datasets from platforms like Kaggle.&lt;/li&gt;
&lt;li&gt;Using libraries such as &lt;strong&gt;Pandas&lt;/strong&gt; for data manipulation, and &lt;strong&gt;Matplotlib&lt;/strong&gt;, &lt;strong&gt;Seaborn&lt;/strong&gt;, or &lt;strong&gt;Plotly&lt;/strong&gt; for visualizations.&lt;/li&gt;
&lt;li&gt;Experimenting with &lt;strong&gt;Scikit-learn&lt;/strong&gt; to train basic models like linear or logistic regression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A typical project:&lt;/strong&gt; You load a CSV into a DataFrame, perform exploratory data analysis with simple visualizations, handle missing values by dropping or filling them, encode categorical features using one-hot encoding, train a model with default hyperparameters, and evaluate with basic metrics like accuracy.&lt;/p&gt;

&lt;p&gt;This environment is perfect for learning and getting immediate feedback. However, these pristine Kaggle datasets rarely mirror the messy realities of real-world data. You're not yet considering issues like data leakage, sophisticated imputation, or scalability. When you start feeling limited by these boundaries, it's time to move up.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 2: Structured Data Science Projects
&lt;/h3&gt;

&lt;p&gt;At Level 2, things get more interesting and challenging. You're now working with &lt;strong&gt;messier, more realistic data&lt;/strong&gt; and structuring your projects like a professional data scientist, moving beyond isolated notebook experiments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your evolving workflow and tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organized Python projects:&lt;/strong&gt; You transition from a single notebook to separate modules for data processing, feature engineering, model training, and evaluation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control:&lt;/strong&gt; You use &lt;strong&gt;Git&lt;/strong&gt; to track changes and collaborate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility:&lt;/strong&gt; Configuration files help ensure your experiments can be replicated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust validation:&lt;/strong&gt; Instead of random shuffling, you use proper train-validation-test splits, often with techniques like walk-forward validation for time series data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Addressing data issues:&lt;/strong&gt; You tackle challenges like class imbalance using techniques like SMOTE or adjusting class weights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced models:&lt;/strong&gt; You might use &lt;strong&gt;LightGBM&lt;/strong&gt;, simple neural networks, or even integrate AI APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hyperparameter tuning:&lt;/strong&gt; You start thinking about and experimenting with advanced options like Bayesian search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic pipelines:&lt;/strong&gt; You might begin using tools like Prefect to build simple data pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;An example project:&lt;/strong&gt; Building a customer churn prediction pipeline that uses data from multiple sources (transaction records, support interactions, usage logs). This involves handling imbalanced classes, performing feature selection, and evaluating the model using precision-recall curves, ROC curves, and business-specific metrics.&lt;/p&gt;

&lt;p&gt;At this stage, your work becomes more structured and robust. But when asked, "When can we use this model in production?" you realize there's a whole new set of challenges awaiting you. This leads to Level 3.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 3: Machine Learning in Production
&lt;/h3&gt;

&lt;p&gt;Level 3 marks the shift from pure data science to &lt;strong&gt;machine learning engineering&lt;/strong&gt;, where your models must work in production, serve real users, and drive business outcomes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New tools and practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Containerization:&lt;/strong&gt; You use &lt;strong&gt;Docker&lt;/strong&gt; to package your models, ensuring consistency between development and production environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API development:&lt;/strong&gt; You create APIs with &lt;strong&gt;FastAPI&lt;/strong&gt; or &lt;strong&gt;Flask&lt;/strong&gt; to serve predictions, or explore frameworks like &lt;strong&gt;BentoML&lt;/strong&gt; for simplification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load testing:&lt;/strong&gt; Setting up tests to ensure your system can handle real-world traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring:&lt;/strong&gt; Deploying logging and dashboards using tools like &lt;strong&gt;Grafana&lt;/strong&gt; to track system performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning:&lt;/strong&gt; Using tools like &lt;strong&gt;DVC&lt;/strong&gt;, &lt;strong&gt;MLflow&lt;/strong&gt;, and model registries for versioning both data and models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;An example project:&lt;/strong&gt; A content recommendation engine for a small media platform. The model is packaged in a Docker container and deployed as a microservice, offering both batch predictions and a real-time API. You track metrics like click-through rates, latency percentiles, and monitor for feature distribution shifts. You also implement shadow deployments or circuit breakers to ensure system resilience.&lt;/p&gt;

&lt;p&gt;At this level, the focus expands beyond just accuracy to include inference latency, throughput, and reliability. As your system scales, you'll inevitably face the challenges that push you to Level 4.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 4: Scalable ML Systems &amp;amp; MLOps
&lt;/h3&gt;

&lt;p&gt;Level 4 is about building &lt;strong&gt;robust, scalable machine learning systems&lt;/strong&gt; that can thrive in complex, ever-changing environments. You're dealing with industrial-scale challenges and implementing sophisticated solutions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced infrastructure and tooling:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloud platforms:&lt;/strong&gt; Leveraging services like AWS SageMaker, Google Vertex AI, or Azure ML for deployment and scaling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration:&lt;/strong&gt; Using &lt;strong&gt;Kubernetes&lt;/strong&gt; and workflow tools like &lt;strong&gt;Airflow&lt;/strong&gt; or &lt;strong&gt;Prefect&lt;/strong&gt; for managing complex pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep learning frameworks:&lt;/strong&gt; Employing &lt;strong&gt;PyTorch&lt;/strong&gt; or &lt;strong&gt;TensorFlow&lt;/strong&gt; for custom model development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model optimization:&lt;/strong&gt; Using methods like quantization, knowledge distillation, and LoRA for efficiently fine-tuning large models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experiment tracking:&lt;/strong&gt; Advanced hyperparameter optimization with tools like &lt;strong&gt;Weights &amp;amp; Biases&lt;/strong&gt; or MLflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced AI models:&lt;/strong&gt; Incorporating techniques like Retrieval Augmented Generation (RAG), prompt tuning, in-context learning, and Mixture of Experts models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed training:&lt;/strong&gt; Training models across GPU clusters using techniques like pipeline parallelism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature stores:&lt;/strong&gt; Implementing feature stores and automated retraining pipelines triggered by data drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comprehensive monitoring:&lt;/strong&gt; Developing robust AB testing frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;An example project:&lt;/strong&gt; Developing a real-time fraud detection system for a global financial institution. This involves utilizing advanced anomaly detection algorithms and ensemble methods, deploying on a cloud platform with autoscaling, and implementing comprehensive monitoring and alerting mechanisms to detect system anomalies, model drift, and ensure regulatory compliance.&lt;/p&gt;

&lt;p&gt;At this level, you're balancing innovative research techniques with practical production constraints, creating systems that are both cutting-edge and reliable. This naturally sets the stage for pushing into research-level innovation, which is Level 5.&lt;/p&gt;




&lt;h3&gt;
  
  
  Level 5: Frontier Machine Learning Systems
&lt;/h3&gt;

&lt;p&gt;Level 5 takes us to the absolute &lt;strong&gt;cutting edge of the field&lt;/strong&gt;, where you are actively defining the future of AI. This isn't just about applying existing solutions; it's about inventing brand-new approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you're exploring:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom neural network architectures&lt;/strong&gt; and self-supervised learning systems leveraging vast amounts of unlabeled data.&lt;/li&gt;
&lt;li&gt;Novel applications of &lt;strong&gt;reinforcement learning&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Development of &lt;strong&gt;hybrid models&lt;/strong&gt; combining symbolic reasoning with neural networks.&lt;/li&gt;
&lt;li&gt;Designing &lt;strong&gt;custom hardware accelerators&lt;/strong&gt; to optimize performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;An example project:&lt;/strong&gt; Building an autonomous scientific discovery system that leverages Retrieval Augmented Generation with neuro-symbolic reasoning to form and test hypotheses in molecular biology. This system might use a large language model fine-tuned on biomedical literature for hypothesis generation, employ symbolic logic modules for experiment design, integrate a reinforcement learning agent to simulate outcomes, and collaborate with human researchers by suggesting novel gene interactions.&lt;/p&gt;

&lt;p&gt;These frontier projects are often experimental, pushing theoretical boundaries while hinting at the transformative potential of AI.&lt;/p&gt;




&lt;h3&gt;
  
  
  What Level Project Do You Need for a Job?
&lt;/h3&gt;

&lt;p&gt;The honest answer is, it depends on the role!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Entry-Level Data Science Positions:&lt;/strong&gt; Aim for solid &lt;strong&gt;Level 2 projects&lt;/strong&gt;. Employers want to see you go beyond tutorial notebooks. Your GitHub should showcase projects where you've handled messy real-world data, applied proper validation techniques, and documented your process clearly. Proficiency with Pandas, Scikit-learn, and visualization libraries on a self-motivated, end-to-end problem is essential.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mid-Level Data Scientist or Entry-Level Machine Learning Engineer Roles:&lt;/strong&gt; &lt;strong&gt;Level 3 projects&lt;/strong&gt; are table stakes. Employers expect an understanding of deploying models in production environments. Projects should demonstrate containerization with Docker, API development, and monitoring systems. Experience with CI/CD and version control for both code and data is a significant plus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Senior Roles or MLOps/ML Platform Engineer Positions:&lt;/strong&gt; &lt;strong&gt;Level 4 projects&lt;/strong&gt; are critical. You need to prove you can build and maintain complex ML systems at scale using cloud platforms, orchestration tools, feature stores, and automated retraining pipelines. Demonstrating how you handle distribution shifts, implement sophisticated monitoring, or design A/B testing frameworks will be required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Research-Focused Roles at AI-First Companies:&lt;/strong&gt; &lt;strong&gt;Level 5 capabilities&lt;/strong&gt; are expected. Publications at conferences and projects that push the boundaries of model architecture or training methodology are highly valued.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's important to remember that you don't need to hit the highest level to have a rewarding career in machine learning. The vast majority of ML jobs in the industry fall between Level 3 and Level 4. One comprehensive Level 3 project that solves a real problem end-to-end is often worth more than a dozen hastily implemented Level 1 notebooks.&lt;/p&gt;




&lt;h3&gt;
  
  
  Your Machine Learning Journey
&lt;/h3&gt;

&lt;p&gt;This progression highlights the evolution of machine learning projects from simple notebook experiments to frontier systems that push the boundaries of what's possible. Each level builds on the skills from the previous one. You don't need to jump straight to Level 5; start where you're comfortable, master those skills, and move up when you're ready.&lt;/p&gt;

&lt;p&gt;What level do you feel like you're currently working at, and what challenges are you facing? Share your thoughts in the comments below!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Supercharge Your Python Types with Annotated</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Mon, 19 May 2025 10:15:34 +0000</pubDate>
      <link>https://dev.to/thearjun/supercharge-your-python-types-with-annotated-29f4</link>
      <guid>https://dev.to/thearjun/supercharge-your-python-types-with-annotated-29f4</guid>
      <description>&lt;p&gt;Imagine you're labeling boxes. You might label a box "Kitchen Utensils." That's a basic type hint. But what if you also want to add a sticky note saying, "Fragile" or "Open First"? That’s where &lt;code&gt;typing.Annotated&lt;/code&gt; comes in. It lets you add extra information, or metadata, to your type hints without changing the fundamental type itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Bother with Extra Info?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Standard type hints (like &lt;code&gt;user_id: int&lt;/code&gt;) are great for telling Python "this should be an integer." But often, you have more to say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"This integer must be positive."&lt;/li&gt;
&lt;li&gt;"This string should be a valid email address."&lt;/li&gt;
&lt;li&gt;"This function parameter is coming from a web request's query string."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Annotated&lt;/code&gt; provides a neat, built-in way to attach these extra details right where you define the type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's See It in Action: The Basics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you'll need to be on Python 3.9 or newer (or use &lt;code&gt;from typing_extensions import Annotated&lt;/code&gt; for older versions).&lt;/p&gt;

&lt;p&gt;The syntax looks like this: &lt;code&gt;Annotated[TheActualType, Metadata1, Metadata2, ...]&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="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;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_type_hints&lt;/span&gt;

&lt;span class="c1"&gt;# A simple variable with an annotation
&lt;/span&gt;&lt;span class="n"&gt;user_pin_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Must be a 4-digit positive number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1234&lt;/span&gt;

&lt;span class="c1"&gt;# A function parameter with an annotation
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Internal order tracking ID, UUID format preferred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing order with ID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# ... actual processing logic ...
&lt;/span&gt;
&lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abc-123-def-456&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# How tools *could* see this metadata (you usually don't do this manually)
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Primary contact email, must be validated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;loyalty_points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot be negative&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Let's peek at the annotations for the Customer class
&lt;/span&gt;&lt;span class="n"&gt;customer_hints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_type_hints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_extras&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;customer_hints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Field: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;field_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Full Hint: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hint&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# The 'include_extras=True' gives us access to __metadata__
&lt;/span&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;hint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__metadata__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  Extra Info (Metadata): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__metadata__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this snippet, &lt;code&gt;Annotated[int, "Must be a 4-digit positive number"]&lt;/code&gt; tells us &lt;code&gt;user_pin_code&lt;/code&gt; is an integer, but also carries the string "Must be a 4-digit positive number" as extra info. For Python itself and standard type checkers (like MyPy), &lt;code&gt;user_pin_code&lt;/code&gt; is still just an &lt;code&gt;int&lt;/code&gt;. The magic happens when other libraries or tools are designed to read and use this metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Making &lt;code&gt;Annotated&lt;/code&gt; Shine: With Libraries like Pydantic and FastAPI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where &lt;code&gt;Annotated&lt;/code&gt; truly comes alive. Libraries like Pydantic (for data validation) and FastAPI (for building web APIs) use it extensively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Pydantic for Smarter Data Classes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pydantic lets you define data structures with validation. &lt;code&gt;Annotated&lt;/code&gt; makes this super clean.&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&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;ValidationError&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Star rating from 1 to 5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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;500&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Optional user comment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;reviewer_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Field&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unique ID of the reviewer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;# Let's try creating a review
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;good_review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProductReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reviewer_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loved it!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Valid Review: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;good_review&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# This one will fail validation
&lt;/span&gt;    &lt;span class="n"&gt;bad_review&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ProductReview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rating&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reviewer_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user456&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# rating &amp;gt; 5
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bad_review&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Oops, something&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s wrong with the review data:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&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;Here, &lt;code&gt;Field(gt=0, le=5)&lt;/code&gt; isn't changing &lt;code&gt;rating&lt;/code&gt; from an &lt;code&gt;int&lt;/code&gt;. It's metadata Pydantic uses to say "this integer must be greater than 0 and less than or equal to 5." This is much clearer than some older ways of doing things!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 2: FastAPI for Robust Web APIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FastAPI uses &lt;code&gt;Annotated&lt;/code&gt; to define details about your API parameters – whether they come from the path, query string, request body, etc., along with validation.&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="c1"&gt;# Body, Depends could also be used
# (Assuming Pydantic BaseModel from previous example if we need request bodies)
&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&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/{item_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Path&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The ID of the item to get&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;short_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&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;50&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&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;
    Fetches an item by its ID.
    Optionally, a short_description can be queried.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;item_data&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;item_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sample Item &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;item_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;short_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;item_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description_snippet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;short_description&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;item_data&lt;/span&gt;

&lt;span class="c1"&gt;# To run this: save as myapi.py, then run: uvicorn myapi:app --reload
# Then open your browser to http://127.0.0.1:8000/items/42?short_description=cool
# Or check out the auto-docs at http://127.0.0.1:8000/docs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;Annotated[int, Path(...)]&lt;/code&gt; tells FastAPI that &lt;code&gt;item_id&lt;/code&gt; is part of the URL path, is an integer, and must be greater than or equal to 1. &lt;code&gt;Annotated[str | None, Query(...)]&lt;/code&gt; says &lt;code&gt;short_description&lt;/code&gt; is an optional string from the query parameters with a max length.&lt;/p&gt;

&lt;p&gt;So, &lt;code&gt;Annotated&lt;/code&gt; is like giving your type hints superpowers, making your intentions clearer and enabling powerful library integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  LangGraph: Managing Information Flow Like a Champ (The "Reducer" Way)
&lt;/h2&gt;

&lt;p&gt;Now, let's switch gears to LangGraph. It's a library for building complex applications, often involving multiple steps and AI models (think "agents"). One of its clever aspects is how it manages the information, or "state," that flows through your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Challenge: Keeping Everyone on the Same Page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a multi-step process, each step might produce some information or need information from previous steps. How do you keep track of all this evolving data in an organized way? LangGraph uses a central "state object."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LangGraph's State: Your Central Hub&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of the LangGraph state as a shared whiteboard. Every step (or "node") in your process can read from this whiteboard and then propose an update to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's a "Reducer" Got to Do With It?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've ever worked with state management in web development (like Redux) or some functional programming patterns, the term "reducer" might ring a bell. A reducer is essentially a function that takes the &lt;em&gt;current state&lt;/em&gt; and some &lt;em&gt;new information&lt;/em&gt;, and produces a &lt;em&gt;new state&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's like a recipe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current state = What's already in your mixing bowl.&lt;/li&gt;
&lt;li&gt;New information = The next ingredient you're adding.&lt;/li&gt;
&lt;li&gt;Reducer = The instruction for &lt;em&gt;how&lt;/em&gt; to combine them (e.g., "stir in," "fold gently," "add to list").&lt;/li&gt;
&lt;li&gt;New state = The updated contents of your mixing bowl.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LangGraph uses this idea to manage its state updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Nodes Update the State in LangGraph&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; A node (a function in your graph) gets the current state.&lt;/li&gt;
&lt;li&gt; It does its job (calls an AI, runs a tool, etc.).&lt;/li&gt;
&lt;li&gt; It then &lt;em&gt;returns a dictionary&lt;/em&gt; indicating which parts of the state it wants to update and with what new values. It doesn't change the state directly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The "Reducer" Magic in LangGraph&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you define your state in LangGraph (often as a special kind of Python dictionary called a &lt;code&gt;TypedDict&lt;/code&gt;), you can specify &lt;em&gt;how&lt;/em&gt; updates to each piece of information (each key in your state dictionary) should be handled.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default: Just Replace It:&lt;/strong&gt; If you don't specify anything special, a new value from a node will simply overwrite the old value for that key in the state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be Specific: Use a Reducer Function!&lt;/strong&gt; For more complex updates, you define a reducer. For example, if a key in your state holds a list of messages (like in a chatbot), you don't want a new message to replace the whole list. You want to &lt;em&gt;add&lt;/em&gt; it to the existing list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Building Up a List of Actions (Reducer Style)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say our LangGraph state needs to keep a list of actions an agent has taken.&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt; &lt;span class="c1"&gt;# We'll use operator.add for list concatenation
&lt;/span&gt;
&lt;span class="c1"&gt;# 1. Define our State with a reducer for 'action_history'
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentWorkflowState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;current_task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="c1"&gt;# When a node returns an update for 'action_history',
&lt;/span&gt;    &lt;span class="c1"&gt;# the new list items will be appended to the existing list.
&lt;/span&gt;    &lt;span class="n"&gt;action_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;final_summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# Default: an update will overwrite
&lt;/span&gt;
&lt;span class="c1"&gt;# (Imagine this is part of a LangGraph StateGraph setup)
# graph_builder = StateGraph(AgentWorkflowState)
# ... add nodes and edges ...
&lt;/span&gt;
&lt;span class="c1"&gt;# 2. A node that performs an action and updates the history
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform_research_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentWorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Node: Performing research for task: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Simulate research and identify actions taken
&lt;/span&gt;    &lt;span class="n"&gt;action1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Looked up &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; on web.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;action2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarized top 3 results for &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# This node returns *only the changes* it wants to make to the state.
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&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;span class="n"&gt;action1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# These will be appended
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Next step for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# This will overwrite
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Another node might add more to the history
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_report_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentWorkflowState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;actions_so_far&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action_history&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Node: Generating report based on &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actions_so_far&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; actions.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;report_action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compiled all findings into a draft report.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Report generated based on task: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; and actions: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actions_so_far&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;report_action&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&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;span class="n"&gt;report_action&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# This will also be appended
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="c1"&gt;# This will overwrite
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# --- How LangGraph might use this (simplified) ---
# Initial state
&lt;/span&gt;&lt;span class="n"&gt;current_state_values&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;current_task&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;Impact of AI on climate change&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;action_history&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;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task initiated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# Start with an initial history item
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_summary&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;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Initial State: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Simulate running the first node
&lt;/span&gt;&lt;span class="n"&gt;updates_from_research&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;perform_research_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# LangGraph applies updates using reducers
# For 'action_history', it uses operator.add (current_history + new_items)
&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;updates_from_research&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&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;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updates_from_research&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;current_task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;State after research: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Simulate running the second node
&lt;/span&gt;&lt;span class="n"&gt;updates_from_report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_report_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;updates_from_report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;action_history&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;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;updates_from_report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;State after report: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_state_values&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this LangGraph scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We defined &lt;code&gt;action_history: Annotated[List[str], operator.add]&lt;/code&gt;. The &lt;code&gt;operator.add&lt;/code&gt; (which works for concatenating lists) is the reducer function.&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;perform_research_node&lt;/code&gt; returns &lt;code&gt;{"action_history": [action1, action2]}&lt;/code&gt;, LangGraph doesn't just replace the old &lt;code&gt;action_history&lt;/code&gt;. It takes the current &lt;code&gt;action_history&lt;/code&gt;, takes the new list &lt;code&gt;[action1, action2]&lt;/code&gt;, and uses &lt;code&gt;operator.add&lt;/code&gt; to combine them.&lt;/li&gt;
&lt;li&gt;This is super handy because if multiple parts of your graph contribute to the same list or need to modify a value in a cumulative way, reducers handle this merge logic cleanly and predictably. LangGraph even has a built-in &lt;code&gt;add_messages&lt;/code&gt; reducer specifically for managing lists of chat messages, which is a common use case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, when you see state updates in LangGraph, especially with &lt;code&gt;Annotated&lt;/code&gt; in the state definition, think "reducer"! It's how LangGraph ensures that information from different parts of your application comes together in a controlled and predictable way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Both &lt;code&gt;typing.Annotated&lt;/code&gt; and LangGraph's reducer-like state management are about making your Python code more expressive, robust, and easier to reason about.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Annotated&lt;/code&gt; lets you embed rich, contextual information directly into your type hints, which libraries can then use for things like validation, serialization, or API documentation.&lt;/li&gt;
&lt;li&gt;LangGraph’s approach to state updates, using node outputs and defined reducers for state keys, ensures that complex flows of information are handled gracefully and predictably.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding these patterns, you can build more sophisticated and maintainable Python applications. Give them a try in your next project!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Django Models Anti Patterns</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sat, 15 May 2021 08:17:44 +0000</pubDate>
      <link>https://dev.to/thearjun/django-models-anti-patterns-1ma1</link>
      <guid>https://dev.to/thearjun/django-models-anti-patterns-1ma1</guid>
      <description>&lt;p&gt;Hello pals,&lt;br&gt;&lt;br&gt;
While working with Django, we all write code that does the job, but some code may be performing excessive computations or operations that we are unaware of. These operations may be ineffective and/or counterproductive in practice.&lt;/p&gt;

&lt;p&gt;Here, I am going to mention some anti-patterns in Django models.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A. &lt;strong&gt;Using &lt;code&gt;len(queryset)&lt;/code&gt; instead of &lt;code&gt;queryset.count()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The queryset in Django are lazily evaluated which means that records in database aren't read from database until we interact with the data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;len(queryset)&lt;/code&gt; performs the count of database records by Python interpreter in application level. For doing so, all the records should be fetched from the database at first, which is computationally heavy operation.&lt;br&gt;&lt;br&gt;
Whereas, &lt;code&gt;queryset.count()&lt;/code&gt; calculates the count at the database level and just returns the count.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a model &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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;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;author&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;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;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we use &lt;code&gt;len(queryset)&lt;/code&gt;, it handles the calculation like &lt;code&gt;SELECT * FROM post&lt;/code&gt; which returns a list of records (queryset) and then python interpreter calculates the length of queryset which is similar to list data structure. Imagine the waste in downloading many records only to check the length and throw them away at the end! But, if we need the records after reading the length, then &lt;code&gt;len(queryset)&lt;/code&gt; can be valid.&lt;/p&gt;

&lt;p&gt;If we use &lt;code&gt;queryset.count()&lt;/code&gt;, it handles the calculation like &lt;code&gt;SELECT COUNT(*) FROM post&lt;/code&gt; at database level. It makes the code execution quicker and improves database performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;B. &lt;strong&gt;Using &lt;code&gt;queryset.count()&lt;/code&gt; instead of &lt;code&gt;queryset.exists()&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;While we kept praising the use of &lt;code&gt;queryset.count()&lt;/code&gt; to check the length of a queryset, using it may be performance heavy if we want to check the existence of the queryset.
For the same model &lt;code&gt;Post&lt;/code&gt;, when we want to check if there are any post written by author &lt;code&gt;Arjun&lt;/code&gt;, we may do something like:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author__iexact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun writes posts here.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun doesnt write posts here.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;posts_by_arjun.count()&lt;/code&gt; performs an SQL operation that scans every row in a database table. But, if we are just interested in &lt;code&gt;If Arjun writes posts here or not ?&lt;/code&gt; then, more efficient code will be:&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;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author__iexact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun writes posts here.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun doesnt write posts here.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;posts_by_arjun.exists()&lt;/code&gt; returns a bool expression that finds out if at least one result exists or not. It simply reads a single record in the most optimized way (removing ordering, clearing any user-defined &lt;code&gt;select_related()&lt;/code&gt; or &lt;code&gt;distinct()&lt;/code&gt; methods.) &lt;/p&gt;

&lt;p&gt;Also, checking existence / truthiness of queryset like this is inefficient.&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;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author__iexact&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;posts_by_arjun&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun writes posts here.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Arjun doesnt write posts here.)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does the fine job in checking if there are any posts by Arjun or not but is computationally heavy for larger no of records. Hence, use of &lt;code&gt;queryset.exists()&lt;/code&gt; is encouraged for checking existence / truthiness of querysets.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;C. &lt;strong&gt;Using &lt;code&gt;signals&lt;/code&gt; excessively&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Django signals are great for triggering jobs based on events. But it has some valid cases, and they shouldn't be used excessively. Think of any alternative for signals within your codebase, brainstorm on its substitution and try to place signals logic in your models itself, if possible.
&lt;/li&gt;
&lt;li&gt;They are not executed asynchronously. There is no background thread or worker to execute them. If you want some background worker to do your job for you, try using &lt;code&gt;celery&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt; As signals are spread over separate files if you're working on a larger project, they can be harder to trace for someone who is a fresh joiner to the company and that's not great. Although, &lt;code&gt;django-debug-toolbar&lt;/code&gt; does some help in tracing the triggered signals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's create a scenario where we want to keep the record of &lt;code&gt;Post&lt;/code&gt; writings in a separate model &lt;code&gt;PostWritings&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostWritings&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;author&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;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;posts_written&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;PositiveIntegerField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to automatically update the &lt;code&gt;PostWritings&lt;/code&gt; record for a use based on records created on &lt;code&gt;Post&lt;/code&gt; model, there are ways to achieve the task with / without signals.&lt;/p&gt;

&lt;p&gt;A. With Signals&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;django.db.models.signals&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;post_save&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;F&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.dispatch&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;receiver&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;

&lt;span class="nd"&gt;@receiver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post_save&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_writing_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PostWritings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_or_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts_written&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;posts_written&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B. Without Signals&lt;/p&gt;

&lt;p&gt;We need to override the &lt;code&gt;save()&lt;/code&gt; method for &lt;code&gt;Post&lt;/code&gt; model.&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;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;F&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;author&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;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;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Overridden method.
&lt;/span&gt;        &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&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;author&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PostWritings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_or_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts_written&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;posts_written&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Post&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="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the same job can be accomplished without signals, the code can be easily traced and prevent unnecessary event triggers.&lt;br&gt;&lt;br&gt;
If someone feels about not having readability on &lt;code&gt;save()&lt;/code&gt; method here, breaking up code is always great. Let's do that.&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;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;F&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;author&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;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;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_update_post_writing&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="n"&gt;created&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PostWritings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_or_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;writing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;posts_written&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;F&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;posts_written&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Overridden method.
&lt;/span&gt;        &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&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;author&lt;/span&gt;
        &lt;span class="n"&gt;created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Post&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="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&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="nf"&gt;_update_post_writing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like we've learned how to mitigate some Django Model Anti Patterns. For now, thank you everyone for having me here. I'll be continuing with more stuffs about Django very soon.&lt;br&gt;
You can also find me on &lt;a href="https://github.com/thearjun/"&gt;GitHub&lt;/a&gt;. Till then &lt;code&gt;keep coding :)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>webdev</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Implement Autocomplete in Django</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sat, 19 Dec 2020 17:49:20 +0000</pubDate>
      <link>https://dev.to/thearjun/implement-autocomplete-in-django-3h20</link>
      <guid>https://dev.to/thearjun/implement-autocomplete-in-django-3h20</guid>
      <description>&lt;p&gt;Hello pals,&lt;br&gt;
In this blog, I am going to guide you to implement autocomplete in Django admin interface. I chose admin interface because it provides CRUD ( CREATE-READ-UPDATE-DELETE ) view for defined models out of the box.&lt;/p&gt;

&lt;p&gt;For implementing auto completion feature, I am going to use &lt;code&gt;django-ajax-selects&lt;/code&gt; currently maintained by  &lt;a href="https://github.com/crucialfelix" rel="noopener noreferrer"&gt;crucialfelix&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a django project.&lt;br&gt;
First of all, I'll create a virtual environment &lt;code&gt;.venv&lt;/code&gt;. You can create  virtual environment just by &lt;code&gt;python -m venv .venv&lt;/code&gt;.&lt;br&gt;
Let's activate the virtual environment &lt;code&gt;.venv\Scripts\activate&lt;/code&gt; as I am currently on Windows environment.&lt;/p&gt;

&lt;p&gt;After that, install &lt;code&gt;django&lt;/code&gt; and &lt;code&gt;django-ajax-selects&lt;/code&gt;  using pip.&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 django django-ajax-selects
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following installing libraries, let's create django project named &lt;code&gt;autocomplete_demo_project&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;django-admin startproject autocomplete_demo_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subsequently, Let's create a django app named &lt;code&gt;blog&lt;/code&gt; .&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 startapp blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And register the app &lt;code&gt;'blog'&lt;/code&gt; and &lt;code&gt;'ajax_select'&lt;/code&gt; in &lt;code&gt;INSTALLED_APPS&lt;/code&gt; inside &lt;code&gt;settings.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Thereafter, let's define URLConfs for &lt;code&gt;ajax_select&lt;/code&gt; so it may load the necessary javascripts, stylesheets for autocompletion.&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;# autocomplete_demo_project/urls.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf.urls.static&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ajax_select&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ajax_select_urls&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ajax_select/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ajax_select_urls&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;admin/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATIC_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;document_root&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Models and Lookups
&lt;/h2&gt;

&lt;p&gt;We have to start through defining models which will later be used for observing auto completion in admin  panel.&lt;br&gt;
Without adding any complexity, I'll just start with a single field &lt;code&gt;name&lt;/code&gt; in Blog model.&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;# blog/models.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils.translation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;gettext_lazy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Blog&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;name&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="nf"&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;Blog&lt;/span&gt;&lt;span class="sh"&gt;"&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;__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;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also create a lookup for the field &lt;code&gt;name&lt;/code&gt; which fetches the most suitable result by matching the query entered while entering a record in admin panel. For doing so, let's create  LookupChannel for our field &lt;code&gt;name&lt;/code&gt; (&lt;code&gt;NameLookup&lt;/code&gt;) in &lt;code&gt;lookup.py&lt;/code&gt; inside &lt;code&gt;blog&lt;/code&gt; app directory.&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;# blog/lookups.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ajax_select&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LookupChannel&lt;/span&gt;

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

&lt;span class="nd"&gt;@register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;names&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;  &lt;span class="nc"&gt;NameLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LookupChannel&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;Blog&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;get_query&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="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="n"&gt;self&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;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name__icontains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;format_item_display&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="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;span class=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;%s&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've observed two methods inside our &lt;code&gt;NameLookup&lt;/code&gt; class. Let's dig into both of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;get_query&lt;/code&gt; method takes &lt;code&gt;q&lt;/code&gt; parameter as query which will be used to filter the record in database.  Here, we've used the &lt;code&gt;name__icontains&lt;/code&gt; approach which will filter the matched records in DB with sub string query &lt;code&gt;q&lt;/code&gt; and return the filtered records. &lt;br&gt;
We may also proceed with &lt;code&gt;name__startswith&lt;/code&gt; approach which only tries to match the starting string with the records in DB with sub string query &lt;code&gt;q&lt;/code&gt; and return the filtered records.  But, let's just stick into one approach ( &lt;code&gt;name__icontains&lt;/code&gt; approach) to implement the auto completion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;format_item_display&lt;/code&gt; methods takes each filtered records and displays&lt;code&gt;blog.name&lt;/code&gt; (data) which is the need in our case with proper styling. We can override the display properties to make it look better and match with our preferences.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also notice that we've registered a lookup name &lt;code&gt;names&lt;/code&gt; with &lt;code&gt;register&lt;/code&gt; decorator which will later be used with form to match with required form field i.e. The form field with the property &lt;code&gt;names&lt;/code&gt; will match with the above lookup.&lt;/p&gt;

&lt;h2&gt;
  
  
  ModelAdmin and Forms
&lt;/h2&gt;

&lt;p&gt;Ensuing step will be to create Django forms which will be provided as property to our ModelAdmin which we'll later create in &lt;code&gt;admin.py&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog/forms.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ajax_select.fields&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoCompleteField&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;forms&lt;/span&gt;

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

&lt;span class="k"&gt;class&lt;/span&gt;  &lt;span class="nc"&gt;BlogForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AutoCompleteField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;names&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt;  &lt;span class="nc"&gt;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;Blog&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;name&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;It's worth noticing that the field name is an &lt;code&gt;AutoCompleteField&lt;/code&gt; with the property &lt;code&gt;names&lt;/code&gt; which is a lookup name we've registered in &lt;code&gt;NameLookup&lt;/code&gt; class inside &lt;code&gt;blog/lookups.py&lt;/code&gt;.  It's how we interlink forms and lookups using  &lt;code&gt;django-ajax-selects.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Following this, let's create &lt;code&gt;ModelAdmin&lt;/code&gt;  inside &lt;code&gt;admin.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# blog/admin.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ajax_select.admin&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AjaxSelectAdmin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.forms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BlogForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Blog&lt;/span&gt;

&lt;span class="nd"&gt;@admin.register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;  &lt;span class="nc"&gt;BlogAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AjaxSelectAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BlogForm&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we've done here is overriding the default &lt;code&gt;form&lt;/code&gt; property provided by Django Admin and get it replaced by our &lt;code&gt;BlogForm&lt;/code&gt; form object.&lt;/p&gt;

&lt;p&gt;Also note that,  the use of &lt;code&gt;BlogForm&lt;/code&gt; isn't limited to ModelAdmin for auto completion. It can also be used in used defined templates by passing &lt;code&gt;form&lt;/code&gt; inside &lt;code&gt;context&lt;/code&gt; parameter from &lt;code&gt;views.py&lt;/code&gt;.&lt;br&gt;
For doing so,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{{ form.media }}
{{ form }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to load &lt;code&gt;((form.media}}&lt;/code&gt; to load the necessary JS and CSS files defined by &lt;code&gt;ajax_selects&lt;/code&gt; app. &lt;/p&gt;

&lt;h2&gt;
  
  
  Observation
&lt;/h2&gt;

&lt;p&gt;After defining lookups, models, forms and modeladmin, now we can make migrations and run the migration files.&lt;br&gt;
&lt;code&gt;python manage.py makemigrations blog&lt;/code&gt;&lt;br&gt;
Post hoc, let's run those migration files.&lt;br&gt;
&lt;code&gt;python manage.py migrate&lt;/code&gt;&lt;br&gt;
Then, create a superuser for accessing admin interface,&lt;br&gt;
&lt;code&gt;python manage.py createsuperuser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, log into &lt;code&gt;127.0.0.1:8000/admin&lt;/code&gt; to access admin interface and navigate to &lt;code&gt;Blog&lt;/code&gt; model.&lt;/p&gt;

&lt;p&gt;Try adding some records and you'll notice auto completion making work easy for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo
&lt;/h3&gt;

&lt;p&gt;I've added some records in my models.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMOTFNvP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMOTFNvP.png" alt="Added Records"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's try to add another record to observe auto-completion.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FfjoYRXx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FfjoYRXx.png" alt="Autcompletion Demo"&gt;&lt;/a&gt;&lt;br&gt;
Notice that, when I am typing &lt;code&gt;A&lt;/code&gt;, the records with the letter &lt;code&gt;A&lt;/code&gt; in their name appeared as dropdown so user may autocomplete the record.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>django</category>
      <category>ajax</category>
      <category>webdev</category>
      <category>python</category>
    </item>
    <item>
      <title>Integrate Django Jazzmin theme to Django Admin | AdminLTE Dashboard</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Fri, 13 Nov 2020 20:15:58 +0000</pubDate>
      <link>https://dev.to/thearjun/integrate-django-jazzmin-theme-to-django-admin-adminlte-dashboard-5aao</link>
      <guid>https://dev.to/thearjun/integrate-django-jazzmin-theme-to-django-admin-adminlte-dashboard-5aao</guid>
      <description>&lt;p&gt;Hello Geeks,&lt;br&gt;
First of all, I would like to thank you for reaching here. No doubt you're gonna be a successful Django developer ahead.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Instructions

&lt;ul&gt;
&lt;li&gt;Setup Virtual Environment (Optional)&lt;/li&gt;
&lt;li&gt;Installing libraries&lt;/li&gt;
&lt;li&gt;Create Django Project&lt;/li&gt;
&lt;li&gt;Register Apps&lt;/li&gt;
&lt;li&gt;Create Model and ModelAdmin&lt;/li&gt;
&lt;li&gt;Make Migrations and Migrate Models&lt;/li&gt;
&lt;li&gt;Enjoy the output&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this blog, I am guiding to integrate &lt;code&gt;django-jazzmin&lt;/code&gt; theme to the Django project.&lt;br&gt;
According to their &lt;a href="https://django-jazzmin.readthedocs.io/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Django Jazzmin is intended as a drop-in app to jazz up your Django admin site, with plenty of things you can easily customise, including a built-in UI customizer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The default admin dashboard provided by Django isn't best fitted for our need every time and we need to customize a lot to match the theme with our need. And some of us may not prefer to go with the default theme which looks like this :&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FpRGyc5T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FpRGyc5T.png" alt="question.png"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For the developers who want to get the customized and better-looking admin dashboard for Django, &lt;code&gt;django-jazzmin&lt;/code&gt; is the one which has better UI components with features like :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop-in admin skin, all configuration optional&lt;/li&gt;
&lt;li&gt;Select2 drop-downs&lt;/li&gt;
&lt;li&gt;Bootstrap 4 &amp;amp; AdminLTE UI components&lt;/li&gt;
&lt;li&gt;Search bar for any given model admin&lt;/li&gt;
&lt;li&gt;Modal windows instead of popups&lt;/li&gt;
&lt;li&gt;Customisable side menu&lt;/li&gt;
&lt;li&gt;Customisable top menu&lt;/li&gt;
&lt;li&gt;Customisable user menu&lt;/li&gt;
&lt;li&gt;Responsive&lt;/li&gt;
&lt;li&gt;Customisable UI (via Live UI changes, or custom CSS/JS)&lt;/li&gt;
&lt;li&gt;Based on the latest adminlte + bootstrap&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;which looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FgP87rSk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FgP87rSk.png" alt="list_view.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To achieve a good looking AdminLTE dashboard on our Django project, we need to follow a sequence of instructions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Instructions
&lt;/h2&gt;

&lt;p&gt;Navigate to your workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ mkdir - ~/workspace/integrate-django-jazzmin
$ cd ~/workspace/integrate-django-jazzmin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup Virtual Environment (Optional)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ python -m virtualenv venv

created virtual environment CPython3.8.6.final.0-64 in 116ms
  creator CPython3Posix(dest=/home/ubuntu/workspace/integrate-django-jazzmin/venv, clear=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/ubuntu/.local/share/virtualenv)
    added seed packages: pip==20.2.4, setuptools==50.3.2, wheel==0.35.1
  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

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

&lt;/div&gt;



&lt;p&gt;This will set up a virtualenv named &lt;code&gt;venv&lt;/code&gt; which isolates libraries and dependencies from the global installation.&lt;br&gt;
Now, activate the 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;$ source venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing libraries
&lt;/h3&gt;

&lt;p&gt;Now, we are good to install the libraries we need to set up the Django project.&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 django django-jazzmin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the &lt;code&gt;django&lt;/code&gt; and &lt;code&gt;django-jazzmin&lt;/code&gt; library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Django Project
&lt;/h3&gt;

&lt;p&gt;It's time to create a Django project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;For a better demonstration of the theme, I'm going to create a Django app named &lt;code&gt;blog&lt;/code&gt;.&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 startapp blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which created directory structure like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Directory Structure
# ====================
.
├── blog
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── dj_jazzmin_demo
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   └── settings.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Register Apps
&lt;/h3&gt;

&lt;p&gt;Now, let's register the &lt;code&gt;blog&lt;/code&gt; app inside &lt;code&gt;INSTALLED_APPS&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;.&lt;br&gt;
Add &lt;code&gt;blog.apps.BlogConfig&lt;/code&gt; after the pre-registered django apps.&lt;br&gt;
Also, we are good to add our theme to the django project. For that, register &lt;code&gt;jazzmin&lt;/code&gt; theme to &lt;code&gt;INSTALLED_APPS&lt;/code&gt;.&lt;br&gt;
But, we're registering &lt;code&gt;jazzmin&lt;/code&gt; on the top of other pre-registered apps because we want the theme to load earlier than other apps.&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;# dj_jazzmin_demo/settings.py
# =============================
&lt;/span&gt;
&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# Pre-loading Third Party apps
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;jazzmin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 

    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.admin&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.auth&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.contenttypes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.sessions&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;django.contrib.staticfiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;# Local Apps
&lt;/span&gt;    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blog.apps.BlogConfig&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;h3&gt;
  
  
  Create Model and ModelAdmin
&lt;/h3&gt;

&lt;p&gt;Now, we have our app and theme registered in our project. Then, we can write models for the app &lt;code&gt;blog&lt;/code&gt;.&lt;br&gt;
Let's write a model named &lt;code&gt;Post&lt;/code&gt; in &lt;code&gt;models.py&lt;/code&gt; inside &lt;code&gt;blog&lt;/code&gt; app.&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;# blog/models.py
# ================
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.utils.translation&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ugettext_lazy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_&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="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Model definition for Post.&lt;/span&gt;&lt;span class="sh"&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="nf"&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;Post&lt;/span&gt;&lt;span class="sh"&gt;'&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;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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;Content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;is_publishable&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;BooleanField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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;Is Publishable ?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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;Created at &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&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;Updated at &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;auto_now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="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="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Meta definition for Post.&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

        &lt;span class="n"&gt;verbose_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Post&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;verbose_name_plural&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Posts&lt;/span&gt;&lt;span class="sh"&gt;'&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="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Unicode representation of Post.&lt;/span&gt;&lt;span class="sh"&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;p&gt;For making our app accessible via the admin dashboard, we're going to register the model &lt;code&gt;Post&lt;/code&gt; in &lt;code&gt;admin.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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


&lt;span class="nd"&gt;@admin.register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostAdmin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelAdmin&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;Admin View for Post&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

    &lt;span class="n"&gt;list_display&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;title&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;is_publishable&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;created_at&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;updated_at&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;span class="n"&gt;list_filter&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;is_publishable&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;created_at&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;updated_at&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;h3&gt;
  
  
  Make Migrations and Migrate Models
&lt;/h3&gt;

&lt;p&gt;Now, we're good to make migrations and migrate the model we created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ python manage.py makemigrations blog
Migrations for 'blog':
  blog/migrations/0001_initial.py
    - Create model Post
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying blog.0001_initial... OK
  Applying sessions.0001_initial... OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For accessing the admin panel, we need to create a superuser which has the privilege to access the admin dashboard and perform operations over there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ python manage.py createsuperuser
Username (leave blank to use 'ubuntu'): ubuntu
Email address: 
Password: 
Password (again): 
Superuser created successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enjoy the output
&lt;/h3&gt;

&lt;p&gt;Finally, we've completed the procedure to create a basic Django project and integrate &lt;code&gt;django-jazzmin&lt;/code&gt; theme.&lt;br&gt;
Now, we can run our django project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Terminal
# =========

$ python manage.py runserver

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
November 13, 2020 - 19:46:51
Django version 3.1.3, using settings 'dj_jazzmin_demo.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have our Django project running. To access it through a web browser, visit the URL &lt;code&gt;http://127.0.0.1:8000/admin/&lt;/code&gt; on a web browser. It loads to a different login interface than default login UI provided by Django.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvUauSfL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvUauSfL.png" alt="Screenshot from 2020-11-14 01-35-56.png"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;After entering credentials, we're navigated to a jazzy looking admin interface provided by &lt;code&gt;django-jazzmin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FHFqmUxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FHFqmUxu.png" alt="Screenshot from 2020-11-14 01-39-00.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's surf through beautiful interfaces provided by &lt;code&gt;django-jazzmin&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Add Post UI&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FVlLp9qK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FVlLp9qK.png" alt="Screenshot from 2020-11-14 01-45-27.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List Display UI&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWTzBoAL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWTzBoAL.png" alt="Screenshot from 2020-11-14 01-45-46.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete Post UI&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMb1cp6C.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMb1cp6C.png" alt="Screenshot from 2020-11-14 01-45-56.png"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filtering through fields&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FE8ZQbyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FE8ZQbyz.png" alt="Screenshot from 2020-11-14 01-46-13.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For now, we've successfully integrated  &lt;code&gt;django-jazzmin&lt;/code&gt; theme to our django_project. In the next part of the blog, we will be customizing admin dashboard through API provided by &lt;code&gt;django-jazzmin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading.&lt;/p&gt;

</description>
      <category>django</category>
      <category>adminlte</category>
      <category>jazzmin</category>
      <category>dashboard</category>
    </item>
    <item>
      <title>Download required folder only from GitHub with Subversion</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sun, 03 May 2020 16:51:29 +0000</pubDate>
      <link>https://dev.to/thearjun/download-required-folder-only-from-github-with-subversion-2gpc</link>
      <guid>https://dev.to/thearjun/download-required-folder-only-from-github-with-subversion-2gpc</guid>
      <description>&lt;p&gt;Hello pals, &lt;br&gt;
We all have experienced a situation where we need to download a folder from GitHub but we are forced to clone a whole bulky repository and then access the required folder. Well, no more reason to fear to worry of these situations. Through this blog tutorial I'm going to guide you to download only the required folder from GitHub without cloning the whole repository.&lt;/p&gt;
&lt;h2&gt;
  
  
  Navigate the repository and directory you want
&lt;/h2&gt;

&lt;p&gt;First of all, navigate to the repository you want to access the folder. Here, I am taking my &lt;a href="https://github.com/theArjun/machine-learning"&gt;Machine Learning&lt;/a&gt; repository as example. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X4Y9wGby--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/W3c5Gd1/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X4Y9wGby--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/W3c5Gd1/image.png" alt="ML Repo" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, I am navigating to the directory named &lt;code&gt;data-visualization&lt;/code&gt; which I want to download. Then copy the URL from the browser address bar which is &lt;a href="https://github.com/theArjun/machine-learning/tree/master/data-visualization"&gt;https://github.com/theArjun/machine-learning/tree/master/data-visualization&lt;/a&gt; in my case. Note this or get it stored in clipboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uLOQAkZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/WB5XBGf/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uLOQAkZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/WB5XBGf/image.png" alt="Data Visualization Repo" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Subversion
&lt;/h2&gt;

&lt;p&gt;I am using &lt;code&gt;subversion&lt;/code&gt; to download the required directory. For doing so,  make sure you've installed it on your system.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install subversion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Tweak URL
&lt;/h2&gt;

&lt;p&gt;I hope you've noted the directory URL from GitHub or get it stored on clipboard which was &lt;a href="https://github.com/theArjun/machine-learning/tree/master/data-visualization"&gt;https://github.com/theArjun/machine-learning/tree/master/data-visualization&lt;/a&gt; in my case.&lt;br&gt;
Now replace the &lt;code&gt;tree/master&lt;/code&gt; with &lt;code&gt;trunk&lt;/code&gt; which results to &lt;a href="https://github.com/theArjun/machine-learning/tree/master/data-visualization"&gt;https://github.com/theArjun/machine-learning/trunk/data-visualization&lt;/a&gt;  and note it again. Good going pals, we're now at the final stage.&lt;/p&gt;
&lt;h2&gt;
  
  
  Download the Directory
&lt;/h2&gt;

&lt;p&gt;Open the terminal and execute the following command : &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;svn checkout https://github.com/theArjun/machine-learning/trunk/data-visualization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The URL was the tweaked URL which I guided in &lt;strong&gt;Tweak URL&lt;/strong&gt; section. The execution of command looks like following in terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ svn checkout https://github.com/theArjun/machine-learning/trunk/data-visualization

A    data-visualization/Data Generation - Classification.ipynb
A    data-visualization/Data Generation - Regression Data.ipynb
A    data-visualization/Data Normalization and Standardization.ipynb
A    data-visualization/Data Visualization - Subplots.ipynb
A    data-visualization/Exploring Sklearn Datasets.ipynb
A    data-visualization/Generating Data using Sk-Learn.ipynb
A    data-visualization/Matplotlib Basics.ipynb
A    data-visualization/Multivariate Normal Distribution  .ipynb
A    data-visualization/Normal Distribution &amp;amp; Histogram.ipynb
A    data-visualization/Numeric Spacing.ipynb
A    data-visualization/PyCharts, BarCharts and Legends.ipynb
A    data-visualization/Template.ipynb
A    data-visualization/Working with Pandas - MNIST Dataset.ipynb
A    data-visualization/Working with Pandas.ipynb
A    data-visualization/csv
A    data-visualization/csv/linearX.csv
A    data-visualization/csv/linearY.csv
A    data-visualization/csv/movie_data.csv
Checked out revision 103.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a directory named data-visualization gets created on the working folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls

data-visualization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This folder contains all the files which are on the &lt;code&gt;data-visualization&lt;/code&gt; folder on the GitHub i.e. totally synced with the remote (GitHub). &lt;/p&gt;

&lt;p&gt;So, no worries, create as many folders you need and download them as required without cloning whole bulky repository.&lt;br&gt;
I hope you enjoyed learning a new trick. I will be back with similar tricks soon. Till then &lt;code&gt;keep coding :)&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>download</category>
      <category>directory</category>
      <category>git</category>
    </item>
    <item>
      <title>Create Django App and Migrations</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sun, 19 Apr 2020 17:31:43 +0000</pubDate>
      <link>https://dev.to/thearjun/create-django-app-and-migrations-1km8</link>
      <guid>https://dev.to/thearjun/create-django-app-and-migrations-1km8</guid>
      <description>&lt;p&gt;Hello pals,&lt;br&gt;
I hope you're following me through the first installment of the series 'Create Django Project'. Upto then, I've created a django project named &lt;code&gt;weather_project&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The typical next step is to start adding apps, which represent discrete areas of&lt;br&gt;
functionality. A single Django project can support multiple apps.&lt;br&gt;
So, I am creating an app inside the Django project for managing my application logic conveniently.&lt;/p&gt;

&lt;p&gt;It may seem confusing with the project that I've created and the app I'm going to create now.&lt;br&gt;
The main difference between app and project in Django is well illustrated as :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;em&gt;project&lt;/em&gt; refers to the entire application and all its parts.&lt;br&gt;
An &lt;em&gt;app&lt;/em&gt; refers to a submodule of the project. It's self-sufficient and not intertwined with the other apps in the project such that, in theory, you could pick it up and plop it down into another project without any modification. &lt;br&gt;
The main thing to keep in mind is this level of interdependence between the &lt;em&gt;apps&lt;/em&gt;. In practice it's all one &lt;em&gt;project&lt;/em&gt;, so there's no sense in going overboard, but keep in mind how co-dependent two apps are. If you find one app is solving two problems, split them into two apps. If you find two apps are so intertwined you could never reuse one without the other, combine them into a single app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let's create an app named &lt;code&gt;weather&lt;/code&gt; inside the project. For creating the app, we are using &lt;code&gt;startapp&lt;/code&gt; command .&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;python manage.py startapp weather&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Executing the &lt;code&gt;startapp&lt;/code&gt; command, Django will automatically create the app for us and we can visualize the directory structure which looks like:&lt;br&gt;
&lt;/p&gt;

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

1 directory, 7 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry, pal. I will be guiding you through each of the files.&lt;/p&gt;

&lt;p&gt;Each app has a &lt;code&gt;__init__&lt;/code&gt;.py file identifying it as a Python package. There are 6 new&lt;br&gt;
files created:&lt;br&gt;
• &lt;code&gt;admin.py&lt;/code&gt; is a configuration file for the built-in Django Admin app.&lt;br&gt;
• &lt;code&gt;apps.py&lt;/code&gt; is a configuration file for the app itself.&lt;br&gt;
• The &lt;code&gt;migrations&lt;/code&gt;  directory stores migrations files for database changes.&lt;br&gt;
• &lt;code&gt;models.py&lt;/code&gt; is where we define our database models.&lt;br&gt;
• &lt;code&gt;tests.py&lt;/code&gt; is for our app-specific tests.&lt;br&gt;
• &lt;code&gt;views.py&lt;/code&gt; is where we handle the request/response logic for our web app.&lt;br&gt;
Typically developers will also create an &lt;code&gt;urls.py&lt;/code&gt; file within each app too for routing.&lt;/p&gt;

&lt;p&gt;For now, we're going to add the app we created into the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; inside the &lt;code&gt;settings.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# weather_project/settings.py
-----------------------------
INSTALLED_APPS  = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# Local
'weather.apps.WeatherConfig',
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that, I've separated the &lt;code&gt;'weather.apps.WeatherConfig'&lt;/code&gt; from the rest for the convenience. It makes easier to look after the apps we created.&lt;/p&gt;

&lt;p&gt;After adding the app to &lt;code&gt;INSTALLED_APPS&lt;/code&gt;, now I'm defining the database requirements. For storing the database information, we need following fields.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;city_name&lt;/li&gt;
&lt;li&gt;updated_at - You'll know why I created this field afterwards. Just stick to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After analysing the database requirements, let's define those fields in &lt;code&gt;models.py&lt;/code&gt; Django ORM helps us to create the schema without writing the SQL commands. That's the power of fully featured web framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# weather/models.py
--------------------
from django.db import models

class  WeatherModel(models.Model):

    city_name = models.CharField(max_length=100)
    updated_at = models.DateTimeField(auto_now=True)

    def  __str__(self):
        return  self.city_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The city_name can be maximum of 100 characters and the updated_at fields get updated to the latest timestamp when we make any update to the record afterwards. We also include a &lt;code&gt;__str__&lt;/code&gt; method so that the city name is appeared in the Admin Panel later.&lt;/p&gt;

&lt;p&gt;Thenceforth, run the &lt;code&gt;makemigrations&lt;/code&gt; to generate the DDL(Data Definition Language ) commands for your database.&lt;br&gt;
Don't get intimidated by two similar words: &lt;code&gt;makemigrations&lt;/code&gt; and &lt;code&gt;migrate&lt;/code&gt;. The difference in simple words seems to be :&lt;br&gt;
&lt;code&gt;python manage.py makemigrations&lt;/code&gt;: Create the migrations (generate the &lt;code&gt;SQL&lt;/code&gt; commands).&lt;br&gt;
&lt;code&gt;python manage.py migrate&lt;/code&gt;: Run the migrations (execute the &lt;code&gt;SQL&lt;/code&gt; commands).&lt;/p&gt;

&lt;p&gt;Always remember you're making migrations first and then running the migration.&lt;/p&gt;

&lt;p&gt;While making the migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Terminal
---------
$ python manage.py makemigrations
Migrations for 'weather':
  weather/migrations/0001_initial.py
    - Create model WeatherModel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And while running the migration,&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, you've successfully created the app and migration with Django. In next installment of the series, I'll be guiding to fetch the weather data from the public API and building beautiful frontend afterwards, Till then, &lt;code&gt;keep coding :)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create Django Project</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sun, 19 Apr 2020 17:16:55 +0000</pubDate>
      <link>https://dev.to/thearjun/create-a-django-web-4065</link>
      <guid>https://dev.to/thearjun/create-a-django-web-4065</guid>
      <description>&lt;p&gt;Hello pals,&lt;br&gt;
In this blog tutorial, I am guiding you to create a Django web application from stratch.&lt;/p&gt;

&lt;p&gt;Like every other Python Developers, we start a project by creating a virtual environment at first. A &lt;strong&gt;virtual environment&lt;/strong&gt; is a tool that helps to keep dependencies required by different projects separate by creating isolated &lt;strong&gt;python virtual environments&lt;/strong&gt; for them. &lt;br&gt;
So, create a virtual environment on your system. If you don't have it installed, install from &lt;code&gt;PyPi&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install virtualenv&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now, create the virtualenv like:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;virtualenv VIRTUAL_ENV_NAME&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Here, I'm naming it &lt;code&gt;.env&lt;/code&gt; for sake of simplicity:&lt;br&gt;
&lt;br&gt;
  &lt;code&gt;virtualenv .env&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now, activate the virtual environment you've created:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;source .env/bin/activate&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now, install the Django using the &lt;code&gt;pip&lt;/code&gt; :&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;pip install Django&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Then, create a workspace folder to store the source code while you're writing this guide. Here, I'm creating a directory named &lt;code&gt;django_workspace&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir django_workspace&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;And change your current working directory to  &lt;code&gt;django_workspace&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd  django_workspace&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Now, create the Django project here with the command :&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;django-admin startproject YOUR_PROJECT_NAME .&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The main objective of the project I'm gonna create is to fetch the weather data from public API of various cities and display on web.&lt;br&gt;
So, let's name it &lt;code&gt;weather_project&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;django-admin startproject weather_project&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Django automatically generates a new project for us. We can visualize the file structure of the directory &lt;code&gt;django_workspace&lt;/code&gt; which looks like :&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We notice that, &lt;code&gt;manage.py&lt;/code&gt; gets created at the root of the project folder. Every Django project starts with a &lt;code&gt;manage.py&lt;/code&gt; file in its root. It's a convenience script that allows you to run administrative tasks .&lt;br&gt;
Using the &lt;code&gt;manage.py&lt;/code&gt;, I'm creating a app inside the project named &lt;code&gt;weather&lt;/code&gt; which will contain the logic that our project carries.&lt;/p&gt;

&lt;p&gt;The files have the following roles:&lt;br&gt;
• &lt;code&gt;asgi.py&lt;/code&gt;is a spiritual successor to &lt;code&gt;wsgi&lt;/code&gt;, intended to provide a standard interface between async-capable Python web servers, frameworks, and applications. &lt;br&gt;
• &lt;code&gt;__init__.py&lt;/code&gt; is a Python way to treat a directory as a package; it is empty.&lt;br&gt;
• &lt;code&gt;settings.py&lt;/code&gt; contains all the configuration for our project.&lt;br&gt;
•&lt;code&gt;urls.py&lt;/code&gt; controls the top-level URL routes.&lt;br&gt;
• &lt;code&gt;wsgi.py&lt;/code&gt; stands for web server gateway interface and helps Django serve the&lt;br&gt;
eventual web pages.&lt;br&gt;
• &lt;code&gt;manage.py&lt;/code&gt; executes various Django commands such as running the local web&lt;br&gt;
server or creating a new app.&lt;/p&gt;

&lt;p&gt;Open the command prompt and run the Django Development Server using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;python manage.py runserver&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This may result something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

April 19, 2020 - 16:20:04
Django version 3.0.5, using settings 'weather_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a message regarding the unapplied migrations. Run &lt;code&gt;migrate&lt;/code&gt; to sync the database with Django’s default settings and reload the local Django web server.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;python manage.py  migrate&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  and&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;python manage.py runserver&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 which results in :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
April 19, 2020 - 16:23:37
Django version 3.0.5, using settings 'weather_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We notice that the message for unapplied migrations has disappeared after running &lt;code&gt;migrate&lt;/code&gt;.&lt;br&gt;
Now, open a web browser to &lt;a href="http://127.0.0.1:8000/"&gt;http://127.0.0.1:8000/&lt;/a&gt; to confirm our project is successfully&lt;br&gt;
installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nRF0V6CJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/HtBsQqq/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nRF0V6CJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/HtBsQqq/image.png" alt="Successful Installation" width="800" height="430"&gt;&lt;/a&gt;&lt;br&gt;
Congrats, pal. You've successfully installed Django on your system.&lt;/p&gt;

&lt;p&gt;In next tutorial, I will be guiding to create an app inside the Django Project.&lt;/p&gt;

</description>
      <category>django</category>
      <category>tutorial</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Locally Host Website using Apache2 Ubuntu Server</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sun, 19 Apr 2020 10:17:33 +0000</pubDate>
      <link>https://dev.to/thearjun/locally-host-website-using-apache2-ubuntu-server-217j</link>
      <guid>https://dev.to/thearjun/locally-host-website-using-apache2-ubuntu-server-217j</guid>
      <description>&lt;p&gt;Hello geeks, In this tutorial I'm guiding you how to host a simple website locally in Apache Web Server in Linux. So, let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Apache
&lt;/h2&gt;

&lt;p&gt;First, let's install Apache from the &lt;code&gt;apt&lt;/code&gt; repository in Linux. Enter the following command on your terminal to install the Apache web server:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 apt install apache2

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

&lt;/div&gt;

&lt;p&gt;After successful installation, here are some commands that may come handy while running Apache web server.&lt;/p&gt;

&lt;p&gt;To start Apache 2, run:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo service apache2 start

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

&lt;/div&gt;

&lt;p&gt;To restart Apache 2, run:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo service apache2 restart

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

&lt;/div&gt;

&lt;p&gt;To stop Apache 2, run:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo service apache2 stop

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

&lt;/div&gt;

&lt;p&gt;To gracefully reload Apache 2, run:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo service apache2 reload

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

&lt;/div&gt;

&lt;p&gt;After starting the Apache Web Server, you may go into any browser and type &lt;code&gt;http://127.0.0.1/&lt;/code&gt; on Address Bar.&lt;br&gt;
The resulting web page looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FMMkFyrt%2Fapachestart.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FMMkFyrt%2Fapachestart.png" alt="Apache2 Start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The web page rendered is the default web page provided by the Apache itself. Now, we'll learn to replace by our website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Website
&lt;/h2&gt;

&lt;p&gt;For maintaining the simplicity, I'm creating a simple web project &lt;code&gt;darkweb&lt;/code&gt; with the following file structure.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

darkweb/
├── css
│   └── style.css
└── index.html

1 directory, 2 files


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

&lt;/div&gt;

&lt;p&gt;Inside &lt;code&gt;index.html&lt;/code&gt; :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE  html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt;  &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Website on Dark Web&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./css/style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;This is my first web site on Dark Web.&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And inside &lt;code&gt;css/style.css&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkslateblue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;which results to form a webpage like :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fd06LjNK%2Fsamplewebsite.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fd06LjNK%2Fsamplewebsite.png" alt="Sample Website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Host Website on Apache Web Server
&lt;/h2&gt;

&lt;p&gt;Going through the default configuration provided by the Apache, we're going to add website we just created to the Apache web server.&lt;/p&gt;

&lt;p&gt;Assuming our web project name is &lt;code&gt;darkweb&lt;/code&gt;, let's move the project to &lt;code&gt;/var/www/html&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo mv darkweb/ /var/www/html

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

&lt;/div&gt;

&lt;p&gt;Now, we've hosted our website on Apache Web Server. To access the website from the Apache, first start the Apache Web Server:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sudo service apache2 start

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

&lt;/div&gt;

&lt;p&gt;And type &lt;code&gt;http://127.0.0.1/darkweb/&lt;/code&gt; on address bar on your browser. Now, you should see the website we just created on the browser. Here, my project name was &lt;code&gt;darkweb&lt;/code&gt;, but the generalized URL for accessing your project is &lt;code&gt;http://127.0.0.1/YOUR_PROJECT_NAME/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After hosting on Apache, the website looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FR0sgStp%2Fresult.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FR0sgStp%2Fresult.png" alt="result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope that now you're able to host website on Apache web server. &lt;/p&gt;

&lt;p&gt;In next tutorial of this series, I'll be guiding you through  how to install SSL certificate on Apache2 Ubuntu Server.&lt;/p&gt;

&lt;p&gt;Till then, &lt;code&gt;keep coding :)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>apache</category>
      <category>hosting</category>
      <category>ubuntu</category>
      <category>website</category>
    </item>
    <item>
      <title>Git 101 - Installation and First Commit</title>
      <dc:creator>Arjun Adhikari</dc:creator>
      <pubDate>Sun, 02 Feb 2020 15:07:25 +0000</pubDate>
      <link>https://dev.to/thearjun/git-101-installation-and-first-commit-23l4</link>
      <guid>https://dev.to/thearjun/git-101-installation-and-first-commit-23l4</guid>
      <description>&lt;p&gt;Imagine you people  are familiar with Microsoft Office, Dropbox and Facebook. Obviously, everyone is.  &lt;/p&gt;

&lt;p&gt;Let's use those as references:&lt;/p&gt;

&lt;p&gt;You know that button in &lt;strong&gt;Microsoft Word&lt;/strong&gt; that says "Edit, Undo"? Git does that but for every change that has ever been made to a project and by any member of your team.&lt;/p&gt;

&lt;p&gt;You know that &lt;strong&gt;Track Changes&lt;/strong&gt; feature in &lt;strong&gt;Word&lt;/strong&gt; with all the red and blue lines showing who changed what? Git does that and it includes comments so you can explain why things were changed.&lt;/p&gt;

&lt;p&gt;You know how &lt;strong&gt;Dropbox&lt;/strong&gt; backs up your files &lt;strong&gt;in the cloud&lt;/strong&gt;, but you still have a local copy on your computer (and maybe your iPhone, too)? GitHub does that for your code.&lt;/p&gt;

&lt;p&gt;You know how &lt;strong&gt;Facebook&lt;/strong&gt; has &lt;strong&gt;Like&lt;/strong&gt; buttons and &lt;strong&gt;threaded comments&lt;/strong&gt; and pictures of your friends and their adventures? While non-programmers find Git to be about as exciting as a fax machine, GitHub makes the process of working with a project through Git feel like using Facebook.&lt;/p&gt;

&lt;p&gt;Now, let's conclude this.&lt;br&gt;
Git is a version control system for tracking changes in files enabling coordination with multiple people working on a project.&lt;/p&gt;

&lt;p&gt;That's how we make software, right ? Coordinating with the people. I feel like it's useful in software development. I'll be checking it. I hope you are following me.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;For &lt;strong&gt;Linux&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apt install git&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Mac&lt;/strong&gt; &lt;em&gt;(with brew)&lt;/em&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brew install git&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;For  &lt;strong&gt;Windows&lt;/strong&gt; :&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Visit&lt;/em&gt; &lt;a href="https://git-scm.com/download/win"&gt;https://git-scm.com/download/win&lt;/a&gt; &lt;em&gt;and download&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the proper demonstration of the Git, I'm creating a directory (folder) named &lt;strong&gt;learning-git&lt;/strong&gt;.  I am assuming this folder as my project folder where I will be working on.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ReJPYTC1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/tDwFDPq/Screenshot-from-2020-02-02-20-01-13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ReJPYTC1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/tDwFDPq/Screenshot-from-2020-02-02-20-01-13.png" alt="Folder Creation" width="770" height="518"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now I'm opening the folder we created,  on the Terminal or  Command Prompt. I am assuming you're familiar with basic Terminal commands.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd learning-git&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now we are on the folder root we just created. Let's initialize our folder as a &lt;strong&gt;Git Project&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git init&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
         &lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;techy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/workspace/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;
         &lt;span class="nx"&gt;Initialized&lt;/span&gt; &lt;span class="nx"&gt;empty&lt;/span&gt; &lt;span class="nx"&gt;Git&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sr"&gt;/home/&lt;/span&gt;&lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt; Now I'm creating a file name hello_world.c to work on.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;touch hello_world.c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This command creates a file on Linux Based systems. I am assuming you can create file on Windows OS too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let's write some code on the file hello_world.c we recently created.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;        &lt;span class="cp"&gt;#include&lt;/span&gt;  &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="mi"&gt;0&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;ul&gt;
&lt;li&gt;Now, I am checking does writing some code on the file results to some changes in Git Project or not. For this, I am checking the &lt;strong&gt;status&lt;/strong&gt; of the Git Project.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
        &lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;techy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/workspace/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;
        &lt;span class="nx"&gt;On&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt; &lt;span class="nx"&gt;master&lt;/span&gt;

        &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="nx"&gt;yet&lt;/span&gt;

        &lt;span class="nx"&gt;Untracked&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git add &amp;lt;file&amp;gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;what&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;committed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="nx"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;

        &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;added&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="nx"&gt;but&lt;/span&gt; &lt;span class="nx"&gt;untracked&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="nf"&gt;present &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;track&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;We can observe that Git System is labelling our file as &lt;strong&gt;untracked&lt;/strong&gt;. Let's keep the file on track by &lt;strong&gt;add&lt;/strong&gt;ing.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git add hello_world.c&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; In Git, every update needs to be committed with a message. This helps us in recognizing the changes we made. So,  let's &lt;strong&gt;commit&lt;/strong&gt; the file with a message we added earlier.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git commit -m " This is the first program I wrote. "&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
        &lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;techy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/workspace/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; This is the first program I wrote. &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;master &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;170953&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;wrote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="nf"&gt;insertions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt; &lt;span class="mi"&gt;100644&lt;/span&gt; &lt;span class="nx"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Let's check the status of the project I'm working on.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git status&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;        &lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;techy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/workspace/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;
        &lt;span class="nx"&gt;On&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt; &lt;span class="nx"&gt;master&lt;/span&gt;
        &lt;span class="nx"&gt;nothing&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;working&lt;/span&gt; &lt;span class="nx"&gt;tree&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Now I want to see what &lt;strong&gt;series of changes&lt;/strong&gt; &lt;em&gt;(log)&lt;/em&gt; I have made. Don't get intimidated, it's not mathematical log.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;git log&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

        &lt;span class="nx"&gt;arjun&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;techy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;/workspace/&lt;/span&gt;&lt;span class="nx"&gt;learning&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;git$&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;
        &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="mi"&gt;170953&lt;/span&gt;&lt;span class="nf"&gt;be4e6fb8f1acdebe6c7c0bd6b897c839ca &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;HEAD&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;master&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;thearjun&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;mailarjunadhikari&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;gmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nx"&gt;Sun&lt;/span&gt; &lt;span class="nx"&gt;Feb&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0545&lt;/span&gt;

             &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;wrote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Looks like we've learned how to add files on the Git System. I am practising what I've learnt on projects. I hope you're doing the same.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will be back with next part of the series.&lt;br&gt;&lt;br&gt;
You can explore more on my GitHub repository to feed your curiosity.&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/theArjun"&gt;
        theArjun
      &lt;/a&gt; / &lt;a href="https://github.com/theArjun/cheatsheet"&gt;
        cheatsheet
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Contains cheatsheets and slides frequently used for development purposes.
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Till then, &lt;code&gt;happy coding :)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>commit</category>
      <category>install</category>
    </item>
  </channel>
</rss>
