mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	This is a big internal change, but mostly backwards compatible with existing code. Also adds a couple of new features. Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658 git-svn-id: http://code.djangoproject.com/svn/django/trunk@7477 bcc190cf-cafb-0310-a4f2-bffc1f526a37
		
			
				
	
	
		
			260 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| """
 | |
| 42. Serialization
 | |
| 
 | |
| ``django.core.serializers`` provides interfaces to converting Django querysets
 | |
| to and from "flat" data (i.e. strings).
 | |
| """
 | |
| 
 | |
| from django.db import models
 | |
| 
 | |
| class Category(models.Model):
 | |
|     name = models.CharField(max_length=20)
 | |
| 
 | |
|     class Meta:
 | |
|        ordering = ('name',)
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return self.name
 | |
| 
 | |
| class Author(models.Model):
 | |
|     name = models.CharField(max_length=20)
 | |
| 
 | |
|     class Meta:
 | |
|         ordering = ('name',)
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return self.name
 | |
| 
 | |
| class Article(models.Model):
 | |
|     author = models.ForeignKey(Author)
 | |
|     headline = models.CharField(max_length=50)
 | |
|     pub_date = models.DateTimeField()
 | |
|     categories = models.ManyToManyField(Category)
 | |
| 
 | |
|     class Meta:
 | |
|        ordering = ('pub_date',)
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return self.headline
 | |
| 
 | |
| class AuthorProfile(models.Model):
 | |
|     author = models.OneToOneField(Author, primary_key=True)
 | |
|     date_of_birth = models.DateField()
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return u"Profile of %s" % self.author
 | |
| 
 | |
| class Actor(models.Model):
 | |
|     name = models.CharField(max_length=20, primary_key=True)
 | |
| 
 | |
|     class Meta:
 | |
|         ordering = ('name',)
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return self.name
 | |
| 
 | |
| class Movie(models.Model):
 | |
|     actor = models.ForeignKey(Actor)
 | |
|     title = models.CharField(max_length=50)
 | |
| 
 | |
|     class Meta:
 | |
|        ordering = ('title',)
 | |
| 
 | |
|     def __unicode__(self):
 | |
|         return self.title
 | |
| 
 | |
| class Score(models.Model):
 | |
|     score = models.FloatField()
 | |
| 
 | |
| __test__ = {'API_TESTS':"""
 | |
| # Create some data:
 | |
| >>> from datetime import datetime
 | |
| >>> sports = Category(name="Sports")
 | |
| >>> music = Category(name="Music")
 | |
| >>> op_ed = Category(name="Op-Ed")
 | |
| >>> sports.save(); music.save(); op_ed.save()
 | |
| 
 | |
| >>> joe = Author(name="Joe")
 | |
| >>> jane = Author(name="Jane")
 | |
| >>> joe.save(); jane.save()
 | |
| 
 | |
| >>> a1 = Article(
 | |
| ...     author = jane,
 | |
| ...     headline = "Poker has no place on ESPN",
 | |
| ...     pub_date = datetime(2006, 6, 16, 11, 00))
 | |
| >>> a2 = Article(
 | |
| ...     author = joe,
 | |
| ...     headline = "Time to reform copyright",
 | |
| ...     pub_date = datetime(2006, 6, 16, 13, 00, 11, 345))
 | |
| >>> a1.save(); a2.save()
 | |
| >>> a1.categories = [sports, op_ed]
 | |
| >>> a2.categories = [music, op_ed]
 | |
| 
 | |
| # Serialize a queryset to XML
 | |
| >>> from django.core import serializers
 | |
| >>> xml = serializers.serialize("xml", Article.objects.all())
 | |
| 
 | |
| # The output is valid XML
 | |
| >>> from xml.dom import minidom
 | |
| >>> dom = minidom.parseString(xml)
 | |
| 
 | |
| # Deserializing has a similar interface, except that special DeserializedObject
 | |
| # instances are returned.  This is because data might have changed in the
 | |
| # database since the data was serialized (we'll simulate that below).
 | |
| >>> for obj in serializers.deserialize("xml", xml):
 | |
| ...     print obj
 | |
| <DeserializedObject: Poker has no place on ESPN>
 | |
| <DeserializedObject: Time to reform copyright>
 | |
| 
 | |
| # Deserializing data with different field values doesn't change anything in the
 | |
| # database until we call save():
 | |
| >>> xml = xml.replace("Poker has no place on ESPN", "Poker has no place on television")
 | |
| >>> objs = list(serializers.deserialize("xml", xml))
 | |
| 
 | |
| # Even those I deserialized, the database hasn't been touched
 | |
| >>> Article.objects.all()
 | |
| [<Article: Poker has no place on ESPN>, <Article: Time to reform copyright>]
 | |
| 
 | |
| # But when I save, the data changes as you might except.
 | |
| >>> objs[0].save()
 | |
| >>> Article.objects.all()
 | |
| [<Article: Poker has no place on television>, <Article: Time to reform copyright>]
 | |
| 
 | |
| # Django also ships with a built-in JSON serializers
 | |
| >>> json = serializers.serialize("json", Category.objects.filter(pk=2))
 | |
| >>> json
 | |
| '[{"pk": 2, "model": "serializers.category", "fields": {"name": "Music"}}]'
 | |
| 
 | |
| # You can easily create new objects by deserializing data with an empty PK
 | |
| # (It's easier to demo this with JSON...)
 | |
| >>> new_author_json = '[{"pk": null, "model": "serializers.author", "fields": {"name": "Bill"}}]'
 | |
| >>> for obj in serializers.deserialize("json", new_author_json):
 | |
| ...     obj.save()
 | |
| >>> Author.objects.all()
 | |
| [<Author: Bill>, <Author: Jane>, <Author: Joe>]
 | |
| 
 | |
| # All the serializers work the same
 | |
| >>> json = serializers.serialize("json", Article.objects.all())
 | |
| >>> for obj in serializers.deserialize("json", json):
 | |
| ...     print obj
 | |
| <DeserializedObject: Poker has no place on television>
 | |
| <DeserializedObject: Time to reform copyright>
 | |
| 
 | |
| >>> json = json.replace("Poker has no place on television", "Just kidding; I love TV poker")
 | |
| >>> for obj in serializers.deserialize("json", json):
 | |
| ...     obj.save()
 | |
| 
 | |
| >>> Article.objects.all()
 | |
| [<Article: Just kidding; I love TV poker>, <Article: Time to reform copyright>]
 | |
| 
 | |
| # If you use your own primary key field (such as a OneToOneField),
 | |
| # it doesn't appear in the serialized field list - it replaces the
 | |
| # pk identifier.
 | |
| >>> profile = AuthorProfile(author=joe, date_of_birth=datetime(1970,1,1))
 | |
| >>> profile.save()
 | |
| 
 | |
| >>> json = serializers.serialize("json", AuthorProfile.objects.all())
 | |
| >>> json
 | |
| '[{"pk": 1, "model": "serializers.authorprofile", "fields": {"date_of_birth": "1970-01-01"}}]'
 | |
| 
 | |
| >>> for obj in serializers.deserialize("json", json):
 | |
| ...     print obj
 | |
| <DeserializedObject: Profile of Joe>
 | |
| 
 | |
| # Objects ids can be referenced before they are defined in the serialization data
 | |
| # However, the deserialization process will need to be contained within a transaction
 | |
| >>> json = '[{"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00", "categories": [4, 1], "author": 4}}, {"pk": 4, "model": "serializers.category", "fields": {"name": "Reference"}}, {"pk": 4, "model": "serializers.author", "fields": {"name": "Agnes"}}]'
 | |
| >>> from django.db import transaction
 | |
| >>> transaction.enter_transaction_management()
 | |
| >>> transaction.managed(True)
 | |
| >>> for obj in serializers.deserialize("json", json):
 | |
| ...     obj.save()
 | |
| 
 | |
| >>> transaction.commit()
 | |
| >>> transaction.leave_transaction_management()
 | |
| 
 | |
| >>> article = Article.objects.get(pk=3)
 | |
| >>> article
 | |
| <Article: Forward references pose no problem>
 | |
| >>> article.categories.all()
 | |
| [<Category: Reference>, <Category: Sports>]
 | |
| >>> article.author
 | |
| <Author: Agnes>
 | |
| 
 | |
| # Serializer output can be restricted to a subset of fields
 | |
| >>> print serializers.serialize("json", Article.objects.all(), fields=('headline','pub_date'))
 | |
| [{"pk": 1, "model": "serializers.article", "fields": {"headline": "Just kidding; I love TV poker", "pub_date": "2006-06-16 11:00:00"}}, {"pk": 2, "model": "serializers.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:11"}}, {"pk": 3, "model": "serializers.article", "fields": {"headline": "Forward references pose no problem", "pub_date": "2006-06-16 15:00:00"}}]
 | |
| 
 | |
| # Every string is serialized as a unicode object, also primary key
 | |
| # which is 'varchar'
 | |
| >>> ac = Actor(name="Zażółć")
 | |
| >>> mv = Movie(title="Gęślą jaźń", actor=ac)
 | |
| >>> ac.save(); mv.save()
 | |
| 
 | |
| # Let's serialize our movie
 | |
| >>> print serializers.serialize("json", [mv])
 | |
| [{"pk": 1, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "G\u0119\u015bl\u0105 ja\u017a\u0144"}}]
 | |
| 
 | |
| # Deserialization of movie
 | |
| >>> list(serializers.deserialize('json', serializers.serialize('json', [mv])))[0].object.title
 | |
| u'G\u0119\u015bl\u0105 ja\u017a\u0144'
 | |
| 
 | |
| # None is null after serialization to json
 | |
| # Primary key is None in case of not saved model
 | |
| >>> mv2 = Movie(title="Movie 2", actor=ac)
 | |
| >>> print serializers.serialize("json", [mv2])
 | |
| [{"pk": null, "model": "serializers.movie", "fields": {"actor": "Za\u017c\u00f3\u0142\u0107", "title": "Movie 2"}}]
 | |
| 
 | |
| # Deserialization of null returns None for pk
 | |
| >>> print list(serializers.deserialize('json', serializers.serialize('json', [mv2])))[0].object.id
 | |
| None
 | |
| 
 | |
| # Serialization and deserialization of floats:
 | |
| >>> sc = Score(score=3.4)
 | |
| >>> print serializers.serialize("json", [sc])
 | |
| [{"pk": null, "model": "serializers.score", "fields": {"score": 3.4}}]
 | |
| >>> print list(serializers.deserialize('json', serializers.serialize('json', [sc])))[0].object.score
 | |
| 3.4
 | |
| 
 | |
| """}
 | |
| 
 | |
| try:
 | |
|     import yaml
 | |
|     __test__['YAML'] = """
 | |
| # Create some data:
 | |
| 
 | |
| >>> articles = Article.objects.all().order_by("id")[:2]
 | |
| >>> from django.core import serializers
 | |
| 
 | |
| # test if serial
 | |
| 
 | |
| >>> serialized = serializers.serialize("yaml", articles)
 | |
| >>> print serialized
 | |
| - fields:
 | |
|     author: 2
 | |
|     categories: [3, 1]
 | |
|     headline: Just kidding; I love TV poker
 | |
|     pub_date: 2006-06-16 11:00:00
 | |
|   model: serializers.article
 | |
|   pk: 1
 | |
| - fields:
 | |
|     author: 1
 | |
|     categories: [2, 3]
 | |
|     headline: Time to reform copyright
 | |
|     pub_date: 2006-06-16 13:00:11
 | |
|   model: serializers.article
 | |
|   pk: 2
 | |
| <BLANKLINE>
 | |
| 
 | |
| >>> obs = list(serializers.deserialize("yaml", serialized))
 | |
| >>> for i in obs:
 | |
| ...     print i
 | |
| <DeserializedObject: Just kidding; I love TV poker>
 | |
| <DeserializedObject: Time to reform copyright>
 | |
| 
 | |
| """
 | |
| except ImportError:
 | |
|     pass
 | |
| 
 |