Preface
sass project video address: https://www.bilibili.com/video/BV1uA411b77M
Link virtual environments: https://blog.csdn.net/weixin_45859193/article/details/115408555
Using Django version 3.2.6, the project name created with untitled7 as the root directory is web. view.py in the web project writes all views. templates file stores template markup language, script stores script tests, database uses sqlite3, ModelForm beautification label related operations in the form file, static stores third-party libraries and static files
urls.py is as follows:
from django.conf.urls import url, include urlpatterns = [ url(r"^web/", include("web.urls")) ]
The web/urls.py is as follows:
from django.conf.urls import url from web import views urlpatterns = [ # ModelForm Beautification Related url(r'register/', views.register, name="register"), url(r'radio/', views.radio, name="radio"), # Picture Authentication Code Related url(r'login/', views.login, name="login"), url(r'image_code/', views.image_code, name="image_code"), ]
1. ModelForm Beautification
Overview: Use the bootstrap style when matching tags rendered through ModelForm yourself in django.
Example: Create a user table structure example.
models.py is as follows:
class UserInfo(models.Model): username = models.CharField(verbose_name="User name", max_length=32) email = models.EmailField(verbose_name="mailbox", max_length=32) phone = models.CharField(verbose_name="Cell-phone number", max_length=32) password = models.CharField(verbose_name="Password", max_length=32)
Create console input through sqllite3:
python manage.py makemigrations python manage.py migrate
The BootStrapForm class (which overrides the django rendering tag style) is as follows:
class BootStrapForm(object): bootstrap_class_exclude = [] # Initialization Method def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Field name and value for each field for name, field in self.fields.items(): if name in self.bootstrap_class_exclude: continue old_class = field.widget.attrs.get('class', "") field.widget.attrs['class'] = '{} form-control'.format(old_class) field.widget.attrs['placeholder'] = 'Please enter{}'.format(field.label)
The view functions are as follows:
from django.shortcuts import render from django.core.validators import RegexValidator from django import forms from web import models from web.form.bootstarp import BootStrapForm class RegisterModelForm(BootStrapForm, forms.ModelForm): # Bootstrap_can be used here if you want to exclude a fieldClass_Exclude = [field] bootstrap_class_exclude = [] # Override Segment Rules phone = forms.CharField(label="Cell-phone number", validators=[RegexValidator(r'^(1[3|5|6|8]\d{9}$)', "Bad format of mobile number")]) password = forms.CharField(label="Password", widget=forms.PasswordInput()) code = forms.CharField(label="Verification Code") class Meta: model = models.UserInfo fields = "__all__" def register(request): form = RegisterModelForm() return render(request, "register.html", {"form": form})
The html template is as follows:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> </head> <style> .account { width: 600px; margin: 0 auto; } </style> <body> <div class="account"> <h1>register</h1> {% for field in form %} {% if field.name == 'code' %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> <div style="display: flex;justify-content: space-between;flex-direction: row-reverse"> <div class="col-xs-5"> <input id="btnSms" class="btn btn-info" type="button" value="Get Authentication Code"> </div> <div class="col-xs-5"> {{ field }} <span class="error-msg"></span> </div> </div> </div> {% else %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <span class="error-msg"></span> </div> {% endif %} {% endfor %} <button type="button" class="btn btn-info">Sign in</button> </div> </body> </html>
The access routes are as follows:
Overview: Tags are rendered using template markup language in django.widgets.forms, but if we want to modify the tag style by overriding it ourselves, take select, radio tags here to show.
For the convenience of showing, we created a table of items.
models.py is as follows:
class Project(models.Model): COLOR_CHOICES = ( (1, '#56b8eb'), (2, '#f28033'), (3, '#ebc656'), (4, '#a2d148'), (5, '#20BFA4'), (6, '#7461c2'), (7, '#20bfa3'), ) name = models.CharField(verbose_name='Project Name', max_length=32) color = models.SmallIntegerField(verbose_name='colour', choices=COLOR_CHOICES, default=1) desc = models.CharField(verbose_name='Item Description', max_length=255, null=True, blank=True) priority_choices = ( ("danger", "high"), ("warning", "in"), ("success", "low"), ) priority = models.CharField(verbose_name='priority', max_length=12, choices=priority_choices, default='danger')
Create console input through sqllite3:
python manage.py makemigrations python manage.py migrate
1. Customize radio label style
Enter the RadioSelect source code for the function generated by django.forms:
class RadioSelect(ChoiceWidget): input_type = 'radio' template_name = 'django/forms/widgets/radio.html' option_template_name = 'django/forms/widgets/radio_option.html'
The template points to html under the Templates folder in django.
Let's first look at radio.html as follows:
{% include "django/forms/widgets/multiple_input.html" %}
multiple_input.html is as follows:
{% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %} <li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}{% for option in options %} <li>{% include option.template_name with widget=option %}</li>{% endfor %}{% if group %} </ul></li>{% endif %}{% endfor %} </ul>{% endwith %}
These are django's template markup languages, which probably generate ul and li tags from widget s, and can be modified based on the template markup language above if we want to modify them.
radio_option.html is as follows:
{% include "django/forms/widgets/input_option.html" %}
input_option.html is as follows:
{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
That's roughly what we're doing now.
Create widgets.py as follows:
from django.forms import RadioSelect class ColorRadioSelect(RadioSelect): # template_name = 'django/forms/widgets/radio.html' # option_template_name = 'django/forms/widgets/radio_option.html' template_name = 'widgets/color_radio/radio.html' option_template_name = 'widgets/color_radio/radio_option.html'
The template in this project creates widgets/color_Two radio.html, radio_under the radio folderOption.html is used for overrides.
radio.html is as follows:
{% with id=widget.attrs.id %} <div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}> {% for group, options, index in widget.optgroups %} {% for option in options %} <label {% if option.attrs.id %} for="{{ option.attrs.id }}"{% endif %} > {% include option.template_name with widget=option %} </label> {% endfor %} {% endfor %} </div> {% endwith %}
The ul and li tags are changed to the div and label tags here.
radio_option.html is as follows:
{% include "django/forms/widgets/input.html" %} <span class="cycle" style="background-color:{{ option.label }}"></span>
There are no changes, just a space tag added to the original.
Now that the radio s have been rewritten, start writing forms and views.
Combine with the ModelForm form above (BootStrapForm function: Beautify tags with bootstarp style).
project.py is as follows:
from django import forms from web.form.bootstarp import BootStrapForm from web import models from .widgets import ColorRadioSelect class ProjectModelForm(BootStrapForm, forms.ModelForm): bootstrap_class_exclude = ['color'] def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request class Meta: model = models.Project fields = ["name","color","desc"] widgets = { 'desc': forms.Textarea, 'color': ColorRadioSelect(attrs={'class': 'color-radio'}), }
As you can see from the init function, the function also supports passing in the request parameter, excluding color (that is, the radio label, in our own way).
view.py is as follows:
from web.form.project import ProjectModelForm def radio(request): form = ProjectModelForm(request) return render(request, "radio.html", {"form": form})
radio.html is as follows:
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'plugin/bootstrap-3.3.7-dist/css/bootstrap.min.css' %} "> </head> <style> .account { width: 600px; margin: 0 auto; } .color-radio label { margin-left: 0; padding-left: 0; } .color-radio input[type="radio"] { display: none; } .color-radio input[type="radio"] + .cycle { display: inline-block; height: 25px; width: 25px; border-radius: 50%; border: 2px solid #dddddd; } .color-radio input[type="radio"]:checked + .cycle { border: 2px solid black; } </style> <body> <div class="account"> {% for field in form %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <span class="error-msg"></span> </div> {% endfor %} </div> </body> </html>
The path to access the rewritten radio s is as follows:
2. Customize select Tag style
For select tags, we can't modify them in the form of styles, so we need other libraries bootstrap-select, font-awesome icon library, jquery.
Download links to these libraries: https://gitee.com/miaojiaxi/s25day01/tree/master/web/static/
bootstrap-select website: https://www.bootstrapselect.cn/
After all the installation is complete, we go to the tag function Select generated by django.forms to see the source code for beautifying the select tag:
class Select(ChoiceWidget): input_type = 'select' template_name = 'django/forms/widgets/select.html' option_template_name = 'django/forms/widgets/select_option.html' add_id_index = False checked_attribute = {'selected': True} option_inherits_attrs = False
Because, like radio s, the internal select.html does not need to be overridden, only the option tag in the select is used, so we only override option_template_name is fine, so let's check the source select_firstOption.html is as follows:
<option value="{{ widget.value|stringformat:'s' }}"{% include "django/forms/widgets/attrs.html" %}>{{ widget.label }}</option>
In widgets/color_Create select.html under the radio folder to override select_option.html is as follows:
<option value="{{ widget.value|stringformat:'s' }}" data-content="<i class='fa fa-circle text-{{ widget.value|stringformat:'s' }}'></i> {{ widget.label }}" {% include "django/forms/widgets/attrs.html" %}> </option>
With the help of the bootstrap-select library, add icons with data-content = "font-awesome icon library". The icon style is a table field in the database.
Modify the previous widgets.pt as follows:
from django.forms import RadioSelect, Select class ColorRadioSelect(RadioSelect): # template_name = 'django/forms/widgets/radio.html' # option_template_name = 'django/forms/widgets/radio_option.html' template_name = 'widgets/color_radio/radio.html' option_template_name = 'widgets/color_radio/radio_option.html' class ColorSelect(Select): option_template_name = 'widgets/color_radio/select.html'
Then modify project.py as follows:
from django import forms from web.form.bootstarp import BootStrapForm from web import models from .widgets import ColorRadioSelect, ColorSelect class ProjectModelForm(BootStrapForm, forms.ModelForm): # Exclude label beautification for color databases bootstrap_class_exclude = ['color'] def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) # ModelForm can pass request parameters by overriding them self.request = request class Meta: model = models.Project fields = "__all__" widgets = { 'desc': forms.Textarea, # Customize radio label beautification 'color': ColorRadioSelect(attrs={'class': 'color-radio'}), # Custom select tag beautification "priority": ColorSelect(attrs={'class': 'selectpicker', "data-live-search": "true"}), }
Finally, import the library we use.
radio.html is as follows:
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'plugin/bootstrap-3.3.7-dist/css/bootstrap.min.css' %} "> <script src="{% static 'js/jquery-3.5.1.js' %}"></script> <script src="{% static 'plugin/bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'plugin/bootstrap-select/js/bootstrap-select.min.js' %}"></script> <link rel="stylesheet" href="{% static 'plugin/font-awesome-4.7.0/css/font-awesome.min.css' %}"> <link rel="stylesheet" href="{% static 'plugin/bootstrap-select/css/bootstrap-select.min.css' %}"> </head> <style> .account { width: 600px; margin: 0 auto; } .color-radio label { margin-left: 0; padding-left: 0; } .color-radio input[type="radio"] { display: none; } .color-radio input[type="radio"] + .cycle { display: inline-block; height: 25px; width: 25px; border-radius: 50%; border: 2px solid #dddddd; } .color-radio input[type="radio"]:checked + .cycle { border: 2px solid black; } </style> <body> <div class="account"> {% for field in form %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} <span class="error-msg"></span> </div> {% endfor %} </div> </body> </html>
The access routes are as follows:
3. django offline script
Overview: By performing certain operations without django being started, it is generally used by crawlers or other operations that need to be called offline.
Example: Create an init_test.py tests the connection to redis.
import os import sys import django base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "untitled7.settings") django.setup() # Note that the import library must wait for django to start import redis # Direct connection redis conn = redis.Redis(host='127.0.0.1', port=6379, password='Password', encoding='utf-8') # Set key value: 15131255089= "9999" and timeout time is 10 seconds (value will be automatically converted to string when written to redis) conn.set('15131255089', 9999, ex=10) # Get the value based on the key: if there is a get value (get the byte type);Return None if none exists value = conn.get('15131255089') print(value)
b'9999'
IV. pillow Generate Authentication Code
Overview: Authentication code recognition used to check whether a user is generating a robot.
Example: Create image_code.py combines form validation to enable user login validation code click switch.
Monaco.ttf font (placed at the root of the project) Access: https://gitee.com/miaojiaxi/s25day01/tree/master/utils
Install pillow
pip3 install pillow
image_code.py is as follows:
import random from PIL import Image, ImageDraw, ImageFont, ImageFilter def check_code(width=120, height=30, char_length=5, font_file='Monaco.ttf', font_size=28): code = [] img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') def rndChar(): """ Generate random letters :return: """ return chr(random.randint(65, 90)) def rndColor(): """ Generate Random Colors :return: """ return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)) # Write text font = ImageFont.truetype(font_file, font_size) for i in range(char_length): char = rndChar() code.append(char) h = random.randint(0, 4) draw.text([i * width / char_length, h], char, font=font, fill=rndColor()) # Write Disturbance Points for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) # Write interference circle for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) x = random.randint(0, width) y = random.randint(0, height) draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor()) # Draw interference lines for i in range(5): x1 = random.randint(0, width) y1 = random.randint(0, height) x2 = random.randint(0, width) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=rndColor()) img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) return img, ''.join(code) if __name__ == '__main__': image_object, code = check_code() print(code) with open('code.png', 'wb') as f: image_object.save(f, format='png')
The Generate Authentication Code View function is as follows:
def image_code(request): image_object, code = check_code() # Verify by saving the verification code with session request.session['image_code'] = code # timeout request.session.set_expiry(60) # Save in memory stream = BytesIO() image_object.save(stream, 'png') return HttpResponse(stream.getvalue())
The login view functions are as follows:
class LoginForm(BootStrapForm, forms.ModelForm): username = forms.CharField(label="User name") password = forms.CharField(label="Password", widget=forms.PasswordInput()) code = forms.CharField(label="Picture Verification Code") class Meta: model = models.UserInfo fields = ["username", "password", "code"] def login(request): form = LoginForm() return render(request, "login.html", {"form": form})
The user rendering tag login.html is as follows:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> </head> <style> .account { width: 600px; margin: 0 auto; } </style> <body> <div class="account"> <form action="{% url 'login' %}" method="post" novalidate> {% csrf_token %} {% for field in form %} {% if field.name == 'code' %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> <div style="display: flex;justify-content: space-between"> <div class="col-xs-7"> {{ field }} </div> <div class="col-xs-5"> <img src="{% url 'image_code' %}" id="imageCode" title="Click to change picture"> </div> </div> </div> {% else %} <div class="form-group"> <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} </div> {% endif %} {% endfor %} <div class="form-group"> <input id="btnSubmit" type="submit" class="btn btn-primary" value="Sign in"> </div> </form> </div> </body> <script> (() => { document.getElementById("imageCode").onclick = function () { // Find str attribute var oldSrc = document.getElementById("imageCode") // Add one for each execution? (Equivalent to refresh) oldSrc.src += "?" } })() </script> </html>
The access routes are as follows: