Tools used in the sass project of the django framework

Keywords: Python Django IDE

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)

Print

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:

Posted by middleman666 on Wed, 01 Sep 2021 09:46:39 -0700