Rest-framework框架的基本组件
快速实例:
https://www.django-rest-framework.org/tutorial/quickstart/#quickstart
序列化类
开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json
之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。
简单实用(基于django原生serializers基于CBV)
models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
pub_date = models.DateField()
publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
authors = models.ManyToManyField("Author")
def __str__(self):
return self.title
class Publish(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
def __str__(self):
return self.name<wiz_code_mirror>
28
1
from django.db import models
2
3
4
class Book(models.Model):
5
title = models.CharField(max_length=32)
6
price = models.IntegerField()
7
pub_date = models.DateField()
8
publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
9
authors = models.ManyToManyField("Author")
10
11
def __str__(self):
12
return self.title
13
14
15
class Publish(models.Model):
16
name = models.CharField(max_length=32)
17
email = models.EmailField()
18
19
def __str__(self):
20
return self.name
21
22
23
class Author(models.Model):
24
name = models.CharField(max_length=32)
25
age = models.IntegerField()
26
27
def __str__(self):
28
return self.name
方式一:
分发url
...
path(‘publishes/‘, views.PublishesView.as_view()),
...<wiz_code_mirror>
3
1
...
2
path(‘publishes/‘, views.PublishesView.as_view()),
3
...
视图类
import json
from django.shortcuts import render, HttpResponse
from django.views import View
from django.forms.models import model_to_dict
from .models import *
class PublishesView(View):
# Publish.objects.all().values("name", "email")
# <QuerySet [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘123@qq.com‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘234@qq.com‘}]>
# list(Publish.objects.all().values("name", "email"))
# [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘123@qq.com‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘234@qq.com‘}]
def get(self, request):
# 序列化方式一
# publish_list = list(Publish.objects.all().values("name", "email")) # 注意这个list()
# return HttpResponse(json.dumps(publish_list))
# 序列化方式二
# 使用model_to_dict(obj)
# publish_list = Publish.objects.all()
# temp = []
# for obj in publish_list: # 每一个obj就是类对象
"""
temp.append({
"name": "obj.name",
"email": "obj.email"
})
"""
# temp.append(model_to_dict(obj))
# return HttpResponse(json.dumps(temp))
# 序列化方式三
# publish_list = Publish.objects.all()
# from django.core import serializers
# ret = serializers.serialize(‘json‘, publish_list)
# return HttpResponse(ret)
采用restframework
def post(self, request):
pass<wiz_code_mirror>
41
1
import json
2
from django.shortcuts import render, HttpResponse
3
from django.views import View
4
from django.forms.models import model_to_dict
5
from .models import *
6
7
8
class PublishesView(View):
9
# Publish.objects.all().values("name", "email")
10
# <QuerySet [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘[email protected]‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘[email protected]‘}]>
11
# list(Publish.objects.all().values("name", "email"))
12
# [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘[email protected]‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘[email protected]‘}]
13
def get(self, request):
14
# 序列化方式一
15
# publish_list = list(Publish.objects.all().values("name", "email")) # 注意这个list()
16
# return HttpResponse(json.dumps(publish_list))
17
18
# 序列化方式二
19
# 使用model_to_dict(obj)
20
# publish_list = Publish.objects.all()
21
# temp = []
22
# for obj in publish_list: # 每一个obj就是类对象
23
"""
24
temp.append({
25
"name": "obj.name",
26
"email": "obj.email"
27
})
28
"""
29
# temp.append(model_to_dict(obj))
30
# return HttpResponse(json.dumps(temp))
31
32
# 序列化方式三
33
# publish_list = Publish.objects.all()
34
# from django.core import serializers
35
# ret = serializers.serialize(‘json‘, publish_list)
36
# return HttpResponse(ret)
37
38
采用restframework
39
40
def post(self, request):
41
pass
使用rest_framework来序列化
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.views import APIView
# 为queryset做序列化
class PublishSerializers(serializers.Serializer):
"""等同于form.Form"""
name = serializers.CharField()
email = serializers.CharField()
class PublishesView(APIView):
def get(self, request):
publish_list = Publish.objects.all()
ps = PublishSerializers(publish_list, many=True) # 即可接收Queryset 也可接收 model_obj
return Response(ps.data)
def post(self, request):
pass<wiz_code_mirror>
20
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4
5
6
# 为queryset做序列化
7
class PublishSerializers(serializers.Serializer):
8
"""等同于form.Form"""
9
name = serializers.CharField()
10
email = serializers.CharField()
11
12
13
class PublishesView(APIView):
14
def get(self, request):
15
publish_list = Publish.objects.all()
16
ps = PublishSerializers(publish_list, many=True) # 即可接收Queryset 也可接收 model_obj
17
return Response(ps.data)
18
19
def post(self, request):
20
pass
得到的结果在页面中不会显示,会在postmen中显示
[
{
"name": "苹果出版社",
"email": "123@qq.com"
},
{
"name": "橘子出版社",
"email": "234@qq.com"
}
]<wiz_code_mirror>
10
1
[
2
{
3
"name": "苹果出版社",
4
"email": "[email protected]"
5
},
6
{
7
"name": "橘子出版社",
8
"email": "[email protected]"
9
}
10
]
解析器request类
django的request类和rest-framework的request类的源码解析
依然是上面的代码 用postmen发送一次post请求
class PublishesView(View):
def post(self, request):
print("POST", request.POST)
print("BODY", request.body)
return HttpResponse("POST")
>>>POST <QueryDict: {‘a‘: [‘1‘], ‘b‘: [‘2‘]}>
[18/Oct/2018 16:19:02] "POST /publishes/ HTTP/1.1" 200 4
BODY b‘a=1&b=2‘<wiz_code_mirror>
10
1
class PublishesView(View):
2
def post(self, request):
3
print("POST", request.POST)
4
print("BODY", request.body)
5
6
return HttpResponse("POST")
7
8
>>>POST <QueryDict: {‘a‘: [‘1‘], ‘b‘: [‘2‘]}>
9
[18/Oct/2018 16:19:02] "POST /publishes/ HTTP/1.1" 200 4
10
BODY b‘a=1&b=2‘
这个过程里面到底发生了什么?
# request 源码的入口
from django.core.handlers.wsgi import WSGIRequest<wiz_code_mirror>
2
1
# request 源码的入口
2
from django.core.handlers.wsgi import WSGIRequest
rest_framework下面的APIview
from rest_framework.views import APIView<wiz_code_mirror>
1
1
from rest_framework.views import APIView
OK reas_framework request 请求的取值问题
from rest_framework.response import Response
from rest_framework.views import APIView
class PublishesView(APIView):
def post(self, request):
# 原生的request支持的操作
# print("POST", request.POST)
# print("BODY", request.body)
return Response("POST")
<wiz_code_mirror>
12
1
from rest_framework.response import Response
2
from rest_framework.views import APIView
3
4
5
class PublishesView(APIView):
6
def post(self, request):
7
# 原生的request支持的操作
8
# print("POST", request.POST)
9
# print("BODY", request.body)
10
11
return Response("POST")
12
from rest_framework import serializers
from rest_framework.response import Response
from rest_framework.views import APIView
# 为queryset做序列化
class BookSerializers(serializers.Serializer):
"""Book表是一个比较复杂的表包含了一对多与多对多"""
title = serializers.CharField()
price = serializers.IntegerField()
pub_date = serializers.DateField()
# 这怎么办?
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
# authors = models.ManyToManyField("Author") # 多对多
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
# 多对多的话这个sourse不好使,得到的是Queryset
authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
bs = BookSerializers(book_list, many=True)
return Response(bs.data)
def post(self, request):
pass<wiz_code_mirror>
27
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4
5
6
# 为queryset做序列化
7
class BookSerializers(serializers.Serializer):
8
"""Book表是一个比较复杂的表包含了一对多与多对多"""
9
title = serializers.CharField()
10
price = serializers.IntegerField()
11
pub_date = serializers.DateField()
12
# 这怎么办?
13
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
14
# authors = models.ManyToManyField("Author") # 多对多
15
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
16
# 多对多的话这个sourse不好使,得到的是Queryset
17
authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
18
19
20
class BookView(APIView):
21
def get(self, request):
22
book_list = Book.objects.all()
23
bs = BookSerializers(book_list, many=True)
24
return Response(bs.data)
25
26
def post(self, request):
27
pass
Postmen中的数据
[
{
"title": "你好,再见",
"price": 99,
"pub_date": null,
"publish": "苹果出版社",
"authors": "<QuerySet [<Author: pontoon>, <Author: toonpon>]>" # 得到一个QuerySet
},
{
"title": "再见,你好",
"price": 88,
"pub_date": null,
"publish": "橘子出版社",
"authors": "<QuerySet [<Author: pontoon>]>"
},
{
"title": "谁动了我的奶酪?",
"price": 77,
"pub_date": null,
"publish": "苹果出版社",
"authors": "<QuerySet []>"
}
]<wiz_code_mirror>
23
1
[
2
{
3
"title": "你好,再见",
4
"price": 99,
5
"pub_date": null,
6
"publish": "苹果出版社",
7
"authors": "<QuerySet [<Author: pontoon>, <Author: toonpon>]>" # 得到一个QuerySet
8
},
9
{
10
"title": "再见,你好",
11
"price": 88,
12
"pub_date": null,
13
"publish": "橘子出版社",
14
"authors": "<QuerySet [<Author: pontoon>]>"
15
},
16
{
17
"title": "谁动了我的奶酪?",
18
"price": 77,
19
"pub_date": null,
20
"publish": "苹果出版社",
21
"authors": "<QuerySet []>"
22
}
23
]
# 为queryset做序列化
class BookSerializers(serializers.Serializer):
"""Book表是一个比较复杂的表包含了一对多与多对多"""
title = serializers.CharField()
price = serializers.IntegerField()
pub_date = serializers.DateField()
# 这怎么办?
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
# authors = models.ManyToManyField("Author") # 多对多
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
# 多对多的话这个sourse不好使,得到的是Queryset
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
# 多对多这样来整
authors = serializers.SerializerMethodField()
def get_authors(self, obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
bs = BookSerializers(book_list, many=True)
return Response(bs.data)
def post(self, request):
pass<wiz_code_mirror>
31
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
"""Book表是一个比较复杂的表包含了一对多与多对多"""
4
title = serializers.CharField()
5
price = serializers.IntegerField()
6
pub_date = serializers.DateField()
7
# 这怎么办?
8
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
9
# authors = models.ManyToManyField("Author") # 多对多
10
publish = serializers.CharField(source="publish.name") # 一对多、类名小写
11
# 多对多的话这个sourse不好使,得到的是Queryset
12
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
13
14
# 多对多这样来整
15
authors = serializers.SerializerMethodField()
16
17
def get_authors(self, obj):
18
temp = []
19
for obj in obj.authors.all():
20
temp.append(obj.name)
21
return temp
22
23
24
class BookView(APIView):
25
def get(self, request):
26
book_list = Book.objects.all()
27
bs = BookSerializers(book_list, many=True)
28
return Response(bs.data)
29
30
def post(self, request):
31
pass
Postmen
[
{
"title": "你好,再见",
"price": 99,
"pub_date": null,
"publish": "苹果出版社",
"authors": [
"pontoon",
"toonpon"
]
},
{
"title": "再见,你好",
"price": 88,
"pub_date": null,
"publish": "橘子出版社",
"authors": [
"pontoon"
]
},
{
"title": "谁动了我的奶酪?",
"price": 77,
"pub_date": null,
"publish": "苹果出版社",
"authors": []
}
]<wiz_code_mirror>
28
1
[
2
{
3
"title": "你好,再见",
4
"price": 99,
5
"pub_date": null,
6
"publish": "苹果出版社",
7
"authors": [
8
"pontoon",
9
"toonpon"
10
]
11
},
12
{
13
"title": "再见,你好",
14
"price": 88,
15
"pub_date": null,
16
"publish": "橘子出版社",
17
"authors": [
18
"pontoon"
19
]
20
},
21
{
22
"title": "谁动了我的奶酪?",
23
"price": 77,
24
"pub_date": null,
25
"publish": "苹果出版社",
26
"authors": []
27
}
28
]
这样的数据就比较好
ModelSerialezer
POST请求的数据
# 为queryset做序列化
class BookSerializers(serializers.Serializer):
"""Book表是一个比较复杂的表包含了一对多与多对多"""
title = serializers.CharField()
price = serializers.IntegerField()
pub_date = serializers.DateField()
# 这怎么办?
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
# authors = models.ManyToManyField("Author") # 多对多
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
# 多对多的话这个sourse不好使,得到的是Queryset
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
# 多对多这样来整
authors = serializers.SerializerMethodField()
def get_authors(self, obj):
temp = []
for obj in obj.authors.all():
temp.append(obj)
return temp
# 这个地方我们对字段进行了一些列的定制
class BookView(APIView):
def get(self, request):
...
def post(self, request):
bs = BookSerializers(data=request.data)
if bs.is_valid(): # 验证码提交过来的数据是否合格
print(bs.validated_data) # 如果是合格的数据走了内置的create()方法,将提交过来的保存至数据库中!
bs.save() # 保存
return Response(bs.data) # 返回数据
else:
return Response(bs.errors) # 返回错误<wiz_code_mirror>
37
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
"""Book表是一个比较复杂的表包含了一对多与多对多"""
4
title = serializers.CharField()
5
price = serializers.IntegerField()
6
pub_date = serializers.DateField()
7
# 这怎么办?
8
# publish = models.ForeignKey("Publish", on_delete=models.CASCADE) # 一对多
9
# authors = models.ManyToManyField("Author") # 多对多
10
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
11
# 多对多的话这个sourse不好使,得到的是Queryset
12
# authors = serializers.CharField(source="authors.all") # 多对多、类名小写.all() 自动执行
13
14
# 多对多这样来整
15
authors = serializers.SerializerMethodField()
16
17
def get_authors(self, obj):
18
temp = []
19
for obj in obj.authors.all():
20
temp.append(obj)
21
return temp
22
23
# 这个地方我们对字段进行了一些列的定制
24
25
26
class BookView(APIView):
27
def get(self, request):
28
...
29
30
def post(self, request):
31
bs = BookSerializers(data=request.data)
32
if bs.is_valid(): # 验证码提交过来的数据是否合格
33
print(bs.validated_data) # 如果是合格的数据走了内置的create()方法,将提交过来的保存至数据库中!
34
bs.save() # 保存
35
return Response(bs.data) # 返回数据
36
else:
37
return Response(bs.errors) # 返回错误
用postmen传数据过来会报错
该咋整,如何将数据保存至数据库中咧?
class BookSerializers(serializers.ModelSerializer):
"""Book表是一个比较复杂的表包含了一对多与多对多"""
class Meta:
model = Book
fields = "__all__"
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
def create(self, validated_data):
"""重写源码中的create方法"""
print("validated_data", validated_data)
book = Book.objects.create(title=validated_data["title"],
price=validated_data[‘price‘],
publish_id=validated_data[‘publish‘][‘pk‘],
)
book.authors.add(*validated_data["authors"])
return book
>>> validated_data {‘publish‘: {‘pk‘: ‘1‘}, ‘title‘: ‘java‘, ‘price‘: 20, ‘authors‘: [<Author: pontoon>, <Author: toonpon>]}
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
bs = BookSerializers(book_list, many=True)
return Response(bs.data)
def post(self, request):
bs = BookSerializers(data=request.data)
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return Response(bs.errors)<wiz_code_mirror>
34
1
class BookSerializers(serializers.ModelSerializer):
2
"""Book表是一个比较复杂的表包含了一对多与多对多"""
3
class Meta:
4
model = Book
5
fields = "__all__"
6
publish = serializers.CharField(source="publish.pk") # 一对多、类名小写
7
8
def create(self, validated_data):
9
"""重写源码中的create方法"""
10
print("validated_data", validated_data)
11
book = Book.objects.create(title=validated_data["title"],
12
price=validated_data[‘price‘],
13
publish_id=validated_data[‘publish‘][‘pk‘],
14
)
15
book.authors.add(*validated_data["authors"])
16
return book
17
18
>>> validated_data {‘publish‘: {‘pk‘: ‘1‘}, ‘title‘: ‘java‘, ‘price‘: 20, ‘authors‘: [<Author: pontoon>, <Author: toonpon>]}
19
20
21
22
class BookView(APIView):
23
def get(self, request):
24
book_list = Book.objects.all()
25
bs = BookSerializers(book_list, many=True)
26
return Response(bs.data)
27
28
def post(self, request):
29
bs = BookSerializers(data=request.data)
30
if bs.is_valid():
31
bs.save()
32
return Response(bs.data)
33
else:
34
return Response(bs.errors)
Postmen在次提交数据
返回成功啦! ,不过这也太吉儿的复杂了把,还得花时间整理!透~
单条数据的get/post请求
url
# 获取所有数据的URL
path(‘books/‘, views.BookView.as_view()),
# 获取单条数据的URL
path(‘books/<int:pk>‘, views.BookDetailView.as_view()),<wiz_code_mirror>
4
1
# 获取所有数据的URL
2
path(‘books/‘, views.BookView.as_view()),
3
# 获取单条数据的URL
4
path(‘books/<int:pk>‘, views.BookDetailView.as_view()),
视图
class BookDetailView(APIView):
"""获取单条数据"""
def get(self, request, pk):
book = Book.objects.get(pk=pk)
bs = BookModelSerializers(book)
return Response(bs.data)
def put(self, request, pk):
""" 想那张表提交那条数据 """
book = Book.objects.get(pk=pk)
bs = BookModelSerializers(book, data=request.data)
if bs.is_valid():
bs.save()
return Response(bs.errors)
def delete(self, request, pk):
Book.objects.get(pk=pk).delete()
return Response()<wiz_code_mirror>
x
1
class BookDetailView(APIView):
2
"""获取单条数据"""
3
def get(self, request, pk):
4
book = Book.objects.get(pk=pk)
5
bs = BookModelSerializers(book)
6
return Response(bs.data)
7
8
def put(self, request, pk):
9
""" 想那张表提交那条数据 """
10
book = Book.objects.get(pk=pk)
11
bs = BookModelSerializers(book, data=request.data)
12
if bs.is_valid():
13
bs.save()
14
return Response(bs.errors)
15
16
def delete(self, request, pk):
17
Book.objects.get(pk=pk).delete()
18
19
return Response()
序列化超链接字段
第二步
效果如图
.wiz-editor-body .wiz-code-container { position: relative; padding: 8px 0; margin: 5px 25px 5px 5px; text-indent: 0; text-align: left }
.CodeMirror { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; color: black; font-size: 0.875rem }
.wiz-editor-body .wiz-code-container .CodeMirror div { margin-top: 0; margin-bottom: 0 }
.CodeMirror-lines { padding: 4px 0 }
.CodeMirror pre { padding: 0 4px }
.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler { background-color: white }
.CodeMirror-gutters { border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap }
.CodeMirror-linenumbers { }
.CodeMirror-linenumber { padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; white-space: nowrap }
.CodeMirror-guttermarker { color: black }
.CodeMirror-guttermarker-subtle { color: #999 }
.CodeMirror-cursor { border-left: 1px solid black; border-right: none; width: 0 }
.CodeMirror div.CodeMirror-secondarycursor { border-left: 1px solid silver }
.cm-fat-cursor .CodeMirror-cursor { width: auto; border: 0 !important; background: #7e7 }
.cm-fat-cursor div.CodeMirror-cursors { z-index: 1 }
.cm-animate-fat-cursor { width: auto; border: 0; background-color: #7e7 }
.CodeMirror-overwrite .CodeMirror-cursor { }
.cm-tab { display: inline-block; text-decoration: inherit }
.CodeMirror-rulers { position: absolute; left: 0; right: 0; top: -50px; bottom: -20px; overflow: hidden }
.CodeMirror-ruler { border-left: 1px solid #ccc; top: 0; bottom: 0; position: absolute }
.cm-s-default .cm-header { color: blue }
.cm-s-default .cm-quote { color: #090 }
.cm-negative { color: #d44 }
.cm-positive { color: #292 }
.cm-header,.cm-strong { font-weight: bold }
.cm-em { font-style: italic }
.cm-link { text-decoration: underline }
.cm-strikethrough { text-decoration: line-through }
.cm-s-default .cm-keyword { color: #708 }
.cm-s-default .cm-atom { color: #219 }
.cm-s-default .cm-number { color: #164 }
.cm-s-default .cm-def { color: #00f }
.cm-s-default .cm-variable,.cm-s-default .cm-punctuation,.cm-s-default .cm-property,.cm-s-default .cm-operator { }
.cm-s-default .cm-variable-2 { color: #05a }
.cm-s-default .cm-variable-3 { color: #085 }
.cm-s-default .cm-comment { color: #a50 }
.cm-s-default .cm-string { color: #a11 }
.cm-s-default .cm-string-2 { color: #f50 }
.cm-s-default .cm-meta { color: #555 }
.cm-s-default .cm-qualifier { color: #555 }
.cm-s-default .cm-builtin { color: #30a }
.cm-s-default .cm-bracket { color: #997 }
.cm-s-default .cm-tag { color: #170 }
.cm-s-default .cm-attribute { color: #00c }
.cm-s-default .cm-hr { color: #999 }
.cm-s-default .cm-link { color: #00c }
.cm-s-default .cm-error { color: #f00 }
.cm-invalidchar { color: #f00 }
.CodeMirror-composing { border-bottom: 2px solid }
div.CodeMirror span.CodeMirror-matchingbracket { color: #0f0 }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: #f22 }
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3) }
.CodeMirror-activeline-background { background: #e8f2ff }
.CodeMirror { position: relative; background: #f5f5f5 }
.CodeMirror-scroll { overflow: hidden !important; margin-bottom: 0; margin-right: -30px; padding: 16px 30px 16px 0; outline: none; position: relative }
.CodeMirror-sizer { position: relative; border-right: 30px solid transparent }
.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none }
.CodeMirror-vscrollbar { right: 0; top: 0 }
.CodeMirror-hscrollbar { bottom: 0; left: 0 !important }
.CodeMirror-scrollbar-filler { right: 0; bottom: 0 }
.CodeMirror-gutter-filler { left: 0; bottom: 0 }
.CodeMirror-gutters { position: absolute; left: 0; top: -5px; min-height: 100%; z-index: 3 }
.CodeMirror-gutter { white-space: normal; height: inherit; display: inline-block; vertical-align: top; margin-bottom: -30px }
.CodeMirror-gutter-wrapper { position: absolute; z-index: 4; background: none !important; border: none !important }
.CodeMirror-gutter-background { position: absolute; top: 0; bottom: 0; z-index: 4 }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; text-align: center }
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines { cursor: text; min-height: 1px }
.CodeMirror pre { border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible }
.CodeMirror-wrap pre { white-space: pre-wrap }
.CodeMirror-linebackground { position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0 }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto }
.CodeMirror-widget { }
.CodeMirror-rtl pre { direction: rtl }
.CodeMirror-code { outline: none }
.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber { }
.CodeMirror-measure { position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden }
.CodeMirror-cursor { position: absolute }
.CodeMirror-measure pre { position: static }
div.CodeMirror-cursors { visibility: hidden; position: relative; z-index: 3 }
div.CodeMirror-dragcursors { visibility: visible }
.CodeMirror-focused div.CodeMirror-cursors { visibility: visible }
.CodeMirror-selected { background: #d9d9d9 }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0 }
.CodeMirror-crosshair { cursor: crosshair }
.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection { background: #d7d4f0 }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0 }
.cm-searching { background: rgba(255, 255, 0, .4) }
.cm-force-border { padding-right: .1px }
.cm-tab-wrap-hack::after { content: "" }
span.CodeMirror-selectedtext { background: none }
.CodeMirror-activeline-background,.CodeMirror-selected { }
.CodeMirror-blur .CodeMirror-activeline-background,.CodeMirror-blur .CodeMirror-selected { visibility: hidden }
.CodeMirror-blur .CodeMirror-matchingbracket { color: inherit !important; outline: none !important; text-decoration: none !important }
.CodeMirror-sizer { min-height: auto !important }
html,.wiz-editor-body { font-size: 12pt }
.wiz-editor-body { font-family: Helvetica, "Hiragino Sans GB", "寰蒋闆呴粦", "Microsoft YaHei UI", SimSun, SimHei, arial, sans-serif; line-height: 1.7; margin: 0 auto; padding: 1.25rem 1rem }
.wiz-editor-body h1,.wiz-editor-body h2,.wiz-editor-body h3,.wiz-editor-body h4,.wiz-editor-body h5,.wiz-editor-body h6 { margin: 1.25rem 0 0.625rem }
.wiz-editor-body h1 { font-size: 1.67rem }
.wiz-editor-body h2 { font-size: 1.5rem }
.wiz-editor-body h3 { font-size: 1.25rem; background-color: #A3A9F5; font-weight: bold }
.wiz-editor-body h4 { font-size: 1.17rem; background-color: #8dd5f5; font-weight: bold }
.wiz-editor-body h5 { font-size: 1rem; background-color: #F5F183; font-weight: bold }
.wiz-editor-body h6 { font-size: 1rem; color: #777777; margin: 1rem 0 }
.wiz-editor-body div,.wiz-editor-body p,.wiz-editor-body ul,.wiz-editor-body ol,.wiz-editor-body dl,.wiz-editor-body li { margin: 8px 0 }
.wiz-editor-body blockquote,.wiz-editor-body table,.wiz-editor-body pre,.wiz-editor-body code { margin: 8px 0 }
.wiz-editor-body .CodeMirror pre { margin: 0 }
.wiz-editor-body ul,.wiz-editor-body ol { padding-left: 2rem }
.wiz-editor-body ol.wiz-list-level1>li { list-style-type: decimal }
.wiz-editor-body ol.wiz-list-level2>li { list-style-type: lower-latin }
.wiz-editor-body ol.wiz-list-level3>li { list-style-type: lower-roman }
.wiz-editor-body blockquote { padding: 0 12px }
.wiz-editor-body blockquote>:first-child { margin-top: 0 }
.wiz-editor-body blockquote>:last-child { margin-bottom: 0 }
.wiz-editor-body img { border: 0; max-width: 100%; height: auto !important; margin: 2px 0 }
.wiz-editor-body table { border-collapse: collapse; border: 1px solid #bbbbbb }
.wiz-editor-body td,.wiz-editor-body th { padding: 4px 8px; border-collapse: collapse; border: 1px solid #bbbbbb; min-height: 28px }
.wiz-hide { display: none !important }
原文地址:https://www.cnblogs.com/pontoon/p/10217408.html