2010-09-30 9 views
11

Je dois écrire des données de modèle (CharField uniquement) dans un fichier XML pour contenir les données d'un fichier Flash. Je suis nouveau à cela, et le processus est un peu flou pour moi de le faire en django. Je crée un fichier XML, puis j'écris les données textuelles dans le fichier (comme c'est le cas avec le module csv, mais avec xml). Un fichier XML très simplifié devrait en résulter pour le fichier flash à lire, à savoir:Générer un fichier XML à partir de données de modèle

<?xml version="1.0" encoding="UTF-8"?> 
<textFields> 
    <textField id="0" text="HELLO WORLD" /> 
    <textField id="1" text="HELLO EARTH" /> 
    ... 
</textFields> 

1. J'utilise un sérialiseur pour écrire les données XML du modèle:

from django.core import serializers 
data = serializers.serialize('xml', myModel.objects.filter(instanceIwantTowrite), fields=('fieldName')) 

2. Je puis créer un fichier en utilisant core.files:

from django.core.files import File  
f = open('/path/to/new/dir/content.xml', 'w') 
myfile = File(f) 

3. Ecrire des données de fichiers et à proximité:

myfile.write(data) 

myfile.close() 

Cela fonctionne jusqu'à présent, bien que la sortie xml contienne les champs pour l'objet "django-objects" etc, et je vais devoir voir si je peux interpréter cela en ActionScript facilement pour le fichier flash. Je préférerais définir manuellement les noms des champs xml comme dans le module csv. Comme je suis nouveau à django et python, je me demande s'il existe une façon plus simple et plus simple de faire cela?

Note: Dans sérialiseur j'utiliser le filtre sur les objets du modèle parce que l'utilisation get pour l'instance de modèle renvoie une erreur object not iterable. En fait, je le filtre deux fois pour obtenir une seule instance, il semble qu'il doit y avoir un meilleur moyen.

+0

Je ne comprends pas le format XML que vous voulez. Un élément 'textField' est-il égal à une seule ligne dans la base de données, chacun avec un seul champ? Si oui, à quoi fait référence le numéro "id"? Si non, comment différenciez-vous les lignes? –

+0

En outre, avez-vous considéré JSON comme un format de sérialisation? C'est beaucoup plus facile à créer et à consommer. –

+0

Oui, textField est une seule entrée charField dans la base de données (chaque champ d'entrée db pour remplir un champ de texte dans un fichier Flash). Désolé, l'identifiant était un peu confus alors, l'idée est qu'il y a plusieurs champs de texte dans le fichier flash, donc les id correspondent à des charFields différents dans le modèle. Ils devraient être différents charFields de modèle. Im regardant dans JSON maintenant, normalement Ive utilisé XML avec AS3, il semble jusqu'à présent que JSON nécessiterait une importation de bibliothèque AS3, et pour cette application ce n'est pas une option malheureusement. – HdN8

Répondre

25

Vous avez deux solutions possibles ici:

1.

Vous pouvez étendre la base django xml sérialiseur (django.core.serializers.xml_serializer.Serializer) et le modifier afin qu'il renvoie des données dans votre structure. Vous pourriez alors courir ex.

YourSerializer('xml', myModel.objects.filter(instanceIwantTowrite), fields=('fieldName')) 

et il va sortir des données dans votre structure.

2.

Ecrire fonction simple qui rendra modèle avec votre structure de données et renvoyer des données XML dans votre format:

code Python

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 

Modèle 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> 
+0

Ok, l'option 2 ressemble à la solution optimale à cela, donc je peux définir la structure xml à volonté en utilisant render_to_string et un template prédéfini (qui pourrait être juste un fichier texte je suppose). Ensuite, j'utilise simplement la méthode file.write() avec 'xml' comme contenu ... ok, j'essaierai d'implémenter cette option, merci! – HdN8

+0

Oui, le modèle est un fichier texte. –

+0

Brillant. Fonctionne sans le problème. +1 – Glycerine

1

Pour une approche plus générique de la résolution de ce problème, vous pouvez éviter les modèles en utilisant un simple poinçon de canard sur Models, et sérialiser n'importe quel graphe d'objet profond en XML en utilisant ElementTree.

Voilà comment je l'ai résolu:

modèles patch singe/poinçon de canard dans votre modèle.py comme:

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 

Cela ajoute une méthode au modèle qui crée une instance d'élément contenant les champs du modèle que vous aimez, sans cruft django.

Ensuite, pour construire votre document XML, faites ceci:

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 

Avec cette approche, vous pouvez obtenir un document XML bien formaté avec tous les champs du modèle django sous forme d'attributs, et construire une hiérarchie profonde n niveau . Chaque noeud xml portera le même nom que la classe de modèle.

Questions connexes