常用字段类型:
字段 |
字段构造方式 |
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(maxlength=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页面时,显示的字段帮助提示信息 |
补充:
| read_only 表明该字段仅用于序列化输出,默认False,如果设置成True,postman中可以看到该字段,修改时,不需要传该字段 |
| write_only 表明该字段仅用于反序列化输入,默认False,如果设置成True,postman中看不到该字段,修改时,该字段需要传 |
-
序列化类高级用法之source,修改序列化字段名字
| |
| 不使用source参数时,会默认 序列化表名.字段名 |
| 使用source参数时,序列化表名.source的参数 下方以Book表为例 |
| class BookSerializer(serializers.Serializer): |
| name_detail = serializers.CharField(max_length=8, min_length=3,source='name') |
| |
| publish_name = serializers.CharField(max_length=8, min_length=3,source='publish.name') |
| |
| xx = serializers.CharField(max_length=8, min_length=3,source='xx') |
| |
| { |
| "name": "西游记", |
| "price": 33, |
| "publish": {name:xx,city:xxx,email:sss} |
| } |
| |
| |
| publish = serializers.SerializerMethodField() |
| def get_publish(self, obj): |
| |
| return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email} |
| |
| def publish_detail(self): |
| return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email} |
| 在序列化中取 |
| publish_detail=serializers.DictField() |
方式一:使用SerializerMethodField
| class BookSerializer(serializers.Serializer): |
| name = serializers.CharField(max_length=8, min_length=3) |
| price = serializers.IntegerField(min_value=10, max_value=99) |
| publish_date = serializers.DateField() |
| |
| |
| publish = serializers.SerializerMethodField() |
| def get_publish(self, obj): |
| |
| return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email} |
| |
| |
| authors = serializers.SerializerMethodField() |
| def get_authors(self, obj): |
| res_list = [] |
| for author in obj.authors.all(): |
| res_list.append({'id': author.id, 'name': author.name, 'age': author.age}) |
| return res_list |
方式二:在表模型中写
| |
| class Book(models.Model): |
| name = models.CharField(max_length=32) |
| price = models.DecimalField(max_digits=5, decimal_places=2) |
| publish_date = models.DateField(null=True) |
| |
| publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) |
| authors = models.ManyToManyField(to='Author') |
| |
| |
| def publish_detail(self): |
| return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email} |
| |
| def author_list(self): |
| res_list = [] |
| for author in self.authors.all(): |
| res_list.append({'id': author.id, 'name': author.name, 'age': author.age}) |
| return res_list |
有关联关系表的反序列化的保存
| |
| |
| publish = serializers.CharField(write_only=True) |
| authors = serializers.ListField(write_only=True) |
| |
| publish_detail = serializers.DictField(read_only=True) |
| author_list = serializers.ListField(read_only=True) |
| |
| |
| def create(self, validated_data): |
| |
| {"name":"三国1演义", |
| "price":19, |
| "publish_date": "2022-09-27", |
| "publish":1, |
| "authors":[1,2] |
| } |
| book = Book.objects.create(name=validated_data.get('name'), |
| price=validated_data.get('price'), |
| publish_date=validated_data.get('publish_date'), |
| publish_id=validated_data.get('publish'), |
| ) |
| authors = validated_data.get('authors') |
| book.authors.add(*authors) |
| return book |
| |
| -字段自己的校验规则 |
| -局部钩子 |
| -全局钩子 |
| |
| |
| |
| -如果继承的是Serializer,写法如下 |
| name=serializers.CharField(max_length=8,min_length=3,error_messages={'min_length': "太短了"}) |
| -如果继承的是ModelSerializer,写法如下 |
| extra_kwargs = { |
| 'name': {'max_length': 8, 'min_length': 3, 'error_messages': {'min_length': "太短了"}}, |
| } |
| |
| |
| |
| -如果继承的是Serializer,写法一样 |
| -如果继承的是ModelSerializer,写法一样 |
| def validate_name(self, name): |
| if name.startswith('sb'): |
| |
| raise ValidationError('不能以sb卡头') |
| else: |
| return name |
| |
| |
| |
| -如果继承的是Serializer,写法一样 |
| -如果继承的是ModelSerializer,写法一样 |
| def validate(self, attrs): |
| if attrs.get('name') == attrs.get('publish_date'): |
| raise ValidationError('名字不能等于日期') |
| else: |
| return attrs |
-
模型类序列化器(ModelSerializer)的使用
| class BookModelSerializer(serializers.ModelSerializer): |
| |
| class Meta: |
| model = Book |
| |
| fields = ['name', 'price', 'publish_date', 'publish', 'authors', 'publish_detail', |
| 'author_list'] |
| |
| |
| extra_kwargs = { |
| 'name': {'max_length': 8}, |
| 'publish': {'write_only': True}, |
| 'authors': {'write_only': True}, |
| } |
总结
| |
| 1 定义一个类继承ModelSerializer |
| 2 类内部写内部内 class Meta: |
| 3 在内部类中指定model(要序列化的表) |
| 4 在内部类中指定fields(要序列化的字段,写__all__表示所有,不包含方法,写[一个个字段]) |
| 5 在内部类中指定extra_kwargs,给字段添加字段参数的 |
| 6 在序列化类中,可以重写某个字段,优先使用你重写的 |
| name = serializers.SerializerMethodField() |
| def get_name(self, obj): |
| return 'sb---' + obj.name |
| |
| 7 以后不需要重写create和update了 |
| -ModelSerializer写好了,兼容性更好,任意表都可以直接存 |
点击查看
| |
| |
| |
| |
| -BaseSerializer内的is_valid()方法 |
| def is_valid(self, *, raise_exception=False): |
| if not hasattr(self, '_validated_data'): |
| try: |
| |
| self._validated_data = self.run_validation(self.initial_data) |
| except ValidationError as exc: |
| return not bool(self._errors) |
| """内部执行了:self.run_validation(self.initial_data)---》本质执行的Serializer的 |
| 如果你按住ctrl键,鼠标点击,会从当前类中找run_validation,找不到会去父类找 |
| 这不是代码的执行,代码执行要从头开始找,从自己身上再往上找 """ |
| def run_validation(self, data=empty): |
| |
| value = self.to_internal_value(data) |
| try: |
| |
| value = self.validate(value) |
| except (ValidationError, DjangoValidationError) as exc: |
| raise ValidationError(detail=as_serializer_error(exc)) |
| return value |
| |
| def to_internal_value(self, data): |
| for field in fields: |
| |
| validate_method = getattr(self, 'validate_' + field.field_name, None) |
| 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[field.field_name] = exc.detail |
| return ret |
| |
图书的5个接口(增删改查)
models.py
| from django.db import models |
| |
| class Book(models.Model): |
| name = models.CharField(max_length=32) |
| price = models.DecimalField(max_digits=5, decimal_places=2) |
| publish_date = models.DateField(null=True) |
| |
| publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE) |
| authors = models.ManyToManyField(to='Author') |
| |
| def __str__(self): |
| return self.name |
| |
| def publish_detail(self): |
| return {'name': self.publish.name, 'city': self.publish.city, 'emial': self.publish.email} |
| |
| def author_list(self): |
| res_list = [] |
| for author in self.authors.all(): |
| res_list.append({'id': author.id, 'name': author.name,'age': author.age}) |
| return res_list |
| |
| class 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.name |
| |
| class AuthorDetail(models.Model): |
| telephone = models.BigIntegerField() |
| birthday = models.DateField() |
| address = models.CharField(max_length=64) |
| |
| class Publish(models.Model): |
| name = models.CharField(max_length=32) |
| city = models.CharField(max_length=32) |
| email = models.EmailField() |
ser.py
| class BookModelSerializer(serializers.ModelSerializer): |
| class Meta: |
| model = Book |
| fields = ['name','price','publish', 'author', 'publish_date', 'publish_detail', |
| 'author_list'] |
| extra_kwargs = { |
| 'name': {'max_length': 8, 'min_length': 3}, |
| 'price': {'max_value': 199, 'min_value': 9}, |
| 'publish': {'write_only': True}, |
| 'authors': {'write_only': True} |
| } |
| def validate_name(self,name): |
| if 'sb' in name: |
| raise ValidationError('名字不能有sb') |
| else: |
| return name |
| |
| def validate_price(self,price): |
| if price == 66: |
| raise ValidationError('价格不能是66') |
| else: |
| return price |
views.py
| class BookView(APIView): |
| |
| def get(self, request): |
| book_list = models.Book.objects.all() |
| res = BookModelSerializer(instance=book_list, many=True) |
| return Response(res.data) |
| |
| def post(self, request): |
| res = BookModelSerializer(data=request.data) |
| if res.is_valid(): |
| res.save() |
| return Response({'code': 100, 'msg': '新增成功'}) |
| else: |
| return Response({'code': 1000, 'msg': res.errors}) |
| |
| class BookDetailView(APIView): |
| |
| def get(self, request,pk): |
| book = models.Book.objects.filter(pk=pk).first() |
| res = BookModelSerializer(instance=book) |
| return Response(res.data) |
| |
| def delete(self,request,pk): |
| models.Book.objects.filter(pk=pk).delete() |
| return Response() |
| |
| def put(self,request,pk): |
| book = models.Book.objects.filter(pk=pk).first() |
| res = BookModelSerializer(instance=book, data=request.data) |
| if res.is_valid(): |
| res.save() |
| return Response({'code': 100, 'msg':'修改成功'}) |
| else: |
| return Response({'code': 1000, 'msg': res.errors}) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!