查看原文
其他

Python自动化运维之改造网页模板

小安Sir Python自动化运维 2024-03-03

ir


了解Python自动化运维↑点击蓝字关注我们 ↑



Hello,大家好!我是小安Sir!

这次主要介绍Python的Django模块,学会这个模块,运维人员也可以做简单的小程序,比如,最近比较热门的健康打卡系统?


这次小安主要讲自动化运维系统,这对小安Sir来说,是一个非常重要的工程!因为工作中和生活中免不了一些繁琐、需要总结、标准化的事情,那就找个契机搭建这个系统,整合自身资源,也是为了持续不断地更新自身技术!


开始之前,要准备好以下技能和材料:

1.网页模板,百度上找,要漂亮的,专业的。

2.Pycharm专业版,请见小安Sir以往的推文。

3.Python Django技能,可以买本书扫盲。

4.Mysql数据库,度娘或买书。


只要肯下功夫,专研一个网页模板,举一反三,搭建自己专属系统不是梦。

ps : 小安学一些前端知识只是为了更好地巩固Django这门语言。

自动化系列







磨刀之用户注册登陆

本文大纲

Attention

    1. 网页模板

    2. Django基础设置

    3. Django APP部分

    4. 演示


网页模板

01


1.1 整体部分

小安Sir的前端水平有限,但将网页改成自己想要的样子,这还是没问题滴(蜜汁自信)。为了弥补时间和技术的不足,我特地从网上下载了一个比较漂亮的模板,正所谓爱美之心,人皆有之。


如果自己写一个网页,额?看着这么丑的界面,小安Sir实在没心情把呕心沥血的代码放上去。


上面都是瞎扯哈,网页模板好处多多哈,有兴趣的老铁可以搞一个合眼缘的模板来玩玩哈。


先看看整体模板演示。

网页模板


下面开始,小安Sir就直接贴改造后的html代码了,如果大家在改造过程中有什么疑惑或者报错的,欢迎加我微或者后台联系我喔!


1.2 登陆页面

login.html

1{% load staticfiles %}
2<!DOCTYPE html>
3<html lang="en">
4<head>
5    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
6    <meta charset="utf-8">
7    <title>Cloud Admin | Login</title>
8    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
9    <meta name="description" content="">
10    <meta name="author" content="">
11    <link rel="stylesheet" type="text/css" href="{% static 'css/cloud-admin.css' %}" >
12    <link href="{% static 'font-awesome/css/font-awesome.min.css' %}" rel="stylesheet">
13    <!-- DATE RANGE PICKER -->
14    <link rel="stylesheet" type="text/css" href="{% static 'js/bootstrap-daterangepicker/daterangepicker-bs3.css' %}" />
15    <!-- UNIFORM -->
16    <link rel="stylesheet" type="text/css" href="{% static 'js/uniform/css/uniform.default.min.css' %}" />
17    <!-- ANIMATE -->
18    <link rel="stylesheet" type="text/css" href="{% static 'css/animatecss/animate.min.css' %}" />
19    <!-- FONTS -->
20</head>
21<body class="login">
22    <!-- PAGE -->
23            <!-- HEADER -->
24            <header>
25                <!-- NAV-BAR -->
26                <div class="container">
27                    <div class="row">
28                        <div class="col-md-4 col-md-offset-4">
29                            <div id="logo">
30                                <a href="{%  url 'Dreaming:index' %}"><img src="{% static 'img/logo/logon_6.png' %}" height="40" alt="logo name" /></a>
31                            </div>
32                        </div>
33                    </div>
34                </div>
35                <!--/NAV-BAR -->
36            </header>
37            <!--/HEADER -->
38            <!-- LOGIN -->
39                <div class="container">
40                    <div class="row">
41                        <div class="col-md-4 col-md-offset-4">
42                            <div class="login-box-plain">
43                                <h2 class="bigintro">Sign In</h2>
44                                <div class="divide-40"></div>
45                                <form role="form"  action="." method="post">
46                                    {% if message %}
47                                        <div class="alert alert-warning">{{ message }}</div>
48                                    {% endif %}
49                                    {% csrf_token %}
50                                  <div class="form-group">
51                                    <label for="{{login_form.username.id_for_label}}">用户</label>
52                                    <i class="fa fa-user"></i>
53                                    <input type="text" name='username' class="form-control" placeholder="Username" autofocus required>
54                                 </div>
55                                  <div class="form-group">
56                                    <label for="{{login_form.password.id_for_label}}">密码</label>
57                                    <i class="fa fa-lock"></i>
58                                    <input type="password" name='password' class="form-control" placeholder="Password" autofocus required>
59                                  </div>
60                                <div class="form-actions">
61                                    <button type="submit" class="btn btn-danger">登 陆</button>
62                                  </div>
63                                </form>
64                                <div class="login-helpers">
65
66                                    Don't have an account with us? <a href="{% url 'Dreaming:register' %}">Register now!</a>
67                                </div>
68                            </div>
69                        </div>
70                    </div>
71                </div>
72
73    <!--/PAGE -->
74    <!-- JAVASCRIPTS -->
75    <!-- Placed at the end of the document so the pages load faster -->
76    <!-- JQUERY -->
77    <script src="{% static 'js/jquery/jquery-2.0.3.min.js' %}"></script>
78    <!-- JQUERY UI-->
79    <script src="{% static 'js/jquery-ui-1.10.3.custom/js/jquery-ui-1.10.3.custom.min.js' %}"></script>
80    <!-- BOOTSTRAP -->
81    <script src="{% static 'bootstrap-dist/js/bootstrap.min.js' %}"></script>
82    <!-- UNIFORM -->
83    <script type="text/javascript" src="{% static 'js/uniform/jquery.uniform.min.js' %}"></script>
84    <!-- CUSTOM SCRIPT -->
85    <script src="{% static 'js/script.js' %}"></script>
86
87    <!-- /JAVASCRIPTS -->
88</body>
89</html>


主要修改了哪里,才能让模板适用于Django架构,请见下面表格。

注意:事实上还要修改很多,但是小安Sir觉得这对老铁们来说,问题不大。

说明
30指定网页app的index链接,与app的urls.py相关。
45
制定表单,acthon=".",当前页面。
46~48
网页渲染,提醒报什么错误。
49
{% csrf_token %},前段通过POST方式 提交数据,免受CSRF攻击,与表单内容一同被提交。
51
替换表单的label,得到前端模板渲染的表单,并单独实现
<input>元素。
61
提交表单。


1.3 注册页面

register.html

1{% load staticfiles %}
2<!DOCTYPE html>
3<html lang="en">
4<head>
5    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
6    <meta charset="utf-8">
7    <title>Cloud Admin | Login</title>
8    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">
9    <meta name="description" content="">
10    <meta name="author" content="">
11    <link rel="stylesheet" type="text/css" href="{% static 'css/cloud-admin.css' %}" >
12    <link href="{% static 'font-awesome/css/font-awesome.min.css' %}" rel="stylesheet">
13    <!-- DATE RANGE PICKER -->
14    <link rel="stylesheet" type="text/css" href="{% static 'js/bootstrap-daterangepicker/daterangepicker-bs3.css' %}" />
15    <!-- UNIFORM -->
16    <link rel="stylesheet" type="text/css" href="{% static 'js/uniform/css/uniform.default.min.css' %}" />
17    <!-- ANIMATE -->
18    <link rel="stylesheet" type="text/css" href="{% static 'css/animatecss/animate.min.css' %}" />
19    <!-- FONTS -->
20</head>
21<body class="login">
22    <!-- PAGE -->
23            <!-- HEADER -->
24            <header>
25                <!-- NAV-BAR -->
26                <div class="container">
27                    <div class="row">
28                        <div class="col-md-4 col-md-offset-4">
29                            <div id="logo">
30                                <a href="{%  url 'Dreaming:index' %}"><img src="{% static 'img/logo/logo-alt.png' %}" height="40" alt="logo name" /></a>
31                            </div>
32                        </div>
33                    </div>
34                </div>
35                <!--/NAV-BAR -->
36            </header>
37            <!--/HEADER -->
38            <!-- REGISTER -->
39                <div class="container">
40                    <div class="row">
41                        <div class="col-md-4 col-md-offset-4">
42                            <div class="login-box-plain">
43                                <h2 class="bigintro">Register</h2>
44                                <div class="divide-40"></div>
45                        <form role="form"  action="." method="post">
46                                    {% if message %}
47                                        <div class="alert alert-warning">{{ message }}</div>
48                                    {% endif %}
49                                    {% csrf_token %}
50                                  <div class="form-group">
51                                    <label for="{{register_form.username.id_for_label}}">Username</label>
52                                    <i class="fa fa-user"></i>
53                                    <input type="text" name='username' class="form-control" autofocus required>
54                                  </div>
55                                  <div class="form-group">
56                                    <label for="{{register_form.emailaddr.id_for_label}}">Email address</label>
57                                    <i class="fa fa-envelope"></i>
58                                    <input type="email" name='emailaddr' class="form-control" autofocus required>
59                                  </div>
60                                  <div class="form-group">
61                                    <label for="{{register_form.password.id_for_label}}">Password</label>
62                                    <i class="fa fa-lock"></i>
63                                    <input type="password" name='password' class="form-control" autofocus required>
64                                  </div>
65                                  <div class="form-group">
66                                    <label for="{{register_form.password2.id_for_label}}">Repeat Password</label>
67                                    <i class="fa fa-check-square-o"></i>
68                                    <input type="password" name='password2' class="form-control" autofocus required>
69                                  </div>
70                                  <div class="form-actions">
71                                    <button type="submit" class="btn btn-success">注 册</button>
72                                  </div>
73                                </form>
74                                <div>
75                                    <a href="{%  url 'Dreaming:login' %}" > Back to Login</a> <br>
76                                </div>
77                            </div>
78                        </div>
79                    </div>
80                </div>
81
82    <!--/PAGE -->
83    <!-- JAVASCRIPTS -->
84    <!-- Placed at the end of the document so the pages load faster -->
85    <!-- JQUERY -->
86    <script src="{% static 'js/jquery/jquery-2.0.3.min.js' %}"></script>
87    <!-- JQUERY UI-->
88    <script src="{% static 'js/jquery-ui-1.10.3.custom/js/jquery-ui-1.10.3.custom.min.js' %}"></script>
89    <!-- BOOTSTRAP -->
90    <script src="{% static 'bootstrap-dist/js/bootstrap.min.js' %}"></script>
91    <!-- UNIFORM -->
92    <script type="text/javascript" src="{% static 'js/uniform/jquery.uniform.min.js' %}"></script>
93    <!-- CUSTOM SCRIPT -->
94    <script src="{% static 'js/script.js' %}"></script>
95
96    <!-- /JAVASCRIPTS -->
97</body>
98</html>


注册页面,小安就不再一一描述了,Label标签要与<input>元素的命名一致,不然views.py的视图函数会报无法接收数据的错误。


Django基础设置

02


2.1 创建项目和APP

略,请见小安Sir之前的推文(链接在最下方)。


2.2 配置settings.py


2.2.1 配置mysql数据库

1import pymysql
2pymysql.install_as_MySQLdb()
3DATABASES = {
4    'default': {
5        'ENGINE''django.db.backends.mysql',
6        'NAME''Dreaming',                                 # 数据库名字
7        'USER''root',                                     # 用户名
8        'PASSWORD''mysql',                                # 密码
9        'HOST''192.168.117.30',                           # IP地址
10        'PORT''3306',                                     # 端口
11    }
12}


2.2.2 配置静态目录

1STATIC_URL = '/static/'
2STATICFILES_DIRS = [
3    os.path.join(BASE_DIR,'static'),
4]


2.3 配置urls.py

1# -*- coding: utf-8 -*-
2from django.contrib import admin
3from django.urls import path,include
4
5urlpatterns = [
6    path('admin/', admin.site.urls),
7    path('Dreaming/', include('Dreaming.urls')),
8]


Django App部分

03


3.1 urls.py

Dreaming这个APP的所有网址都在urls.py配置里面,每个网页会用哪个视图函数,有什么链接别名,都写在下面,方便管理。

1# -*- coding: utf-8 -*-
2from django.urls import path
3from . import views
4
5app_name = "Dreaming"
6
7urlpatterns = [
8    path('<int:article_id>/', views.blog_article, name='blog_article'),
9    path('', views.index, name='index'),
10    path('sqlmon/', views.sql_mon,name='sqlmon'),
11    path('reboot/', views.reboot_info, name='reboot'),
12    path('login/', views.login, name='login'),
13    path('register/', views.register, name='register'),
14    path('no_ipaddress/', views.no_ipaddress, name='no_ipaddress'),
15    path('sliders_progress/', views.sliders_progress, name='sliders_progress'),
16    path('mys_cluster/', views.mys_cluster, name='mys_cluster'),
17]


3.2 models.py

编写数据模型类,即定义表结构,不需要通过SQL语句直接跟数据库打交道。不过这里要注意,不要跟forms.py混淆,

1# -*- coding: utf-8 -*-
2# Create your models here.
3from django.db import models
4from django.utils import timezone
5
6class UserProfile(models.Model):
7    username = models.CharField(max_length=30, unique=True)
8    password = models.CharField(max_length=30)
9    emailaddr = models.EmailField(max_length=30, null=True)
10    sex = models.CharField(max_length=32, default='未知')
11    hobby = models.CharField(max_length=128,null=True)
12    company = models.CharField(max_length=128,null=True)
13    position = models.CharField(max_length=128,null=True)
14    c_time = models.DateTimeField(auto_now_add=True)
15
16    def __str__(self):
17        return self.username
18
19    class Meta:
20        ordering = ['c_time']


3.3 admin.py

相当于该项目的数据管理员了,这里就不多说了,可以参考以往的文章。

1# -*- coding: utf-8 -*-
2from django.contrib import admin
3from .models import UserProfile
4
5### 用户相关
6class UserProfileAdmin(admin.ModelAdmin):
7    list_display = ("username","password","emailaddr","sex","hobby","company","position","c_time")
8admin.site.register(UserProfile,UserProfileAdmin)


3.4 forms.py

编写表单类是必须的,有自定义的表单,还有来自models的。

1from django import forms
2from .models import UserProfile
3
4class LoginForm(forms.Form):
5    username  = forms.CharField(widget=forms.TextInput())
6    password = forms.CharField(widget=forms.PasswordInput)
7
8class RegistrationForm(forms.ModelForm):
9    username  = forms.CharField(widget=forms.TextInput())
10    password  = forms.CharField(label="Password",widget=forms.PasswordInput)
11    password2 = forms.CharField(label="Repeat Password",widget=forms.PasswordInput)
12
13    class Meta:
14        model = UserProfile
15        fields= ["emailaddr"]



说明
2
导入models的数据模型。
4
创建LoginForm表单类(未绑定实例),提交表单后不会对数据库表进行改变。 
8
将RegistrationForm表单中数据写入数据库表,就要让表单类继承ModelForm类。
13~15
fields,表单选用数据库表的部分字段。


2.4 views.py

业务逻辑层,包含存取模型及调用相应模板的相关逻辑,是模型M和模板T之间的桥梁。在Django得到用户的请求后,根据url映射关系到调用相应的视图,视图则调用和处理有关的数据。

基本上业务逻辑处理都在views.py实现,也就是说可能要导N多包。

1# -*- coding: utf-8 -*-
2# Create your views here.
3
4from django.shortcuts import render,redirect,render_to_response
5from Dreaming import models
6from django.template.loader import get_template
7from django.http import HttpResponse
8
9from .forms import LoginForm         ### 用户登录表单
10from .forms import RegistrationForm  ### 用户注册表单
11
12import os
13import sys
14
15def index(request):
16    return render(request,"Cloud/index.html") # pass
17
18def login(request):
19    if request.method == "POST":
20        login_form = LoginForm(request.POST)
21        if login_form.is_valid():
22            username = login_form.cleaned_data['username']
23            password = login_form.cleaned_data['password']
24            try:
25                user = models.UserProfile.objects.get(username=username)
26                if user.password == password:
27                    return render(request, 'Cloud/index.html')
28                else:
29                    message = "密码不正确!"
30            except:
31                message = "用户不存在!"
32        return render(request, 'Cloud/login.html',locals())
33    else:
34        login_form = LoginForm()
35        return render(request,'Cloud/login.html')
36
37def register(request):
38    if request.method == "POST":
39        register_form = RegistrationForm(request.POST)
40        if register_form.is_valid():
41            new_user = register_form.save(commit=False)
42            username = register_form.cleaned_data['username']
43            emailaddr = register_form.cleaned_data['emailaddr']
44            password = register_form.cleaned_data['password']
45            password2 = register_form.cleaned_data['password2']
46            exist_user = models.UserProfile.objects.filter(username=username)
47            if exist_user:
48                message = "用户已经存在,请重新选择用户名!"
49                return render(request, 'Cloud/register.html', locals())
50            else:
51                if password != password2:
52                    message = "两次输入的密码不同!"
53                    return render(request, 'Cloud/register.html', locals())
54                else:
55                    new_user.username = username
56                    new_user.password = password
57                    new_user.emailaddr = emailaddr
58                    new_user.save()
59                    return redirect('Dreaming:login')
60    else:
61        register_form = RegistrationForm()
62        return render(request, 'Cloud/register.html', locals())



说明
4render(request, )是后者的快捷方式,render_to_reponse()将数据渲染到指定模板。redirect跳转url页面。
10-11
import 表单类
17login视图函数,处理前端提交登陆的数据,视图函数必须使用request作为第一个参数。
18
request.method是HttpRequest对象的一个常用属性,本次前端浏览器向服务器提交表单内容(类字典对象),采用POST方法。
19
建立绑定实例。
20
验证传入的数据是否合法,是否符合表单类属性要求。True为符合,False为不符合。
21-22
cleaned_data,以字典形式返回实例具体数据(前端输入的用户名、密码),若传入数据不合法,则cleaned_data结果无法显示。
24-26
从数据库的表过滤username字段的值,并返回对象(含该行所有字段信息),如果存在,且对象密码与前端输入的密码相等,则返回app的index页面。
28-31
渲染,如果密码不对,网页会显示报错信息(自定义显示信息)。
40
commit=False,数据还未保存到数据库,只是生成了一个数据对象。
54-56
因为表单返回的键值,与数据库表中的字段并非一一对应,含密码验证,故逐一指定字段的值。
57
保存到数据库中。



演示

04


4.1 注册已经存在用户报错


4.2 注册密码不一致


4.3 用户注册成功


4.4 用户登陆报错


4.5 用户成功登陆


还等什么,抄家伙啊!

——————我是安老师下期预告的分割线——————

"安老师,你这用户登陆还告诉别人密码错误啊,别人不黑死你啊?"。

"只是演示,无伤大雅!应该把时间花在解决痛点上,而不是为了好看而好看哈!

下期分享什么好呢?一键部署mysql集群、一键生成Oracle所有重启项还是本次的报错汇总呢?敬请期待!"


如有侵权,请联系删除,谢谢!


往期回顾

Python切割文件教程一 | 我的“大马士革命刀"

Python切割文件教程二 | 我的“大马士革命刀"不Like补刀

Django博客教程一  |  Django架构介绍

Django博客教程二  |  Django入门版博客

Django博客教程三  |  Django进阶版博客数据篇

Django博客教程四  |  Django进阶版博客网页篇


Python

自动化运维

长按识别左侧二维码,

关注Python自动化运维喔~

继续滑动看下一个

Python自动化运维之改造网页模板

小安Sir Python自动化运维
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存