Search code examples
pythondjangoviewmodelsforeign-key-relationship

Django / views- add field to model and return to template


I've got three models: Address, Address_localisation (where address_id is ForeignKey) and Address_users (where address_id is ForeignKey again).

In first step I would like to get all the addresses with it's localisation. I tried to use:

data = address.objects.select_related().all().annotate(
            longitude=F('address_localisation__longitude'),
            latitude=F('address_localisation__latitude')
        )  

but if in address_users i've got two (or more) users for one address, this gives me two (or more) rows with the same address (because of joining models).

So I would like to get Addresses and connected localisations only. What i've tried:

data = address.objects.prefetch_related('address_localisation_set').all()

        for e in data.all():
            for ee in e.address_localisation_set.all():                    
                e.longitude = ee.longitude
                e.latitude = ee.latitude

        data = list(data.values('id',            
        'longitude',
        'latitude'
            ))

        data = json.dumps(data)  
        data = json.loads(data)
        return JsonResponse(data, safe = False)

But it leads me to an error: "Cannot resolve keyword 'longitude' into field. Choices are: id.. (listed fileds from Address model)"

As far as I understand it's because in the main model I don't have longitude/latitude fields... but how should I add them?

I know I could iterate through address_localisation_set in template (i didn't tried that, but find solution on stackoverflow), but adding fields could be useful in another place of my sourcecode, so I would like to know how to do it.

Thank you in advance for your time


Solution

  • You really can't add fields to a model; but you can add any attribute to a model instance because that's how Python works - an object can be assigned attributes "on the fly"; but this is not really what you need in your scenario.

    You need to build a custom data set and send it to your template, which is easily done in your view:

    results = [] # This is what you will send to the template
    
    for location in address.objects.select_related():
        data = {} # an empty dictionary
        localized_data = location.address_localisation_set.first()
        data['lat'] = localized_data.latitude
        data['lon'] = localized_data.longitude
        data['id'] = location.id
        results.append(data)
    
    return JsonResponse(json.dumps(results), safe=False)