コード例 #1
0
class DemographicDataSerializer(UuidHyperlinkedModelSerializer):
    resource_name = "demographics"
    country = serializers.CharField(default="")
    date_created = serializers.DateTimeField(read_only=True,
                                             source="created_at")

    url = serializers.HyperlinkedIdentityField(
        view_name="api:demographicdata-detail", lookup_field="uuid")

    class Meta:
        model = DemographicData
        fields = (
            "url",
            "number_of_children",
            "child_birthdays",
            "languages_spoken_at_home",
            "number_of_guardians",
            "number_of_guardians_explanation",
            "race_identification",
            "age",
            "gender",
            "education_level",
            "spouse_education_level",
            "annual_income",
            "former_lookit_annual_income",
            "lookit_referrer",
            "number_of_books",
            "additional_comments",
            "country",
            "state",
            "density",
            "extra",
            "date_created",
            "pk",
        )
コード例 #2
0
class BaseSerializer(serializers.ModelSerializer):
    created_at = serializers.DateTimeField(read_only=True)

    def is_valid(self, *args, **kwargs):
        # Prime data so the validators are called (and default values filled
        # if client didn't pass them.)
        self.initial_data.setdefault("created_by_group", self._default_group())
        self.initial_data.setdefault("modified_by_group",
                                     self._default_group())
        return super().is_valid(*args, **kwargs)

    def validate(self, *args, **kwargs):
        validated_data = super().validate(*args, **kwargs)

        user = self.context["request"].user
        validated_data["created_by_user"] = user.username
        validated_data["modified_by_user"] = user.username

        self.Meta.model.check_permissions(self.context["request"])
        if self.instance is not None:
            self.instance.check_object_permissions(self.context["request"])

        return validated_data

    def validate_created_by_group(self, value):
        # Created by group can be set on creation, then must remain constant
        if self.instance:
            # can't change created_by_group on existing instances
            return self.instance.created_by_group
        else:
            return self._validate_group(value, "created_by_group")

    def validate_modified_by_group(self, value):
        # Modified by group is validated against the user's list of groups,
        # with a fallback to the default group if no value is given
        return self._validate_group(value or self._default_group(),
                                    "modified_by_group")

    def _validate_group(self, value, field_name):
        user = self.context["request"].user
        if value and value not in user.groups:
            raise ValidationError(
                f"Given {field_name} '{value}' is not part of user's assigned groups"
            )
        return value

    def _default_group(self):
        user = self.context["request"].user
        return user.group if not isinstance(user, AnonymousUser) else None

    class Meta:
        fields = (
            "created_at",
            "created_by_user",
            "created_by_group",
            "modified_at",
            "modified_by_user",
            "modified_by_group",
            "meta",
        )
コード例 #3
0
ファイル: serializers.py プロジェクト: winged/alexandria
class BaseSerializer(serializers.ModelSerializer):
    created_at = serializers.DateTimeField(read_only=True)

    def validate(self, *args, **kwargs):
        validated_data = super().validate(*args, **kwargs)

        self.Meta.model.check_permissions(self.context["request"])
        if self.instance is not None:
            self.instance.check_object_permissions(self.context["request"])

        user = self.context["request"].user
        group = user.group if not isinstance(user, AnonymousUser) else None

        validated_data["modified_by_user"] = user.username
        validated_data["modified_by_group"] = group
        if self.instance is not None:
            validated_data["created_by_user"] = user.username
            validated_data["created_by_group"] = group
        return validated_data

    class Meta:
        fields = (
            "created_at",
            "created_by_user",
            "created_by_group",
            "modified_at",
            "modified_by_user",
            "modified_by_group",
            "meta",
        )
コード例 #4
0
class ResponseSerializer(UuidHyperlinkedModelSerializer):
    """Gets hyperlink related fields.

    XXX: It's important to keep read_only set to true here - otherwise, a queryset is necessitated, which implicates
    get_attribute from ResourceRelatedField
    """

    created_on = serializers.DateTimeField(read_only=True,
                                           source="date_created")
    url = serializers.HyperlinkedIdentityField(view_name="api:response-detail",
                                               lookup_field="uuid")

    study = PatchedHyperlinkedRelatedField(
        read_only=True,
        related_link_view_name="api:study-detail",
        related_link_lookup_field="study.uuid",
        related_link_url_kwarg="uuid",
    )
    user = PatchedHyperlinkedRelatedField(
        read_only=True,
        source="child",
        related_link_view_name="api:user-detail",
        related_link_lookup_field="child.user.uuid",
        related_link_url_kwarg="uuid",
        required=False,
    )
    child = PatchedHyperlinkedRelatedField(
        read_only=True,
        related_link_view_name="api:child-detail",
        related_link_lookup_field="child.uuid",
        related_link_url_kwarg="uuid",
    )
    demographic_snapshot = PatchedHyperlinkedRelatedField(
        read_only=True,
        related_link_view_name="api:demographicdata-detail",
        related_link_lookup_field="demographic_snapshot.uuid",
        related_link_url_kwarg="uuid",
        required=False,
    )

    class Meta:
        model = Response
        fields = (
            "url",
            "conditions",
            "global_event_timings",
            "exp_data",
            "sequence",
            "completed",
            "child",
            "user",
            "study",
            "completed_consent_frame",
            "demographic_snapshot",
            "created_on",
            "is_preview",
            "pk",
            "withdrawn",
        )
コード例 #5
0
class CollectionSerializer(serializers.Serializer):
    id = serializers.CharField(read_only=True)
    title = serializers.CharField(required=True)
    description = serializers.CharField(required=False, allow_blank=True)
    tags = serializers.CharField(required=False, allow_blank=True)
    settings = serializers.JSONField(required=False)
    submission_settings = serializers.JSONField(required=False)
    created_by_org = serializers.CharField(allow_blank=True, required=False)
    created_by = RelationshipField(
        related_view='user-detail',
        related_view_kwargs={'user_id': '<created_by.pk>'},
    )
    date_created = serializers.DateTimeField(read_only=True)
    date_updated = serializers.DateTimeField(read_only=True)
    groups = RelationshipField(related_view='collection-group-list',
                               related_view_kwargs={'pk': '<pk>'})
    items = RelationshipField(related_view='collection-item-list',
                              related_view_kwargs={'pk': '<pk>'})

    class Meta:
        model = Collection
        fields = ['id', 'title', 'description', 'tags', 'created_by']

    class JSONAPIMeta:
        resource_name = 'collections'

    def create(self, validated_data):
        user = self.context['request'].user
        collection = Collection.objects.create(created_by=user,
                                               **validated_data)
        assign_perm('api.approve_collection_items', user, collection)
        return collection

    def update(self, collection, validated_data):
        collection.title = validated_data.get('title', collection.title)
        collection.description = validated_data.get('description',
                                                    collection.description)
        collection.tags = validated_data.get('tags', collection.tags)
        collection.settings = validated_data.get('settings',
                                                 collection.settings)
        collection.submission_settings = validated_data.get(
            'submission_settings', collection.submission_settings)
        collection.created_by_org = validated_data.get(
            'created_by_org', collection.created_by_org)
        collection.save()
        return collection
コード例 #6
0
class MeetingSerializer(CollectionSerializer):
    location = serializers.CharField(allow_blank=True,
                                     allow_null=True,
                                     required=False)
    address = serializers.CharField(allow_blank=True,
                                    allow_null=True,
                                    required=False)
    start_date = serializers.DateTimeField(allow_null=True, required=False)
    end_date = serializers.DateTimeField(allow_null=True, required=False)
    groups = RelationshipField(related_view='meeting-group-list',
                               related_view_kwargs={'pk': '<pk>'})
    items = RelationshipField(related_view='meeting-item-list',
                              related_view_kwargs={'pk': '<pk>'})

    class Meta:
        model = Meeting

    class JSONAPIMeta:
        resource_name = 'meetings'

    def create(self, validated_data):
        user = self.context['request'].user
        meeting = Meeting.objects.create(created_by=user, **validated_data)
        assign_perm('api.approve_meeting_items', user, meeting)
        return meeting

    def update(self, meeting, validated_data):
        meeting.title = validated_data.get('title', meeting.title)
        meeting.description = validated_data.get('description',
                                                 meeting.description)
        meeting.tags = validated_data.get('tags', meeting.tags)
        meeting.settings = validated_data.get('settings', meeting.settings)
        meeting.submission_settings = validated_data.get(
            'submission_settings', meeting.submission_settings)
        meeting.created_by_org = validated_data.get('created_by_org',
                                                    meeting.created_by_org)
        meeting.location = validated_data.get('location', meeting.location)
        meeting.start_date = validated_data.get('start_date',
                                                meeting.start_date)
        meeting.end_date = validated_data.get('end_date', meeting.end_date)
        meeting.save()
        return meeting
コード例 #7
0
class ProviderRegistrationSerializer(ShareModelSerializer):
    status = serializers.SerializerMethodField()
    submitted_at = serializers.DateTimeField(read_only=True)
    submitted_by = serializers.HiddenField(default=serializers.CurrentUserDefault())

    def get_status(self, obj):
        return ProviderRegistration.STATUS[obj.status]

    class Meta:
        model = models.ProviderRegistration
        fields = '__all__'
コード例 #8
0
class GroupSerializer(serializers.Serializer):
    id = serializers.CharField(read_only=True)
    title = serializers.CharField(required=True)
    description = serializers.CharField(allow_blank=True, required=False)
    created_by = UserSerializer(read_only=True)
    date_created = serializers.DateTimeField(read_only=True)
    date_updated = serializers.DateTimeField(read_only=True)
    items = RelationshipField(
        related_view='group-item-list',
        related_view_kwargs={'pk': '<collection.id>', 'group_id': '<pk>'}
    )
    items = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='track-detail'
    )

    class Meta:
        model = Group

    class JSONAPIMeta:
        resource_name = 'groups'

    def create(self, validated_data):
        user = self.context['request'].user
        collection_id = self.context.get('collection_id', None) or self.context['request'].parser_context['kwargs'].get(
            'pk', None)
        collection = CollectionBase.objects.get(id=collection_id)
        return Group.objects.create(
            created_by=user,
            collection=collection,
            **validated_data
        )

    def update(self, group, validated_data):
        group.title = validated_data.get('title', None)
        description = validated_data.get('description', None)
        if description:
            group.description = description
        group.save()
        return group
コード例 #9
0
ファイル: serializers.py プロジェクト: sbor23/emeis
class BaseSerializer(serializers.ModelSerializer):
    created_at = serializers.DateTimeField(read_only=True)
    modified_at = serializers.DateTimeField(read_only=True)
    created_by_user = serializers.ResourceRelatedField(read_only=True)

    def create(self, validated_data):
        user = self.context["request"].user
        if not isinstance(user, AnonymousUser):
            validated_data["created_by_user"] = user

        return super().create(validated_data)

    def validate(self, *args, **kwargs):
        validated_data = super().validate(*args, **kwargs)
        self.Meta.model.check_permissions(self.context["request"])
        if self.instance is not None:
            self.instance.check_object_permissions(self.context["request"])

        return validated_data

    class Meta:
        fields = ("created_at", "modified_at", "created_by_user", "meta")
コード例 #10
0
ファイル: serializers.py プロジェクト: enrobyn/lookit-api
class ResponseSerializer(UUIDSerializerMixin, ModelSerializer):
    created_on = serializers.DateTimeField(read_only=True,
                                           source='date_created')
    url = serializers.HyperlinkedIdentityField(view_name='response-detail',
                                               lookup_field='uuid')

    study = UUIDResourceRelatedField(
        queryset=Study.objects,
        many=False,
        related_link_view_name='study-detail',
        related_link_lookup_field='uuid',
    )
    user = UUIDResourceRelatedField(source='child.user',
                                    queryset=User.objects,
                                    many=False,
                                    related_link_view_name='user-list',
                                    related_link_lookup_field='uuid',
                                    required=False)
    child = UUIDResourceRelatedField(
        queryset=Child.objects,
        many=False,
        related_link_view_name='child-detail',
        related_link_lookup_field='uuid',
    )
    demographic_snapshot = UUIDResourceRelatedField(
        queryset=DemographicData.objects,
        many=False,
        related_link_view_name='demographicdata-detail',
        related_link_lookup_field='uuid',
        required=False)

    class Meta:
        model = Response
        fields = (
            'url',
            'conditions',
            'global_event_timings',
            'exp_data',
            'sequence',
            'completed',
            'child',
            'user',
            'study',
            'demographic_snapshot',
            'created_on',
            'pk',
        )
コード例 #11
0
class ChangedFieldSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=200, required=False)
    priority = serializers.IntegerField(min_value=1,
                                        max_value=5,
                                        required=False)
    resolution = serializers.CharField(required=False)
    due_date = serializers.DateTimeField(required=False, allow_null=True)
    assigned_to = serializers.PrimaryKeyRelatedField(
        required=False,
        allow_null=True,
        queryset=Person.objects.all(
        )  # TODO restrict this queryset to something more sensible
    )

    signaled_by = serializers.PrimaryKeyRelatedField(
        required=False, allow_null=True, queryset=Person.objects.all())

    organization = serializers.PrimaryKeyRelatedField(
        required=False, allow_null=True, queryset=Organization.objects.all())

    department = serializers.PrimaryKeyRelatedField(
        required=False, allow_null=True, queryset=Team.objects.all())
コード例 #12
0
class ShipmentActionRequestSerializer(serializers.Serializer):
    action_type = UpperEnumField(ActionType, lenient=True, ints_as_names=True)
    tracking_data = serializers.CharField(required=False, allow_null=True)
    document_id = serializers.CharField(required=False, allow_null=True)
    raw_asset_physical_id = serializers.CharField(required=False, allow_null=True)
    asset_physical_id = serializers.CharField(required=False, allow_null=True)
    action_timestamp = serializers.DateTimeField(required=False)

    def validate_action_type(self, action_type):
        shipment = self.context['shipment']
        action_type.value.func.__self__ = shipment  # Hack for getting dynamic partial funcs to work w/ can_proceed
        if not can_proceed(action_type.value.func):
            # Bad state transition
            raise exceptions.ValidationError(f'Action {action_type.name} not available while Shipment '
                                             f'is in state {TransitState(shipment.state).name}')
        return action_type

    def validate_action_timestamp(self, action_timestamp):
        if settings.PROFILES_ENABLED and not is_internal_call(self.context['request'], 'third-party-integrator'):
            raise exceptions.ValidationError('Can only manually set timestamp for action on internal calls')
        if action_timestamp > datetime.now(timezone.utc):
            raise exceptions.ValidationError('Cannot set action for datetime in the future.')
        return action_timestamp
コード例 #13
0
class ItemSerializer(serializers.Serializer):
    id = serializers.CharField(read_only=True)
    source_id = serializers.CharField()
    title = serializers.CharField(required=True)
    type = serializers.ChoiceField(
        choices=['project', 'preprint', 'registration', 'meeting', 'website'])
    status = serializers.ChoiceField(
        choices=['approved', 'pending', 'rejected'])
    url = serializers.URLField()
    created_by = UserSerializer(read_only=True)
    metadata = serializers.JSONField(required=False)
    date_added = serializers.DateTimeField(read_only=True, allow_null=True)
    date_submitted = serializers.DateTimeField(read_only=True)

    class Meta:
        model = Item

    class JSONAPIMeta:
        resource_name = 'items'

    def create(self, validated_data):
        user = self.context['request'].user
        collection_id = self.context.get(
            'collection_id',
            None) or self.context['request'].parser_context['kwargs'].get(
                'pk', None)
        collection = Collection.objects.get(id=collection_id)

        allow_all = None
        if collection.settings:
            collection_settings = json.loads(collection.settings)
            allow_all = collection_settings.get('allow_all', None)
            collection_type = collection_settings.get('type', None)
            if collection_type and validated_data['type'] != collection_type:
                raise ValueError('Collection only accepts items of type ' +
                                 collection_type)

        status = 'pending'
        if user.has_perm('api.approve_items', collection) or allow_all:
            status = 'approved'
            validated_data['date_added'] = timezone.now()

        group_id = self.context.get(
            'group_id',
            None) or self.context['request'].parser_context['kwargs'].get(
                'group_id', None)
        if group_id:
            validated_data['group'] = Group.objects.get(id=group_id)

        validated_data['status'] = status
        item = Item.objects.create(created_by=user,
                                   collection=collection,
                                   **validated_data)
        return item

    def update(self, item, validated_data):
        user = self.context['request'].user
        status = validated_data.get('status', item.status)
        collection_id = self.context.get(
            'collection_id',
            None) or self.context['request'].parser_context['kwargs'].get(
                'pk', None)
        if collection_id:
            collection = Collection.objects.get(id=collection_id)
        else:
            collection = item.collection

        if status != item.status and user.has_perm('api.approve_items',
                                                   collection):
            raise exceptions.PermissionDenied(
                detail='Cannot change submission status.')
        elif user.id != item.created_by_id and validated_data.keys() != [
                'status'
        ]:
            raise exceptions.PermissionDenied(
                detail='Cannot update another user\'s submission.')

        group_id = self.context.get(
            'group_id',
            None) or self.context['request'].parser_context['kwargs'].get(
                'group_id', None)
        if group_id:
            group = Group.objects.get(id=group_id)
        else:
            group = None

        item_type = validated_data.get('type', item.type)
        if collection.settings:
            collection_settings = json.loads(collection.settings)
            collection_type = collection_settings.get('type', None)
            if collection_type and item_type != collection_type:
                raise ValueError('Collection only accepts items of type ' +
                                 collection_type)

        item.group = group
        item.source_id = validated_data.get('source_id', item.source_id)
        item.title = validated_data.get('title', item.title)
        item.type = item_type
        item.status = status
        item.url = validated_data.get('url', item.url)
        item.metadata = validated_data.get('metadata', item.metadata)
        item.save()
        return item
コード例 #14
0
class BaseSerializer(serializers.ModelSerializer):
    created_at = serializers.DateTimeField(read_only=True)
    modified_at = serializers.DateTimeField(read_only=True)
    created_by_user = serializers.ResourceRelatedField(read_only=True)
コード例 #15
0
class KaznetTaskSerializer(GenericForeignKeySerializer):
    """
    Main Task Serializer class
    """
    start = serializers.DateTimeField(required=False)
    submission_count = serializers.SerializerMethodField()
    amount = SerializableAmountField(source='bounty',
                                     required=False,
                                     write_only=True)
    total_bounty_payout = SerializableAmountField(read_only=True)
    current_bounty_amount = SerializableAmountField(read_only=True)
    bounty = BountySerializer(read_only=True)
    locations_input = TaskLocationCreateSerializer(many=True,
                                                   required=False,
                                                   write_only=True)
    task_locations = serializers.SerializerMethodField(read_only=True)

    # pylint: disable=too-few-public-methods
    class Meta:
        """
        Meta options for KaznetTaskSerializer
        """
        fields = [
            'id',
            'created',
            'created_by',
            'modified',
            'name',
            'amount',
            'parent',
            'estimated_time',
            'approved_submissions_count',
            'pending_submissions_count',
            'rejected_submissions_count',
            'total_bounty_payout',
            'current_bounty_amount',
            'required_expertise',
            'description',
            'xform_title',
            'xform_id_string',
            'xform_version',
            'xform_owner',
            'xform_owner_url',
            'xform_ona_id',
            'xform_project_id',
            'status_display',
            'required_expertise_display',
            'client',
            'start',
            'end',
            'timing_rule',
            'total_submission_target',
            'user_submission_target',
            'status',
            'submission_count',
            'bounty',
            'target_content_type',
            'target_id',
            'segment_rules',
            'locations',
            'created_by_name',
            'client_name',
            'locations_input',
            'task_locations',
        ]
        model = Task
        read_only_fields = [
            'locations', 'created_by', 'created_by_name', 'client_name'
        ]

    def get_submission_count(self, obj):  # pylint: disable=no-self-use
        """
        Add a custom method to get submission count
        """
        try:
            return obj.submission_count
        except AttributeError:
            return obj.submissions

    # pylint: disable=no-self-use
    def validate_timing_rule(self, value):
        """
        Validate timing rule
        """
        if value is not None:
            if validate_rrule(value) is True:
                return value
            raise serializers.ValidationError(INVALID_TIMING_RULE)
        return None

    def validate_parent(self, value):
        """
        Validate task parent field
        """
        valid_parent = validate_parent_field(self.instance, value)
        if not valid_parent and self.instance is not None:
            # tasks cannot be their own parents
            raise serializers.ValidationError(SAME_PARENT)
        return value

    def validate(self, attrs):
        """
        Object level validation method for TaskSerializer
        """
        if not self.instance:
            attrs = self._validate_new(attrs)

        # If end date is present we validate that it is greater than start_date
        if attrs.get('end') is not None:
            # If end date is lesser than the start date raise an error
            the_start = attrs.get('start')
            if the_start is None and self.instance is not None:
                the_start = self.instance.start

            if not the_start:
                raise serializers.ValidationError(
                    {'start': INVALID_START_DATE})

            if attrs['end'] < the_start:
                raise serializers.ValidationError({'end': INVALID_END_DATE})

            # if status is active and end date is in the past raise an error
            if attrs['end'] < timezone.now() and\
                    attrs.get('status') == Task.ACTIVE:
                raise serializers.ValidationError({'end': PAST_END_DATE})

        # If start date is present and this is an existing object, we validate
        # that the start date is not greater than the existing end date
        if attrs.get('start') is not None and self.instance is not None\
                and self.instance.end is not None and attrs.get('start') >\
                self.instance.end:
            raise serializers.ValidationError({'start': INVALID_START_DATE})

        # set automated statuses

        # scheduled => tasks which start in the future
        if attrs.get('start') and attrs.get('start') > timezone.now():
            attrs['status'] = Task.SCHEDULED

        # draft => tasks with no form
        target_object_id = attrs.get('target_object_id')

        if target_object_id is None and self.instance is not None:
            target_object_id = self.instance.target_object_id

        if target_object_id is None:
            attrs['status'] = Task.DRAFT

        return super().validate(attrs)

    def _validate_new(self, attrs):
        """
        Object level validation method run on New
        Task Instances
        """

        # get timing_rule from input
        timing_rule_from_input = attrs.get('timing_rule')

        # get start from input
        start_from_input = attrs.get('start')

        # get timing rules from task locations
        tasklocation_timing_rules = []
        for location_input in attrs.get('locations_input', []):
            tasklocation_timing_rules.append(location_input['timing_rule'])

        # get start and end from timing rules
        timing_rules = [timing_rule_from_input] +\
            tasklocation_timing_rules
        timing_rule_start, timing_rule_end =\
            get_start_end_from_timing_rules(timing_rules)

        if not start_from_input:
            # start was not input by user, we try and generate it from
            # timing rules
            if not timing_rule_start:
                # we cannot determine a start time
                raise serializers.ValidationError({
                    'timing_rule':
                    MISSING_START_DATE,
                    'start':
                    MISSING_START_DATE,
                    'locations_input':
                    MISSING_START_DATE
                })

            attrs['start'] = timing_rule_start

        # get end
        attrs['end'] = attrs.get('end', timing_rule_end)

        return attrs

    def get_task_locations(self, obj):
        """
        Get serialized TaskLocation objects
        """
        # pylint: disable=no-member
        queryset = TaskLocation.objects.filter(task=obj)
        return TaskLocationSerializer(queryset, many=True).data

    def create(self, validated_data):
        """
        Custom Create method for Task
        """
        # get current user and set that as created_by
        try:
            request = self.context['request']
        except KeyError:
            pass
        else:
            if request is not None:
                user = getattr(request, 'user', None)
                if user.is_authenticated:
                    validated_data['created_by'] = user

        # get the supplied amount
        try:
            amount = validated_data.pop('bounty')
        except KeyError:
            amount = None

        # get the input locations
        locations_data = validated_data.pop('locations_input', [])

        # create the task
        task = super().create(validated_data)

        # create the bounty object
        create_bounty(task, amount)

        # create the TaskLocations
        for location_data in locations_data:
            location_data['task'] = task
            TaskLocationSerializer.create(TaskLocationSerializer(),
                                          validated_data=location_data)

        return task

    def update(self, instance, validated_data):
        """
        Custom Update method for Task
        """
        # get the supplied amount
        try:
            amount = validated_data.pop('bounty')
        except KeyError:
            amount = None

        # get the input locations
        try:
            locations_data = validated_data.pop('locations_input')
        except KeyError:
            locations_data = None

        # update the task
        task = super().update(instance, validated_data)

        # create the bounty object
        create_bounty(task, amount)

        if locations_data is not None:
            # update the TaskLocations
            # we assume that this (locations_data) is the one final list of
            # locations to be linked to this task and that other relationships
            # should be removed.
            # If task_locations is empty it means the user is
            # removing all Task and Location relationships

            # pylint: disable=no-member
            TaskLocation.objects.filter(task=task).delete()
            for location_data in locations_data:
                location_data['task'] = task
                TaskLocationSerializer.create(TaskLocationSerializer(),
                                              validated_data=location_data)

        return task
コード例 #16
0
 class Meta:
     start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
     end_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
     model = ActivityRecord
     fields = ('id', 'url', 'name', 'locations', 'start_time', 'end_time')
コード例 #17
0
class UserProfileSerializer(serializers.ModelSerializer):
    """
    Serializer class for UserProfile model
    """

    first_name = serializers.CharField(source="user.first_name")
    last_name = serializers.CharField(source="user.last_name")
    email = serializers.EmailField(source="user.email")
    password = serializers.CharField(
        source="user.password",
        allow_null=True,
        default=None,
        required=False,
        write_only=True,
    )
    last_login = serializers.DateTimeField(
        source="user.last_login", read_only=True)
    submission_count = serializers.SerializerMethodField()
    amount_earned = SerializableAmountField(read_only=True)
    avg_amount_earned = SerializableAvgAmountEarnedField(read_only=True)
    metadata = serializers.JSONField(read_only=True)

    class Meta:  # pylint:  disable=too-few-public-methods
        """
        class meta options
        """

        model = UserProfile
        fields = [
            "id",
            "created",
            "modified",
            "role_display",
            "gender_display",
            "expertise_display",
            "first_name",
            "last_name",
            "password",
            "email",
            "ona_pk",
            "ona_username",
            "payment_number",
            "approved_submissions",
            "rejected_submissions",
            "approval_rate",
            "amount_earned",
            "last_login",
            "avg_submissions",
            "avg_approved_submissions",
            "avg_rejected_submissions",
            "avg_approval_rate",
            "avg_amount_earned",
            "phone_number",
            "role",
            "expertise",
            "gender",
            "national_id",
            "submission_count",
            "address",
            "metadata",
        ]

    owner_only_fields = ("metadata", )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if self.instance and hasattr(self.Meta, "owner_only_fields"):
            request = self.context.get("request")
            is_permitted = (request and request.user
                            and request.user == self.instance.user)
            if isinstance(self.instance,
                          QuerySet) or not is_permitted or not request:
                for field in getattr(self.Meta, "owner_only_fields"):
                    self.fields.pop(field)

    def get_submission_count(self, obj):  # pylint: disable=no-self-use
        """
        Get the submission count
        """
        return obj.user.submission_set.count()

    def validate_password(self, value):
        """
        Custom validation for Password Field
        """
        if not self.instance:
            # On create of a new user Password shouldn't be none
            if value is None:
                raise serializers.ValidationError(NEED_PASSWORD_ON_CREATE)

        if value is not None:
            validate_password(value)

        return value

    def create(self, validated_data):
        """
        Custom create method to create User object then UserProfile object
        """
        user_data = validated_data.pop("user")
        user_data["username"] = validated_data.get("ona_username")
        first_name = user_data.get("first_name")
        last_name = user_data.get("last_name")
        email = user_data.get("email")
        password = user_data.get("password")

        created, data = create_ona_user(
            settings.ONA_BASE_URL,
            user_data["username"],
            first_name,
            last_name,
            email,
            password,
        )

        if not created:
            raise serializers.ValidationError(data)

        if not data:
            raise serializers.ValidationError(CANNOT_ACCESS_ONADATA)

        ona_pk = data.get("id")
        metadata = data.get("metadata")

        add_team_member(settings.ONA_BASE_URL, user_data["username"],
                        settings.ONA_MEMBERS_TEAM_ID)

        # make user an admin of organisation at ona
        if validated_data.get("role") == UserProfile.ADMIN:
            updated = change_user_role(
                settings.ONA_BASE_URL,
                settings.ONA_ORG_NAME,
                user_data["username"],
                settings.ONA_OWNER_ROLE,
            )
            if not updated:
                # default to contributor role incase admin fails
                validated_data["role"] = UserProfile.CONTRIBUTOR
        elif validated_data["role"] == UserProfile.CONTRIBUTOR:
            change_user_role(
                settings.ONA_BASE_URL,
                settings.ONA_ORG_NAME,
                user_data["username"],
                settings.ONA_CONTRIBUTER_ROLE,
            )

        # set an unusable password by not passing the password to the create
        # method.  Why, you ask?  Because we don't want to store passwords
        # on the Kaznet site.  Ona is the source of truth for this.
        try:
            del user_data["password"]
        except KeyError:
            pass

        # create the User object
        user = UserSerializer.create(
            UserSerializer(), validated_data=user_data)
        # populate the UserProfile object
        userprofile = user.userprofile
        userprofile.ona_pk = ona_pk
        userprofile.ona_username = user.username
        userprofile.payment_number = validated_data.get("payment_number")
        userprofile.phone_number = validated_data.get("phone_number")
        if validated_data.get("role"):
            userprofile.role = validated_data.get("role")
        userprofile.gender = validated_data.get("gender")
        if validated_data.get("national_id"):
            userprofile.national_id = validated_data.get("national_id")
        userprofile.expertise = validated_data.get("expertise")

        if metadata:
            userprofile.metadata["last_password_edit"] = metadata.get(
                settings.ONA_LAST_PASSWORD_EDIT_FIELD)
        userprofile.metadata["gravatar"] = data.get("gravatar")
        userprofile.save()

        return userprofile

    # pylint: disable=too-many-branches, too-many-statements
    def update(self, instance, validated_data):
        """
        Custom update method for UserProfiles
        """
        # deal with the user object
        user = instance.user
        user_data = validated_data.pop("user")
        username = user.username
        first_name = user_data.get("first_name")
        last_name = user_data.get("last_name")
        data = {}

        # you can't change username
        try:
            del user_data["username"]
        except KeyError:
            pass

        # you can't change email
        # this is because Onadata requires your current password when changing
        # the email.  And we cannot get the user's current password
        try:
            del user_data["email"]
        except KeyError:
            pass

        # you can't change password
        # this is because Onadata requires your current password when changing
        # the password.  And we cannot get the user's current password
        try:
            del user_data["password"]
        except KeyError:
            pass

        # only pick changed values significant to ona profile
        update_data = {}
        if first_name != instance.user.first_name:
            update_data["first_name"] = first_name
        if last_name != instance.user.last_name:
            update_data["last_name"] = last_name

        # update on ona only if there is are changes made significant to ona
        if any(update_data):
            updated, data = update_details(settings.ONA_BASE_URL, username,
                                           update_data)

            if not updated:
                raise serializers.ValidationError(data)

            if not data:
                raise serializers.ValidationError(CANNOT_ACCESS_ONADATA)

        # change role to admin if the user is not initially an admin
        if (validated_data.get("role") == UserProfile.ADMIN
                and instance.role != UserProfile.ADMIN):
            updated = change_user_role(
                settings.ONA_BASE_URL,
                settings.ONA_ORG_NAME,
                username,
                settings.ONA_OWNER_ROLE,
            )
            if not updated:
                # default to previous role incase change to admin fails
                validated_data["role"] = instance.role

        # change role to contributor if user was admin initially
        elif (validated_data.get("role") != UserProfile.ADMIN
              and instance.role == UserProfile.ADMIN):
            updated = change_user_role(
                settings.ONA_BASE_URL,
                settings.ONA_ORG_NAME,
                username,
                settings.ONA_CONTRIBUTER_ROLE,
            )
            if not updated:
                # default to previous role incase change to contributor fails
                validated_data["role"] = instance.role

        UserSerializer().update(instance=user, validated_data=user_data)

        # deal with the userprofile object
        instance.payment_number = validated_data.get("payment_number",
                                                     instance.payment_number)
        instance.phone_number = validated_data.get("phone_number",
                                                   instance.phone_number)
        instance.role = validated_data.get("role", instance.role)
        instance.gender = validated_data.get("gender", instance.gender)
        if instance.national_id:
            instance.national_id = validated_data.get("national_id",
                                                      instance.national_id)
        instance.expertise = validated_data.get("expertise",
                                                instance.expertise)

        if any(data):
            metadata = data.get("metadata")
            gravatar = data.get("gravatar")

            try:
                instance.metadata["last_password_edit"] = metadata.get(
                    settings.ONA_LAST_PASSWORD_EDIT_FIELD)
            except AttributeError:
                pass

            instance.metadata["gravatar"] = gravatar
        instance.save()

        return instance