drf序列化与序列化器的使用

序列化类的使用

使用序列化类实现五个接口功能,但是我们发现并没有做数据校验,也没有做反序列化,是我们自己手动去进反序列化,是我们自己使用for来进行拼接的,很不方便,我们可以使用一个drf自带的名叫序列化器,来完成

路由

urlpatterns = [path('admin/', admin.site.urls),path('publish/',views.PublishView.as_view()),
]

视图函数

class PublishView(APIView):def get(self, request):publish_list = Publish.objects.all()l = []for i in publish_list:l.append({'name': i.name, 'addr': i.addr, })return Response({'code': 100, 'msg': 'ok', 'results': l})def post(self, request):publish_list = Publish.objects.create(name=request.data.get('name'), addr=request.data.get('addr'))return Response({'code': 100, 'msg': 'ok', 'results': {'name': publish_list.name, 'price': publish_list.addr}})class PublishDetail(APIView):def get(self, request, pk):book_list = Publish.objects.filter(id=pk).first()l = []for i in book_list:l.append({'name': i.name, 'price': i.price, })return Response({'code': 100, 'msg': 'ok', 'results': l})def delete(self, request, pk):book_list = Publish.objects.filter(id=pk).delete()return Response({'code': 100, 'msg': 'ok', 'results': book_list})def put(self, request):publish_list = Publish.objects.update(**request.data)return Response({'code': 100, 'msg': 'ok', 'results': {'name': publish_list.name, 'price': publish_list.addr}})

序列化类-Serializer

Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

from rest_framework import serializersfrom app01.models import Publishclass PublishSerializer(serializers.ModelSerializer):name=serializers.CharField()addr=serializers.CharField()class Meta:model=Publishfields=['name','addr'] # 或指定所有__all__
  1. 建立一个名为Serializer的py文件·
  2. 写一个类,继承为Serializer.Serializer
  3. 在类中写需要序列化的字段
  4. 在视图类中使用,完成序列化

使用序列化类
导入我们自己的序列化器
from app01.Serializer import PublishSerializer# 使用序列化类做序列化
class PublishView(APIView):def get(self, request):publish_list = Publish.objects.all()ser=PublishSerializer(instance=publish_list,many=True)return Response({'code': 100, 'msg': 'ok', 'results': ser.data})class PublishDetail(APIView):def get(self, request, pk):publish_list = Publish.objects.filter(id=pk).first()ser=PublishSerializer(instance=publish_list)return Response({'code': 100, 'msg': 'ok', 'results': ser.data}))
  1. 如果序列化多个则需要加上many=Ture,

使用序列化类进行校验

三层校验:

  1. 字段的校验
  2. 局部钩子:校验失败,主动使用ValidationError抛出错误
  3. 全局钩子
from rest_framework import serializers
from rest_framework.exceptions import ValidationErrorfrom app01.models import Publish, Booksclass PublishSerializer(serializers.ModelSerializer):# 第一层:写需要序列化的字段名name = serializers.CharField()addr = serializers.CharField()
# 第二层 局部钩子def validate_name(self, name):if name.startswith('sb'):raise ValidationError('不能以sb开头')else:return namedef validate_addr(self, addr):if 'sb'in addr:raise ValidationError("不能以sb开头")else:return addr# 第三层全局钩子def validate(self, attrs):# attrs是校验过后的数据print(attrs)if attrs.get('name')[:3]==attrs.get('addr')[:3]:raise ValidationError("名称不能重复")return attrsclass Meta:model = Publishfields = ['name', 'addr']  # 或指定所有__all__

全局钩子:def validate(self, attrs):

补充:attrs是已经校验过后的数据,如果前端传入了数据字段,但是我的类中并没有这个字段,那么最终校验过后的数据attrs中是没有前端传入的数据的,因为那条数据已经被删除了

put和post保存到数据库
class BookSerializer(serializers.ModelSerializer):name = serializers.CharField(max_length=18, min_length=3)price = serializers.IntegerField(max_value=999, min_value=10)pub_date = serializers.CharField(max_length=32)def validate_name(self, name):l = ['金瓶梅', 'sb', '傻逼']for i in l:if i in name:raise ValidationError('不能使用敏感字')return namedef validate_price(self, price):if price < 10:raise ValidationError('价格不能小于10')elif price > 999:raise ValidationError('价格不能大于999')else:return pricedef validate(self, attrs):# attrs是校验过后的数据print(attrs)if attrs.get('pub_date')[:3] == attrs.get('name')[:3]:raise ValidationError("名称不能重复")return attrsdef create(self, validated_data):# validated_data:校验过的数据,之前传入没有校验的数据,在这没有publish = Publish.objects.create(**validated_data)return publish  # 一定要返回publish对象,后续会拿着这个对象进行序列化,ser.def update(self, instance, validated_data):# 本方法# instance.name = validated_data.get('name')# instance.price = validated_data.get('price')# instance.pub_date = validated_data.get('pub_date')# instance.save() # book的对象save的对象保存到数据库中# 高级写法for item in validated_data:# setattr(books,'name','上海出版社')setattr(instance, item, validated_data[item])instance.save()return instanceclass Meta:model = Booksfields = ['name', 'price', 'pub_date']

路由

class BookView(APIView):def get(self, request):book_list = Books.objects.all()ser = BookSerializer(instance=book_list, many=True)return Response({'code': 100, 'msg': 'ok', 'results': ser.data})def post(self, request):ser = BookSerializer(data=request.data)if ser.is_valid():ser.save()  # 使用序列化类进行保存,但是会报错,因为没有指定到哪一个表,所以需要重新写createprint(ser.data)return Response({'code': 100, 'msg': 'ok', 'results': ser.data})else:print(ser.errors)return Response({'code': 100, 'msg': ser.errors})def delete(self, request, pk):book_list = Books.objects.filter(id=pk).delete()ser = BookSerializer(instance=book_list)return Response({'code': 100, 'msg': 'ok', 'results': ser.data})def put(self, request):book_list = Books.objects.update(**request.data)ser = BookSerializer(instance=book_list, data=request.data)if ser.is_valid():ser.save()print(ser.data)return Response({'code': 100, 'msg': '修改成功', 'results': ser.data})else:print(ser.errors)return Response({'code': 100, 'msg': ser.errors})
  1. instance:需要序列化的数据,如果是queryset对象,即便是一个数,也需要使用many=Ture
  2. serializers.data 转为字典格式,return Response(serializers.data)这样就实现序列化了
  3. 视图中使用新增与修改:
"""新增"""
serializers=Bookserializers(data=reuqest.data)
新增后执行视图函数中的is_valid:就是执行三层校验
成功后保存ser.save()
"""修改"""
ser = BookSerializer(instance=book_list, data=request.data)
is_valid()
ser.save()def update(self, instance, validated_data):Book.objects.filer(pk=instanc).update(*validated_data)return instance修改第二种方式def update(self, instance, validated_data):Book.objects.filer(pk=instanc).update(**validated_data)return instance

常用的字段名

小技巧:如果跟表模型中对不上,可以直接使用CharField。

字段类型

字段

字段构造方式

BooleanField

BooleanField()

NullBooleanField

NullBooleanField()

CharField

CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)

EmailField

EmailField(max_length=None, min_length=None, allow_blank=False)

RegexField

RegexField(regex, max_length=None, min_length=None, allow_blank=False)

SlugField

SlugField(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9*-]+

URLField

URLField(max_length=200, min_length=None, allow_blank=False)

UUIDField

UUIDField(format='hex_verbose') format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"

IPAddressField

IPAddressField(protocol='both', unpack_ipv4=False, **options)

IntegerField

IntegerField(max_value=None, min_value=None)

FloatField

FloatField(max_value=None, min_value=None)

DecimalField

DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置

DateTimeField

DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)

DateField

DateField(format=api_settings.DATE_FORMAT, input_formats=None)

TimeField

TimeField(format=api_settings.TIME_FORMAT, input_formats=None)

DurationField

DurationField()

ChoiceField

ChoiceField(choices) choices与Django的用法相同

MultipleChoiceField

MultipleChoiceField(choices)

FileField

FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

ImageField

ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

ListField

ListField(child=, min_length=None, max_length=None)

DictField

DictField(child=)

选项参数:

参数名称

作用

max_length

最大长度

min_lenght

最小长度

allow_blank

是否允许为空

trim_whitespace

是否截断空白字符

max_value

最小值

min_value

最大值

通用参数:

参数名称

说明

read_only

表明该字段仅用于序列化输出,默认False

write_only

表明该字段仅用于反序列化输入,默认False

required

表明该字段在反序列化时必须输入,默认True

default

反序列化时使用的默认值

allow_null

表明该字段是否允许传入None,默认False

validators

该字段使用的验证器

error_messages

包含错误编号与错误信息的字典

label

用于HTML展示API页面时,显示的字段名称

help_text

用于HTML展示API页面时,显示的字段帮助提示信息

字段校验有四层:

  1. 字段自己
  2. validdators校验
  3. 局部钩子
  4. 全局钩子

序列化高级之soruce

soruce:用来修改返回字段的

1 修改字段,映射字段 publish_name表中不存在

publish_name = serializers.CharField(source='name')

2 修改字段,映射方法

sb_name是表模型中一个方法

name = serializers.CharField(source='sb_name')

3 修改字段,跨表查询

book表中可以链表查询

publish=models.ForeignKey(to='Publish.name')

序列化高级之返回字段

定制序列化返回字段格式

  1. 在表模型中写,在序列化中做映射,可以使用soruce

建表

from django.db import modelsclass Book(models.Model):name = models.CharField(max_length=32)price = models.DecimalField(max_digits=5, decimal_places=2)publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)authors = models.ManyToManyField(to='Author')def __str__(self):return self.nameclass Author(models.Model):name = models.CharField(max_length=32)age = models.IntegerField()author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)def __str__(self):return self.nameclass AuthorDetail(models.Model):telephone = models.BigIntegerField()birthday = models.DateField()addr = models.CharField(max_length=64)class Publish(models.Model):name = models.CharField(max_length=32)city = models.CharField(max_length=32)email = models.EmailField()def __str__(self):return self.nameclass Meta:verbose_name = '出版社'verbose_name_plural = verbose_name

models

class Book(models.Model):name = models.CharField(max_length=32)price = models.DecimalField(max_digits=5, decimal_places=2)publish_name = models.ForeignKey(to='Publish', on_delete=models.CASCADE)author = models.ManyToManyField(to='Author')def __str__(self):return self.name# def book_name(self):#     return self.name+'sb'# def publish_detail(self):#     return {'name': self.name, 'price': self.price, 'publish_name': self.publish_name.addr}## def author_list(self):#     l=[]#     for i in self.author.all():#         l.append({'name':i.name, 'age':i.age})##     return l# def publish_detail(self):#     return {'name': self.name, 'price': self.price, 'publish_name': self.publish_name.addr}### def author_list(self):#     l=[]#     for i in self.author.all():#         l.append({'name':i.name, 'age':i.age})#         return l#class Meta:verbose_name_plural='图书表'

view

class BookView(APIView):def get(self, request):obj = Book.objects.all()ser = BookSerializer(instance=obj, many=True)'''[{"name": "西游记","price": "66.00","publish_detail": {name:名字,city:城市},"authors_list":[{name:名字,age:19}]},]'''return Response(ser.data)

序列化类

### 定制返回字段
class BookSerializer(serializers.Serializer):name = serializers.CharField()price = serializers.CharField()#### 定制返回字段---》方案一:在表模型中写方法,在序列化类中做映射# publish_detail = serializers.CharField()  # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,强行用CharField字符串接收# publish_detail = serializers.DictField()  # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,用DictField接收# author_list = serializers.ListField()###定制返回字段---》方案二:在序列化类中写  SerializerMethodField# 只要写了这个字段类SerializerMethodField,必须配合一个方法:get_字段名,这个方法返回什么,前端这个字段就显示什么publish_detail = serializers.SerializerMethodField()def get_publish_detail(self, obj):# 当前序列化到的book对象return {'name': obj.publish.name, 'city': obj.publish.city}author_list = serializers.SerializerMethodField()def get_author_list(self, obj):l = []for author in obj.authors.all():l.append({'name': author.name, 'age': author.age})return lbook_name = serializers.SerializerMethodField()def get_book_name(self, obj):return obj.name + 'sb'

多表关联反序列化
# 反序列化保存
# 使用同一个序列化类会出现-序列化字段和反序列化字段不一致-序列化字段namepricepublish_detailauthor_list-反序列化字段:namepricepublishauthor-如果是共同的,不需要额外处理-如果是不同的,需要通过字段参数控制read_only	表明该字段仅用于序列化输出,默认False,序列化过程write_only	表明该字段仅用于反序列化输入,默认False,反序列化过程

serializer
class BookSerializer(serializers.Serializer):name = serializers.CharField(max_length=18, min_length=3, required=True) # 公共的price = serializers.IntegerField() # 公共的publish = serializers.IntegerField(write_only=True)# 反序列化author = serializers.ListField(write_only=True)# 反序列化publish_detail=serializers.SerializerMethodField(read_only=True) #序列化author_list = serializers.SerializerMethodField(read_only=True) #序列化def validate_name(self, name):if name.startswith('sb'):raise ValidationError("不能使用敏感字开头")return namedef validate_price(self, price):if price <= 0:raise ValidationError("不能等于0")return pricedef validate(self, attrs):# attrs是校验过后的数据if attrs.get('name')[:3] == attrs.get('addr')[:3]:raise ValidationError("名称不能重复")return attrsdef get_publish_detail(self, obj):# obj就是当前序列化到的return {'name': obj.publish_name.name ,'addr': obj.publish_name.addr}# 返回的' name':obj.publish.name, 'price':obj.publish.addr就相当于给了这个publish_detaildef get_author_list(self,obj):l=[]for i in obj.author.all():l.append({'name':i.name, 'age':i.age})return ldef create(self, validated_data):author=validated_data.pop('author')book = Book.objects.create(**validated_data)# book=Book.objects.create(name=validated_data['name'], price=validated_data['price'],publish_name=validated_data['publish_name'])book.author.add(*author)return book

ModelSerializer
  1. ModelSerializer跟表是一一对应的,r,需要重写create和update
  2. 之前写的Serializer.serializer跟表没有必然的联系
  3. 继承ModleSerializer可以少写很多代码
### 继承ModelSerializer--->少写代码
class BookSerializer(serializers.ModelSerializer):# name = serializers.CharField(max_length=18,min_length=3)  # 公共的# price = serializers.CharField()  # 公共的# publish = serializers.IntegerField(write_only=True)  # 只用来做反序列化# authors = serializers.ListField(write_only=True)  # 只用来做反序列化# 上述操作,通过 Meta实现了# 扩写的字段,也要在fields注册# 方式二:定制字段# publish_detail = serializers.SerializerMethodField(read_only=True)  # 只用来做序列化# author_list = serializers.SerializerMethodField(read_only=True)  # 只用来做序列化# def get_publish_detail(self, obj):#     return {'name': obj.publish.name, 'city': obj.publish.city}# def get_author_list(self, obj):#     l = []#     for author in obj.authors.all():#         l.append({'name': author.name, 'age': author.age})#     return l# 方式二:定制字段方式一# publish_detail = serializers.DictField(read_only=True)# author_list = serializers.ListField(read_only=True)class Meta:model = Book  # 写了这两句,会把表模型中Book,所有字段映射过来# fields='__all__'fields = ['name', 'price', 'publish', 'authors', 'publish_detail', 'author_list']extra_kwargs = {  # 给某个或某几个字段设置字段属性'name': {'max_length': 18, 'min_length': 3},'publish': {'write_only': True},'authors': {'write_only': True},'publish_detail': {'read_only': True},'author_list': {'read_only': True},}# 一般不需要写create和update了---》ModelSerializer帮咱们实现了# 局部钩子和全局钩子,该怎么写还怎么写

反序列化的源码分析
#1  执行 ser.is_valid() 就会执行 反序列化的校验---》字段自己--》局部钩子---》全局钩子
#2  入口是:ser.is_valid()---》BaseSerializer 找到了1 自己写的BookSerializer---》serializer.Serializer---->BaseSerializer 2 源码如下def is_valid(self, *, raise_exception=False):# self 是 ser对象---》自己写的BookSerializer的对象--》一开始没有# 一旦有了,就不执行了,优化is_valid被多次调用,只会走一次校验if not hasattr(self, '_validated_data'):try:# 一旦执行过,以后self中就有_validated_data# 接下来看self.run_validation(self.initial_data)self._validated_data = self.run_validation(self.initial_data)except ValidationError as exc:self._validated_data = {}self._errors = exc.detailelse:self._errors = {}if self._errors and raise_exception:raise ValidationError(self.errors)return not bool(self._errors)3 self.run_validation(self.initial_data)---》serializer.Serializer类的,不要按住ctrl点击,否则会进 Field 类,看错了4 serializer.Serializer类的run_validationdef run_validation(self, data=empty):# data前端传入的--{"name":"张三","age":68}# value是---》前端传入的,字段自己校验通过的字典---{"name":"张三","age":68}value = self.to_internal_value(data) # 执行局部钩子try:self.run_validators(value) # 先不看,忽略掉# self 是 BookSerializer的对象,如果我们写了全局钩子,走我们自己的,如果没写,走父类的,父类的根本没做校验# value={"name":"张三","age":68}value = self.validate(value)# 执行全局钩子except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value5 全局钩子读完了:self 是 BookSerializer的对象,如果我们写了全局钩子,走我们自己的,如果没写,走父类的,父类的根本没做校验6 局部钩子:value = self.to_internal_value(data)--》Serializer类的# for循环着去BookSerializer的对象中反射  validate_字段名的方法,如果有就执行,没有就不执行def to_internal_value(self, data):for field in fields: # 序列化类中所有字段类的对象 name=CharField()# self 是BookSerializer类的对象# 去BookSerializer类中,反射  validate_field字段类的对象.field_namevalidate_method = getattr(self, 'validate_' + field.field_name, None)try:# 如果能拿到,说明咱么写了局部钩子if validate_method is not None:# 执行局部钩子--》传入了当前字段的value值validated_value = validate_method(validated_value)except ValidationError as exc:# 如果抛异常,会被捕获errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)return ret# #####读了局部和全局钩子的执行位置#####
# 保存,修改也好,都要用validated_data,它是最准确的

执行is_valid()就会执反序列化的校验

  • 字段自己的校验
  • 局部钩子
  • 全局钩子
  1. 查看源码从is_valid()中去查看,建议不使用ctrl点击查看,去ser,is_valid()的对象就是Booksserializer中查看-----没有找到,去父类的serializer中去寻找,没有继续去Serializer中找is_valiid(),没有继续去BaseSerializer中找,如果直接从ctrl中点击的话,可能直接跳转到不是BaseSerializer中了。
  2. 源码如下
 2 源码如下def is_valid(self, *, raise_exception=False):#判断self中有没有_validated_dataif not hasattr(self, '_validated_data'):try:self._validated_data = self.run_validation(self.initial_data)except ValidationError as exc:self._validated_data = {}self._errors = exc.detailelse:self._errors = {}if self._errors and raise_exception:raise ValidationError(self.errors)return not bool(self._errors)

逐步解析:

  1. if not hasattr(self, '_validated_data'):----判断self中有没有_validated_data
  • 其中的self就是ser对象,ser对象其实就是自己写的BookSerializer类的对象,因为从BookSerializer进入的
  • 一开始是没有_validated_data,(如果有就不会执行下面的hasattr,如果执行过is_valid(),那么之后的is_valid就不会执行了,多次调用也只会执行一次)所以执行下面的反射hasattr
  1. self._validated_data = self.run_validation(self.initial_data)------去Serializer中去找run_validation

不要直接ctrl直接进去找,不然找到了fild里就不对了

    def run_validation(self, data=empty):# 局部钩子value = self.to_internal_value(data)try:self.run_validators(value) value = self.validate(value) # 全局钩子# 不符合直接捕获错误except (ValidationError, DjangoValidationError) as exc:raise ValidationError(detail=as_serializer_error(exc))return value

在run_validation中

全局钩子: 不符合直接捕获错误 value = self.validate(value) 全局钩子:self是BookSerializer的对象,如果自己写了钩子,那么就执行我们的,没写走父类,父类中直接返回了,并没有做校验

局部钩子

value = self.to_internal_value(data)-----是Serializer的

for循环去BookSerializer的对象去反射,validata_字段名的方法,如果有就执行,

  • value就前端传入的数据
    def to_internal_value(self, data):for field in fields:validate_method = getattr(self, 'validate_' + field.field_name, None)#去BookSerializer中反射validate_加上字段名 :  validate_field字段类的对象.field_nameprimitive_value = field.get_value(data)try:# 如果能拿到,说明写了局部钩子,否则抛出异常validated_value = field.run_validation(primitive_value)if validate_method is not None:validated_value = validate_method(validated_value)except ValidationError as exc:#如果抛异常,会被捕获到,放入下面errors中errors[field.field_name] = exc.detailexcept DjangoValidationError as exc:errors[field.field_name] = get_error_detail(exc)except SkipField:passelse:set_value(ret, field.source_attrs, validated_value)if errors:raise ValidationError(errors)# 最终返回return ret

for field in fields: 序列化类中所有字段的对象:

validate_method = getattr(self, 'validate_' + field.field_name, None)

去BookSerializer中反射validate_加上字段名 : validate_field字段类的对象.field_name

断言
   assert hasattr(self, 'initial_data'), ('Cannot call `.is_valid()` as no `data=` keyword argument was ''passed when instantiating the serializer instance.')
判断self里有没有'initial_data'没有就报错
a = 10## assert 后写条件,只要不符合条件,就会抛AssertionError异常,后面写异常信息
assert a == 11, ("不等于11,报错了")# 等同于---》上面只要一行代码,源码中喜欢用
if not a == 11:raise Exception('不等于11,报错了')# 源码中使用
assert value is not None, '.validate() should return the validated data'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.Net实现海鲜添加(三层架构,异常处理)

演示功能&#xff1a; 点击启动生成页面 点击添加跳转新界面 此处设置文本框多行 点击Button添加 步骤&#xff1a; 1、建文件 下图是三层架构列表&#xff0c;Models里面有模拟数据库中列的类&#xff0c;DAL中有DBHelper和service,BLL中有BllManager文件用于ui界面直接调用…

SpringBoot之多环境开发配置

1 多环境开发配置 问题导入 在实际开发中&#xff0c;项目的开发环境、测试环境、生产环境的配置信息是否会一致&#xff1f;如何快速切换&#xff1f; 1.1 多环境启动配置 yaml文件多环境启动 不同环境使用—隔开 示例代码&#xff1a; spring:profiles:active: dev#生产…

易天推出10G SFP+ 可调 DWDM光模块:网络通信新升级

随着网络技术的飞速发展&#xff0c;为了满足用户对高速数据传输日益增长的需求。易天研发团队在原来的基础上推出了全新升级的10G SFP 可调 DWDM光模块&#xff0c;本文将详细介绍这款新升级光模块的特点、优势以及应用场景。 易天光通信10G SFP 可调 DWDM光模块具有出色的波…

三、C#面向对象编程(继承与多态)

在C#中&#xff0c;面向对象编程&#xff08;OOP&#xff09;是编程的基本范式&#xff0c;它使用类和对象的概念来构建软件应用程序。面向对象编程的三个主要特性是封装、继承和多态。 封装&#xff1a;封装是将数据&#xff08;属性&#xff09;和操作数据的函数&#xff08;…

大数据学习(31)-Spark非常用及重要特性

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

项目中接入神策埋点

项目中接入神策埋点&#xff08;免费&#xff09;&#xff0c;react和vue通用 1、下包 使用npm 或 yarn 或 pnpm 安装依赖 npm install --save sa-sdk-javascript 2、初始化准备&#xff1a; 定义环境变量 VITE_PROJECT_ENV (prod demo test) 3、初始化神策 在 utils 文…

QT基础知识

QT基础知识 文章目录 QT基础知识1、QT是什么2、Qt的发展史3、为什么学习QT4、怎么学习QT1、工程的创建(环境的下载与安装请百度&#xff09;2、创建的工程结构说明3、怎么看帮助文档1、类使用的相关介绍2. 查看所用部件&#xff08;类&#xff09;的相应成员函数&#xff08;功…

为什么说 $mash 是 Solana 上最正统的铭文通证?

早在 2023 年的 11 月&#xff0c;包括 Solana、Avalanche、Polygon、Arbitrum、zkSync 等生态正在承接比特币铭文生态外溢的价值。当然&#xff0c;因铭文赛道过于火爆&#xff0c;当 Avalanche、BNB Chain 以及 Polygon 等链上 Gas 飙升至极值&#xff0c;Arbitrum、zkSync 等…

多任务并行处理相关面试题

我自己面试时被问过两次多任务并行相关的问题&#xff1a; 假设现在有10个任务&#xff0c;要求同时处理&#xff0c;并且必须所有任务全部完成才返回结果 这个面试题的难点是&#xff1a; 既然要同时处理&#xff0c;那么肯定要用多线程。怎么设计多线程同时处理任务呢&…

.babky勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复

导言&#xff1a; 网络安全威胁不断进化&#xff0c;其中.babky勒索病毒引起了广泛关注。这篇文章91数据恢复将深入介绍.babky的狡猾特征&#xff0c;以及在遭受其袭击时如何高效地恢复被加密的数据&#xff0c;并提供实用的预防方法。当面对被勒索病毒攻击导致的数据文件加密…

基于Java课程作业管理系统

基于Java课程作业管理系统 功能需求 1、作业发布&#xff1a;系统需要支持教师发布作业&#xff0c;包括作业题目、要求、截止日期等信息。 2、作业提交&#xff1a;学生可以通过系统提交作业&#xff0c;系统需要支持多种文件格式的上传&#xff0c;并能够自动保存提交记录…

vue-vuex持久化处理

在src/utils文件夹下&#xff0c;创建storage.js文件 // 约定一个通用的键名 const INFO_KEY hm_shopping_info// 获取个人信息 export const getInfo () > {const defaultObj { token: , userId: }const result localStorage.getItem(INFO_KEY)return result ? JSON…

proteus元器件搜索

proteus元器件搜索 常用元器件类 电阻&#xff1a;Resistor 可变电阻&#xff1a;Variable Resistor 电位器 &#xff1a;potentiometer 三极管&#xff1a;在Transistors里查找&#xff0c;可以用指定的型号搜索&#xff0c;比如2N3904。也可使用npn和pnp查找。 二极管&…

Linux 网络系统管理 技能大赛 DNS赛题配置

主DNS服务部署 yum -y install bind bind-chroot bind-utils systemctl start named //开启named systemctl enable named //开机自启动 ss -tnl |grep 53 //查看端口是否正常启动 vim /etc/named.conf //编辑全局配置文件listen-on port 53 {any;}; //监听所有…

java多线程及线程锁

概述 程序&#xff08;program&#xff09;&#xff1a;为完成特定任务&#xff0c;用某种语言编写的一组指令的集合。即指一段静态的代码&#xff0c;静态对象。 进程&#xff08;process&#xff09;&#xff1a;程序的一次执行过程&#xff0c;或是正在内存中运行的应用程序…

什么是自动化测试?为啥要学自动化测试?

什么是自动化测试&#xff0c;接着对常用的自动化测试框架进行了对比分析&#xff0c;最后&#xff0c;介绍了如果将自动化测试框架Cypress运用在项目中。 一、自动化测试概述 为了保障软件质量&#xff0c;并减少重复性的测试工作&#xff0c;自动化测试已经被广泛运用。在开…

C++ 字符串操作说明 续

一、strstr函数 extern char *strstr(char *str1, const char *str2); 1. strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。如果是&#xff0c;则该函数返回str2在str1中首次出现的地址&#xff1b;否则&#xff0c;返回NULL。 2. str1: 被查找目标 string …

【LLM】大型语言模型综述论文

今天我将与大家分享一篇精彩的论文。这项调查提供了LLM文献的最新综述&#xff0c;这对研究人员和工程师来说都是一个有用的资源。 为什么选择LLM&#xff1f; 当参数尺度超过一定水平时&#xff0c;这些扩展的语言模型不仅实现了显著的性能改进&#xff0c;而且还表现出一些…

一文掌握 Golang 中的类型断言

目录 什么是类型断言 类型断言的基本语法 类型断言示例 类型断言原理 类型断言的使用场景 深入理解类型断言 类型断言的最佳实践 小结 类型断言是 Golang 中的一个非常重要的特性&#xff0c;使用类型断言可以判断一个接口的实际类型是否是预期的类型&#xff0c;以便进…

一份阅读量13万+免费的C#/.NET/.NET Core面试宝典(基础版)

前言 C#/.NET/.NET Core相关技术常见面试题汇总&#xff0c;不仅仅为了面试而学习&#xff0c;更多的是查漏补缺、扩充知识面和大家共同学习进步。该知识库主要由自己平时学习实践总结、网上优秀文章资料收集&#xff08;这一部分会标注来源&#xff09;和社区小伙伴提供三部分…