Generate XML file from model data
I need to write model data (CharField
s only) to an XML file to contain the data for a flash file. I am new to this, and the process is a little unclear to me for doing this in django. I am creating an xml file, and then writing the text data to the file (as is done with the csv module, but to xml). A very simplified xml file should result for the flash file to read, ie:
<?xml version="1.0" encoding="UTF-8"?>
<textFields>
<textField id="0" text="HELLO WORLD" />
<textField id="1" text="HELLO EARTH" />
...
</textFields>
1. I am using a serializer to write the xml data from the model:
from django.core import serializers
data = serializers.serialize('xml', myModel.objects.filter(instanceIwantTowrite), fields=('fieldName'))
2. I then create file using core.files
:
from django.core.files import File
f = open('/path/to/new/dir/content.xml', 'w')
myfile = File(f)
3. Write File data and close:
myfile.write(data)
myfile.close()
This works so far, although the xml output contains the fields f开发者_C百科or the object "django-objects" etc, and I will have to see if I can interpret this in ActionScript easily for the flash file. I would prefer to define the xml field names manually like in the csv module. As I am new to django and python, I am wondering if there is an easier, simpler way to do this?
Note: In serializer I use filter on the model objects because using get
for the model instance returns an object not iterable
error. In fact I filter it twice to get a single instance, seems like there must be a better way.
You have two possible solutions here:
1.
You can extend base django xml serializer(django.core.serializers.xml_serializer.Serializer
) and modify it so it will return data in your structure. You could then run ex.
YourSerializer('xml', myModel.objects.filter(instanceIwantTowrite), fields=('fieldName'))
and it will output data in your structure.
2.
Write simple function that will render template with your data structure and return xml data in your format:
Python code
from django.template.loader import render_to_string
def my_serialize(query_set):
xml = render_to_string('xml_template.xml', {'query_set': query_set})
return xml
Template xml_template.xml
<?xml version="1.0" encoding="UTF-8"?>
<textFields>
{% for object in query_set %}
<textField id="{{ object.pk }}" text="{{ object.my_field }}" />
{% endfor %}
</textFields>
For a more generic approach to solving this problem, you can avoid templates by using a simple duck punch on Models, and serialize any deep object graph to XML using ElementTree.
Here's how I solved it:
Monkey patch/duck punch models in your Model.py like:
if hasattr(models.Model, "to_element")==False:
import xml.etree.ElementTree as ET
def to_element(self):
ele = ET.Element(self.__class__.__name__)
for field in self._meta.fields:
ele.attrib[field.attname]=str(getattr(self,field.attname))
return ele
models.Model.to_element = to_element
This adds a method to Model which creates an Element instance containing the fields from the model that you care about, without the django cruft.
Then, to construct your xml document, just do this:
dealer = Dealer.objects.get(id=dealer_id)
makes = DealerMake.objects.filter(dealer=dealer)
root = dealer.to_element()
for make in makes:
root.append(make.to_element())
xml = ET.tostring(root)
print xml
With this approach you can get a nicely formatted xml document with all django model fields as attributes, and construct an n-level deep hierarchy. Each xml node will be named the same as the model class.
精彩评论