mysqldjangoormprefetchannotate

Django Annotate - Concat from last created ManyToMany Object Fields


class User(models.Model):
    name=CharField()


class Address(models.Model):
    user= Foreignkey(user, related_name="Addresses")
    buildingname=CharField()
    street=CharField()
    ...

I have a models like top and want to extract data as list below.

{
    [
        ['USERNAME1', 'A XYZBUILDING 14 Drain St. '],
        ['USERNAME2', 'C XXXBUILDING 13 Drain St. '],
        ['USERNAME3', 'B ZZZBUILDING 12 Drain St. '],
        ...
    ]
    
}

Also as a workaround, this is a closest thing to the answer but i could not make it finish

without looping every user or

without executing raw sql in extra method's select field.

I want to achive this with Django ORM.


Solution

  • Not the best solution probably, but it covers the requirements.

    from django.db.models import Subquery, CharField, Value, F, OuterRef
    from django.db.models.functions import Coalesce, Trim, Concat
    
    from myfile import my_custom_filters, Address, User
    
    address_subquery = Address.objects.filter(
        user__id=OuterRef('id')
    ).order_by('-created')
    User.objects.filter(**my_custom_filters).annotate(
        street_str=Subquery(
            Coalesce(
                address_subquery.values_list('street', flat=True)[:1], 
                Value("")
            ),
            output_field=CharField()
        ),
        building_name_str=Subquery(
            Coalesce(
                address_subquery.values_list('building_name', flat=True)[:1], 
                Value("")
            ),
            output_field=CharField()
        )
    ).annotate(
        address_text_str=Trim(
            Concat(
                F('street_str'),
                Value(" "),
                F('building_name_str')
            )
        )
    ).values_list('name', 'address_text_str')