【问题标题】:duplicate Key violation in Django insert doing after Django update在 Django 更新后,Django 插入中的重复键违规
【发布时间】:2020-10-21 14:53:56
【问题描述】:

首先我更新我的模型实例,然后我尝试插入新数据但显示

"IntegrityError('重复键值违反了唯一约束"RFIDActivation_ActivationId_key"\nDETAIL: Key ("ActivationId")=(6de9ed9a) 已经存在。\n',)"

模型.py

class RFIDActivation(models.Model):
    RFIDActivationId = models.AutoField(primary_key=True, db_column='RFIDActivationId')
    Device = models.ForeignKey(Device, on_delete=models.CASCADE, db_column='DeviceId')
    Employee = models.ForeignKey(Employee, on_delete=models.CASCADE, db_column='EmployeeId')
    ActivationId = models.CharField(max_length=10, unique=True, default=uuid4().hex[:8])
    ActivationStatus = models.CharField(max_length=1)default=None)

    class Meta:
       db_table = "RFIDActivation"

我的序列化器.py

class RFIDActivationSerializer(serializers.ModelSerializer):
    class Meta:
        model = RFIDActivation
        fields = '__all__'

view.py

@api_view(["POST"])
@permission_classes([IsAuthenticated])
def rfid_activation_initial(request):
     RFIDActivation.objects.filter(Employee=request.POST.get("Employee")).update(
            ActivationStatus='2',
            ActivationMessage='Abort'
        )

    rfid_activation = {
        'Employee': request.POST.get("Employee"),
        'Device': request.POST.get("Device"),
        'ActivationStatus': "0",
        'ActivationMessage': "RFID Activation Initiated"
    }
    rfid_serializer = RFIDActivationSerializer(data=rfid_activation)
    if rfid_serializer.is_valid():
        rfid_serializer.save()

但是 rfid_serializer.save() 显示异常exception

Previous ActivationId 用于保存新数据。 ActivationId 是唯一的并且是自动生成的。我该如何解决这个问题。错误显示在更新查询后尝试插入

view.py 用于仅插入工作正常的代码。

@api_view(["POST"])
@permission_classes([IsAuthenticated])
def rfid_data_add(request):
    rfid_activation = {
        'Employee': request.POST.get("Employee"),
        'Device': request.POST.get("Device"),
        'ActivationStatus': "0",
        'ActivationMessage': "RFID Activation Initiated"
    }
    rfid_serializer = RFIDActivationSerializer(data=rfid_activation)
    if rfid_serializer.is_valid():
        rfid_serializer.save()

【问题讨论】:

  • 在您的主键中指定 read_only=TrueRFIDActivationId = models.AutoField(primary_key=True, db_column='RFIDActivationId', read_only=True)
  • @minglyu ,同时添加 read_only=True ,显示错误 TypeError: __init__() got an unexpected keyword argument 'read_only'
  • @minglyu 在这里我正在尝试更新现有详细信息,然后插入新数据。在这种情况下,显示重复键值的唯一键 ActivationId(非主键)违反了唯一约束错误。但插入没有更新查询工作正常
  • 您还遇到问题吗?

标签: django django-models django-rest-framework django-serializer


【解决方案1】:

在restframework中,serializer.save()根据创建和更新有不同的行为。如果你将 instance 传递给序列化器,它将更新对象,否则,它将创建一个新对象

@api_view(['POST', 'PUT'])
def rfid_data(request, pk):
    """
    Update or delete a rfid data.
    """

    rfid_activation = {
         ...
    }

    if request.method == 'POST':
        rfid_serializer = RFIDActivationSerializer(data=rfid_activation)
        if rfid_serializer.is_valid():
            rfid_serializer.save()
            return Response(rfid_serializer.data,status=status.HTTP_201_CREATED)
        return return Response(rfid_serializer.data, status=status.HTTP_400_BAD_REQUEST)

    # PUT is used for object update
    elif request.method == 'PUT':
        rfid = RFIDActivation.objects.get(pk=pk)
        # pass instance to your serializer
        # pass partial=True to allow partial updates
        rfid_serializer = RFIDActivationSerializer(instance=rfid, data=rfid_activation, partial=True)
        if rfid_serializer.is_valid():
            rfid_serializer.save()
            return Response(rfid_serializer.data)
        return Response(rfid_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

更新

defaultimport time 计算,在您的情况下,activation_id 的默认值计算一次,并且不会在后续实例中更改。 您必须定义一个函数,因此每次创建对象时都会更新默认可调用对象,阅读更多here

def activation_id_generator(self):
    return uuid4().hex[:8]

# then in your class
class RFIDActivation(models.Model):
    ...
    ActivationId = models.CharField(max_length=10, unique=True, default=activation_id_generator)

【讨论】:

  • 我没有两种请求方法,只有一种方法存在。我想做更新和插入我同样的请求..在这种情况下,更新工作正常,更新后,插入不能正常工作..接受以前值的唯一键..
  • @ElmaAlida 在 REST 中使用 POST 创建并使用 PUT 进行更新是一个很好的约定。看教程django-rest-framework.org/tutorial/2-requests-and-responses
  • @minglyu 为什么是partial=True?我试过没有它,它工作正常。
  • @minglyu ,我没有很好地工作.. 如果 POST 方法也显示错误 "IntegrityError('duplicate key value 违反唯一约束 "RFIDActivation_ActivationId_key"\nDETAIL: Key ("ActivationId")=( 6de9ed9a) 已经存在。\n',)" 我们可以插入 1 次 den 当我尝试插入相同的数据时。但显示错误...
  • @minglyu 非常感谢你:) ...它工作正常..这就是我正在寻找的..你帮了我很多.. :) 非常感谢你
猜你喜欢
  • 2015-04-20
  • 1970-01-01
  • 2018-02-22
  • 2011-09-16
  • 2016-08-02
  • 2017-04-20
  • 2013-08-02
  • 1970-01-01
  • 2017-07-03
相关资源
最近更新 更多