Django Technical Paper
Published: 2023-06-15 13:07:13

###      What is secret key?
A Django secret key is a random string that is used to protect your Django application from security attacks. It is used for a variety of purposes, including:
-   Signing cookies: Cookies are small files that are stored on a user's computer when they visit your website. They can be used to store information about the user, such as their username, password, and session ID. Django uses a secret key to sign cookies, which helps to prevent them from being tampered with.
- -   Generating CSRF tokens: CSRF (Cross-Site Request Forgery) is a type of attack that allows an attacker to trick a user into performing an action on a website without their knowledge or consent. Django uses a secret key to generate CSRF tokens, which are used to protect against CSRF attacks.
- -   Generating password reset tokens: When a user forgets their password, they can request a password reset link to be sent to their email address. This link contains a password reset token, which is used to verify the user's identity and reset their password. Django uses a secret key to generate password reset tokens.
- It is important to keep your Django secret key secret. If it is compromised, an attacker could use it to perform a variety of security attacks on your application. You should never share your Django secret key with anyone, and you should never commit it to version control.
- To generate a Django secret key, you can use the following command:

Code snippet

```
python -c 'import random; print(random.SystemRandom().get_random_bytes(32))'

```
This will generate a 32-character random string. You can then copy and paste this string into your Django settings file.

The Django secret key is a critical part of your Django application's security. By keeping it secret, you can help to protect your application from security attacks.


###   What are the default Django apps inside it? Are there more?
  
Django comes with a number of default apps that are installed when you create a new project. These apps provide basic functionality that is commonly needed in web applications, such as:

-   **Admin:**  A web-based interface for managing your Django project's content, users, and other settings.
-   **Auth:**  A system for authenticating users and managing their permissions.
-   **Contenttypes:**  A system for defining and managing the types of content that can be stored in your Django project.
-   **Sessions:**  A system for tracking user sessions and storing session data.
-   **Messages:**  A system for sending and receiving messages between users.
-   **Staticfiles:**  A system for managing static files, such as images, CSS, and JavaScript.

In addition to the default apps, there are a number of third-party apps that can be installed and used with Django. These apps provide additional functionality, such as:

-   **Django Rest Framework:**  A powerful framework for building RESTful APIs.
-   **Django Channels:**  A framework for building real-time applications.
-   **Django Celery:**  A framework for running asynchronous tasks.
-   **Django South:**  A migration tool for managing changes to your Django project's database schema.
-   **Django Debug Toolbar:**  A powerful tool for debugging Django applications.

The number of default Django apps is subject to change, but there will always be a number of core apps that are included with Django. These apps provide the basic functionality that is needed to build a web application. Third-party apps can be used to add additional functionality to your Django project.

If you are new to Django, I recommend that you start with the default apps. Once you have a basic understanding of how Django works, you can start exploring third-party apps.

###  What is middleware in django? What are different kinds of middleware in django? Read up a little on each security issue?
Middleware in Django is a way to add custom functionality to your Django application. It is a general-purpose framework that allows you to intercept and modify requests and responses before they reach your views. Middleware can be used for a variety of purposes, such as:

-   Authentication and authorization
-   Session management
-   Caching
-   Security
-   Performance optimization

Django includes a number of built-in middleware, such as:

-   AuthenticationMiddleware: This middleware handles authentication for your application.
-   SessionMiddleware: This middleware handles session management for your application.
-   GzipMiddleware: This middleware compresses responses to reduce bandwidth usage.
-   CommonMiddleware: This middleware provides a number of common features, such as error handling and static file serving.

You can also write your own middleware. To do this, you need to create a class that inherits from the `MiddlewareMixin` class. Your class must define the `process_request()` and `process_response()` methods. The `process_request()` method is called before the request is passed to your views, and the `process_response()` method is called after the response is generated by your views.

Here are some of the security issues that can be addressed with middleware:

-   Cross-site request forgery (CSRF): CSRF is a type of attack where an attacker tricks a user into submitting a form to your application without their knowledge. This can be used to perform actions on behalf of the user, such as transferring money out of their account or making a purchase.
-   Cross-site scripting (XSS): XSS is a type of attack where an attacker injects malicious code into a web page that is viewed by a user. This malicious code can then be executed on the user's computer, potentially stealing their cookies or other sensitive information.
-   Session fixation: Session fixation is a type of attack where an attacker tricks a user into using a session ID that the attacker has chosen. This allows the attacker to take control of the user's session and perform actions on their behalf.

Middleware can be used to mitigate these security risks by checking requests for malicious content, enforcing authentication, and managing sessions securely.

Here are some examples of how middleware can be used to improve security:

-   The  `CSRFMiddleware`  class checks requests for the presence of a CSRF token. If the token is not present or is invalid, the request is rejected.
-   The  `XSSMiddleware`  class scans responses for malicious code. If any malicious code is found, it is replaced with harmless text.
-   The  `SessionMiddleware`  class ensures that sessions are created securely and that session IDs are not exposed to users.

By using middleware, you can add additional security features to your Django application and protect your users from a variety of attacks.

## Cross site request forgery (CSRF) 

CSRF attacks allow a malicious user to execute actions using the credentials of another user without that user’s knowledge or consent.

Django has built-in protection against most types of CSRF attacks, providing you have  [enabled and used it](https://docs.djangoproject.com/en/4.0/ref/csrf/#using-csrf)  where appropriate. However, as with any mitigation technique, there are limitations. For example, it is possible to disable the CSRF module globally or for particular views. You should only do this if you know what you are doing. There are other  [limitations](https://docs.djangoproject.com/en/4.0/ref/csrf/#csrf-limitations)  if your site has subdomains that are outside of your control.

[CSRF protection works](https://docs.djangoproject.com/en/4.0/ref/csrf/#how-csrf-works)  by checking for a secret in each POST request. This ensures that a malicious user cannot “replay” a form POST to your website and have another logged in user unwittingly submit that form. The malicious user would have to know the secret, which is user specific (using a cookie).

When deployed with  [HTTPS](https://docs.djangoproject.com/en/4.0/topics/security/#security-recommendation-ssl),  `CsrfViewMiddleware`  will check that the HTTP referer header is set to a URL on the same origin (including subdomain and port). Because HTTPS provides additional security, it is imperative to ensure connections use HTTPS where it is available by forwarding insecure connection requests and using HSTS for supported browsers.

Be very careful with marking views with the  `csrf_exempt`  decorator unless it is absolutely necessary.

## SQL injection protection

SQL injection is a type of attack where a malicious user is able to execute arbitrary SQL code on a database. This can result in records being deleted or data leakage.

Django’s querysets are protected from SQL injection since their queries are constructed using query parameterization. A query’s SQL code is defined separately from the query’s parameters. Since parameters may be user-provided and therefore unsafe, they are escaped by the underlying database driver.

Django also gives developers power to write  [raw queries](https://docs.djangoproject.com/en/4.0/topics/db/sql/#executing-raw-queries)  or execute  [custom sql](https://docs.djangoproject.com/en/4.0/topics/db/sql/#executing-custom-sql). These capabilities should be used sparingly and you should always be careful to properly escape any parameters that the user can control. In addition, you should exercise caution when using  [`extra()`](https://docs.djangoproject.com/en/4.0/ref/models/querysets/#django.db.models.query.QuerySet.extra "django.db.models.query.QuerySet.extra")  and  [`RawSQL`](https://docs.djangoproject.com/en/4.0/ref/models/expressions/#django.db.models.expressions.RawSQL "django.db.models.expressions.RawSQL").

## Clickjacking protection:
Clickjacking is a type of attack where a malicious site wraps another site in a frame. This attack can result in an unsuspecting user being tricked into performing unintended actions on the target site.

Django contains  [clickjacking protection](https://docs.djangoproject.com/en/4.0/ref/clickjacking/#clickjacking-prevention)  in the form of the  [`X-Frame-Options  middleware`](https://docs.djangoproject.com/en/4.0/ref/middleware/#django.middleware.clickjacking.XFrameOptionsMiddleware "django.middleware.clickjacking.XFrameOptionsMiddleware")  which in a supporting browser can prevent a site from being rendered inside a frame. It is possible to disable the protection on a per view basis or to configure the exact header value sent.

The middleware is strongly recommended for any site that does not need to have its pages wrapped in a frame by third party sites, or only needs to allow that for a small section of the site.

# Gateways in Django:
  
WSGI and ASGI are both Python web application programming interfaces (APIs) that allow you to create web applications using Python. WSGI was the first widely adopted API for Python web applications, and it is still in use today. ASGI is a newer API that is designed to be more efficient and scalable than WSGI.

**WSGI**

WSGI stands for Web Server Gateway Interface. It is a specification that defines how a web server communicates with a Python web application. WSGI applications are typically written as a set of functions that handle requests and return responses. The web server calls these functions in response to incoming requests.

WSGI is a synchronous API, which means that the web server blocks while it is waiting for the Python application to return a response. This can lead to performance problems in applications that handle a lot of concurrent requests.

**ASGI**

ASGI stands for Asynchronous Server Gateway Interface. It is a newer API that is designed to be more efficient and scalable than WSGI. ASGI applications are typically written using asynchronous programming techniques. This allows the web server to continue handling other requests while the Python application is processing a request.

ASGI is a more flexible API than WSGI. It supports a wider range of web servers and Python web frameworks. ASGI is also more future-proof than WSGI. It is designed to support new technologies, such as WebSockets.

**Django**

Django is a popular Python web framework. Django supports both WSGI and ASGI. Django applications that use WSGI are typically deployed using a web server such as Gunicorn or uWSGI. Django applications that use ASGI are typically deployed using a web server such as Daphne or Hypercorn.

**Which API should you use?**

If you are creating a new Python web application, you should use ASGI. ASGI is the more modern API and it offers a number of advantages over WSGI. If you are already using WSGI and you are happy with the performance, you can continue using WSGI. However, if you are experiencing performance problems, you should consider migrating your application to ASGI.

Here is a table that summarizes the key differences between WSGI and ASGI


###  What is ondelete Cascade in models in django?
The `on_delete` option in Django's `models.py` file is used to specify what should happen to a model instance when the model instance that it is related to is deleted. The `on_delete` option can be set to one of the following values:

-   `CASCADE`: When the parent model instance is deleted, all of the child model instances that are related to it will also be deleted.
-   `PROTECT`: When the parent model instance is deleted, the delete operation will be prevented if any child model instances are related to it.
-   `SET_NULL`: When the parent model instance is deleted, the foreign key field in the child model instances will be set to  `NULL`.
-   `SET_DEFAULT`: When the parent model instance is deleted, the foreign key field in the child model instances will be set to the default value.
-   `SET(...)`: When the parent model instance is deleted, the foreign key field in the child model instances will be set to a custom value.

The `on_delete` option is a powerful tool that can be used to maintain the integrity of your database. However, it is important to use it carefully, as it can also lead to data loss if it is not used correctly.

Here is an example of how the `on_delete` option can be used:



```
class Post(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-created_at']

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    author = models.CharField(max_length=255)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True

```

-   **Fields**  are used to store data in your models. They can be used to store simple data types, such as strings and numbers, or more complex data types, such as lists and dictionaries.
-   **Validators**  are used to validate data before it is stored in your models. They can be used to check for things like invalid characters, empty values, and out-of-range values.

Here are some of the most commonly used fields and validators in Django:

-   **CharField**  is used to store a string of text. It has a max_length argument that can be used to limit the length of the string.
-   **TextField**  is used to store a long string of text. It does not have a max_length argument, so there is no limit to the length of the string.
-   **IntegerField**  is used to store an integer value. It has a min and max argument that can be used to limit the range of the integer.
-   **FloatField**  is used to store a floating-point value. It has a min and max argument that can be used to limit the range of the floating-point value.
-   **BooleanField**  is used to store a boolean value. It can be set to True or False.
-   **DateField**  is used to store a date value. It can be set to a specific date or to the current date.
-   **DateTimeField**  is used to store a date and time value. It can be set to a specific date and time or to the current date and time.

Here are some of the most commonly used validators in Django:

-   **MinLengthValidator**  is used to check that the value is not shorter than a certain length.
-   **MaxLengthValidator**  is used to check that the value is not longer than a certain length.
-   **EmailValidator**  is used to check that the value is a valid email address.
-   **URLValidator**  is used to check that the value is a valid URL.
-   **RegexValidator**  is used to check that the value matches a specific regular expression.

You can also write your own custom validators. To do this, you need to create a class that inherits from the `django.core.validators.Validator` class. Your class must define a `validate()` method that takes the value to be validated as its argument.

Fields and validators are a powerful way to ensure that the data in your models is valid. By using them, you can help to prevent errors and make your applications more robust.


###   Understanding the difference between Python module and Python class?
-   **Modules**

A module is a self-contained unit of code that can be imported into another module. Modules are typically used to organize code and to share code between different applications. For example, you might have a module that contains code for performing mathematical operations, and you might have another module that contains code for performing string manipulation operations. You could then import these modules into your application and use the code in them to perform the desired operations.

-   **Classes**

A class is a blueprint for creating objects. Classes define the properties and methods of an object. Properties are data that is associated with an object, and methods are actions that an object can perform. For example, you might have a class that represents a car. The class could define properties such as the car's make, model, and year, and it could define methods such as start_engine, drive, and stop. You could then create objects that are instances of the car class. Each object would have its own set of properties, and it could perform the actions defined by the methods in the class.


### ## Using ORM queries in Django Shell
Sure, you can use ORM queries in the Django shell to interact with your database. The Django shell is a Python interpreter that is pre-loaded with all of the Django models and functions. This makes it easy to write and test ORM queries without having to start a web server.

To use the Django shell, you need to first start it. You can do this by running the following command:

Code snippet

```
python manage.py shell
```

Once the Django shell is started, you can import the models that you want to use. For example, if you have a model called `User`, you would import it like this:

Code snippet

```
from myapp.models import User
```

Once you have imported the models, you can start writing ORM queries. ORM queries are written in Python, and they use the same syntax as SQL queries. For example, the following query will select all of the users from the database:

Code snippet

```
users = User.objects.all(
```
The `users` variable will now contain a list of all of the users in the database. You can then iterate through the list to access the individual users. For example, the following code will print the name of the first user in the list:

Code snippet

```
for user in users:
    print(user.name)
```
You can also use ORM queries to filter and sort the results. For example, the following query will select all of the users who are active:

Code snippet

```
active_users = User.objects.filter(is_active=True)

```
The `active_users` variable will now contain a list of all of the active users in the database. You can also sort the results by any field. For example, the following query will sort the users by their name:

Code snippet

```
sorted_users = User.objects.order_by('name')

```
The `sorted_users` variable will now contain a list of all of the users in the database, sorted by their name.


### ## Turning ORM to SQL in Django Shell

  
Sure, you can turn ORM queries to SQL in the Django shell by using the `.query` attribute. The `.query` attribute returns a `QuerySet` object, which is a representation of the SQL query that will be executed. You can then use the `.sql` method to get the SQL query as a string.

For example, the following code will select all of the users from the database and print the SQL query that will be executed:

Code snippet

```
from myapp.models import User

users = User.objects.all()

query = users.query

print(query.sql)
```

The output of the `print` statement will be the following SQL query:

Code snippet

```
SELECT * FROM users

```
You can also use the `.query` attribute to modify the SQL query before it is executed. For example, the following code will select all of the users who are active and print the SQL query that will be executed:

Code snippet

```
from myapp.models import User

users = User.objects.filter(is_active=True)

query = users.query

print(query.sql)
```

The output of the `print` statement will be the following SQL query:

Code snippet

```
SELECT * FROM users WHERE is_active = 1
```

### ## What are Aggregations in django?
  
Sure, here's what you need to know about Aggregations in Django:

In Django, aggregations are used to perform calculations on data. They can be used to find the total, average, minimum, maximum, or count of data in a QuerySet.

There are a number of different aggregations that can be used in Django. Some of the most common aggregations include:

-   **Count():**  This aggregation returns the number of objects in a QuerySet.
-   **Sum():**  This aggregation returns the sum of the values in a field.
-   **Avg():**  This aggregation returns the average of the values in a field.
-   **Min():**  This aggregation returns the minimum value in a field.
-   **Max():**  This aggregation returns the maximum value in a field.

To use an aggregation, you can use the `aggregate()` method on a QuerySet. The `aggregate()` method takes a dictionary as its argument. The keys of the dictionary are the names of the aggregations that you want to use, and the values of the dictionary are the arguments that you want to pass to the aggregations.

For example, the following code will find the total number of users in the database:

Code snippet

```
from django.db.models import Count

users = User.objects.all()

total_users = users.aggregate(Count('id'))['id__count']

print(total_users)
```

###  What are Annotations in django

Annotations in Django are a way to add additional data to each object in a QuerySet. They are similar to aggregations, but they are applied to each object in the QuerySet, rather than the entire QuerySet as a whole.

To use annotations, you can use the `annotate()` method on a QuerySet. The `annotate()` method takes a dictionary as its argument. The keys of the dictionary are the names of the annotations that you want to use, and the values of the dictionary are the expressions that you want to use to calculate the annotations.

For example, the following code will add a new field called `total_orders` to each user object in the QuerySet:

Code snippet

```
from django.db.models import Count

users = User.objects.all()

users = users.annotate(total_orders=Count('orders'))

for user in users:
    print(user.total_orders)
```

###   What is a migration file? Why is it needed?
Django, a migration file is a Python file that describes the changes that need to be made to a database schema. Migration files are used to keep the database schema in sync with the Django models.

Migration files are needed because Django models are defined in Python, but databases are defined in SQL. Migration files bridge the gap between these two languages by providing a way to describe the changes that need to be made to the database schema in Python.

When you make changes to your Django models, you need to create a new migration file that describes the changes. You can then use the `migrate` command to apply the changes to the database.

Migration files are also used to roll back changes to the database schema. If you make a change to your Django models that you don't like, you can use the `revert` command to roll back the changes to the previous migration.

Migration files are a powerful tool that can help you keep your database schema in sync with your Django models. They are a valuable part of the Django development process.

Here are some of the benefits of using migration files:

-   **They help to keep your database schema in sync with your Django models.**  This can help to prevent errors and data loss.
-   **They make it easy to roll back changes to the database schema.**  This can be helpful if you make a mistake or if you need to revert to a previous version of the database.
-   **They can be used to automate the creation and deployment of database schemas.**  This can save you time and effort.

If you are using Django, I recommend that you use migration files to manage your database schema. They are a valuable tool that can help you to develop and deploy your Django applications more effectively.


###  What are SQL transactions? (non ORM concept)

In SQL, a transaction is a set of operations that are performed together as a unit. Transactions are used to ensure that data is always consistent in the database.

There are four properties of transactions that are known as ACID:

-   **Atomicity:**  All of the operations in a transaction must be completed successfully, or none of them can be completed.
-   **Consistency:**  The database must be in a consistent state before and after the transaction is completed.
-   **Isolation:**  Transactions should not interfere with each other.
-   **Durability:**  Once a transaction is completed, the changes made to the database should be permanent.

Transactions are implemented using locks. A lock is a mechanism that prevents other transactions from accessing data that is being modified by a transaction.

###    What are atomic transactions?
An atomic transaction is a set of database operations that are treated as a single, indivisible unit. This means that either all of the operations in the transaction are performed successfully, or none of them are performed.

Atomicity is one of the four ACID properties of transactions, which also include consistency, isolation, and durability.

Atomicity is important for ensuring the integrity of data in a database. If a transaction is not atomic, it is possible for the database to be left in an inconsistent state. For example, if a transaction withdraws money from one account and deposits it into another, but the withdrawal fails, the account from which the money was withdrawn will be left with less money than it had before.

Atomic transactions are implemented using locks. When a transaction starts, it acquires locks on the data that it needs to modify. This prevents other transactions from accessing the data until the current transaction finishes.

If a transaction fails, the locks that it acquired are released. This allows other transactions to access the data again.

Atomic transactions are a fundamental concept of database management systems. They are used to ensure the integrity of data in databases, and they are a key part of many database applications.

Here are some examples of atomic transactions:

-   **Transferring money from one bank account to another:**  This transaction involves two operations: withdrawing money from one account and depositing it into another. If either of these operations fails, the transaction will fail and the money will not be transferred.
-   **Updating a customer's record:**  This transaction involves two operations: updating the customer's name and updating the customer's address. If either of these operations fails, the transaction will fail and the customer's record will not be updated.
-   **Deleting a product from an inventory system:**  This transaction involves one operation: deleting the product from the inventory system. If this operation fails, the product will not be deleted from the inventory system.

Atomic transactions provide a number of benefits, including:

-   **Data integrity:**  Atomic transactions ensure that data is always consistent in the database. This is important for applications that need to maintain accurate data.
-   **Data reliability:**  Atomic transactions help to protect data from corruption. If a transaction fails, the database will be rolled back to the state it was in before the transaction started.
-   **Data availability:**  Atomic transactions can help to improve data availability. If a transaction fails, other transactions will not be blocked. This can help to improve the performance of your database applications.