standard run locally google engine deploy app python django google-app-engine

python - google - run django app locally



Cómo crear un campo de lista en django (7)

Considere django-jsonfield , las ventajas son:

  • Guarde y cargue objetos de listas nativas, no necesita conversión
  • Solución bien probada y madura
  • Podría tener otras ventajas dentro de su proyecto
  • Admite filtrado en la base de datos y expresiones regulares (si es necesario)

además:

  • Soporte cruzado
  • Admite Python 2.7 a Python 3.4 y Django 1.4 a 1.8
  • Realmente fácil :)

¿Cómo creo un ListField en Django (Python) como la propiedad ListProperty en Google App Engine (Python)? Mi información es una lista como esta: 3,4,5,6,7,8 .

¿Qué propiedad debo definir y cómo obtendré valores de ella?


Hago esto:

def get_comma_field(self, field): data = getattr(self, field) if data: return data.split('','') return [] def set_comma_field(self, val, field): if isinstance(val, types.StringTypes): setattr(self, field, val) else: setattr(self, field, '',''.join(val)) def make_comma_field(field): def getter(self): return get_comma_field(self, field) def setter(self, val): return set_comma_field(self, val, field) return property(getter, setter) class MyModel(models.Model): _myfield = models.CharField(max_length=31) myfield = make_comma_field(''_myfield'')

Pero supongo que ahora podría ser excesivo. Necesitaba bastantes, por lo que escribí la función make_comma_field.



Revisando esto con un tipo ListField que puede usar. Pero hace algunas suposiciones, como el hecho de que no está almacenando tipos complejos en su lista. Por este motivo, utilicé ast.literal_eval() para exigir que solo los tipos simples incorporados se puedan almacenar como miembros en un ListField :

from django.db import models import ast class ListField(models.TextField): __metaclass__ = models.SubfieldBase description = "Stores a python list" def __init__(self, *args, **kwargs): super(ListField, self).__init__(*args, **kwargs) def to_python(self, value): if not value: value = [] if isinstance(value, list): return value return ast.literal_eval(value) def get_prep_value(self, value): if value is None: return value return unicode(value) def value_to_string(self, obj): value = self._get_val_from_obj(obj) return self.get_db_prep_value(value) class Dummy(models.Model): mylist = ListField()

Tomándolo por una vuelta:

>>> from foo.models import Dummy, ListField >>> d = Dummy() >>> d.mylist [] >>> d.mylist = [3,4,5,6,7,8] >>> d.mylist [3, 4, 5, 6, 7, 8] >>> f = ListField() >>> f.get_prep_value(d.numbers) u''[3, 4, 5, 6, 7, 8]''

Ahí lo tiene que una lista se almacena en la base de datos como una cadena unicode, y cuando se tira hacia atrás se ejecuta a través de ast.literal_eval() .

Anteriormente, sugerí esta solución en esta publicación de blog sobre Custom Fields en Django :

Una alternativa al CommaSeparatedIntegerField, le permite almacenar cualquier valor separado. También puede especificar opcionalmente un parámetro de token.

from django.db import models class SeparatedValuesField(models.TextField): __metaclass__ = models.SubfieldBase def __init__(self, *args, **kwargs): self.token = kwargs.pop(''token'', '','') super(SeparatedValuesField, self).__init__(*args, **kwargs) def to_python(self, value): if not value: return if isinstance(value, list): return value return value.split(self.token) def get_db_prep_value(self, value): if not value: return assert(isinstance(value, list) or isinstance(value, tuple)) return self.token.join([unicode(s) for s in value]) def value_to_string(self, obj): value = self._get_val_from_obj(obj) return self.get_db_prep_value(value)


Si bien la respuesta de Jonathan es genial, recibí el siguiente error al intentar usar el comando dumpdata :

Error: Unable to serialize database: get_db_prep_value() takes at least 3 arguments (2 given)

El problema es que la llamada self.get_db_prep_value en el método value_to_string requiere que se proporcione un valor de connection (al menos en Django 1.4.10 , que es lo que estoy usando). Al final, realmente no vi lo que se ganaba llamando al método value_to_string en primer lugar y lo __init__ , junto con el método __init__ innecesario. Esto es con lo que terminé:

class ListField(models.TextField): __metaclass__ = models.SubfieldBase description = "Stores a python list" def to_python(self, value): if not value: value = [] if isinstance(value, list): return value converted = ast.literal_eval(value) if not isinstance(converted, list): raise ValueError(''Value "%s" not a list'' % converted) return converted


Si está utilizando postgresql, django admite postgres con arrayfield .


Simplemente, puede almacenar la lista como una cadena y cada vez que la use, use ast.literal_eval () para convertir primero a lista de cadena. p.ej:

import ast class MyModel(models.Model): field_1 = models.any kind of field() list_field = models.CharField(max_length=255) def get_list(self): list = ast.literal_eval(self.list_field) return list

De la misma manera en las vistas, etc. Al guardar, haga opraciones en la lista y finalmente conviértalo en una cadena de la siguiente manera:

model.list_field = str(list) model.save()