0

first i update my model instance, after that i tried to insert a new data but showing

"IntegrityError('duplicate key value violates unique constraint "RFIDActivation_ActivationId_key"\nDETAIL: Key ("ActivationId")=(6de9ed9a) already exists.\n',)"

Models.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"

my serializer.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()

but rfid_serializer.save() shows exceptionexception

Previous ActivationId is using to saving the new data. ActivationId is unique and auto generated. How can i solve this. Error is showing trying to insert after update query

view.py for working fine code only insertion.

@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()
  • specify **`read_only=True`** in your primary key, `RFIDActivationId = models.AutoField(primary_key=True, db_column='RFIDActivationId', read_only=True)` – minglyu Jul 01 '20 at 08:05
  • @minglyu , while adding read_only=True , showing error TypeError: __init__() got an unexpected keyword argument 'read_only' –  Jul 01 '20 at 08:29
  • @minglyu here i am trying to update the existing details, then inserting new data.. in this case unique key ActivationId(not primary key) showing the duplicate key value violates unique constrain error.. but insertion with out update query is working fine –  Jul 01 '20 at 08:35
  • are you still facing issues? – neferpitou Jul 02 '20 at 04:02

1 Answers1

2

In restframework, serializer.save() has different behavior based on creation and update. If you pass instance to serializer, it will update the object, otherwise, it will create a new one

@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)

UPDATE

default is calculated at import time, in your case, your default value for activation_id is calculated once and never change for subsequent instances. You have to define a function, thus default callable will be updated each time on object creation, read more 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)
minglyu
  • 2,958
  • 2
  • 13
  • 32
  • i am not having 2 request method, only one method is exist. i want to do update and insertion i same request.. at that case, update is working fine and after update , insertion not working fine.. unique key accepting the previous values.. –  Jul 01 '20 at 10:57
  • @ElmaAlida It's a good convention in REST to use `POST` for creation and `PUT` for update. Take a look of the tutorial https://www.django-rest-framework.org/tutorial/2-requests-and-responses/ – minglyu Jul 01 '20 at 11:03
  • @minglyu why `partial=True`? I have tried without it and it works fine. – neferpitou Jul 01 '20 at 23:26
  • @minglyu , I didnt working good.. in case of POST method also showing the erroro "IntegrityError('duplicate key value violates unique constraint "RFIDActivation_ActivationId_key"\nDETAIL: Key ("ActivationId")=(6de9ed9a) already exists.\n',)" We can insert 1 time , den when i tried to insert the same data .but showing the error... –  Jul 02 '20 at 05:25
  • @minglyu thank you so much :) ... its working fine.. this is what i am looking.. you helped me a lot.. :) thank you so much –  Jul 02 '20 at 07:13