python - serializacion - Serialización de objetos clave extranjeros en Django
serializacion de objetos python (4)
ACTUALIZACIÓN: En realidad, la solución de Manoj está un poco desactualizada, el serializador de Wad of Stuff se ha dejado sin actualizar durante un tiempo y cuando lo intenté, parece que ya no es compatible con Django 1.6.
Sin embargo, eche un vistazo al documento oficial de Django aquí . Proporciona una forma de evitar el uso de la clave natural incorporada. Parece que el serializador incorporado de django tiene un pequeño problema para usar ImageField como parte de la clave natural. Pero eso puede ser arreglado fácilmente por usted mismo.
He estado trabajando en el desarrollo de algunos Servicios RESTful en Django para ser utilizado con aplicaciones tanto de Flash como de Android.
El desarrollo de la interfaz de servicios ha sido bastante simple, pero me he encontrado con un problema al serializar objetos que tienen una clave externa y muchas a muchas relaciones.
Tengo un modelo como este:
class Artifact( models.Model ):
name = models.CharField( max_length = 255 )
year_of_origin = models.IntegerField( max_length = 4, blank = True, null = True )
object_type = models.ForeignKey( ObjectType, blank = True, null = True )
individual = models.ForeignKey( Individual, blank = True, null = True )
notes = models.TextField( blank = True, null = True )
Luego, realizaría una consulta en este modelo de esta manera, usando select_related()
, para asegurarme de que se siguen las relaciones con la clave externa:
artifact = Artifact.objects.select_related().get(pk=pk)
Una vez que tengo el objeto, lo serializo y lo devuelvo a mi vista:
serializers.serialize( "json", [ artifact ] )
Esto es lo que recibo, tenga en cuenta que las claves foráneas (object_type e individual) son solo las identificaciones de sus objetos relacionados.
[
{
pk: 1
model: "artifacts.artifact"
fields: {
year_of_origin: 2010
name: "Dummy Title"
notes: ""
object_type: 1
individual: 1
}
}
]
Esto es genial, pero lo que esperaba al usar select_related()
era que rellenaría automáticamente los campos de clave externa con el objeto relacionado, no solo el ID del objeto.
Soy un converso reciente a Django, pero dedico bastante tiempo al desarrollo con CakePHP.
Lo que realmente me gusta de Cake ORM es que seguiría las relaciones y crearía objetos anidados de forma predeterminada, con la capacidad de desvincular las relaciones cuando llamabas a tu consulta.
Esto hizo que fuera muy fácil resumir los servicios de una manera que no requiriera ninguna intervención caso por caso.
Veo que Django no hace esto por defecto, pero ¿hay alguna manera de serializar automáticamente un objeto y todos sus objetos relacionados? Cualquier consejo o lectura sería muy apreciado.
Agregando una respuesta más nueva a esta pregunta anterior: django-serializable-model y recientemente publiqué django-serializable-model como una forma fácilmente extensible de serializar modelos, gerentes y conjuntos de consulta. Cuando sus modelos amplían SerializableModel
, reciben un método de serialización .serialize
que tiene soporte integrado para todas las relaciones.
Usando su ejemplo, una vez que todos los modelos involucrados extiendan SerializableModel
:
joins = [''object_type'', ''individual'']
artifact = Artifact.objects.select_related(*joins).get(pk=pk)
artifact.serialize(*joins)
Llamar a .serialize
con las relaciones como argumentos hará que la biblioteca sea recurrente sobre los objetos relacionados, invocando .serialize
también. Esto devuelve un diccionario que se ve así:
{
''id'': 1,
''year_of_origin'': 2010,
''name'': ''Dummy Title'',
''notes'': '''',
''object_type_id'': 1,
''individual_id'': 1,
''object_type'': { ... nested object here ... },
''individual'': { ... nested object here ... }
}
A continuación, puede llamar a json.dumps
en este diccionario para transformarlo en JSON.
De forma predeterminada, la extensión de SerializableModel
también configurará el administrador del modelo en SerializableManager
(puede ampliarlo usted mismo si está usando un administrador personalizado) que usa SerializableQuerySet
. Esto significa que también puede llamar a .serialize
en un administrador o conjunto de consulta:
artifacts = Artifact.objects.select_related(*joins).all()
artifacts.serialize(*joins)
Esto simplemente llama a .serialize
en cada objeto de modelo en el conjunto de consulta, devolviendo una lista de diccionarios en el mismo formato que el anterior.
django-serializable-model también le permite anular fácilmente el comportamiento predeterminado por modelo, lo que le permite hacer cosas como: agregar listas blancas o listas negras aplicadas a cada .serialize
. serializar, siempre serializar ciertas uniones (para que no lo haga) tiene que agregarlos como argumentos todo el tiempo) ¡y más!
Puede encontrar más información en este ticket:
Permita la serialización exhaustiva especificando la profundidad para seguir la relación https://code.djangoproject.com/ticket/4656
Tenía un requisito similar, aunque no con fines RESTANTES. Pude lograr lo que necesitaba usando un módulo de serialización "completo", en mi caso Django Full Serializers
. Esto es parte de wadofstuff y se distribuye bajo la nueva licencia BSD.
Wadofstuff hace esto bastante fácil. Por ejemplo, en tu caso, necesitarías hacer lo siguiente:
Primero, instale wadofstuff.
En segundo lugar, agregue la siguiente configuración a su archivo settings.py
:
SERIALIZATION_MODULES = {
''json'': ''wadofstuff.django.serializers.json''
}
En tercer lugar, realice un ligero cambio en el código utilizado para la serialización:
artifact = Artifact.objects.select_related().get(pk=pk)
serializers.serialize( "json", [ artifact ], indent = 4,
relations = (''object_type'', ''individual'',))
El cambio de clave es el parámetro de palabras clave de relations
. El único (menor) problema es usar el nombre de los campos que forman la relación, no los nombres de los modelos relacionados.
Advertencia
De la documentation :
Los serializadores Wad of Stuff son 100% compatibles con los serializadores de Django al serializar un modelo. Al deserializar una secuencia de datos, la clase
Deserializer
actualmente solo funciona con datos serializados devueltos por los serializadores estándar de Django .
(Énfasis añadido)
Espero que esto ayude.