diff -r b07f8d11f2b8 -r e2ccb0093452 src/p4l/api/serializers.py --- a/src/p4l/api/serializers.py Sat Sep 07 14:41:20 2013 +0200 +++ b/src/p4l/api/serializers.py Mon Sep 09 01:48:26 2013 +0200 @@ -5,11 +5,12 @@ @author: ymh ''' from django.core.exceptions import ValidationError -from p4l.models import (Record, Title, Issn, Isbn, DocumentCode, Abstract, - AddedTitle, TitleMainDocument, Imprint, Collation, VolumeIssue, Periodical, - Meeting, SubjectMeeting, Serie, Url) +from p4l.models import Record from rest_framework import serializers import logging +from rest_framework.serializers import NestedValidationError +import copy +from django.db.models.fields.related import ForeignKey logger = logging.getLogger(__name__) @@ -32,84 +33,87 @@ raise ValidationError(msg) -class BaseTitleSerializer(serializers.ModelSerializer): - class Meta: - fields = ('title', 'lang') +class P4lModelSerializer(serializers.ModelSerializer): + -class TitleSerializer(BaseTitleSerializer): - class Meta(BaseTitleSerializer.Meta): - model = Title + def get_nested_field(self, model_field, related_model, to_many): + field_exclude = () + if model_field is None: + fk = [f.name for f in related_model._meta.fields if (isinstance(f, ForeignKey) and f.rel.to == Record)][0] + field_exclude = ('id', fk) + class NestedModelSerializer(P4lModelSerializer): + class Meta: + model = related_model + depth = self.opts.depth - 1 + exclude = field_exclude -class AddedTitleSerializer(BaseTitleSerializer): - class Meta(BaseTitleSerializer.Meta): - model = AddedTitle - -class TitleMainDocumentSerializer(BaseTitleSerializer): - class Meta(BaseTitleSerializer.Meta): - model = TitleMainDocument + return NestedModelSerializer(many=to_many) -class IssnSerializer(serializers.ModelSerializer): - class Meta: - model = Issn - fields = ('issn', 'lang') - -class IsbnSerializer(serializers.ModelSerializer): - class Meta: - model = Isbn - fields = ('isbn', 'lang') - -class DocumentCodeSerializer(serializers.ModelSerializer): - class Meta: - model = DocumentCode - fields = ('documentCode', 'lang') + + def field_from_native(self, data, files, field_name, into): + """ + Override default so that the serializer can be used as a writable + nested field across relationships. + """ + if self.read_only: + return -class AbstractSerializer(serializers.ModelSerializer): - class Meta: - model = Abstract - fields = ('abstract', 'lang') + try: + value = data[field_name] + except KeyError: + if self.default is not None and not self.partial: + # Note: partial updates shouldn't set defaults + value = copy.deepcopy(self.default) + else: + if self.required: + raise ValidationError(self.error_messages['required']) + return -class ImprintSerializer(serializers.ModelSerializer): - class Meta: - model = Imprint - fields = ('imprintCity', 'publisher', 'imprintDate', 'lang') - -class CollationSerializer(serializers.ModelSerializer): - class Meta: - model = Collation - fields = ('collation', 'lang') - -class VolumeIssueSerializer(serializers.ModelSerializer): - class Meta: - model = VolumeIssue - fields = ('volume', 'number', 'lang') - -class PeriodicalSerializer(serializers.ModelSerializer): - class Meta: - model = Periodical - fields = ('label', 'lang') + # Set the serializer object if it exists + obj = getattr(self.parent.object, field_name) if self.parent.object else None -class MeetingSerializer(serializers.ModelSerializer): - class Meta: - model = Meeting - fields = ('label', 'meetingNumber', 'meetingPlace', 'meetingDate', 'meetingYear', 'lang') - -class SubjectMeetingSerializer(serializers.ModelSerializer): - class Meta: - model = SubjectMeeting - fields = ('label', 'meetingNumber', 'meetingPlace', 'meetingDate', 'meetingYear') + if self.source == '*': + if value: + into.update(value) + else: + if value in (None, ''): + into[(self.source or field_name)] = None + elif self.many and hasattr(value, '__iter__'): + obj.all().delete() + nested_items = [] + for val in value: + kwargs = { + 'instance': None, + 'data': val, + 'context': self.context, + 'partial': self.partial, + 'many': False + } + serializer = self.__class__(**kwargs) + nested_items.append(serializer.from_native(val, files)) + into[self.source or field_name] = nested_items + else: + kwargs = { + 'instance': obj, + 'data': value, + 'context': self.context, + 'partial': self.partial, + 'many': self.many + } + serializer = self.__class__(**kwargs) -class SerieSerializer(serializers.ModelSerializer): - class Meta: - model = Serie - fields = ('title', 'volume', 'lang') - -class UrlSerializer(serializers.ModelSerializer): - class Meta: - model = Url - fields = ('address', 'display', 'accessLevel') + if serializer.is_valid(): + into[self.source or field_name] = serializer.object + else: + # Propagate errors up to our parent + raise NestedValidationError(serializer.errors) -class RecordSerializer(serializers.ModelSerializer): + + + +#class RecordSerializer(serializers.ModelSerializer): +class RecordSerializer(P4lModelSerializer): ''' Serializer for record ''' @@ -121,23 +125,6 @@ projectNames = ThesaurusSerializer(many=True, slug_field='uri') subjectCorporateBodies = ThesaurusSerializer(many=True, slug_field='uri') corporateAuthors = ThesaurusSerializer(many=True, slug_field='uri') -# titles = TitleSerializer(many=True, read_only=False) -# addedTitles = AddedTitleSerializer(many=True, read_only=False) -# issns = IssnSerializer(many=True, read_only=False) -# isbns = IsbnSerializer(many=True, read_only=False) -# documentCodes = DocumentCodeSerializer(many=True, read_only=False) -# abstracts = AbstractSerializer(many=True, read_only=False) -# titlesMainDocument = TitleMainDocumentSerializer(many=True, read_only=False) -# imprints = ImprintSerializer(many=True, read_only=False) -# collations = CollationSerializer(many=True, read_only=False) -# volumeIssues = VolumeIssueSerializer(many=True, read_only=False) -# periodicals = PeriodicalSerializer(many=True, read_only=False) -# meetings = MeetingSerializer(many=True, read_only=False) -# subjectMeetings = SubjectMeetingSerializer(many=True, read_only=False) -# series = SerieSerializer(many=True, read_only=False) -# authors = serializers.SlugRelatedField(many=True, read_only=False, slug_field="name") -# subjectPersons = serializers.SlugRelatedField(many=True, read_only=False, slug_field="name") -# urls = UrlSerializer(many=True, read_only=False) class Meta: model = Record @@ -146,16 +133,10 @@ fields = ("identifier", "uri", "subjects", "notes", "otherLanguages", "language", "editionStatement", "recordType", "isDocumentPart", "isMultilingual", "themes", "countries", "projectNames", - "subjectCorporateBodies", "corporateAuthors") -# fields = ( -# "editionStatement", "recordType","isDocumentPart", -# "isMultilingual","subjects", "themes", "countries", -# "projectNames", "subjectCorporateBodies", "corporateAuthors", -# "titles", "issns", "isbns", "documentCodes", "abstracts", -# "addedTitles", "titlesMainDocument", "imprints", -# "collations", "volumeIssues", "periodicals", "meetings", -# "subjectMeetings", "series", "authors", "subjectPersons", -# "urls") - + "subjectCorporateBodies", "corporateAuthors", "imprints", + "titles", "addedTitles", "issns", "isbns", "documentCodes", + "abstracts", "titlesMainDocument", "collations", "volumeIssues", + "periodicals", "meetings", "subjectMeetings", "series", + "authors", "subjectPersons", "urls")