2010-03-31 9 views
3

Étant donné un modèle Django likeso:Django compresser automatiquement les modèles de terrain sur save() et décomprimer lorsque le champ est accessible

from django.db import models 

class MyModel(models.Model): 
    textfield = models.TextField() 

Comment peut-on compresser automatiquement textfield (par exemple avec zlib) sur save() et décompressez lorsque la propriété textfield est accessible (c.-à-pas sur la charge), avec un flux de travail comme celui-ci:


m = MyModel() 
textfield = "Hello, world, how are you?" 
m.save() # compress textfield on save 
m.textfield # no decompression 
id = m.id() 

m = MyModel.get(pk=id) # textfield still compressed 
m.textfield # textfield decompressed 

Je serais enclin à penser que vous surcharger MyModel.save, mais je ne sais pas le pa ttern pour la modification sur place de l'élément lors de la sauvegarde. Je ne connais pas non plus la meilleure façon de décompresser Django quand le champ est accédé (surcharge __getattr__?).

Ou une meilleure façon de faire ceci serait d'avoir un custom field type?

Je suis certain que j'ai vu un exemple de presque exactement cela, mais hélas, je n'ai pas été en mesure de le trouver récemment.

Merci d'avoir lu – et pour toute contribution que vous pourriez être en mesure de fournir.

Répondre

1

Vous devez implémenter to_python et get_prep_value dans votre type de champ personnalisé pour respectivement décompresser et compresser vos données.

2

Les types de champs personnalisés sont définitivement la solution. C'est le seul moyen fiable de s'assurer que le champ est compressé lors de la sauvegarde et décompressé au chargement. Assurez-vous de définir la métaclasse comme décrit dans votre lien.

+1

Tout à fait d'accord. Ils sont faciles à créer et peuvent simplifier n'importe quel nombre de problèmes communs. Google sur "django strip charfield" pour plusieurs prend une simple extension de models.CharField(), à savoir dépouiller les espaces de début/fin. Franchement, je suis surpris qu'il ne l'ait jamais fait dans le coffre. –

0

Voir aussi https://djangosnippets.org/snippets/2014/ semble un peu plus facile ... Encore juste un TextField sous le capot.

class CompressedTextField(models.TextField): 
    """ 
    model Fields for storing text in a compressed format (bz2 by default) 
    """ 
    __metaclass__ = models.SubfieldBase 

    def to_python(self, value): 
     if not value: 
      return value 

     try: 
      return value.decode('base64').decode('bz2').decode('utf-8') 
     except Exception: 
      return value 

    def get_prep_value(self, value): 
     if not value: 
      return value 

     try: 
      value.decode('base64') 
      return value 
     except Exception: 
      try: 
       tmp = value.encode('utf-8').encode('bz2').encode('base64') 
      except Exception: 
       return value 
      else: 
       if len(tmp) > len(value): 
        return value 

       return tmp 
+0

Cela peut théoriquement répondre à la question, mais il serait préférable d'inclure les parties essentielles de la réponse ici pour les futurs utilisateurs, et de fournir le lien pour référence. [Les réponses dominées par lien] (// meta.stackexchange.com/questions/8231) peuvent devenir invalides via [link rot] (// en.wikipedia.org/wiki/Link_rot). – Mogsdad

Questions connexes