<?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: Akanni Modupe Adegoke</title>
    <description>The latest articles on DEV Community by Akanni Modupe Adegoke (@goke).</description>
    <link>https://dev.to/goke</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%2F1064555%2Fcfbe58e1-d1a8-49a3-a7ac-518f32d203eb.jpg</url>
      <title>DEV Community: Akanni Modupe Adegoke</title>
      <link>https://dev.to/goke</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/goke"/>
    <language>en</language>
    <item>
      <title>Securing Your Flask Application: Hashing Passwords Tutorial</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Fri, 26 May 2023 21:48:59 +0000</pubDate>
      <link>https://dev.to/goke/securing-your-flask-application-hashing-passwords-tutorial-2f0p</link>
      <guid>https://dev.to/goke/securing-your-flask-application-hashing-passwords-tutorial-2f0p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction:&lt;/strong&gt;&lt;br&gt;
In this tutorial, we will explore an important aspect of Flask application security: hashing passwords. Storing passwords securely is crucial to protect user accounts and sensitive information. We'll walk through the process of hashing passwords using the Werkzeug security module in Flask, ensuring that even if your application's database is compromised, passwords remain secure. By the end of this tutorial, you'll have a strong understanding of how to implement password hashing in your Flask application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of Contents:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why Password Hashing?&lt;/li&gt;
&lt;li&gt;Setting Up the Flask Application&lt;/li&gt;
&lt;li&gt;Installing Dependencies&lt;/li&gt;
&lt;li&gt;Creating a User Model&lt;/li&gt;
&lt;li&gt;Implementing Password Hashing&lt;/li&gt;
&lt;li&gt;Authenticating Users&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Section 1: Why Password Hashing?&lt;/strong&gt;&lt;br&gt;
In this section, we'll discuss the importance of password hashing and why it's necessary to protect user passwords in your Flask application. Storing passwords securely is crucial to safeguard user accounts and sensitive information.&lt;/p&gt;

&lt;p&gt;When users create an account on your application, they typically provide a password that grants them access to their account. Storing these passwords in plain text format is highly risky because if an attacker gains unauthorized access to your application's database, they can easily retrieve and exploit these passwords.&lt;/p&gt;

&lt;p&gt;To mitigate this risk, it's crucial to use password hashing. Password hashing is a cryptographic technique that converts a plain text password into an irreversible string of characters, known as a hash. This hash is stored in the database instead of the plain text password. When a user attempts to log in, their entered password is hashed and compared against the stored hash. If the hashes match, the password is considered valid.&lt;/p&gt;

&lt;p&gt;By using password hashing, even if an attacker gains access to the database, they won't be able to retrieve the original passwords. Instead, they would only have access to the hashed passwords, which are computationally infeasible to reverse-engineer back to their original plain text form.&lt;/p&gt;

&lt;p&gt;Flask provides a convenient way to implement password hashing through the Werkzeug security module, which offers robust hashing algorithms and methods for password storage and verification.&lt;/p&gt;

&lt;p&gt;In the following sections, we'll explore how to incorporate password hashing into a Flask application and demonstrate best practices for securing user passwords.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 2: Setting Up the Flask Application&lt;/strong&gt;&lt;br&gt;
Before diving into password hashing, we need to set up a basic Flask application structure. This section will guide you through the process of creating the necessary files and directories for your Flask application.&lt;/p&gt;

&lt;p&gt;Start by creating a new directory for your project. Inside that directory, create a virtual environment to isolate your application's dependencies. Activate the virtual environment, and then install Flask 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;$ mkdir flask-app
$ cd flask-app
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install Flask

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

&lt;/div&gt;



&lt;p&gt;Next, create a new Python file named app.py in your project directory. This file will serve as the entry point for your Flask application. Open app.py in a text editor and add the following code to set up a basic Flask application:&lt;br&gt;
&lt;/p&gt;

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

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

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

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

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

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we import the Flask class from the flask module and create a new instance of it. We define a route for the root URL '/' and return a simple HTML template using the render_template function.&lt;/p&gt;

&lt;p&gt;Now, let's create the templates directory and an index.html file inside it. In the templates directory, create a new file named index.html and add some basic HTML content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Flask Application&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to My Flask Application&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;With this basic setup, you have a functioning Flask application that displays a welcome message on the home page. You can run the application by executing the app.py file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ python app.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open your web browser and visit &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; to see the application in action.&lt;/p&gt;

&lt;p&gt;In the next section, we'll install the necessary dependencies for password hashing and user authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 3: Installing Dependencies&lt;/strong&gt;&lt;br&gt;
To implement password hashing and user authentication in Flask, we need to install a few dependencies. Apart from Flask itself, we'll install Flask-WTF for form handling and Flask-SQLAlchemy for working with databases.&lt;/p&gt;

&lt;p&gt;Activate your virtual environment if it's not already active. In your terminal, run the following commands to install the required dependencies:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ pip install Flask-WTF Flask-SQLAlchemy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These commands will install Flask-WTF and Flask-SQLAlchemy along with their respective dependencies. Flask-WTF provides us with convenient form handling and validation capabilities, while Flask-SQLAlchemy allows us to interact with databases using an Object-Relational Mapping (ORM) approach.&lt;/p&gt;

&lt;p&gt;With the dependencies installed, we're now ready to proceed with creating the User model and implementing password hashing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 4: Creating a User Model&lt;/strong&gt;&lt;br&gt;
In this section, we'll define a User model using SQLAlchemy, which will represent users in our application. The User model will have attributes such as username, email, and password. By utilizing SQLAlchemy, we can interact with the database using Python objects.&lt;/p&gt;

&lt;p&gt;Create a new file named models.py in your project directory. This file will contain the User model definition. Open models.py in a text editor and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SQLAlchemy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;werkzeug.security&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;generate_password_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check_password_hash&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SQLAlchemy&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;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&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;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&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="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;nullable&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&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;nullable&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;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_password&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;password&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;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_password_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&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;check_password&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;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;check_password_hash&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;password_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we import the SQLAlchemy class from flask_sqlalchemy and the generate_password_hash and check_password_hash functions from werkzeug.security. We create an instance of SQLAlchemy named db.&lt;/p&gt;

&lt;p&gt;The User class represents the User model in our application. It inherits from db.Model, which is the base class provided by SQLAlchemy for defining database models. Inside the User class, we define the following attributes:&lt;/p&gt;

&lt;p&gt;id: An integer field representing the user's ID, with the primary_key=True parameter indicating that it serves as the primary key for the table.&lt;br&gt;
username: A string field representing the user's username. We set unique=True to ensure that each username is unique in the database.&lt;br&gt;
email: A string field representing the user's email address. Similar to username, we set unique=True to enforce uniqueness.&lt;br&gt;
password_hash: A string field representing the hashed password. We store the hashed password in the database instead of the plain text password.&lt;br&gt;
We define two methods inside the User class:&lt;/p&gt;

&lt;p&gt;set_password(self, password): This method takes a plain text password as input and uses generate_password_hash from Werkzeug to hash the password and store the resulting hash in the password_hash attribute.&lt;br&gt;
check_password(self, password): This method takes a plain text password as input and compares it with the stored hashed password using check_password_hash from Werkzeug. It returns True if the passwords match, indicating that the entered password is valid.&lt;br&gt;
By creating the User model and incorporating password hashing functionality, we've established the foundation for secure user authentication in our Flask application. In the next section, we'll implement the user registration functionality, allowing users to create accounts and store their hashed passwords securely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 5: Implementing Password Hashing&lt;/strong&gt;&lt;br&gt;
In this section, we'll focus on implementing password hashing using the Werkzeug security module. We'll explain the concepts of salt and hashing algorithms and demonstrate how to generate secure password hashes.&lt;/p&gt;

&lt;p&gt;Werkzeug provides a generate_password_hash function that takes a plain text password as input and returns a securely hashed password. It uses a random salt, which adds an extra layer of security by ensuring that even if two users have the same password, their hashes will be different.&lt;/p&gt;

&lt;p&gt;To incorporate password hashing into our registration process, we need to update our Flask routes and forms. Let's start by modifying the app.py file.&lt;/p&gt;

&lt;p&gt;Open app.py in a text editor and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_wtf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlaskForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wtforms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SubmitField&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wtforms.validators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataRequired&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;EqualTo&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;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-secret-key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SQLALCHEMY_DATABASE_URI&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sqlite:///app.db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlaskForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;confirm_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Confirm Password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nc"&gt;EqualTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SubmitField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Register&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&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;GET&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;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&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="nc"&gt;RegistrationForm&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;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_on_submit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&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;data&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;

        &lt;span class="c1"&gt;# Create a new user and set their password
&lt;/span&gt;        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Add the user to the database
&lt;/span&gt;        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="sh"&gt;'&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;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we import additional modules required for form handling and validation: FlaskForm, StringField, PasswordField, SubmitField, and various validators from wtforms. We also import the redirect and url_for functions from Flask to handle redirects.&lt;/p&gt;

&lt;p&gt;We define a new RegistrationForm class, which inherits from FlaskForm. Inside the class, we define fields for username, email, password, and confirm_password. Each field is associated with a corresponding label and validators to ensure the form inputs meet certain requirements.&lt;/p&gt;

&lt;p&gt;Inside the index route, we create an instance of the RegistrationForm and pass it to the template. If the form is submitted and passes the validation checks, we retrieve the form data (username, email, and password), create a new user instance, and set their password using the set_password method we defined earlier. We then add the user to the database using SQLAlchemy's session and commit the changes.&lt;/p&gt;

&lt;p&gt;Now that we've updated the routes and forms, let's make a few modifications to the User model in models.py to support the changes we made:&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;# ...
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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="c1"&gt;# ...
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&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;username&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;username&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;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;

    &lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we've added an &lt;strong&gt;init&lt;/strong&gt; method to the User class to initialize the username and email attributes when creating a new user instance.&lt;/p&gt;

&lt;p&gt;With these changes in place, our registration process now securely hashes the user's password before storing it in the database. However, we still need to implement user authentication to verify the entered password during the login process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 6: Authenticating Users&lt;/strong&gt;&lt;br&gt;
In this section, we'll focus on user authentication, allowing users to log in using their registered credentials. We'll verify the entered password by comparing it with the hashed password stored in the database.&lt;/p&gt;

&lt;p&gt;Let's update the app.py file to add the login functionality.&lt;/p&gt;

&lt;p&gt;Open app.py in a text editor and update it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask_wtf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlaskForm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wtforms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SubmitField&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;wtforms.validators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Email&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;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SECRET_KEY&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-secret-key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SQLALCHEMY_DATABASE_URI&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sqlite:///app.db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlaskForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FlaskForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PasswordField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;DataRequired&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;
    &lt;span class="n"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SubmitField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&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;GET&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;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/login&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&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;GET&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;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&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="nc"&gt;LoginForm&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;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_on_submit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
        &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;

        &lt;span class="c1"&gt;# Retrieve the user from the database
&lt;/span&gt;        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&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;user&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Logged in successfully!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Invalid username or password.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;login.html&lt;/span&gt;&lt;span class="sh"&gt;'&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;form&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we've defined a new LoginForm class, similar to the RegistrationForm class. It contains fields for username, password, and a submit button.&lt;/p&gt;

&lt;p&gt;Inside the /login route, we create an instance of the LoginForm and pass it to the template. If the form is submitted and passes the validation checks, we retrieve the entered username from the form and query the database to find the corresponding user. If the user exists and their password matches the entered password using the check_password method we defined earlier, we display a success message. Otherwise, we display an error message indicating invalid credentials.&lt;/p&gt;

&lt;p&gt;Create a new template file named login.html inside the templates directory. Open login.html in a text editor and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        {{ form.hidden_tag() }}
        &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
            {{ form.username.label }}
            {{ form.username() }}
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
            {{ form.password.label }}
            {{ form.password() }}
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
            {{ form.submit() }}
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/form&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;In the template, we render the form fields and labels using the form..label and form.() syntax.&lt;/p&gt;

&lt;p&gt;With the login functionality in place, users can now authenticate using their registered credentials. We've successfully implemented password hashing and user authentication in our Flask application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 8: Conclusion&lt;/strong&gt;&lt;br&gt;
In this tutorial, we explored the importance of password hashing and learned how to implement it in a Flask application using the Werkzeug security module. We discussed the risks associated with storing plain text passwords and demonstrated how hashing addresses those risks.&lt;/p&gt;

&lt;p&gt;We started by setting up the Flask application, installing the necessary dependencies, and creating a User model using SQLAlchemy. We then implemented password hashing by utilizing the generate_password_hash and check_password_hash functions from Werkzeug. The User model was updated to incorporate the set_password and check_password methods.&lt;/p&gt;

&lt;p&gt;Next, we implemented user registration and authentication functionality. During registration, passwords were securely hashed before storing them in the database. During login, the entered password was compared with the hashed password to verify the user's credentials.&lt;/p&gt;

&lt;p&gt;It's important to note that security is a complex and evolving field, and this tutorial covers only one aspect of securing a Flask application. To ensure comprehensive security, it's crucial to consider other measures such as protection against SQL injection, cross-site scripting (XSS), and other common vulnerabilities.&lt;/p&gt;

&lt;p&gt;Remember to stay updated on the latest security best practices, keep your application's dependencies and libraries up to date, and regularly review and improve your security measures.&lt;/p&gt;

&lt;p&gt;With the knowledge gained from this tutorial, you have a solid foundation for implementing password hashing and user authentication in your Flask application.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>flask</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Best Practices for Writing Clean and Maintainable Code</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Sat, 06 May 2023 21:50:20 +0000</pubDate>
      <link>https://dev.to/goke/best-practices-for-writing-clean-and-maintainable-code-4f4i</link>
      <guid>https://dev.to/goke/best-practices-for-writing-clean-and-maintainable-code-4f4i</guid>
      <description>&lt;p&gt;Writing clean and maintainable code is not just a matter of personal preference; it is a professional responsibility for software engineers. Clean code is easier to understand, debug, and enhance, leading to improved productivity and reduced maintenance costs. In this article, we will explore some best practices and guidelines that can help you write clean and maintainable code, regardless of the programming language or technology stack you're using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent Code Formatting:&lt;/strong&gt;&lt;br&gt;
Consistency in code formatting is crucial for readability and maintainability. Adopt a coding style guide and adhere to it throughout your project. Consistent indentation, proper spacing, and naming conventions make the code more readable and easier to navigate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modular and DRY (Don't Repeat Yourself) Code:&lt;/strong&gt;&lt;br&gt;
Breaking down your code into small, reusable modules promotes reusability and enhances maintainability. Avoid duplicating code by extracting common functionalities into separate functions or classes. This not only reduces code redundancy but also makes it easier to update or fix issues in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meaningful Variable and Function Names:&lt;/strong&gt;&lt;br&gt;
Choose descriptive names for your variables, functions, and classes. Avoid single-letter or cryptic names that may confuse other developers or even yourself in the future. Well-named entities make the code self-explanatory and eliminate the need for excessive comments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commenting and Documentation:&lt;/strong&gt;&lt;br&gt;
While clean code should be self-explanatory, there are cases where comments are necessary. Document complex algorithms, important decisions, and any code that might be unclear to other developers. However, use comments sparingly, focusing on the "why" rather than the "how."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proper Error Handling:&lt;/strong&gt;&lt;br&gt;
Handle errors and exceptions gracefully. Use appropriate try-catch blocks to catch and handle exceptions effectively. Avoid catching and suppressing exceptions without proper handling, as it can lead to hidden bugs and make troubleshooting difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit Testing:&lt;/strong&gt;&lt;br&gt;
Adopt a test-driven development (TDD) approach and write unit tests for your code. Unit tests help ensure that your code behaves as expected and can be easily maintained when changes are made. Good test coverage provides confidence in code modifications and helps catch regressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modular and Independent Components:&lt;/strong&gt;&lt;br&gt;
Strive for loose coupling and high cohesion in your codebase. Develop small, independent components that perform a single responsibility. This not only improves code organization but also enables easier testing, reuse, and modification of individual parts without affecting the entire system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version Control and Collaboration:&lt;/strong&gt;&lt;br&gt;
Utilize a version control system, such as Git, to track changes and collaborate effectively with other developers. Follow branching and merging best practices to maintain a clean and manageable codebase. Commit often and write meaningful commit messages to document changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Continuous Integration and Delivery:&lt;/strong&gt;&lt;br&gt;
Implement continuous integration and continuous delivery (CI/CD) practices to automate code builds, testing, and deployment. This ensures that the codebase remains clean and stable, reducing the chances of introducing bugs and enabling faster and more reliable releases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refactoring:&lt;/strong&gt;&lt;br&gt;
Regularly review and refactor your code to improve its quality and maintainability. Refactoring involves restructuring code without changing its external behavior, eliminating code smells, and improving overall design. It helps keep the codebase clean, readable, and adaptable to changing requirements.&lt;/p&gt;

&lt;p&gt;Writing clean and maintainable code is a crucial skill for software engineers. By following best practices like consistent formatting, modularization, meaningful naming, proper documentation, and thorough testing, you can enhance the readability, maintainability, and overall quality of your code. Embrace these practices, and your codebase will become more efficient, bug-free, and easier to work with, enabling you and your team to deliver exceptional software products.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Beginner's Guide to Radix Sort: Step-by-Step Guide and Python Code</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Thu, 20 Apr 2023 05:47:42 +0000</pubDate>
      <link>https://dev.to/goke/a-beginners-guide-to-radix-sort-step-by-step-guide-and-python-code-2fa5</link>
      <guid>https://dev.to/goke/a-beginners-guide-to-radix-sort-step-by-step-guide-and-python-code-2fa5</guid>
      <description>&lt;p&gt;Sorting is an essential task in computer science, and there are many sorting algorithms available, each with its advantages and disadvantages. One of the most efficient and straightforward sorting algorithms is the Radix Sort. In this article, we will explore how Radix Sort works, step-by-step, and provide Python code examples to implement it.&lt;/p&gt;

&lt;p&gt;How Radix Sort Works&lt;br&gt;
Radix Sort is a non-comparative, stable, and linear-time sorting algorithm that sorts data by grouping elements based on their significant digits or characters. It sorts the data by sorting each digit or character of the element individually, from the least significant digit to the most significant digit.&lt;/p&gt;

&lt;p&gt;Let's take an example of sorting the following list of integers using Radix Sort:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[170, 45, 75, 90, 802, 24, 2, 66]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Determine the maximum number of digits in the list and pad the elements with zeroes if necessary. In our example, the maximum number of digits is three, so we will pad the elements with zeroes to make them all three digits long:&lt;br&gt;
&lt;code&gt;[170, 045, 075, 090, 802, 024, 002, 066]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sort the list by the least significant digit (i.e., the rightmost digit). Create ten buckets (0-9) and place each element in the bucket corresponding to its digit. For example, 170, 090, and 802 have a 0 in the rightmost digit, so they will be placed in bucket 0. The list after this step will look like this:&lt;br&gt;
&lt;code&gt;[802, 002, 024, 045, 075, 066, 170, 090]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Concatenate the buckets in order, starting with bucket 0 and ending with bucket 9. The list after this step will look like this:&lt;br&gt;
&lt;code&gt;[802, 002, 024, 045, 075, 066, 170, 090]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Repeat steps 2 and 3 for the next significant digit (i.e., the second digit from the right), and continue until all the digits have been sorted. The final sorted list will be:&lt;br&gt;
&lt;code&gt;[002, 024, 045, 066, 075, 090, 170, 802]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Python Code for Radix Sort&lt;br&gt;
Now that we understand how Radix Sort works let's implement it in Python. Here is the Python code for Radix Sort:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;radix_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Determine the maximum number of digits
&lt;/span&gt;    &lt;span class="n"&gt;max_digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

    &lt;span class="c1"&gt;# Pad the elements with zeroes if necessary
&lt;/span&gt;    &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&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;num&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;zfill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_digit&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;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Sort the list by each digit
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_digit&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="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="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;buckets&lt;/span&gt; &lt;span class="o"&gt;=&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;buckets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buckets&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Convert the elements back to integers
&lt;/span&gt;    &lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&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;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nums&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;nums&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The code takes a list of integers as input and returns the sorted list using Radix Sort. It starts by determining the maximum number of digits in the list and pads the elements with zeroes if necessary. It then sorts the list by each digit, starting with the most significant digit, using the same steps we discussed earlier.&lt;/p&gt;

&lt;p&gt;In addition to its simplicity and efficiency, one of the significant advantages of Radix Sort is its time complexity. The time complexity of Radix Sort is O(nk), where n is the number of elements to be sorted, and k is the maximum number of digits or characters in an element. This makes Radix Sort an efficient sorting algorithm for large datasets.&lt;/p&gt;

&lt;p&gt;To see why the time complexity of Radix Sort is O(nk), let's consider the following:&lt;/p&gt;

&lt;p&gt;In step 1, we need to determine the maximum number of digits or characters in the elements, which takes O(n) time.&lt;br&gt;
In step 2, we need to iterate through each digit or character in each element, which takes O(kn) time.&lt;br&gt;
In step 3, we need to concatenate the buckets, which takes O(n) time.&lt;br&gt;
We repeat steps 2 and 3 for each digit or character in the elements, which takes O(kn) time.&lt;br&gt;
Therefore, the total time complexity of Radix Sort is O(nk).&lt;/p&gt;

&lt;p&gt;In conclusion, Radix Sort is a simple, efficient, and stable sorting algorithm that sorts data by grouping elements based on their significant digits or characters. With its time complexity of O(nk), it is an excellent choice for sorting large datasets. The Python code we provided in this article can be easily adapted to sort different types of data, including strings and tuples. By understanding how Radix Sort works and its time complexity, you can apply it to real-world scenarios and improve the performance of your applications.&lt;/p&gt;

</description>
      <category>python</category>
      <category>dsa</category>
      <category>algorithms</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Contribution to Open Source: A Technical Guide</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Fri, 14 Apr 2023 07:05:35 +0000</pubDate>
      <link>https://dev.to/goke/contribution-to-open-source-a-technical-guide-4kpk</link>
      <guid>https://dev.to/goke/contribution-to-open-source-a-technical-guide-4kpk</guid>
      <description>&lt;p&gt;Open source software has become a vital part of the modern technology landscape, with developers worldwide collaborating to create and improve software that is freely available to everyone. Contributing to open source projects is not only a great way to give back to the community but also an excellent opportunity to enhance your skills and network with other developers.&lt;/p&gt;

&lt;p&gt;In this technical guide, we will discuss the basics of contributing to open source software and provide some tips for getting started.&lt;/p&gt;

&lt;p&gt;Finding a Project&lt;br&gt;
The first step to contributing to open source is to find a project that interests you. There are many open source projects available on platforms like GitHub, GitLab, and Bitbucket. You can start by searching for projects related to your area of expertise or interest.&lt;/p&gt;

&lt;p&gt;It's also essential to consider the project's popularity and activity level before deciding to contribute. Projects with a large community of developers are generally more active and have a better chance of accepting your contributions.&lt;/p&gt;

&lt;p&gt;Understanding the Project&lt;br&gt;
Before contributing to a project, it's crucial to understand the project's goals, structure, and codebase. Start by reading the project's documentation, including its README file, CONTRIBUTING.md file, and code of conduct.&lt;/p&gt;

&lt;p&gt;You can also explore the project's codebase by browsing its source code, issue tracker, and pull request history. Understanding the project's structure and codebase will help you identify areas where you can contribute.&lt;/p&gt;

&lt;p&gt;Contributing to the Project&lt;br&gt;
Once you have identified a project and understood its structure, you can start contributing. There are many ways to contribute to open source projects, including:&lt;/p&gt;

&lt;p&gt;Reporting issues: If you find a bug or have an idea for a new feature, you can report it by creating an issue on the project's issue tracker.&lt;/p&gt;

&lt;p&gt;Fixing issues: If you have the skills to fix a reported issue, you can create a pull request with your proposed changes.&lt;/p&gt;

&lt;p&gt;Adding new features: If you have an idea for a new feature, you can create a pull request with your proposed changes.&lt;/p&gt;

&lt;p&gt;Improving documentation: If you find errors or inconsistencies in the project's documentation, you can submit a pull request to fix them.&lt;/p&gt;

&lt;p&gt;It's important to follow the project's guidelines for contributing, including its code style, testing requirements, and submission process.&lt;/p&gt;

&lt;p&gt;Interacting with the Community&lt;br&gt;
Contributing to open source is not just about writing code. It's also about engaging with the project's community of developers. You can interact with the community by:&lt;/p&gt;

&lt;p&gt;Asking for help: If you have questions about the project, you can ask for help on the project's issue tracker or discussion forum.&lt;/p&gt;

&lt;p&gt;Providing feedback: If you have used the project, you can provide feedback to the developers to help improve the project.&lt;/p&gt;

&lt;p&gt;Reviewing code: You can review other developers' pull requests to help ensure the code meets the project's standards.&lt;/p&gt;

&lt;p&gt;Participating in discussions: You can participate in the project's discussions and share your ideas and opinions.&lt;/p&gt;

&lt;p&gt;Benefits of Contributing to Open Source&lt;br&gt;
Contributing to open source has many benefits, including:&lt;/p&gt;

&lt;p&gt;Enhancing your skills: Contributing to open source projects can help you enhance your skills in programming, testing, and collaboration.&lt;/p&gt;

&lt;p&gt;Building your portfolio: Contributing to open source projects can help you build your portfolio of work and demonstrate your skills to potential employers.&lt;/p&gt;

&lt;p&gt;Networking with other developers: Contributing to open source projects can help you network with other developers in your field.&lt;/p&gt;

&lt;p&gt;Giving back to the community: Contributing to open source projects is a way to give back to the community and help improve software that is freely available to everyone.&lt;/p&gt;

&lt;p&gt;Contributing to open source software is a rewarding experience that offers numerous benefits for developers. By following the steps outlined in this technical guide, you can find a project that interests you, understand the project's goals and structure, contribute to the project in meaningful ways, and engage with the project's community of developers. Whether you are looking to enhance your skills, build your portfolio, or give back to the community, contributing to open source is an excellent way to achieve these goals while making a positive impact on the world of software development.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>The Importance of Python in Software Engineering: A Versatile and Efficient Tool</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Thu, 13 Apr 2023 23:36:38 +0000</pubDate>
      <link>https://dev.to/goke/the-importance-of-python-in-software-engineering-a-versatile-and-efficient-tool-4cli</link>
      <guid>https://dev.to/goke/the-importance-of-python-in-software-engineering-a-versatile-and-efficient-tool-4cli</guid>
      <description>&lt;p&gt;Python is a general-purpose programming language that has gained immense popularity over the years. It is a powerful tool for software engineering and has become an essential language for developers in various fields, from web development to scientific computing. Python’s popularity in software engineering is due to its simple and readable syntax, easy-to-learn nature, and extensive range of libraries and frameworks. In this blog post, we will discuss the importance of Python in software engineering.&lt;/p&gt;

&lt;p&gt;Easy to learn and use&lt;br&gt;
Python is an easy-to-learn language, making it an excellent language for beginners to learn. The syntax of Python is simple and readable, making it easy for developers to understand and write code. This makes it an ideal language for rapid prototyping and testing, making it easier for developers to iterate and improve their software.&lt;/p&gt;

&lt;p&gt;Large Community and Support&lt;br&gt;
Python has one of the largest developer communities, with thousands of developers contributing to the language's libraries, frameworks, and tools. The vast community ensures that there are plenty of resources available for developers, making it easier to learn, solve problems and get help when needed.&lt;/p&gt;

&lt;p&gt;Versatile&lt;br&gt;
Python's versatility makes it an excellent language for software engineering. Python can be used for various applications ranging from web development, scientific computing, artificial intelligence, and machine learning. Python's extensive range of libraries and frameworks, including Flask, Django, Numpy, and Pandas, makes it easier for developers to create sophisticated software applications.&lt;/p&gt;

&lt;p&gt;Time-saving and efficient&lt;br&gt;
Python is a time-saving and efficient language. Python's syntax and built-in libraries allow developers to write code more quickly and efficiently, reducing development time. Python's automation and scripting abilities also make it easier for developers to automate repetitive tasks, making their work easier and more efficient.&lt;/p&gt;

&lt;p&gt;Integration&lt;br&gt;
Python's integration with other languages makes it an excellent choice for software engineering. Python can be integrated with languages like C++ and Java, allowing developers to use the power of both languages in their applications. This integration enables developers to take advantage of Python's ease of use and C++ or Java's performance and scalability.&lt;/p&gt;

&lt;p&gt;In conclusion, Python is an essential language for software engineering. Its easy-to-learn nature, large community and support, versatility, time-saving and efficient properties, and integration capabilities make it an ideal choice for developing complex software applications. Python's popularity continues to grow, and it is expected to become even more popular in the future.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>python</category>
    </item>
    <item>
      <title>Introduction to Python Programming Language</title>
      <dc:creator>Akanni Modupe Adegoke</dc:creator>
      <pubDate>Thu, 13 Apr 2023 23:19:17 +0000</pubDate>
      <link>https://dev.to/goke/introduction-to-python-programming-language-jna</link>
      <guid>https://dev.to/goke/introduction-to-python-programming-language-jna</guid>
      <description>&lt;p&gt;Python is a popular high-level programming language that is widely used for developing various applications. Guido van Rossum created Python in the late 1980s, and it has since become one of the most popular programming languages in the world. Python is an interpreted language, which means that it does not need to be compiled like other programming languages such as C or Java. Instead, Python code is interpreted by an interpreter, which converts the code into machine-readable code that can be executed by the computer.&lt;/p&gt;

&lt;p&gt;Python is known for its simplicity and ease of use, making it an excellent choice for beginners to programming. The language has a clean and readable syntax, making it easy to learn and understand. Python is also an object-oriented language, which means that it is designed to work with objects and classes. This allows developers to organize their code into reusable modules, making it easier to maintain and update.&lt;/p&gt;

&lt;p&gt;One of the strengths of Python is its wide range of libraries and modules that are available for developers to use. These libraries and modules can be used to perform various tasks, such as web development, data analysis, machine learning, and artificial intelligence. Some of the popular Python libraries and modules include NumPy, Pandas, Matplotlib, TensorFlow, and PyTorch.&lt;/p&gt;

&lt;p&gt;Python is also a versatile language that can be used for a wide range of applications, including web development, desktop applications, scientific computing, and game development. Python's versatility is due to its ability to be integrated with other programming languages and technologies, such as JavaScript, HTML, CSS, and SQL. This makes Python an excellent choice for full-stack development.&lt;/p&gt;

&lt;p&gt;In conclusion, Python is a popular and versatile programming language that is widely used for developing various applications. Its simplicity, ease of use, and wide range of libraries and modules make it an excellent choice for beginners to programming and experienced developers alike. With its object-oriented design and ability to integrate with other technologies, Python is an excellent choice for developing a wide range of applications, from web development to scientific computing and game development.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
      <category>python</category>
    </item>
  </channel>
</rss>
