Feature Request: Allow Serialize Foreign Keys as Ids

82 views
Skip to first unread message

Ryan Gartin

unread,
Aug 3, 2023, 4:46:48 PM8/3/23
to Django developers (Contributions to Django itself)
I came across this issue calling the following and FK fields with _id are ignored:
serialize('json', ...., fields=['title', 'state_id'])

State is a ForeignKey on my queryset. I can perform fields=['title', 'state'] and I get serialization correctly of {'state': int}. However, if I specify fields=['state_id'] then the serialization completely ignores that field. It would be nice if we could serialize foreign keys on either field.name or field.attname. 

I wrote a hack to make it work myself but it breaks the non-id use case.

def start_serialization(self):
for field in [x for x in self.selected_fields if '_id' in x]:
self.selected_fields.append(field.replace('_id', ''))
super().start_serialization()

def handle_fk_field(self, obj, field):
if not self.use_natural_foreign_keys and not hasattr(field.remote_field.model, "natural_key"):
self._current[field.attname] = getattr(obj, field.attname)
else:
return super().handle_fk_field(obj, field)

Curtis Maloney

unread,
Aug 3, 2023, 9:46:27 PM8/3/23
to 'Mike Hansen' via Django developers (Contributions to Django itself)
Hi Mike,

On Fri, 4 Aug 2023, at 06:03, Ryan Gartin wrote:
I came across this issue calling the following and FK fields with _id are ignored:
serialize('json', ...., fields=['title', 'state_id'])

I think the problem you've run into here is "state_id" is not a Field on your model; it's where the raw PK value for your ForeignKey is stored.

I've just double checked the code for serialize, and I'm pretty sure the default behavior for a ForeignKey field _is_ _already_ to output the PK value.

What happens in your code if you put "state" instead of "state_id" in the field list?

--
Curtis

Ryan Gartin

unread,
Aug 4, 2023, 4:47:12 PM8/4/23
to Django developers (Contributions to Django itself)
You are correct state_id is not a field on the model, state is, and using “state” in the field lists works.

I would like to propose that if  ‘state_id’ is a valid property on the queryset (and in the database) that is should be serialized.

It is my preference that a serialized JSON property (to be consumed in a strongly typed language) is reserved for a specific type. I realize Django will determine that `state: int` is an Int and it needs to do a FK lookup and populate that property with the state model but a strongly typed language does not have that ability to determine between two types nor does it have the ability to requery. So my preference when I consume JSON response into my apps is to reserve state: { title: str, etc...} to an object representing State model and use state_id: int wherever I just need the Integer. 

While I understand that this is my personal preference I think it is reasonable to request that if QuerySet.state_id returns a valid value then it should also be capable of being serialized as well. 

Vansh NaiK

unread,
Aug 5, 2023, 1:23:35 PM8/5/23
to Django developers (Contributions to Django itself)
How toh hack account

Curtis Maloney

unread,
Aug 5, 2023, 9:22:52 PM8/5/23
to 'Mike Hansen' via Django developers (Contributions to Django itself)
On Sat, 5 Aug 2023, at 06:47, Ryan Gartin wrote:
You are correct state_id is not a field on the model, state is, and using “state” in the field lists works.

I would like to propose that if  ‘state_id’ is a valid property on the queryset (and in the database) that is should be serialized.

I think the main limitation you're hitting here is the core serializers in Django are really primarily only tuned for generating fixtures; This is why pretty much every REST API framework for Django has had its own version of the idea.

The built in ones are simply not flexible enough.

IMHO the serializer is the most important part of any REST / API framework.

While I understand that this is my personal preference I think it is reasonable to request that if QuerySet.state_id returns a valid value then it should also be capable of being serialized as well. 
Way back in the mid 2000s I did my own sub-classes of the core Serializers to allow this sort of thing. Since then I've tried maybe half a dozen REST API libs (including writing my own), and none of them used core serializers.

That's not to say your idea is without merit. I think if you give it an afternoon's digging you could add an option to the django core serializers to list non-field attributes to include.

--
Curtis
Reply all
Reply to author
Forward
Message has been deleted
0 new messages