class LateCustomizationSerializer(serializers.ModelSerializer): type = serializers.ChoiceField(choices=(("webapp", "webapp"), ("extension", "extension"))) app = relations.PrimaryKeyRelatedField(required=False, queryset=Webapp.objects) extension = relations.PrimaryKeyRelatedField(required=False, queryset=Extension.objects) carrier = SlugChoiceField(required=True, choices_dict=mkt.carriers.CARRIER_MAP) region = SlugChoiceField(required=True, choices_dict=mkt.regions.REGION_LOOKUP) class Meta: model = LateCustomizationItem def to_representation(self, obj): if obj.app is None: e = ExtensionSerializer(context=self.context) data = e.to_representation(obj.extension) data['latecustomization_id'] = obj.pk data['latecustomization_type'] = 'extension' else: a = SimpleAppSerializer(context=self.context) data = a.to_representation(obj.app) data['latecustomization_id'] = obj.pk data['latecustomization_type'] = 'webapp' return data def create(self, data): del data['type'] return serializers.ModelSerializer.create(self, data)
class OperatorPermissionSerializer(serializers.ModelSerializer): carrier = SlugChoiceField(choices_dict=mkt.carriers.CARRIER_MAP) region = SlugChoiceField(choices_dict=mkt.regions.REGION_LOOKUP) class Meta: fields = ('carrier', 'region') model = OperatorPermission
class PriceCurrencySerializer(ModelSerializer): resource_uri = HyperlinkedIdentityField(view_name='price-currency-detail') tier = HyperlinkedRelatedField(view_name='price-tier-detail') currency = ChoiceField(choices=ALL_CURRENCIES.items()) carrier = SlugChoiceField(choices_dict=CARRIER_MAP, required=False, empty=None) price = DecimalField() provider = EnumeratedField(PROVIDER_CHOICES) method = EnumeratedField(PAYMENT_METHOD_CHOICES) region = SlugChoiceField(choices_dict=dict(REGIONS_CHOICES_SLUG)) paid = BooleanField() dev = BooleanField() class Meta: model = PriceCurrency fields = ['carrier', 'currency', 'dev', 'method', 'paid', 'price', 'provider', 'region', 'resource_uri', 'tier']
class FeedShelfSerializer(BaseFeedCollectionSerializer): """ A serializer for the FeedBrand class, a type of collection that allows editors to quickly create content without involving localizers. """ apps = serializers.SerializerMethodField('get_apps') background_image = FeedImageField( source='*', view_name='api-v2:feed-shelf-image-detail', format='png') background_image_landing = FeedLandingImageField( source='*', view_name='api-v2:feed-shelf-landing-image-detail', format='png') carrier = SlugChoiceField(choices_dict=mkt.carriers.CARRIER_MAP) description = TranslationSerializerField(required=False) is_published = serializers.BooleanField(source='is_published', required=False) name = TranslationSerializerField() region = SlugChoiceField(choices_dict=mkt.regions.REGION_LOOKUP) class Meta: fields = [ 'app_count', 'apps', 'background_image', 'background_image_landing', 'carrier', 'description', 'id', 'is_published', 'name', 'region', 'slug', 'url' ] model = FeedShelf url_basename = 'feedshelves' def get_apps(self, obj): """ Return a list of serialized apps, adding each app's `group` to the serialization. """ ret = [] memberships = FeedShelfMembership.objects.filter(obj_id=obj.id) field = TranslationSerializerField() field.initialize(self, 'group') field.context = self.context for member in memberships: data = AppSerializer(member.app, context=self.context).data data['group'] = field.field_to_native(member, 'group') ret.append(data) return ret
class FeedShelfSerializer(BaseFeedCollectionSerializer): """ A serializer for the FeedBrand class, a type of collection that allows editors to quickly create content without involving localizers. """ background_image = FeedImageField( source='*', view_name='api-v2:feed-shelf-image-detail', format='png') background_image_landing = FeedLandingImageField( source='*', view_name='api-v2:feed-shelf-landing-image-detail', format='png') carrier = SlugChoiceField(choices_dict=mkt.carriers.CARRIER_MAP) description = TranslationSerializerField(required=False) is_published = serializers.BooleanField(source='is_published', required=False) name = TranslationSerializerField() region = SlugChoiceField(choices_dict=mkt.regions.REGION_LOOKUP) class Meta: fields = ['app_count', 'apps', 'background_image', 'background_image_landing', 'carrier', 'description', 'id', 'is_published', 'name', 'region', 'slug', 'url'] model = FeedShelf url_basename = 'feedshelves'
class FeedItemSerializer(URLSerializerMixin, serializers.ModelSerializer): """ A serializer for the FeedItem class, which wraps all items that live on the feed. """ carrier = SlugChoiceField(required=False, choices_dict=mkt.carriers.CARRIER_MAP) region = SlugChoiceField(required=False, choices_dict=mkt.regions.REGION_LOOKUP) category = UnicodeChoiceField(required=False, choices=CATEGORY_CHOICES) item_type = serializers.SerializerMethodField('get_item_type') # Types of objects that are allowed to be a feed item. app = SplitField(relations.PrimaryKeyRelatedField(required=False), FeedAppSerializer()) brand = SplitField(relations.PrimaryKeyRelatedField(required=False), FeedBrandSerializer()) collection = SplitField(relations.PrimaryKeyRelatedField(required=False), FeedCollectionSerializer()) shelf = SplitField(relations.PrimaryKeyRelatedField(required=False), FeedShelfSerializer()) class Meta: fields = ('app', 'brand', 'carrier', 'category', 'collection', 'id', 'item_type', 'region', 'shelf', 'url') item_types = ('app', 'brand', 'collection', 'shelf',) model = FeedItem url_basename = 'feeditems' def validate(self, attrs): """ Ensure that at least one object type is specified. """ item_changed = any(k for k in self.Meta.item_types if k in attrs.keys()) num_defined = sum(1 for item in self.Meta.item_types if attrs.get(item)) if item_changed and num_defined != 1: message = ('A valid value for exactly one of the following ' 'parameters must be defined: %s' % ','.join( self.Meta.item_types)) raise serializers.ValidationError(message) return attrs def get_item_type(self, obj): for item_type in self.Meta.item_types: if getattr(obj, item_type): return item_type return def validate_shelf(self, attrs, source): """ If `shelf` is defined, validate that the FeedItem's `carrier` and `region` match the `carrier` and `region on `shelf`. """ shelf_id = attrs.get(source) if shelf_id: shelf = FeedShelf.objects.get(pk=shelf_id) carrier = CARRIER_CHOICE_DICT[shelf.carrier] if attrs.get('carrier') != carrier.slug: raise serializers.ValidationError( 'Feed item carrier does not match operator shelf carrier.') region = REGIONS_CHOICES_ID_DICT[shelf.region] if attrs.get('region') != region.slug: raise serializers.ValidationError( 'Feed item region does not match operator shelf region.') return attrs
class CollectionSerializer(serializers.ModelSerializer): name = TranslationSerializerField() description = TranslationSerializerField() slug = serializers.CharField(required=False) collection_type = serializers.IntegerField() apps = CollectionMembershipField(many=True, source='apps') image = HyperlinkedRelatedOrNullField( source='*', view_name='collection-image-detail', format='png', predicate=lambda o: o.has_image) carrier = SlugChoiceField(required=False, empty=None, choices_dict=mkt.carriers.CARRIER_MAP) region = SlugChoiceField(required=False, empty=None, choices_dict=mkt.regions.REGION_LOOKUP) category = SlugModelChoiceField(required=False, queryset=Category.objects.filter(type=amo.ADDON_WEBAPP)) class Meta: fields = ('apps', 'author', 'background_color', 'can_be_hero', 'carrier', 'category', 'collection_type', 'default_language', 'description', 'id', 'image', 'is_public', 'name', 'region', 'slug', 'text_color',) model = Collection def to_native(self, obj): """ Remove `can_be_hero` from the serialization if this is not an operator shelf. """ native = super(CollectionSerializer, self).to_native(obj) if native['collection_type'] != COLLECTIONS_TYPE_OPERATOR: del native['can_be_hero'] return native def validate(self, attrs): """ Prevent operator shelves from being associated with a category. """ existing = getattr(self, 'object') exc = 'Operator shelves may not be associated with a category.' if (not existing and attrs['collection_type'] == COLLECTIONS_TYPE_OPERATOR and attrs.get('category')): raise serializers.ValidationError(exc) elif existing: collection_type = attrs.get('collection_type', existing.collection_type) category = attrs.get('category', existing.category) if collection_type == COLLECTIONS_TYPE_OPERATOR and category: raise serializers.ValidationError(exc) return attrs def full_clean(self, instance): instance = super(CollectionSerializer, self).full_clean(instance) if not instance: return None # For featured apps and operator shelf collections, we need to check if # one already exists for the same region/category/carrier combination. # # Sadly, this can't be expressed as a db-level unique constaint, # because this doesn't apply to basic collections. # # We have to do it ourselves, and we need the rest of the validation # to have already taken place, and have the incoming data and original # data from existing instance if it's an edit, so full_clean() is the # best place to do it. unique_collections_types = (COLLECTIONS_TYPE_FEATURED, COLLECTIONS_TYPE_OPERATOR) qs = Collection.objects.filter( collection_type=instance.collection_type, category=instance.category, region=instance.region, carrier=instance.carrier) if instance.pk: qs = qs.exclude(pk=instance.pk) if (instance.collection_type in unique_collections_types and qs.exists()): self._errors['collection_uniqueness'] = _( u'You can not have more than one Featured Apps/Operator Shelf ' u'collection for the same category/carrier/region combination.' ) return instance