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?
- A kind of media that can read data faster or storage methods that can speed up data reading;
- Generally used to store temporary data;
- 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
- Cache the data into the server memory (test type, usually stored in redis)
- 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?
- 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;
- 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;
- 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:
- Middleware must inherit Django utils. deprecation. Middlewaremixin class;
- 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:
- Open Csrf in midview in settings
- 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
- Easy to read
- 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
- Change the response content type to text/csv
- 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: