Bypass FK check on save()

I have in my models :

class ServiceOrder(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, blank=True, null=True)
    name = models.CharField(max_length=255)
    manager = models.ForeignKey(get_user_model(), null=True, blank=True, on_delete=models.SET_NULL, related_name='manager')

Now manager is a FK to users table where manager can’t be 0.
But when we migrated the old database into the new project, manager is 0 in many cases and hence :

>>> from service_order.models import ServiceOrder
>>> sof = ServiceOrder.objects.get(id=666)
ValueError: The database backend does not accept 0 as a value for AutoField.

I need to bypass this FK check even if manager is 0.

Looks like you need to override the default database features backend.
This is documented here, looking at the error message that you’re receiving this is what i found out on the django codebase.

The error is being raised by the function validate_autopk_value
That is calling the allows_auto_pk_0 cached property.

Its not related to PK - there already exists a field with value 0 but its a FK to a users table and 0 is not acceptable. I was updating the table and not inserting a new row.

Is this a solution ?
In :

cursor_cloud = connections['default'].cursor()
cursor_cloud.execute("SET FOREIGN_KEY_CHECKS=0;")

I can’t state that this is a solution or not.
I searched the django codebase for the error message that you were receiving and ended up on the code linked on the previous message, I believe you should also check that code to better understand how you can bypass this check, that would be, from my point of view, overriding a DatabaseBackend.

Have you considered writing a clean() method that checks for a value of 0 and sets None instead?

sof.full_clean()  # runs your ServiceOrder.clean() method  # succeeds

Thanks for letting me know about the .full_clean() method.


File C:\path\to\project\env\lib\site-packages\django\db\models\, in Model.full_clean(self, exclude, validate_unique, validate_constraints)
   1499         errors = e.update_error_dict(errors)
   1501 if errors:
-> 1502     raise ValidationError(errors)

ValidationError: {'prev_status': ['Value 0 is not a valid choice.'], 'review_approved_by': ['user instance with id 0 does not exist.']}

I want it to set it to NULL because MySQL accepts NULL.

Suggest implementing clean() on your model to convert 0 to None, and then perhaps call clean() before/instead of full_clean().