Reputation: 173
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;
Upvotes: 2
Views: 228
Reputation: 445
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')
)
)
Upvotes: 1
Reputation: 445
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')
)
)
Upvotes: 2