Django REST Framework API开发:Countries模型groupId字段处理困惑
Django REST Framework 国家API开发:groupId字段处理方案
我正在用Django REST Framework开发API,目前仅创建了Countries模型,已定义好POST请求与响应格式,但不确定如何处理模型中的groupId字段。
请求与响应格式
POST请求格式
{"name": "Czech Republic","countryCode": "CZ"}
响应格式
{ "name": "Czech Republic", "countryCode": "CZ", "id": 123, "createdAt": "2022-08-21T11:49:39.239Z", "groupId": 123 }
当前模型代码
class Countries(models.Model): name = models.CharField(unique=True, max_length=100) countryCode = models.CharField(unique=True, max_length=100) createdAt = models.DateTimeField(auto_now=True) groupId = models.CharField(unique=True, max_length=100) def __str__(self): return self.name
具体处理方案
先修正模型里的两处细节:
createdAt字段用auto_now=True会在每次保存时更新时间,不符合"创建时间"的语义,建议改成auto_now_add=True,仅在对象创建时设置时间。- 响应里的
groupId是数值类型,但模型里定义为CharField,如果业务上groupId是数字,改成IntegerField更合理;若确实为字符串类型,保留CharField即可。
下面分三种常见场景处理groupId:
场景1:groupId为固定默认值
如果所有国家都属于同一个固定组,直接给groupId设置默认值,同时去掉unique=True(否则多条数据会因groupId重复报错):
class Countries(models.Model): name = models.CharField(unique=True, max_length=100) countryCode = models.CharField(unique=True, max_length=100) createdAt = models.DateTimeField(auto_now_add=True) # 改为IntegerField并设置固定默认值 groupId = models.IntegerField(default=123) def __str__(self): return self.name
场景2:groupId为自动生成的唯一值
如果需要每个国家的groupId唯一且自动生成,可选择自增整数或UUID:
# 方案A:自增整数 class Countries(models.Model): name = models.CharField(unique=True, max_length=100) countryCode = models.CharField(unique=True, max_length=100) createdAt = models.DateTimeField(auto_now_add=True) groupId = models.IntegerField(unique=True, auto_created=True) def __str__(self): return self.name # 方案B:UUID字符串(适合全局唯一标识场景) import uuid class Countries(models.Model): name = models.CharField(unique=True, max_length=100) countryCode = models.CharField(unique=True, max_length=100) createdAt = models.DateTimeField(auto_now_add=True) groupId = models.UUIDField(unique=True, default=uuid.uuid4, editable=False) def __str__(self): return self.name
场景3:groupId关联其他模型(如Group表)
如果groupId是关联分组模型的外键ID,修改模型为外键关联,并通过属性暴露groupId:
# 先定义Group模型 class Group(models.Model): name = models.CharField(max_length=100) # 其他分组相关字段 class Countries(models.Model): name = models.CharField(unique=True, max_length=100) countryCode = models.CharField(unique=True, max_length=100) createdAt = models.DateTimeField(auto_now_add=True) # 关联Group模型 group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='countries') # 定义属性返回groupId @property def groupId(self): return self.group.id def __str__(self): return self.name
序列化器与视图实现
不管哪种场景,序列化器都要设置groupId为只读(请求不需要传入),同时格式化createdAt输出格式:
from rest_framework import serializers from .models import Countries class CountrySerializer(serializers.ModelSerializer): # 格式化createdAt为响应要求的ISO格式 createdAt = serializers.DateTimeField(format='%Y-%m-%dT%H:%M:%S.%fZ', read_only=True) class Meta: model = Countries fields = ['id', 'name', 'countryCode', 'createdAt', 'groupId'] # 标记groupId为只读,禁止前端传入 extra_kwargs = { 'groupId': {'read_only': True} } # 场景3需额外配置groupId来源: # groupId = serializers.IntegerField(source='group.id', read_only=True)
视图直接使用DRF的CreateAPIView即可:
from rest_framework import generics from .models import Countries from .serializers import CountrySerializer class CountryCreateAPIView(generics.CreateAPIView): queryset = Countries.objects.all() serializer_class = CountrySerializer
内容的提问来源于stack exchange,提问作者Michal Lečbych
相关产品推荐
相关产品推荐

