Generating custom primary key

Hello, Everyone
I am working with Django + MS SQL Server
I need to create a primary key manually. I am new to framework. I tried django-sequences but not working with SQL Server. I am facing issues where should I increment my primary key in models or in view.py. I tried to create primary key manually in views.py ‘perform_create’ method I am saving serializer.save() in perform_create method also in my create method. Anyone can give me a complete code snippet how I can generate PK manually. I’ll put code below.
Anyone can please help. thanks

This is my model:

class DrycleanMcustomerinfomaster(models.Model):
    uniqid = models.DecimalField(primary_key=True, db_column='UniqID',max_digits=18, decimal_places=0, null=False)
    tcounter = models.IntegerField(null=False, db_column='tcounter', default=0)
    isVerified = models.BooleanField(null=False,db_column='isVerified', default=0)

    class Meta:
        db_table = 'DryClean_mCustomerInfoMaster'

This is my view.py

class CustomerSignUpView(viewsets.ViewSet):
    def list(self, request):
        permission_classes = []
        authentication_classes = []
        qs = DrycleanMcustomerinfomaster.objects.filter().order_by('uniqid')[:10]
        serializer_class = CustomerSerializer(qs, many=True)
        return  Response(serializer_class.data)

    def create(self, request, *args, **kwargs):
        serializer_class = CustomerSerializer(data=request.data)
        if serializer_class.is_valid(self):
            serializer_class.save()
            # self.perform_create(serializer_class)
            return Response(serializer_class.data, status=status.HTTP_201_CREATED)
        return Response(serializer_class.data, status=status.HTTP_400_BAD_REQUEST)

perform_create method

 @transaction.atomic
    def perform_create(self, serializer_class):
        top = DrycleanMcustomerinfomaster.objects.select_for_update(nowait=True).order_by('uniqid').latest('uniqid')
        try:
            with transaction.atomic():
                uniqid = top.uniqid + 1
                serializer_class.save(uniqid=uniqid)
                return serializer_class.data
        except IntegrityError:
            print(IntegrityError)

What you’ve described and posted is still subject to a race condition.

If you set uniqid as an integer field with primary_key = True, Django should create that field in the database with the appropriate sequence.

You really don’t want to try to manage this yourself. Let this work be done in the database where it belongs.

In database ‘UniqID’ is not AutoIncremental field. If I set UniqID is Integer field in my database I get error. Either I put manually PK everytime or whenever data is inserted it auto increment the UiqID
I attached the SC.

This is my serializer

class CustomerSerializer(serializers.ModelSerializer):
    uniqid = serializers.ReadOnlyField(read_only=True)
    class Meta:
        model = DrycleanMcustomerinfomaster
        fields = ['uniqid', 'customer_first_name', 'customer_phone', 'customer_email_address','customer_terms_conditions','frenchise']

        def validate(self, data):
            customer_first_name = data.get('customer_first_name', '')
            customer_phone = data.get('customer_phone', '')  # get - Provide defualt param is email not inserted
            customer_email_address = data.get('customer_email_address', '')
            customer_terms_conditions = data.get('customer_terms_conditions', '')
            frenchise = data.get('frenchise', '')  # get - Provide defualt param is email not inserted
            if customer_first_name == "":
                raise serializers.ValidationError("name is missing")
            return data

Correct. That’s the problem.

1 Like

Yes, It works fine with perform_create method I am generating PK manually. Then problem comes in serializer validation.

No, it just currently looks like it’s working fine. But you have a race condition in your code that will periodically throw errors.

You fix and prevent this by creating your primary key properly - as an auto increment field. (Or, you create the appropriate database-level code - trigger or UDF - to create that field. What you don’t do is try to manage it within Django.)

yes, you are right it looks working fine. Can we access db triggers or store procedure ?

I’m not sure I understand what you’re asking here.

You would not be “accessing” or “using” those triggers from within your Django code - they would work on the data being submitted to the database as sent from Django. You would effectively be recreating the “autoincrement” functionality within your own code instead of using the feature as provided by the database.