Opened 3 weeks ago

Closed 3 weeks ago

Last modified 3 weeks ago

#36911 closed Bug (wontfix)

Raise an error when GeneratedField provided to fields argument of bulk_update()

Reported by: jaffar Khan Owned by:
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: bulk_update GeneratedField
Cc: jaffar Khan Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Currently, bulk_update() does not validate if the fields provided in the fields=[...] argument are GeneratedField instances.

Model:

    class Product(models.Model):
        price = models.IntegerField()
        quantity = models.IntegerField()
        total = models.GeneratedField(
            expression=models.F("price") * models.F("quantity"),
            output_field=models.IntegerField(),
            db_persist=True,
        )

test function:

def run_test():
    
    # Create product
    p = Product.objects.create(price=10, quantity=2)

    p.total = 9999
    
    try:
        Product.objects.bulk_update([p], fields=["total"])        
        print("silent failure")
            
    except Exception as e:
        print(f"CRASH: {e}")

output:
silent failure

If a developer accidentally includes a GeneratedField in bulk_update(), Django attempts to include it in the SQL UPDATE statement.
On SQLite, this results in a silent failure (no error is raised, but the value is obviously not updated as it is generated).
On strict databases (like PostgreSQL), this likely results in an OperationalError.

Django should raise a FieldError immediately when bulk_update() is called with a GeneratedField, similar to how it handles other read-only fields or invalid field names.

Change History (3)

comment:1 by jaffar Khan, 3 weeks ago

I have a patch and will work on it if this ticket is accepted.

comment:2 by Jacob Walls, 3 weeks ago

Resolution: wontfix
Status: newclosed
Summary: bulk_update() incorrectly allows updating GeneratedField (silent failure on SQLite)Raise an error when GeneratedField provided to fields argument of bulk_update()

Thanks for the ticket, but bulk_update() behaves the same as update() here, which has silently skipped GeneratedFields since their introduction. I also don't see a way to get OperationalError on other databases.

comment:3 by jaffar Khan, 3 weeks ago

I manually checked the PostgreSQL behavior on GeneratedField and it does raise an error, so I initially expected Django to raise an error as well. I now understand that bulk_update() behaves like update() and silently skips GeneratedField since their introduction. Thanks for clarification.

Note: See TracTickets for help on using tickets.
Back to Top