Question

J'utilise le render_to_response de Django pour renvoyer un document XML. Ce document XML spécifique est destiné à une bibliothèque de graphiques à base de mémoire flash. La bibliothèque nécessite que le document XML commence par une BOM (marqueur d'ordre d'octet). Comment faire en sorte que Django prépare la nomenclature à la réponse?

Cela fonctionne pour insérer la nomenclature dans le modèle, mais cela n’est pas pratique car Emacs la supprime à chaque fois que je modifie le fichier.

J'ai essayé de réécrire render_to_response comme suit, mais il échoue car la nomenclature est en cours de codage UTF-8:

def render_to_response(*args, **kwargs):
    bom = kwargs.pop('bom', False)
    httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
    s = django.template.loader.render_to_string(*args, **kwargs)
    if bom:
        s = u'\xef\xbb\xbf' + s
    return HttpResponse(s, **httpresponse_kwargs)
Était-ce utile?

La solution

Vous ne parlez pas vraiment d'une nomenclature (Byte Order Mark), car UTF-8 n'a pas de nomenclature. D'après votre exemple de code, la bibliothèque s'attend à ajouter 3 octets supplémentaires au texte pour une raison inexplicable.

Votre code est presque correct, mais vous devez ajouter les octets en tant que octets et non en caractères. Essayez ceci:

def render_to_response(*args, **kwargs):
    bom = kwargs.pop('bom', False)
    httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
    s = django.template.loader.render_to_string(*args, **kwargs)
    if bom:
        s = '\xef\xbb\xbf' + s.encode("utf-8")
    return HttpResponse(s, **httpresponse_kwargs)

Autres conseils

Cette solution, basée sur une version précédente de la réponse de John Millikin, est plus complexe que celle que j'ai acceptée, mais je l'inclue ici par souci d'exhaustivité. Commencez par définir une classe de middleware:

class AddBOMMiddleware(object):
    def process_response(self, request, response):
        import codecs
        if getattr(response, 'bom', False):
            response.content = codecs.BOM_UTF8 + response.content
        return response

Ajoutez son nom à MIDDLEWARE_CLASSES dans vos paramètres. Puis redéfinissez render_to_response :

def render_to_response(*args, **kwargs):
    bom = kwargs.pop('bom', False)
    httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype', None)}
    rendered = django.template.loader.render_to_string(*args, **kwargs)
    response = django.http.HttpResponse(rendered, **httpresponse_kwargs)
    if bom:
        response.bom = True
    return response

Maintenant, vous pouvez faire render_to_response ("foo.xml", mimetype = "text / xml", bom = True) afin d'ajouter la nomenclature à une réponse particulière.

Le plus simple serait peut-être de configurer Emacs pour ne pas supprimer la nomenclature.

Mais render_to_response n'est pas une fonction compliquée. C'est fondamentalement:

def render_to_response(*args, **kwargs):
    return HttpResponse(loader.render_to_string(*args, **kwargs))

Vous pouvez facilement appeler render_to_string et ajouter la nomenclature à la fin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top