class IdentificationSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() identification_type_name = serializers.SerializerMethodField() party = GenericRelatedField(many=False, url_only=True, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) party_role = GenericRelatedField(many=False, url_only=True, serializer_dict={}) class Meta: model = Identification fields = ('type', 'url', 'identification_type', 'identification_type_name', 'valid_from', 'valid_to', 'number', 'party', 'party_role') def get_identification_type_name(self, obj): if obj.identification_type: return obj.identification_type.name else: return None
class GenericPartyRoleSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() telephonenumbers = TelephoneNumberSerializer(many=True, read_only=True) associations_from = GenericRelatedField( many=True, serializer_dict={ PartyRoleAssociation: PartyRoleAssociationFromBasicSerializer(), }) associations_to = GenericRelatedField( many=True, serializer_dict={ PartyRoleAssociation: PartyRoleAssociationToBasicSerializer(), }) class Meta: model = GenericPartyRole fields = ( 'type', 'url', 'valid_from', 'valid_to', 'name', 'telephonenumbers', 'associations_from', 'associations_to', )
class CustomerSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() party = GenericRelatedField(many=False, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) managed_by = serializers.HyperlinkedRelatedField( required=False, allow_null=True, view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) associations_from = GenericRelatedField( many=True, serializer_dict={ PartyRoleAssociation: PartyRoleAssociationFromBasicSerializer(), }) associations_to = GenericRelatedField( many=True, serializer_dict={ PartyRoleAssociation: PartyRoleAssociationToBasicSerializer(), }) class Meta: model = Customer fields = ( 'type', 'url', 'customer_number', 'managed_by', 'customer_status', 'party', 'customer_accounts', 'physical_contacts', 'telephone_numbers', 'associations_from', 'associations_to', ) def create(self, validated_data): validated_data.pop('customer_accounts', None) validated_data.pop('associations_from', None) validated_data.pop('associations_to', None) return Customer.objects.create(**validated_data) def update(self, instance, validated_data): validated_data.pop('customer_accounts', None) validated_data.pop('associations_from', None) validated_data.pop('associations_to', None) validated_data.pop('physical_contacts', None) validated_data.pop('telephone_numbers', None) for key, value in validated_data.items(): setattr(instance, key, value) instance.save() return instance
class TimesheetSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = Timesheet fields = ('type', 'url', 'staff', 'start_date', 'end_date', 'timesheet_entries')
class SupplierAccountSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = SupplierAccount fields = ('type', 'url', 'valid_from', 'valid_to', 'supplier', 'account_number', 'account_status', 'account_type', 'name')
class TimesheetEntrySerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = TimesheetEntry fields = ('type', 'url', 'timesheet', 'start', 'end', 'duration', 'notes')
class LocationSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = Location fields = ('type', 'url', 'name', 'type', 'postcode', 'address_line1', 'address_line2', 'latitude', 'longitude', 'rural_property_address', 'urban_property_address')
class TelephoneNumberSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() #party_role = serializers.HyperlinkedRelatedField( # view_name='genericpartyrole-detail', queryset=GenericPartyRole.objects.all()) class Meta: model = TelephoneNumber fields = ('type', 'url', 'number')
class UrbanPropertyAddressSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = UrbanPropertyAddress fields = ('type', 'url', 'country', 'city', 'province', 'locality', 'postcode', 'street_name', 'street_number_first', 'street_number_first_suffix', 'street_number_last', 'street_number_last_suffix', 'street_suffix', 'street_type')
class IdentificationTypeSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() issuer = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = IdentificationType fields = ('type', 'url', 'name', 'issuer', 'system')
class CustomerAccountContactSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() party = GenericRelatedField(many=False, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) class Meta: model = CustomerAccountContact fields = ('type', 'url', 'party', 'customer_accounts')
class CustomerPaymentSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() account = CustomerAccountSerializer() vendor = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = CustomerPayment fields = ('type', 'url', 'channel', 'vendor', 'datetime', 'docket_number', 'customer', 'account', 'amount', 'tax')
class SupplierSerializer(serializers.HyperlinkedModelSerializer): party = GenericRelatedField(many=False, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) type = TypeField() class Meta: model = Supplier fields = ('type', 'url', 'party') def create(self, validated_data): return Supplier.objects.create(**validated_data)
class PoBoxAddressSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = PoBoxAddress fields = ( 'type', 'url', 'country', 'city', 'province', 'locality', 'box_number', )
class CreditBalanceEventSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = CreditBalanceEvent fields = ( 'type', 'url', 'credit', 'customer', 'account', 'datetime', 'amount', 'balance', )
class OwnerSerializer(LimitDepthMixin, serializers.HyperlinkedModelSerializer): type = TypeField() party = GenericRelatedField(many=False, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) class Meta: model = Owner fields = ( 'type', 'url', 'party', )
class StaffSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() party = GenericRelatedField(many=False, serializer_dict={ Individual: IndividualSerializer(), Organisation: OrganisationSerializer(), }) company = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = Staff fields = ('type', 'url', 'company', 'party')
class CreditAlertSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() credit_agency = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = CreditAlert fields = ( 'type', 'url', 'customer', 'profile', 'credit_agency', 'alert_type', 'description', )
class PhysicalResourceSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() physical_objects = GenericRelatedField(many=True, serializer_dict={ Device: DeviceSerializer(), }) class Meta: model = PhysicalResource fields = ( 'type', 'url', 'usage_state', 'name', 'owner', 'serial_number', 'power_state', 'physical_objects', )
class CreditProfileSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() credit_agency = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = CreditProfile fields = ( 'type', 'url', 'customer', 'credit_agency', 'valid_from', 'valid_to', 'created', 'credit_risk_rating', 'credit_score', )
class CreditSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() liability_ownership = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = Credit fields = ( 'type', 'url', 'liability_ownership', 'customer', 'account', 'credit_limit', 'credit_status', 'transaction_limit', 'credit_balance', )
class CustomerAccountSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() credit_liabilities = CreditSerializer(many=True, ) managed_by = serializers.HyperlinkedRelatedField( view_name='organisation-detail', lookup_field='enterprise_id', queryset=Organisation.objects.all()) class Meta: model = CustomerAccount fields = ( 'type', 'url', 'created', 'valid_from', 'valid_to', 'customer', 'account_number', 'account_status', 'managed_by', 'credit_liabilities', 'account_type', 'name', 'pin', 'customer_account_contact', ) def create(self, validated_data): credit_liabilities_data = validated_data.pop('credit_liabilities') account = CustomerAccount.objects.create(**validated_data) return account def update(self, instance, validated_data): credit_liabilities_data = validated_data.pop('credit_liabilities') for key, value in validated_data.items(): setattr(instance, key, value) instance.save() return instance
class PartyRoleAssociationSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() association_from = GenericRelatedField( many=False, serializer_dict={ Customer: CustomerSerializer(), GenericPartyRole: GenericPartyRoleSerializer(), } ) association_to = GenericRelatedField( many=False, serializer_dict={ Customer: CustomerSerializer(), GenericPartyRole: GenericPartyRoleSerializer(), } ) class Meta: model = PartyRoleAssociation fields = ('type', 'url', 'association_type','association_from','association_to')
class IndividualSerializer(LimitDepthMixin, serializers.HyperlinkedModelSerializer): type = TypeField() identifiers = serializers.HyperlinkedRelatedField( view_name='identification-detail', many=True, read_only=True) gender = serializers.ChoiceField(choices=GENDER_CHOICES, required=False, allow_blank=True) marital_status = serializers.ChoiceField(choices=MARITAL_STATUS_CHOICES, required=False, allow_blank=True) class Meta: model = Individual fields = ( 'type', 'url', 'user', 'name', 'given_names', 'family_names', 'middle_names', 'form_of_address', 'gender', 'legal_name', 'marital_status', 'nationality', 'place_of_birth', 'identifiers', ) def create(self, validated_data): validated_data.pop('identifiers', None) print(validated_data) return Individual.objects.create(**validated_data)
class OrganisationSerializer(LimitDepthMixin, serializers.HyperlinkedModelSerializer): type = TypeField() url = serializers.HyperlinkedIdentityField(view_name='organisation-detail', lookup_field='enterprise_id') name = serializers.CharField(required=False) sub_organisations = serializers.HyperlinkedRelatedField( view_name='organisation-detail', many=True, read_only=True) identifiers = serializers.HyperlinkedRelatedField( view_name='identification-detail', many=True, read_only=True) class Meta: model = Organisation fields = ( 'type', 'url', 'parent', 'organisation_type', 'enterprise_id', 'name', 'sub_organisations', 'identifiers', )
class PaymentChannelSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = PaymentChannel fields = ('type', 'url', 'name')
class ExtendedHyperlinkedSerialiser(serializers.HyperlinkedModelSerializer): """ Serialiser for models with writable related fields. Related fields should deserialise to dicts as the parent instance may not be saved yet Includes a type field to allow fields specified in the serialiser to know how to serialise correctly. Derived from hyper-linked serialiser and the url field must be present on the serialiser """ type = TypeField() def to_representation(self, instance): # TODO: Why is this returning an ordered dict? #if "{}".format(type(instance)) == "<class 'sample_project.app.models.SalesChannel'>": # print("foo", super(ExtendedHyperlinkedSerialiser, self).to_representation(instance)) ret = super(ExtendedHyperlinkedSerialiser, self).to_representation(instance) return ret def create(self, validated_data): # Remove nested fields from validated data and add to separate dict fields = [] related = [] for field in validated_data.keys(): if type(self.fields[field]) == ExtendedModelSerialiserField: # Check if we have a URL so we can assign as part of creation if type(validated_data[field]) == dict: if "url" not in validated_data[field]: related.append(field) else: resolved_func, unused_args, resolved_kwargs = resolve(urlparse(validated_data[field]["url"]).path) objects = resolved_func.cls.queryset.filter(pk=resolved_kwargs['pk']) del validated_data[field]["url"] objects.update(**validated_data[field]) validated_data[field] = objects[0] fields.append(field) elif type(self.fields[field]) == ManyRelatedField: related.append(field) else: fields.append(field) # Create instance of serialiser Meta.model must get pk to attach related objects instance = self.Meta.model() for field in fields: setattr(instance, field, validated_data[field]) instance.save() # For all related fields attach the listed objects for field in related: for obj_dict in validated_data[field]: attr = getattr(instance, field) if type(obj_dict) != dict: # If we have an object then add it object = obj_dict else: # If we have a dictionary then create (TODO: or update) object = self.fields[field].serializer.Meta.model(**obj_dict) setattr(object, attr.field.name, instance) object.save() attr.add(object) instance.save() return instance def update(self, instance, validated_data): # Create a list of fields to update and a list of related objects fields = [] related = [] for field in validated_data.keys(): #print(field,type(self.fields[field])) if type(self.fields[field]) == ExtendedModelSerialiserField: if validated_data[field] is not None: related.append(field) elif type(self.fields[field]) in (ManyRelatedField, HyperlinkedRelatedField): related.append(field) # Exclude read only fields elif not self.fields[field].read_only: fields.append(field) # Set all valid attributes of the instance to the validated data for field in fields: setattr(instance, field, validated_data.get( field, getattr(instance, field))) # Loop through sub objects, deserialise and add to parent for field in related: need_save = True if validated_data[field] != None: # Handle Foreign keys by creating list of 1 (many=False will result in dict not list of dicts) if type(validated_data[field]) != list: validated_data[field] = [validated_data[field],] # For each sub object of the instance field there is a dict containing attributes and values or the instance for obj_dict in validated_data[field]: attr = getattr(instance, field) if type(obj_dict) != dict: # If no fields specified in payload (just URL) then no need to save sub object need_save = False if type(obj_dict) == str: resolved_func, unused_args, resolved_kwargs = resolve(urlparse(obj_dict).path) object = resolved_func.cls.queryset.get(pk=resolved_kwargs['pk']) else: object = obj_dict else: # Input may specify an existing or new sub object. If existing, there must be a url field for us to look it up if "url" in obj_dict.keys(): # Get object from url and update from deserialised dict resolved_func, unused_args, resolved_kwargs = resolve(urlparse(obj_dict["url"]).path) object = resolved_func.cls.queryset.get(pk=resolved_kwargs['pk']) serializer = self.fields[field].serializer # If only the url is in the data then no need to update the sub-object fields or save if len(obj_dict.keys()) > 1: serializer.fields val = serializer.validate(obj_dict) serializer.update(object,val) else: need_save = False else: # Create object from deserialised dict object = self.fields[field].serializer.Meta.model(**obj_dict) # Note: Do not save new object until we have set the attribute to the parent depending on relationship type if need_save: # Handle all types of relationships if attr.__class__.__name__ == "ManyRelatedManager": # ManyToMany object.save() getattr(instance,field).add(object) elif attr.__class__.__name__ == "RelatedManager": # Reverse relationship to foreign keys setattr(object, attr.field.name, instance) object.save() attr.add(object) #TODO: Check if this works for both lists and singles else: # Foreign keys object.save() setattr(instance, field, object) #TODO: Removal of missing related objects if partial instance.save() return instance
class GeographicAreaSerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = GeographicArea fields = ('type', 'url', 'name')
class CountrySerializer(serializers.HyperlinkedModelSerializer): type = TypeField() class Meta: model = Country fields = ('type', 'url', 'code', 'name')