Fork me on GitHub

hexo设置

hexo设置

typora编写的md文档,其中的图片会存放到 文件同名.asset文件夹下,编译成网页后,图片未显示出来;解决方案: 参考blog

我采取的解决方案

_config.yml

1
post_asset_folder: true

post_asset_folder 设置为True,在创建md文件时,才会创建同名的存放文件的文件夹

image-20221014162708065

若想hexo能读取到图片,图片必须存放在同名的文件夹下:

image-20221013130807591

image-20221013130807591

没有 django设置.assets 目录,图片存放在 django设置 目录下,image-20221013130807591

在hexo编译后依然能显示出图片

django设置

Django设置

apps

在项目根目录下创建apps目录,把app都放在apps文件夹下

image-20221012215758162

1
2
3
# 新建apps目录
cd apps
python ../manage.py startapp users

apps目录添加进系统路径中

settings.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import sys
import os

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# 添加导包路径
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",

# apps for this project
"users.apps.UsersConfig",
]

由于apps已进入系统目录,故"users.apps.UsersConfig",无需写前面的apps文件夹名

migrations

报错

出现了 如下报错

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency users.0001
_initial on database ‘default’.

  • 根据报错的信息,删除数据库中,该表的数据。

image-20221011172831519

  • 鼠标右键点击删除
image-20221011172932906
  • 提交,保存修改到数据库中
image-20221011173040345
  • 重新进行迁移,但是依然失败了image-20221011173333682

  • 根据报错信息,将表 django_admin_log删除

  • 继续报错,继续删表

    image-20221013130807591

  • 把数据库中的很多表删除后,重新迁移

若还遇到其他迁移失败的报错,可以尝试如下操作:

  1. 删除数据库记录该model的记录

image-20221013161725041

  1. 删除记录迁移的文件,接着重新迁移;

image-20221013161452474

密码正确登录不上

修改管理员密码后,发现还是登录不上,我是按如下方式处理的

  • 删除了数据库的所有表,除了sqlite_开头的两个表

image-20221013183956861

  • 清理记录迁移的文件

    image-20221013161452474

跨域

前后端在不同的域名下,需要解决跨域问题

Simple JWT

djangorestframework-jwt库,在17年已不再维护,推荐使用

CORS

提交token时,被Django的CORS给拦截了

pip install django-cors-headers

Django项目关于跨域cors及解决方案(配置项)

Postman

这篇文章 关于 postman给 jwt 传递参数写的比较细

我发现使用 postman,不会涉及到CORS,以及跨域访问的问题;即使没有在Django 的 setting.py中进行任何的设置,Postman也是可以使用

使用Postman编辑传递的参数,使用网页端的postman失败了

image-20221013220548895

下载了桌面版的Postman传参,成功

1
2
3
4
{
"refresh": "xxx",
"access": "xxx"
}

使用access作为token,提交给服务器

pyVSjs

pyVSjs

数组赋值

一维数组

python

arr = [0] * n;

javascript

const idx1 = new Array(n).fill(0);

判真

经常会使用 while(xxx) 或者 if(xxx)

[ ] 空数组

python

  • [ ] 转 bool是 False

javascript

  • [ ] 转bool是 true

排序

排序基础知识

javascript

1
2
arr = [...];
arr.sort((a,b)=>a-b);
  • arr.sort((a,b)=>a-b);

    从小往大排序

  • arr.sort((a,b)=>b-a);

    从大往小排序

js的 arr.sort(),与python不同,js有返回值的,但是返回值是原数组的引用,不是深拷贝;

py的arr.sort(),无返回值;

保留下标排序

希望数组经过排序后,依然保留着原先的下标

python

1
2
3
n = len(nums1)
idx1 = list(range(n))
idx1.sort(key=lambda x: nums1[x])

javascript

1
idx1.sort((i, j) => nums1[i] - nums1[j]);

DRF

DRF

创建Serializer对象

除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

1
DepartmentSerializer(data={'name': '运营'},context={"add":"end"})

DepartmentSerializer序列化器内部使用context:

1
2
3
4
def validate_name(self, attrs):
if '部' not in attrs:
return attrs + "部" + self.context.get('add')
return attrs

使用self.context,即可拿到传入的额外参数值

在序列化器定义的createupdate函数的返回最后给到save()的返回值

1
2
3
4
5
6
class DepartmentSerializer(serializers.Serializer):
...
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.save()
return "instance"

mysql

1
2
3
4
5
--两种情况
--1.新建数据库
CREATE DATABASE 数据库名称 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
--2.修改原有数据库
ALTER DATABASE 数据库名称 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

sql django文档

utf8_general_ci 字符序。这将导致所有字符串的平等比较以一种 不区分大小写 的方式

leetcode入门

leetcode

动态规划

  • 节约空间

动态规划经常用到一个记录状态的数组,若始终只用到当前值和前一个值的话,只需使用一个变量存下前一个值即可。无需使用数组存一些以后不会用到的值。

结尾检查

2414. 最长的字母序连续子字符串的长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
def longestContinuousSubstring(self, s: str) -> int:
max_len = 1
pre = s[0]
cnt = 1
for ch in s[1::]:
if ord(ch) - ord(pre) == 1:
cnt += 1
else:
max_len = max(max_len,cnt)
cnt = 1
pre = ch
# 容易遗漏
max_len = max(max_len,cnt)
return max_len

最后在循环外的 max_len = max(max_len,cnt) 检查,很容易遗漏。

在for循环中的检查不会遗漏,但是若恰好在循坏的最后一个阶段得到了最后解,此时循环结束,没有下一个循环状态来更新,所以造成漏解。故若循环有状态更新,一定留意循环结束时的状态是否需要更新。

token认证

token

token适用于前后端分离项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import time
from django.core import signing
import hashlib

HEADER = {'typ': 'JWP', 'alg': 'default'}
KEY = "jie220622-fd%HG56Fsgy-fdsM4&%ghNh44da64"
SALT = "jieshenai"


def encrypt(obj):
"""加密:signing 加密 and Base64 编码"""
value = signing.dumps(obj, key=KEY, salt=SALT)
value = signing.b64_encode(value.encode()).decode()
return value


def decrypt(src):
"""解密:Base64 解码 and signing 解密"""
src = signing.b64_decode(src.encode()).decode()
raw = signing.loads(src, key=KEY, salt=SALT)
return raw


def create_token(username):
"""生成token信息"""
# 1. 加密头信息
header = encrypt(HEADER)
# 2. 构造Payload(有效期28天)
payload = {"username": username, "iat": time.time(),
"exp": time.time() + 2419200.0}
payload = encrypt(payload)
# 3. MD5 生成签名
md5 = hashlib.md5()
md5.update(("%s.%s" % (header, payload)).encode())
signature = md5.hexdigest()
token = "%s.%s.%s" % (header, payload, signature)
return token


def get_payload(token):
"""解析 token 获取 payload 数据"""
payload = str(token).split('.')[1]
payload = decrypt(payload)
return payload


def get_username(token):
"""解析 token 获取 username"""
payload = get_payload(token)
return payload['username']


def get_exp_time(token):
"""解析 token 获取过期时间"""
payload = get_payload(token)
return payload['exp']


def check_token(username, token):
"""验证 token:检查 username 和 token 是否一致且未过期"""
return get_username(token) == username and get_exp_time(token) > time.time()

用户在登录时,服务器端检查用户的账号和密码无误后:

根据用户名创建token,token中设定了token的有效期, 将token返回给用户

1
return JsonResponse({"code": 200, "data": {"token": _token, "nickName": username}})

用户的浏览器接收到token后,将token存到内存中,以后发起请求时,将token带上。(这一步不是浏览器自动完成,由前端程序员,使用js编码实现)

后端在app/middleware/auth.py 中间件中,对用户的每一次请求进行token验证。

前端的请求会将token, username放置到request.headers中,

使用request.headers.get("token") 即可拿到token值。

Vue简洁之道

Vue 简化代码

下述代码是从组件中抽取出来的;

1
2
3
4
5
export function fillParagraphText() {
let nodes = this.$refs.content.childNodes;
let arr = paragraphTextArr(nodes);
this.$store.commit("paper/fill", { paperId: this.paperId, chse: this.chse, arr });
}

我们希望下述函数体内的this指向依然是原来的组件;只需在组件的method中接收上述函数即可;

1
2
3
methods: {
fillParagraphText,
}

因为javascript,this 它是动态的,this 由调用它的对象决定;

this

this

函数的this

单个函数的this是什么

window

嵌套函数的this

1
2
3
4
5
6
7
8
9
function parent() {
let name = "parent";
function son() {
let name = "son";
console.log(this);
}
son();
}
parent();

输出也是window

对象

单层函数

1
2
3
4
5
6
7
let obj = {
name: "obj",
sayHi: function () {
console.log(this);
},
}
obj.sayHi();

obj 这个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
let parent = {
name: "parent",
son() {
let name = "son";
let arrow = () => {
console.log("arrow", this);
};
function th() {
console.log("th", this);
}
return {
name: "re",
arrow,
th,
}
}
}
parent.son().arrow();
parent.son().th();
</script>

1
2
arrow {name: 'parent', son: ƒ}
th {name: 're', arrow: ƒ, th: ƒ}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
grandPa = {
name: "gradnPa",
parent() {
// let name = "parent";
return function son() {
let name = "son";
let arrow = () => {
console.log("arrow", this);
};
function th() {
console.log("th", this);
}
return {
name: "re",
arrow,
th,
}
}
}
}
grandPa.parent()().arrow();
grandPa.parent()().th();
</script>

arrow Window {window: Window, self: Window, document: document, name: ‘’, location: Location, …}
th {name: ‘re’, arrow: ƒ, th: ƒ}

less

less

less官网: https://lesscss.org/

参考笔记: https://brucecai55520.gitee.io/bruceblog/notes/less/less.html

vscode安装插件:Easy LESS

浏览器测试

1
2
3
4
5
6
7
8
9
10
11
<style type="text/less">
.head {
background-color: skyblue;
p {
color: red;
}
}
</style>

// 写在尾部
<script src="./less-1.3.1.min.js"></script>

注释

// 开头注释,不会被编译到css文件中

/**/包裹的注释,被编译到css文件中

less 变量

1
2
3
4
5
6
7
8
9
10
11
<style scoped lang="less">
@color: aqua;
@selector: p;
@c: color;

.head {
@{selector} {
@{c}: @color;
}
}
</style>

@{c}: @color; 展示了属性名和属性值作为变量的写法;

属性名 和 选择器 作为变量需要用{}包裹;

变量的延迟加载

less 内的变量都是块级作用域, 延迟加载;

1
2
3
4
5
6
7
8
9
10
@var: 0;
.class{
@var: 1;
.brass{
@var: 2;
three: @var; // 3,延迟加载
@var: 3;
}
one: @var;
}

编译后的结果是:

1
2
3
4
5
6
.class{
one: 1;
}
.class .brass{
three: 3;
}

css嵌套规则

1
2
3
4
5
.cls{
&:hover{
xxx
}
}

&表示平级;

若不加编译之后是: .cls :hover,就变成了父子关系;

less混合

混合将一系列属性从一个规则集,引入到另一个规则集;

1
2
3
4
5
6
7
8
<div class="head">
<p class="c1">
文字
</p>
<p class="c2">
文字
</p>
</div>

普通混合

.c1 和 .c2 直接使用.func定义好的样式

1
2
3
4
5
6
7
8
9
10
11
12
13
.func {
color: red;
}

.head {
.c1 {
.func;
}

.c2 {
.func;
}
}

带参数的混合

带参数,指定默认值为 aqua

1
2
3
.func(@c: aqua) {
color: @c;
}

调用

1
2
3
4
5
6
7
.c1 {
.func(pink);
}

.c2 {
.func();
}

命名参数

在传实参时,指定参数; 用于有多个参数和默认参数值时,指定传的参数;

1
.func(@c:aqua)

匹配模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<template>
<div class="container">
<div class="son">
</div>
</div>
</template>

<script>
export default {
name: "MyHello"
}
</script>

<style scoped lang="less">
.pos(@_, @w, @h) {
background-color: red;
}

.pos(L, @w, @h) {
float: left;
width: 200px;
height: 200px;
}

.pos(R, @w, @h) {
float: right;
width: @w;
height: @h;
}

.container {
width: 300px;
height: 300px;
background-color: aquamarine;
.son {
.pos(R, 200px, 200px);
}
}
</style>

.pos,通过在形参里添加标志L,R,从而避免了重新定义混合的问题;

.pos(@_, @w, @h) 都能匹配上,可以上公共部分放在其中。

arguments 变量

实参列表

1
2
3
4
5
6
7
.border(@w,@sytle,@c){
border: @arguments;
}

.xxxClass {
.border(1px,solid,black)
}

计算

在less计算中,双方只要有一方带单位就行了

1
2
3
.xxxClass{
width: (100 + 100px);
}

继承

混合的缺点:在转成css时,很多共有的css属性不能合并,这样导致文件变大;

如下的代码,在混合中实现不了

1
2
3
h1,h2{
...
}

继承不能带参数;

继承性能比混合高,灵活性没有混合强;

1
2
3
4
5
6
7
8
9
10
.parent{
background-color: aqua;
}

.div:extend(.parent){
width: 200px;
&:nth-child(1){
font-size: 12px;
}
}

1
2
3
.parent{
background-color: aqua;
}

错误写法❌

父后面不能跟(),也不能像继承那样参数

1
2
3
.parent(){

}

继承的两种写法

  • 1
    2
    3
    .div:extend(.parent){

    }
  • 1
    2
    3
    .div{
    &:extend(.parent);
    }

继承 all

1
2
3
4
5
6
7
.parent{
background-color: aqua;
}

.parent:hover{
background-color: skyblue;
}

.parent 指定了鼠标悬浮更换背景色;在继承时,需要在其后加上 all, .parent:hover 才会生效;

1
&:extend(.parent all);

编译成css

1
2
3
4
5
6
7
8
9
10
.parent,
.div {
background-color: aqua;
}
.div {
width: 200px;
}
.div:nth-child(1) {
font-size: 12px;
}

由于.div继承了.parent,故形成了如下代码

1
2
3
4
.parent,
.div {
background-color: aqua;
}

避免编译

  • Copyrights © 2022 Jie Shen
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信