Skip to content

Commit

Permalink
feat(mock_api): add version field to avoid update by older data (#201)
Browse files Browse the repository at this point in the history
Co-authored-by: rikasai233 <rikasai233@gmail.com>
  • Loading branch information
lihuacai168 and trumpchifan committed Mar 12, 2024
1 parent 5c52e0a commit 8d26f03
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 0 deletions.
3 changes: 3 additions & 0 deletions mock/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class MockAPI(BaseTable):
api_id = models.CharField(max_length=32, default=lambda: uuid.uuid4().hex, unique=True)
enabled = models.BooleanField(default=True)

# 添加version字段用于乐观锁控制
version = models.IntegerField(default=1) # 新增版本字段,默认值为1

# TODO 改成many to many
# followers: list = models.JSONField(null=True, blank=True, default=[], verbose_name="关注者")

Expand Down
1 change: 1 addition & 0 deletions mock/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Meta:
"request_method",
"request_body",
"response_text",
"version",
"is_active",
"api_id",
"api_desc",
Expand Down
31 changes: 31 additions & 0 deletions mock/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,37 @@ class MockAPIViewset(viewsets.ModelViewSet):
filter_backends = [DjangoFilterBackend]
filterset_class = MockAPIFilter

def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()

# 获取传入的版本号
incoming_version = request.data.get('version')

# 如果数据库中的版本号比传入的版本号更大,阻止更新并返回错误
if incoming_version is not None and instance.version > int(incoming_version):
return Response({
'status': 'error',
'message': 'There is a newer version of this API already saved.'
}, status=status.HTTP_409_CONFLICT)

serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)

# 序列化器保存了实例,但我们还没有更新版本号
self.perform_update(serializer)

# 保存成功后,递增版本号并更新实例
instance.version += 1
instance.save(update_fields=['version']) # 只更新版本字段

if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}

return Response(serializer.data)

class RequestObject:
def __init__(self, request):
self.method: str = request.method
Expand Down
1 change: 1 addition & 0 deletions web/src/pages/mock_server/mock_api/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def execute(req, resp):
],
paginationSize: 10,
operationButtonType: 'button',
searchForm: [
{
type: 'input',
Expand Down
1 change: 1 addition & 0 deletions web/src/pages/mock_server/mock_project/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default {
dataPath: "results",
totalPath: "count",
paginationSize: 10,
operationButtonType: 'button',
canDelete: () => false,
form: [
{
Expand Down

0 comments on commit 8d26f03

Please sign in to comment.