Django Technical Paper
Published: 2023-06-16 07:35:00


 Django is a high level Python web framework that enables rapid development of secure and maintainable websites.

## Settings file
### What is secret key ?
- Django secret key is used to provide cryptographic signing. This key is mostly used to sign session cookies, create hashes and tokens for sensitive information like csrf tokens or password reset tokens.
### What are default Django apps inside it ? Are there more ?
- **django.contrib.admin** - Provides Django administration interface, which allows users to manage and update application's data.
- **django.contrib.auth** - Provides the authentication system, including user modes, login/logout views and password management.
- **django.contrib.contenttypes** - Provides the track of all the models along with a high-level, generic interface for working with our models.
- **django.contrib.sessions**- This app lets us store and retrieve session data for each visitor to your site.
- **django.contrib.messages** - This framework allows us to temporarily store messages in one request and retrieve them for display in subsequent request.
- **django.contrib.staticfiles** - Helps in managing static files (eg- CSS, JavaScript) in Django project and serves them during development.

These are default installed apps, other apps that can be added to our Django project include:-

- **sites** - Provides framework for managing multiple sites
- **sitemaps** -  Helps in generating XML sitemaps for Django site
- **humanize** Provides a set of template filters that help in formatting data in a more human readable way.
- **redirects** app allows to manage URL redirects
- **gis**- Provides support for geographic data and includes spatial fields, spatial indexes.
###  What is middleware ? What are different kinds of middleware ?
- Defined as classes with methods that handle the processing of requests and responses.
- Middlewares can perform authentication, session management, content encoding, URL redirection and more.
 **List of middlewares** :-
1.  `django.middleware.security.SecurityMiddleware`: This middleware adds several security-related HTTP headers to the responses, such as enforcing HTTPS, preventing click-jacking attacks, and setting content type options.
    
2.  `django.middleware.csrf.CsrfViewMiddleware`: This middleware provides protection against Cross-Site Request Forgery (CSRF) attacks by adding and verifying CSRF tokens in POST requests.
    
3.  `django.contrib.sessions.middleware.SessionMiddleware`: This middleware enables session management by storing session data in cookies or a database, and it makes the session data available in request objects.
    
4.  `django.contrib.auth.middleware.AuthenticationMiddleware`: This middleware associates authenticated users with requests by adding the `User` object to the request.
    
5.  `django.contrib.messages.middleware.MessageMiddleware`: This middleware enables the messaging framework, which allows the temporary storage of messages that can be displayed to the user on subsequent requests.
    
6.  `django.middleware.locale.LocaleMiddleware`: This middleware handles language selection and translation by detecting the user's preferred language and activating the corresponding translation.
    
7.  `django.middleware.common.CommonMiddleware`: This middleware performs common operations, such as URL rewriting, response gzip compression, and appending a slash to the end of URLs.

### CSRF
- Stands for Cross site request forgery.
- CSRF attacks allow a malicious user to execute actions using the credentials of another user without that user's knowledge or consent.
- Django provides CSRF tokens for security.
- When a user visits a Django site, a CSRF token is generated ands stored in their sessions or cookies.
- When the server receives POST request it verifies the CSRD token, if they match the POST request is determined as valid otherwise rejected.
-  **CsrfViewMiddleware** is responsible for generating and validating tokens.
- In HTML templates we use { % csrf_token %}

### XSS
- Stands for Cross-Site Scripting
- Type of security vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users.
- Occurs when web application doesn't verify user input.
- Code is executed by the victims and lets attackers bypass access controls and impersonate users.
### Click Jacking
- Here the attacker cons the victim by making them perform clicking action on a seemingly harmless element or perform any action on a web page without their consent.
- This is done by deceiving the victim with the help of interface.
- Eg:- Victim accesses a decoy website and clicks on a button to win a prize. Unknowingly, they have been deceived by an attacker into pressing an alternative hidden button and this results in the payment of an account on another site.

### WSGI
- Pronounced as "whiskey"  :P
- It is a specification that defines a simple and universal interface between web servers and web applications or frameworks.
- Provides a set of rules and guidelines for how a web server should communicate with a web application or framework.
- The communication between the server and the application/framework happens through a callable object called the "application" or "app" object. This object is responsible for handling incoming requests and returning appropriate responses.

### Models

__Models.py__

- File contains the definition of the application's data models using Django's Object-Relational Mapping (ORM) system. Models define the structure and behavior of database tables, allowing you to interact with data in a Pythonic way.


**Field Options**
1. **null** - 
		 If `True`, Django will store empty values as `NULL` in the database. Default is `False`.
2. **blank** - 
		If `True`, the field is allowed to be blank. Default is `False`.
3. **choices** - 
	  A tuple of tuples or a list of tuples, where each tuple represents a choice option. The first element of each tuple is the value stored in the database, and the second element is the human-readable label displayed to the user.
4. **default** - 
The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.
  
5. **error_messages** -
The `error_messages` argument lets you override the default messages that the field will raise. Pass in a dictionary with keys matching the error messages you want to override.
6. **primary_key** - 
If  `True`, this field is the primary key for the model.
If you don’t specify  `primary_key=True`  for any field in your model, Django will automatically add a field to hold the primary key
7. **unique** - 
If `True`, this field must be unique throughout the table

**Field Types**

1. **AutoField**
	- An IntegerField that automatically increments according to available IDs.

2. **BigIntegerField**
	- A 64-bit integer, much like an IntegerField except that it is guaranteed to fit numbers from `-9223372036854775808` to `9223372036854775807`. 
3. **BinaryField**
	- A field to store raw binary data. It can be assigned  bytes bytearray, or  memoryview.
By default,  `BinaryField`  sets  editable to  `False`, in which case it can’t be included in a  ModelForm.
4. **BooleanField**
	 - A true/false field.
5. **CharField**
	- A string field, for small- to large-sized strings.
	- has extra arguments:
	- **.max_length** - The maximum length (in characters) of the field. The max_length is enforced at the database level
6. **DateField**
	- Field type used to store and handle date values. It typically provides functionalities to parse, format, and validate dates.
7. **DecimalField**
	- Field type used to store decimal numbers with a fixed precision and scale. It is often used when precise decimal calculations are required, such as in financial applications.
8. **FileField**
-	Field type used to handle file uploads. It allows users to upload files, and the FileField stores the file on the server and keeps track of its location or other relevant information.
9. **EmailField** 
- Field type used for email address input and validation. It typically ensures that the entered value follows the format of an email address.
10. **JSONField**
-	Field type used to store JSON (JavaScript Object Notation) data. It allows you to store JSON objects or arrays in a database field and provides functionalities to access and manipulate the JSON data.
11. **TextField**
-	Field type used to store large amounts of text data. It is suitable for storing long-form textual content, such as blog posts or user comments, where a predefined limit on the text length is not necessary.
12. **UUIDField**
-	Field type used to store universally unique identifiers (UUIDs). UUIDs are 128-bit identifiers that are unique across all devices and systems, making them suitable for various identification purposes.
13.  **SlugField**
-       Field type used to generate and store a URL-friendly version of a string. It is commonly used in web development frameworks to create human-readable and search engine-friendly URLs based on other field values.
 
 ## Django ORM
```python
>>> from iplapp.models import *
>>> Matches.objects.all()
<QuerySet [<Matches: Matches object (1)>, <Matches: Matches object (2)>, <Matches: Matches object (3)>, <Matches: Matches object (4)>, <Matches: Matches object (5)>, <Matches: Matches object (6)>, <Matches: Matches object (7)>, <Matches: Matches object (8)>, <Matches: Matches object (9)>, <Matches: Matches object (10)>, <Matches: Matches object (11)>, <Matches: Matches object (12)>, <Matches: Matches object (13)>, <Matches: Matches object (14)>, <Matches: Matches object (15)>, <Matches: Matches object (16)>, <Matches: Matches object (17)>, <Matches: Matches object (18)>, <Matches: Matches object (19)>, <Matches: Matches object (20)>, '...(remaining elements truncated)...']>
>>>
>>>
>>>
>>> Matches.objects.aggregate(count=Count('id'))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'Count' is not defined
>>> from django.models import Count
Traceback (most recent call last):
  File "<console>", line 1, in <module>
ModuleNotFoundError: No module named 'django.models'
>>> from django.db.models import Count
>>> Matches.objects.aggregate(count=Count('id'))
{'count': 636}
>>> 
```
### Turning ORM to SQL in Django Shell

Run the python shell

```shell
python manage.py shell
```

Import models and perform ORM query
```python

>>> from django.db.models import *
>>>
>>> query = Matches.objects.all()

>>> print(query.query)

SELECT "iplapp_matches"."id", "iplapp_matches"."season", "iplapp_matches"."city", "iplapp_matches"."date", "iplapp_matches"."team1", "iplapp_matches"."team2", "iplapp_matches"."toss_winner", "iplapp_matches"."toss_decision", "iplapp_matches"."result", "iplapp_matches"."dl_applied", "iplapp_matches"."winner", "iplapp_matches"."win_by_runs", "iplapp_matches"."win_by_wickets", "iplapp_matches"."player_of_match", "iplapp_matches"."venue", "iplapp_matches"."umpire1", "iplapp_matches"."umpire2", "iplapp_matches"."umpire3" FROM "iplapp_matches"
```

__AGGRGATIONS__:

* These are special mathematical operations that can be performed on __Fields__(vertically)
* The common aggrigate functions are  SUM, COUNT, MIN, MAX, AVG etc
* Aggrigate functions should be imported from django models class
__Example__
* Move to shell
```python
>>> from app.models import ModelName
>>> from django.db.models import Count,Sum,Min,Max,Avg
>>> ModelName.objects.aggregate(Count("id"))
>>> ModelName.objects.aggregate(Sum("Attribute"))
>>> ModelName.objects.aggregate(Avg("Attribute"))
>>> ModelName.objects.aggregate(Min("Attribute"))

```

__ANNOTATIONS__

* Annotations are used to add an extra field to the query set object

Example:

```python
>>> from app.models import ModelName
>>> from django.db.models import Count,Sum,Min,Max,Avg
>>> queryset = ModelName.objects.annotate(count = Count("id"))
```
- Here each queryset object will have attribute 'count'


__What is a migration file? Why is it needed?__

* Migrations files are generated by django when we hit command
```python
python manage.py makemigrations  # It will show the changes that it's going to make

python manage.py migrate # This will change the state of database
```
* django will keep track of all the changes that we do the models as a files with dependencies on each other in a migrations folder
* ORM will check for the state of database when we hit migrate .if it come accross any changes it will try to do that in the process if any interruption happens because of some migrations file missing etc, it will collapse the database. 

__What are SQL Transactions__

- Transactions in SQL are the bundle or set of operations that are performed for one functionality.
- Transaction involves one or more database operations
- These will make sure that either all the operations are successful or non of them exicutes, so that consistency has maintained in the database

**ATOMIC  TRANSACTIONS**

* These are the transactions that make sure the operations should be performed as a whole not individually
* Since django uses the auto save, transactions are default not atomic
* So, to make them atomic, we can use transactions from django.db

```python

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()
``` 
- Using Context manager

```python

def  view(self,  *args  ,  **options):
	
	with transaction.atomic():
		# db operations 

```
### References
- [Django Docs](https://docs.djangoproject.com/en/4.2/)
- [StackOverFlow](https://stackoverflow.com/)
- [GeeksforGeeks](https://www.geeksforgeeks.org/django-tutorial/)