There are things that need to be checked and learned online.
paging
- Pagination means that there is a large amount of data to be displayed on the web page. In order to facilitate reading, only part of the data is displayed in each page.
- Benefits:
- Easy to read
- Reduce the amount of data extraction and reduce the pressure on the server.
- Django provides Paginator class, which can easily realize paging function
- The Paginator class is located in Django core. Paginator module.
Paginator object
- Responsible for the overall management of paging data
- Construction method of object
- paginator = Paginator(object_list, per_page)
- parameter
- object_list list of objects that need classified data
- per_page number of data per page
- Return value:
- Paginator object
- Paginator property
- count: the total number of objects requiring classification data
- num_pages: total number of pages after paging
- page_range: a range object starting from 1, which is used to record the current number of face codes
- per_page number of data per page
- Paginator method
- page(number)
- The parameter number is the page number information (starting from 1)
- Returns the page information corresponding to the current number page
- If the provided page number does not exist, an InvalidPage exception is thrown
- page(number)
- Paginator exception
- InvalidPage: the total exception base class, including the following two abnormal subclasses
- PageNotAnInteger: thrown when a value other than an integer is passed to page()
- EmptyPage: thrown when a valid value is provided to page() but there is no object on that page
- InvalidPage: the total exception base class, including the following two abnormal subclasses
Page object
- Be responsible for the data management of a specific page
- create object
The Page () method of the Paginator object returns the Page object
page = paginator.page(Page number)
- Page object properties
object_list: a list of all data objects on the current page
Number: the sequence number of the current page, starting from 1
Paginator: Paginator object related to the current page object
- Page object method
has_next (): returns True if there is a next page
has_previous(): returns True if there is a previous page
has_other_pages (): returns True if there is a previous or next page
next_page_number(): returns the page number of the next page. If the next page does not exist, an InvalidPage exception is thrown
previous_page_number(): returns the page number of the previous page. If the previous page does not exist, an InvalidPage exception is thrown
len(): returns the number of objects on the current page
- explain:
The Page object is an iterative object. You can use the for statement to access each object in the current Page
- Reference documents https://docs.djangoproject.com/en/2.2/topics/pagination/
- Paging example:
View function
from django.core.paginator import Paginato def book(request): bks = Book.objects.all() paginator = Paginator(bks, 10) cur_page = request.GET.get('page', 1) # Get the default current page page = paginator.page(cur_page) return render(request, 'bookstore/book.html', locals())
Template design
<html> <head> <title>Pagination display</title> </head> <body> {% for b in page %} <div>{{ b.title }}</div> {% endfor %} {% if page.has_previous %} <a href="{% url 'book' %}?page={{ page.previous_page_number }}">previous page</a> {% else %} previous page {% endif %} {% for p in paginator.page_range %} {% if p == page.number %} {{ p }} {% else %} <a href="{% url 'book' %}?page={{ p }}">{{ p }}</a> {% endif %} {% endfor %} {% if page.has_next %} <a href="{% url 'book' %}?page={{ page.next_page_number }}">next page</a> {% else %} next page {% endif %} </body> </html>
File download
Django can directly generate csv files in the view function and respond to the browser
import csv from django.http import HttpResponse from .models import Book def make_csv_view(request): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="mybook.csv"' all_book = Book.objects.all() writer = csv.writer(response) writer.writerow(['id', 'title']) for b in all_book: writer.writerow([b.id, b.title]) return response
- The response gets a special MIME type text / csv. This tells the browser that the document is a CSV file, not an HTML file
- The response gets an additional content disposition header that contains the name of the CSV file. It will be used by the browser for the save as... Dialog box
- For each line in the CSV file, call writer Writerow, which passes an iteratable object, such as a list or tuple.
File upload
- File upload must be submitted by POST
- The file content data in the form < form > can only be included when the file is uploaded with enctype = "multipart / form data".
- Upload files in the form with < input type = "file" name = "XXX" > tag
The name XXX corresponds to request Memory buffered file stream object corresponding to files ['xxx ']. You can pass the request The object returned by files ['xxx '] obtains the uploaded file data
file=request.FILES['xxx'] file is bound to the file stream object, and the file data can be obtained through the following information of the file stream object
file.name file name
file. Byte stream data of file
- Form writing method of uploaded file
<!-- file: index/templates/index/upload.html --> <html> <head> <meta charset="utf-8"> <title>File upload</title> </head> <body> <h3>Upload file</h3> <form method="post" action="/test_upload" enctype="multipart/form-data"> <input type="file" name="myfile"/><br> <input type="submit" value="upload"> </form> </body> </html>
- In setting Py to set media related configuration; Django refers to the files uploaded by users as media resources
# file : settings.py MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
- Create a media folder under the current project folder
$ mkdir media
- View processing function scheme 1 of uploaded files: traditional writing
# file views.py from django.http import HttpResponse from django.conf import settings from django.views.decorators.csrf import csrf_exempt import os @csrf_exempt def upload_view(request): if request.method == 'GET': return render(request, 'test_upload.html') elif request.method == "POST": a_file = request.FILES['myfile'] print("Upload file name is:", a_file.name) filename =os.path.join(settings.MEDIA_ROOT, a_file.name) with open(filename, 'wb') as f: data = a_file.file.read() f.write(data) return HttpResponse("receive files:" + a_file.name + "success")
- View processing function scheme 2 of uploaded files with the help of orm
#test_upload/models.py from django.db import models # Create your models here. class Content(models.Model): desc = models.CharField(max_length=100) myfile = models.FileField(upload_to='myfiles') #test_upload/views.py from test_upload.models import * from django.views.decorators.csrf import csrf_exempt @csrf_exempt def upload_view_dj(request): if request.method == 'GET': return render(request, 'test_upload.html') elif request.method == 'POST': title = request.POST['title'] a_file = request.FILES['myfile'] Content.objects.create(desc=title,myfile=a_file) return HttpResponse('----upload is ok-----')
- To access the uploaded resources in the browser, you need to add the binding of media route under the main route of the project in the runserver environment
from django.conf import settings from django.conf.urls.static import static urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Browser accessible http://127.0.0.1:8000/media/xxxx
User authentication in Django (using Django authentication system)
- Django comes with a user authentication system. It handles user accounts, groups, permissions, and cookie based user sessions.
- effect:
- Add ordinary users and super users
- Change Password
- Documentation see
- User model class
- Location: from Django contrib. auth. models import User
- The basic attributes of the default user are:
auth basic model operation:
- Create user
Create ordinary user create_use
from django.contrib.auth.models import Use user = User.objects.create_user(username='user name', password='password', email='mailbox',...)
- Create superusercreate_ superuse
from django.contrib.auth.models import Use user = User.objects.create_superuser(username='user name', password='password', email='mailbox',...)
- delete user
from django.contrib.auth.models import Use try: user = User.objects.get(username='user name') user.is_active = False # The current user is invalid user.save() print("Delete ordinary user succeeded!") except: print("Failed to delete ordinary user")
- Modify password set_password
from django.contrib.auth.models import Use try: user = User.objects.get(username='xiaonao') user.set_password('654321') user.save() return HttpResponse("Password modification succeeded!") except: return HttpResponse("Failed to modify password!")
- Check whether the password is correct_ password
from django.contrib.auth.models import Use try: user = User.objects.get(username='xiaonao') if user.check_password('654321'): # Returns True for success and False for failure return HttpResponse("The password is correct") else: return HttpResponse("Password error") except: return HttpResponse("There is no such user!")
auth extension field
If you need to expand new fields on the default auth table, such as phone
- Add new app
- Defining model class inherits AbstractUser
- settings. Auth is indicated in py_ USER_ Model = 'application name Class name '
#models.py case from django.db import models from django.contrib.auth.models import AbstractUser # Create your models here. class UserInfo(AbstractUser): phone = models.CharField(max_length=11, default='') #settings.py add configuration AUTH_USER_MODEL = 'user.UserInfo' #Add user from user.models import UserInfo UserInfo.objects.create_user(username='guoxiao', password='123456', phone='13488871101')
Email sending
- Use QQ email to send email
- django. core. The mail sub package encapsulates the automatic sending SMTP protocol of e-mail
- Preparation before:
- Application QQ number
- Log in QQ email with QQ number and modify the settings
- Log in to with the QQ number and password you applied for https://mail.qq.com/
- Modify QQ mailbox - > Settings - > account - > POP3/IMAP... Service
- Set the of Django server and send e-mail with simple mail transfer protocol (SMTP)
- settings.py settings
# Send mail settings EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # Fixed writing EMAIL_HOST = 'smtp.qq.com' # Tencent QQ email SMTP server address EMAIL_PORT = 25 # Port number of SMTP service EMAIL_HOST_USER = 'xxxx@qq.com' # QQ mailbox for sending mail EMAIL_HOST_PASSWORD = '******' # The authorization code obtained in QQ email - > Settings - > account - > POP3/IMAP... Service to log in to QQ email from a third party EMAIL_USE_TLS = True # Whether to start TLS link (secure link) when communicating with SMTP server. The default is false
In view function
from django.core import mail mail.send_mail( subject, #subject message, # Message content from_email, # Sender [currently configured mailbox] recipient_list=['xxx@qq.com'], # Recipient mailing list )
Project deployment
- Project deployment refers to the actual installation of the development board software running on the development machine on the server for long-term operation after the software development is completed
- Deployment should be carried out in the following steps
Install and configure the same version of the environment on the installation machine
- django project migration
- $sudo scp current project source code remote host address and folder
sudo scp /home/tarena/django/mysite1 root@88.77.66.55:/home/root/xxx Please enter root password:
3. Replace python3 manage with uwsgi The PY runserver method starts the server
4. Configure nginx reverse proxy server
5. Configure the static file path with nginx to solve the problem of static path
uWSGI gateway interface configuration (ubuntu 18.04 configuration)
- WSGI (Web Server Gateway Interface) Web server gateway interface is an interface between Python application or framework and web server, which is widely used
- Use Python manage Py runserver is usually used only in development and test environments.
- When the development is finished, the perfect project code needs to run in an efficient and stable environment. At this time, WSGI can be used
- uwsgi is a kind of WSGI. It implements http protocol, WSGI protocol and uwsgi protocol
- Install uWSGI
The terminal inputs the following commands
sudo pip3 install uwsgi==2.0.18 -i https://pypi.tuna.tsinghua.edu.cn/simple/
Check whether the installation is successful
sudo pip3 freeze|grep -i 'uwsgi' #If the installation is successful, the output is displayed uWSGI==2.0.18
- Configure uWSGI
- Add a folder with the same name as the profile item / uwsgi ini
For example: mysite1 / mysite1 / uwsgi ini
[uwsgi] # IP address in socket mode: port number # socket=127.0.0.1:8000 # IP address of Http communication mode: port number http=127.0.0.1:8000 # Current working directory of the project chdir=/home/tarena/.../my_project Here, you need to change to the absolute path of the project folder # WSGI The directory of the PY file, relative to the current working directory wsgi-file=my_project/wsgi.py # Number of processes process=4 # Number of threads per process threads=2 # pid record file of the service pidfile=uwsgi.pid # Destination file location of the service daemonize=uwsgi.log # Turn on main process management mode master=true
- Modify settings Py change DEBUG=True to DEBUG=False
- Modify settings Py will allow_ Hosts = [] changed to ALLOWED_HOSTS = ['website domain name'] or ['service listening ip address']
- Operation management of uWSGI
Start uwsgi
$ Enter the folder with the same name of the project [i.e settings.py Directory] $ sudo uwsgi --ini uwsgi.ini
Stop uwsgi
$ Enter the folder with the same name of the project [i.e settings.py Directory] $ sudo uwsgi --stop uwsgi.pid
explain:
- When uwsgi is started, the program of the current django project has become a background daemon, and this process will not stop when the current terminal is closed.
- If the stop operation fails, you need to execute the following operations to kill the process
ps aux|grep 'uwsgi' -> see uwsgi process tarena 103408 0.0 0.9 137172 39984 ? S 10:02 0:01 uwsgi --ini uwsgi.ini tarena 103410 0.0 0.9 436200 38552 ? Sl 10:02 0:00 uwsgi --ini uwsgi.ini ps -ef | grep 'uwsgi' | grep -v grep | awk '{print $2}' | xargs sudo kill -9
Test:
- Input at browser side http://127.0.0.1:8000 Test
- Note that the port number is 8000
nginx and reverse proxy configuration
- Nginx is a lightweight high-performance Web server, which provides a series of important features such as HTTP proxy and reverse proxy, load balancing, caching and so on.
- High efficiency in writing and executing C language
- nginx action
- Load balancing, multiple servers process requests in turn
- Reverse proxy
- Principle:
- The client requests nginx, and then nginx forwards the request to django run by uWSGI
- nginx installation under ubuntu $ sudo apt install nginx
vim /etc/apt/sources.list Change domestic source sudo apt-get update
- nginx configuration
- Modify the configuration file of nginx / etc / nginx / sites enabled / default
# Add a new location item under the server node, pointing to the ip and port of uwsgi. server { ... location / { uwsgi_pass 127.0.0.1:8000; # Redirect to port 8000 of 127.0.0.1 include /etc/nginx/uwsgi_params; # Turn all parameters to uwsgi } ... } nginx service control SHELL 1 2 3 $ sudo /etc/init.d/nginx start|stop|restart|status # or $ sudo service nginx start|stop|restart|status
Start, stop, restart and status can be used to start, stop, restart and operate nginx services
- Modify uWSGI configuration
Modify the folder with the same name as the project / uwsgi The Http communication mode under ini is changed to socket communication mode
[uwsgi] # Remove the following # http=127.0.0.1:8000 # Change to socket=127.0.0.1:8000
- Restart uWSGI service
Enter the folder with the same name as the project $ sudo uwsgi --stop uwsgi.pid $ sudo uwsgi --ini uwsgi.ini
Test:
Input at browser side http://127.0.0.1 Test
be careful:
1. At this time, the port number is 80 (nginx default)
2. Any modification in Django needs to restart uwsgi, otherwise the modification will not take effect
nginx configuration static file path
- Create a new path - it mainly stores all static files of Django, such as: / home/tarena / project name_ static/
- At Django settings Add new configuration to PY
STATIC_ROOT = '/home/tarena/Project name_static/static #Note that this configuration path is used to store all static files required in the formal environment
- Enter the project and execute Python 3 manage py collectstatic . After executing this command, Django copies all static files of the project to static_ [including the built-in background file of Django]
- Add new configuration to Nginx configuration
# file : /etc/nginx/sites-enabled/default # Add a new location /static routing configuration and redirect to the specified path created in the first step server { ... location /static { # The first step of root is to create the absolute path of the folder, such as: root /home/tarena/Project name_static; } ... }
404 / 500 interface
- Add 404 in the template folder HTML template, which will be displayed when the view triggers Http404 exception
- 404.html works only in the release version (i.e. when DEBUG=False in setting.py)
- When the Http404 exception is triggered to the corresponding processing function, it will jump to the 404 interface
from django.http import Http404 def xxx_view( ): raise Http404 # Direct return 404
Mail alarm
Some error tracking will be displayed in the error message, and sensitive information such as password will appear in these error tracking. Django has modified the filtering of sensitive information in the configuration file to multiple asterisks, but the user-defined view function requires the user to manually filter sensitive information
1. Local variables in view function
from django.views.decorators.debug import sensitive_variables @sensitive_variables('user', 'pw', 'cc') def process_info(user): pw = user.pass_word cc = user.credit_card_number name = user.name ... #be careful: #1 if the error message involves the values of local variables such as user,pw,cc, etc., it will be replaced with * * * * *, and the name variable also displays its real value #2 when there are more than one decorator, it needs to be placed on the top #3 if no parameter is passed, the values of all local variables will be filtered
2. Data in POST submission
from django.views.decorators.debug import sensitive_post_parameters @sensitive_post_parameters('password', 'username') def index(request): s = request.POST['username'] + request.POST['abcd'] #'abcd' does not exist. An error is raised at this time #The values of username and password in POST will be replaced with******