Search code examples
djangopostgresqldjango-querysetdjango-orm

Django ORM model default not applying in python queryset


I have the below Django ORM which represents a PostgreSQL view.

For the field cost_requirement I have set the default value to 0. However the queryset object still populates with None if data is missing for this field.

I have made all migrations and I just want the default to apply at the Python side (nothing to do with the database). From the Django documentation I understand I am using this argument correctly.

Any suggestions why the default value of 0 is not being applied?

class DashboardProduct(models.Model):
    date = models.DateField()
    product_id = models.CharField(max_length=50)
    base_l = models.FloatField(default=0)   
    cost_requirement =  models.FloatField(blank=False, null=False, default=0)
    book = models.CharField(max_length=100, blank=True, null=True)
    portfolio = models.CharField(max_length=100, blank=True, null=True)
    sales_5_pnl = models.FloatField(default=0)   
    

    class Meta: 
        managed = False 
        db_table = 'view_dashboard_product'

Solution

  • the default=… [Django-doc] is when you create records, but you here work with a view, so it does not create anything, it will thus keep the results from the query. It does not use default=… as a fallback for NULL.

    You can use coalesce in the query, like:

    from django.db.models import Value
    from django.db.models.functions import Coalesce
    
    
    class DashboardProductManager(models.Manager):
        def get_queryset(self, *args, **kwargs):
            return (
                super()
                .get_queryset()
                .annotate(cost_requirement=Coalesce('_cost_requirement', Value(0)))
            )
    
    
    class DashboardProduct(models.Model):
        date = models.DateField()
        product_id = models.CharField(max_length=50)
        base_l = models.FloatField(default=0)
        _cost_requirement = models.FloatField(
            db_column='cost_requirement', blank=False, null=False, default=0
        )
        book = models.CharField(max_length=100, blank=True, null=True)
        portfolio = models.CharField(max_length=100, blank=True, null=True)
        sales_5_pnl = models.FloatField(default=0)
    
        objects = DashboardProductManager()
    
        class Meta:
            managed = False
            db_table = 'view_dashboard_product'