MYSQL query equivalent in django

Question:

I have a django project with 2 models called wca and identifiers, I am wanting to update a field called ‘secid’ within identifiers model pulled from the equivalent field in wca model where code from identifiers model matches isin field in wca model.

Models

class Identifier(TimeStampMixin, models.Model):
    secid = models.IntegerField(default=0, db_index=True)
    code_type = models.CharField(max_length=10, null=True)
    code = models.CharField(max_length=12, db_index=True)
    account = models.ForeignKey(Account, on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.code
        
        
class Wca(models.Model):
    secid = models.IntegerField(blank=False, null=False, db_index=True)
    isin = models.CharField(max_length=12, blank=True, db_index=True)
    uscode = models.CharField(max_length=9, blank=True, db_index=True)
    sedol = models.CharField(max_length=7, blank=True, db_index=True)
    
    def __str__(self):
        return str(self.secid)  

I have the working sql code for this but would like to convert into django equivalent for best practice. My sql query is as follows:

    UPDATE portfolio_identifier
    left outer join product_wca on portfolio_identifier.code = product_wca.isin
    SET
    portfolio_identifier.SecID = product_wca.secid
    WHERE
    code_type = 'ISIN';

Edit

The following is the updated MYSQL query to handle mismatches (NULL values):

UPDATE portfolio_identifier
inner join product_wca on portfolio_identifier.code = product_wca.isin and portfolio_identifier.code_type = 'ISIN'
SET portfolio_identifier.SecID = product_wca.secid;
Asked By: rob

||

Answers:

This should work with some changes in the model and fields names.

from django.db.models import OuterRef, Subquery

Identifier.objects.filter(code_type='ISIN').update(
    secid=Subquery(
        Wca.objects.filter(
            isin=OuterRef('code')
        ).values('secid')
    )
)
from django.db.models import OuterRef, Subquery, F, When, Case, Value, IntegerField

Identifier.objects.filter(
    code_type='ISIN'
    code__in=Wca.objects.values('isin')
).update(
    secid=Subquery(
        Wca.objects.filter(
            isin=OuterRef('code')
        ).annotate(
            secid_new=Case(
                When(
                    secid__isnull=False,
                    then=F('secid')
                ),
                default=Value(0),
                output_field=IntegerField()
            )
       ).values('secid_new').distinct()
    )
)

Or if the case when the WCA secid is not needed then:

Identifier.objects.filter(
    code_type='ISIN'
    code__in=Wca.objects.values('isin')
).update(
    secid=Subquery(
        Wca.objects.filter(
            isin=OuterRef('code')
        ).values('secid')
    )
)
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.