Django framework learning -- 8 -- cache & Middleware

Key points of this article:

        1. How to respond faster through caching?

        2. What is middleware?

        3. How to realize the paging function of the website?

        4. Generate csv file

1. Cache

What is caching?

  1. A kind of media that can read data faster or storage methods that can speed up data reading;
  2. Generally used to store temporary data;
  3. Commonly used media are memory with fast reading speed.

Website response speed limit threshold:

Network speed is not the main threshold. It is mainly in the back-end database. Due to too many data tables or improper sql query methods, the background data is transmitted to the front-end and displayed too slowly.

Cache optimization scheme provided by Django:

given a URL, try finding that page in the cache

if the page is in the cache: 
    return the cached page
else: 
    generate the page ,
    save the generate page in the cacher(for next time) 
    return the generated pageļ¼›

Cache scene:

  • Blog list, e-commerce product details page
  • Scene features: where the data is cached, the frequency of data changes is less

Configuring cache in django

1. Database cache

The cache medium is a back-end database. Although the cache medium has not been replaced, when the results of a query are directly stored in the table, complex queries can be avoided.

settings. Configuration of CACHES field in py file

# Database cache configuration - database cache (need to create cache table manually)
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',
        'TIMEOUT': 300, #The unit of cache saving time is seconds. The default value is 300,
        'OPTIONS': {
            'MAX_ENTRIES': 300, #Maximum number of cached data
            'CULL_FREQUENCY': 2, #When the number of cache entries reaches the maximum, delete 1/x of cache data
        }
    }
    
}

2. Browser cache

Workflow diagram of browser cache:

Browser cache can be divided into two types: strong cache and negotiation cache

Strong cache

No request will be sent to the server and resources will be read directly from the cache

  • Response header expires: Specifies the expiration time of the resource
  • Response header cache control: the number of seconds after the request creation time, and the cache is invalid (this field is judged first)

Negotiation cache

Once the data in the strong cache expires, it also needs to communicate with the server to obtain the latest data (for some large files)

Negotiation cache - mode 1

  • Response header - last modified: the last modified time of the file
  • Request header - if modified since: sends a negotiation to the server, and the server returns 304 response [representing the continued use of the cache], and 200 response represents that the cache is unavailable [the response body is the latest resource]

Negotiation cache - mode 2

  • ETag response header - returns a unique identifier (hash value) of the current resource file
  • If none match request header - the negotiation result is consistent with the above policy

3. Other types of cache

  1. Cache the data into the server memory (test type, usually stored in redis)
  2. File system cache (not recommended)

How to use cache?

1. Overall cache strategy

  • In view function

Usage: add decorator @ cache in front of view function_ Page (parameter); The following parameters indicate how long the cache of the current view function will survive;

Function: if there is requested data in the cache, it will be returned directly. If not, go to the view function and return the result to the decorator for next storage.

The previous cached data in the sample code lives for 15 seconds and will not change until 15 seconds after obtaining the timestamp.

@cache_page(15)
def test_cache(request):
    t = time.time()
    return HttpResponse('t is %s' %(t))
  • Routing
from jdango.views.decorators.cache import cache_page

urlpatterns = [
    path('foo/', cache_page(15)(my_view)),
]

2. Local cache strategy

The use of cache API (Application Programming Interface) is similar to that of dictionary

# Mode 1
from django.core.cache import caches
cache1 = caches['myalias']

# Mode 2
from django.core.cache import cache
# Compared with the 'default' item directly introduced into the cache configuration item

Storage, acquisition and deletion methods of cache:

# Storage cache
cache.set(key, value, timeout) 
cache.add(key, value) # It only takes effect when the key does not exist
cache.set_many(dict, timeout) # Returns an array of key s that failed to be inserted
# Get cache
cache.get(key)
cache.get_many(key_list)
cache.get_or_set(key,value,timeout)
#Delete cache
cache.delete(key)
cache.delete_many(key_list)

2. Middleware

What is middleware?

  1. The hook framework of Django request and response, a lightweight and low-level 'plug-in' system, is used to globally change the input or output of Django;
  2. Filter response, filter route, filter view, etc., equivalent to toll station; For example, the middleware is placed in front of the request before it reaches the main route;
  3. Middleware is embodied in the form of classes, and each middleware component is responsible for doing some specific functions.

Schematic diagram of Middleware

How to write Middleware

1. Write Middleware

Create and manage Py the middleware folder of the same level directory, and then create it in it__ init__.py and mymiddleware Py (user-defined file name) module, and all subsequent middleware are written in the user-defined file name module;

Middleware writing requirements:

  1. Middleware must inherit Django utils. deprecation. Middlewaremixin class;
  2. The middleware must implement one or more of the following five methods.
process_request(self, request)
#It will be called before the route is executed. It will be called on each request and return a None or HttpResponse object (blocked)
process_view(self, request, callback, callback_args, callback_kwargs)
#It is called before calling the view. It is called on each request and returns a None or HttpResponse object
#Callback view function, callback_args location parameter, callback_kwargs keyword parameters
process_response(self, request, response)
# All responses are returned to the browser and called on each request to return the HttpResponse object
process_exception(self, request, exception)
# When an exception is thrown during processing, it is called to return an HttpResponse object
process_template_reponse(self, request, response)
# It is called when the view function is executed and the view return object contains the render method, which needs to return the response object implementing the render method

When most of the above methods return None, it means to ignore the current operation and proceed to the next event

When the HttpResponse object is returned, it means that the request ends and is returned directly to the client

2. Register Middleware

#settings.py
MIDDLEWARE=[
    'middleware.mymiddleware.MyMW',
]

django calls the middleware class to process the request from top to bottom in the order of registering the middleware, and then return the response from bottom to top.

case

The middleware is used to force an IP address to send five requests only to the address beginning with / test

class VisitLimit(MiddlewareMixin):
    
    visit_times = {}
    
    def process_request(self, request):
        # Address and route of visitors
        ip_address = request.META['REMOTE_ADDR'] 
        path_url = request.path_info 
        # Use regular matching
        if not re.match('^/test', path_url):
            return 
        times = self.visit_times.get(ip_address, 0)
        print('ip', ip_address, 'Already visited', times)
        self.visit_times[ip_address] = times + 1
        if times < 5:
            return
        return HttpResponse('You have visited' + str(times)+ 'Times, no access')

Note: if you want to undo and re time the number of accesses, you can restart the local server and set the visit equivalent to the memory value (variable)_ Reset of times

3. CSRF attack - cross site forged request attack

The login status is saved in Cookies and submitted automatically

Solution:

  1. Open Csrf in midview in settings
  2. In the template, add the tag {% csrf_token%} to the form tag

If a view does not need to be csrf protected by django, you can close the inspection of this view with the decorator

@csrf_exempt
def my_view(request):
        return HttpResponse('hi')

4. Paging function

Function of paging function

  1. Easy to read
  2. Reduce the amount of data extraction and reduce the pressure on the server

How does Django implement paging?

Paginator class can easily realize paging function (responsible for the overall management of paging data)

Paginator object

Construction method of object

paginator = Paginator(object_list, per_page)

Meaning of parameters:

  • object_list list of objects that need classified data
  • per_page number of data per page

Paginator property

  • count = total number of objects for paging data
  • num_pages total number of pages after paging
  • page_range = range object from the beginning
  • per_page returns the second parameter

Page object

The Paginator object can only handle the paging data as a whole and cannot manage a page. Here we refer to the page object, which can manage the data of a specific page

Construction method of object

page1 = paginator object.page(Page number)

Generate page object - manage the data of a page

Page object properties

  • object_list the list of all data objects on the current page
  • Number the sequence number of the current page, starting from 1
  • Paginator the Paginator object related to the current page object

case

Writing view functions

def test_page(request):
    # test_page/4
    # test_page?page=1
    page_num = request.GET.get('page', 1)
    all_data = ['a', 'b', 'c', 'd', 'e']
    paginator = Paginator(all_data, 2)
    c_page = paginator.page(int(page_num))
    return render(request, 'test_page.html', locals())

html file in template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>paging</title>
</head>
<body>
    {% for p in c_page %}
    <p>
        {{ p }}
    </p>
    {% endfor %}

    {% if c_page.has_previous %}
    <a href="/test_page?page={{ c_page.previous_page_number }}">Go up</a>
    {% else %}
        Go up
    {% endif %}
    {% for p_num in paginator.page_range %}
        {% if p_num == c_page.number %}
        {{ p_num }}
        {% else %}
        <a href="/test_page?page={{ p_num }}">{{ p_num }}</a>
        {% endif %}
    {% endfor %}
    {% if c_page.has_next %}
    <a href="/test_page?page={{ c_page.next_page_number }}"> Go down </a>
    {% else %}
        Go down
    {% endif %}
    
</body>
</html>

Effect achieved:

5. Generate csv file

  • Comma separated values (character separator)
  • It can be read directly by common tabulation tools, such as excel

csv writing

import csv

with open('csv.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['a','b','c'])
#For a brief description, please refer to other teaching contents for details 

csv file download

  1. Change the response content type to text/csv
  2. The response will get an additional content disposition header, which will be used by the browser to open the Save As dialog box

case

Just add the following code to the body tag in the html file of the previous case:

<a href="/make_page_csv?page={{ c_page.number }}">generate csv file</a>

Effect achieved:

Keywords: Python Django Back-end

Added by thebluebus on Thu, 03 Feb 2022 05:56:07 +0200