Django FrameWork
Tags: django, python
Published: 2023-06-15 16:09:53



- It is a python framework developed for rapid development of web applications
- The following are some of the core concepts of the framework


## Secret Key :

- This is the key present in the settings.py file which is randomly generated by django for security purpose
- Project will not run without the secrete key. If you try to runserver without secret key, It will throw a message saying "Please contact admin"
- This Secret key is used in Criptographic signing in django
- Example Snippet
-Run the code inside django shell
```python
>>> from django.core.signing import Signer
>>> signer = Signer()
>>> value = signer.sign("My string")
>>> value
>>>'My string:GdMGD6HNQ_qdgxYP8yBZAdAIV1w'
>>> unsign = signer.unsign(value)
>>>"My string"
```
- The above code generate the random signed value based on secret key
- If we remove or alter the secret key all the signed values will be last
- It is helpfull in data hiding or password redirecting page etc

## Default Django Apps

- `django.contrib.admin` : This is responsible for django admin page and creating superuser etc

- `django.contrib.auth` : django has some inbuilt user authentication system which is coming from auth app

- `django.contrib.contenttypes` : This allows us to create a general model which has foreign key of ContentType that can be reused for different models in the project

`django.contrib.sessions` It is sessions framework used to manage user sessions in the web application

`django.contrib.messages`: This is used to send messages to the templates while redirecting. e.g: Success Message, Error Messages in forms etc


## CSRF

- Cross Site Request Forgery is a technique where attacker makes user to click on some link which make some JavaScript code run making request to the targetted website and sends the required payload by taking advantage of user session
- This can be avoided by using csrf tokens which are related to user session
- In django, Forms should have csrf token, The Token is passed to the server side along with payload and validation is done at the server side.

## XSS

- Cross Site Scripting is a technique where attacker's send the script or html that is harmful as a input
- To prevent this django automatically escapes the user generated content which have html script
- We have an option to turn it off as incase if we want to render html itself

##  Click Jacking
 
 - 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 uses XFrameOptionsMiddleware to prevent this


##  Middleware

- These are the layers that are present between webserver and the views
- The request that browser makes will go to web server and from there it will pass through all the middle layers called middlewares and reaches the view
- View will send a response which again will pass through the middle layers for adding addtional contents
- Middlewares are helpfull in filtering the requests, for example if a form without csrf tocken is posted, request will not reach till view because csrf layer will return it to browser with exception
- Some of the Default middlewares that django have are:
```python

MIDDLEWARE =  [
	'django.middleware.security.SecurityMiddleware',
	'django.contrib.sessions.middleware.SessionMiddleware',
	'django.middleware.common.CommonMiddleware',
	'django.middleware.csrf.CsrfViewMiddleware',
	'django.contrib.auth.middleware.AuthenticationMiddleware',
	'django.contrib.messages.middleware.MessageMiddleware',
	'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
```

### WSGI

- Web Server Gateway Interface : It is interface between web server and a framework like django
- wsgi is a specification that should be followed in the request , response flow
- This helps in writing a server side scripts independent of web server

## Models



### Foreign Key

- In django models if the field is foreignKey, we need to pass two arguments to it
- ONE: Model class name to which it is refering
- TWO: Property- on_delete:
`on_delete=models.CASCADE` : This will delete the record in the model, if object of parent model is deleted from the database
`on_delete=models.RESTRICT` : allows deletion of child only if all of its owners(parents) are deleted in past or currently are being deleted
`on_delete = models.SET_NULL`: Let parent gets deleted but set child to null
`on_delete = models.PROTECT` : Let parent gets deleted but child will not 

## Fields and Validators

Some Common Fields :

`null` : 

- This can be true or false, default will be false, if true, django will store the Empty values as null

`blank`: 

- This can be true or false, default will be false. This is for form validation purpose
- if blank is true, then form will validate else user will have to give the input

`choices`: 

- This will take array of tuples having two values [(a1,b1),(a2,b2)]
- First value of tuple is the value of model object and second element is human readable option

`db_index`: 

-django will create index for the field in the table for faster searching

`default`: 

- This will be the default value if nothing is provided in the field
- It can be a callable function which returns some value

`primery_key`:

- Django will automatically provides primery key column, if no field with pk is provided
- If you want to make a field primery , make preimery_key = True

`unique`:

- Values in the field should be unique, if true. default will be false
- unique implise creating a index so no need to provide db_index

`validators`: 

- This will take a list of validation functions which will rise ValidationError if fails

__Field Types__:

`models.CharFiled(max_length=20)`

- Takes in the text value of size less than max_length

`models.IntegerField()`: 
- Takes integer value

`models.DateField(auto_now=False, auto_now_add=False)`: 

- This takes the date value
- if auto_now is true, this will updates the data every time it is saved
- if auto_now_add = True, then it will assign the date to at the time of creation only

`models.DateTimeField(auto_now=False,auto_now_add=False)`:

- In addition to date, time also added and both  the properties work the same way

`models.EmailField(max_length=254_, **options)`:

- This checks if the given email is valid or not by Email Validator

`models.SlugField(_max_length=50_, _**options_)`:

-This is generally used for url storage


__Validators__:

```python
from django.core.validators import <validator_name>
```

- Some of the commonly used validators are

`validate_email(email)`: Validates Email
`MaxLengthValidator(text)` : reises validation error if text is greater than given length
`MinLengthValidator(text)` : reises validation error if text is less than given length
`URLValidatior(url)` : checks if url is valid or not
`validate_slug(slug)` : checks for slug
`validate_integer(number)` : checks if it is integer or not

- We can write our own custom validator functions and pass them to fields


## Django ORM

__Using django SHELL__:

- Following command to move into django shell

```python
python manage.py shell
```
- Import the models that we want to work with

```python
>>> from app.models import ModelName
>>> from django.db.models import Count,Sum,Min,Max
>>> querySet = ModelName.objects.all()
>>> ModelName.objects.filter(attribute__gt = value)
>>> ModelName.objects.values("Attribute1").annotate(Count("Attribute2"))
>>> ModelName.objects.aggregate("id")
```

- The above are some of the commonly used queries, filter will result a query set with all the records that satisfy condition
- values() before annotate will act as a group by and aggregate functions can be applied on them

__Turning ORM to SQL__

To know the sql query that orm is going to exicute use query attribute of querySet in the shell

example:
- move to shell
```python
python manage.py shell
```
- open shell and perform
```python

>>> from app.models import ModelName

>>> querySet = ModelName.objects.filter(attribute=value)
>>> print(querySet.query)
 # SQL Query which orm is going to excicute will be printed here 
```

__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 


```