Customizing Django Serializers
Django Serializers are suppose to take entries from your DB
and serialize in either Json or XML.
The problem is, they’re not very customizable,
and their defaults are not what I was looking for.
For example, Django Serializers expose the item’s PK (usually ID), and Model name.
These are things I don’t necessarily want to expose by default, and it’s pretty tricky to disable that.
I had to extend the current serializers and overwrite a few classes (and the functions thereof).
In my App’s folder, I created a folder named “serializers”,
I copied to it from /usr/local/lib/pythonX.X/dist-packages/django/core/serializers
(your path may vary) the files:
- __init__.py (it’s not empty!)
- xml_serializer.py
- python.py
- json.py
Then I changed the __init__.py file (line 24, so to import the customized serializers):
1
2
3
4
5
BUILTIN_SERIALIZERS = {
"xml" : "myApp.serializers.xml_serializer",
"python" : "myApp.serializers.python",
"json" : "myApp.serializers.json",
}
the json.py (line 10, again, importing the customized serializer):
1
2
from myApp.serializers.python import Serializer as PythonSerializer
from myApp.serializers.python import Deserializer as PythonDeserializer
python.py (replacing lines 30, the self.objects.append block):
1
self.objects.append(self._current)
and finally xml_serializer.py (replacing lines 48-54):
1
attrs = {}
Obviously a lot more customization can be done, for instance the tags in the xml serializers are always <field…>, and I wanted the tags to represent the fields (<title>, <description> etc.) so on xml_serializer.py (line 71) I changed the:
1
self.xml.startElement("field", {
to
1
self.xml.startElement(field.name, {
This way, you’d probably won’t need the “name” on line 72 at all.
Don’t forget to change the endElement too (line 82):
1
self.xml.endElement(field.name)
All in all, it’s a bit more complicated than most of the overwriting that can be easily done on Django, but it’s nothing extreme.
It’s definitely worth it, if you want more control over your feeds.
Another option would be to use the Django Rest Framework, which in this case I figured would take longer to implement, so I just fixed it myself.