Example #1
0
class ListAuctionItems(ListAPIView):
    """

    API to list all items on auction, upcoming auctions, previous auctions.

    """
    serializer_class = AuctionItemSerializer
    schema = AutoSchema(manual_fields=[
        coreapi.Field(
            name="page",
            required=False,
            location="query",
            schema=coreschema.Integer(description="Page to be retrieved. Defaults to 0"),
        ),
        coreapi.Field(
            "items_per_page",
            required=False,
            location="query",
            schema=coreschema.Integer(description="Number of items to be displayed per page. Defaults to 10")
        ),
        coreapi.Field(
            "upcoming",
            required=False,
            location="query",
            schema=coreschema.Boolean(
                description="Display only upcoming Auction Items. Takes boolean. Defaults to false")
        ),
        coreapi.Field(
            "previous",
            required=False,
            location="query",
            schema=coreschema.Boolean(
                description="Display only previous Auction Items. Takes boolean. Defaults to false")
        ),
    ])

    def get_queryset(self):
        queryset = AuctionItem.objects.all()
        page = self.request.query_params.get('page', 0)
        items_per_page = self.request.query_params.get('items_per_page', 10)
        upcoming = self.request.query_params.get('upcoming', False)
        previous = self.request.query_params.get('previous', False)
        if upcoming:
            queryset = queryset.filter(start_time__gt=timezone.now())
        if previous:
            queryset = queryset.filter(end_time__lt=timezone.now())
        queryset = queryset[page * items_per_page: (page + 1) * items_per_page]
        return queryset
Example #2
0
 def get_schema_fields(self, view):
     super().get_schema_fields(view)
     choices = {
         STATES.DRAFT: 'Incomplete metadata',
         STATES.SUBMITTED: 'Pending validation',
         STATES.REFUSED: 'Refused',
         STATES.ACCEPTED: 'Validated',
     }
     return [
         coreapi.Field(
             name='status',
             required=False,
             location='query',
             schema=coreschema.Boolean(
                 title="Campaign status",
                 description="0 for closed campaign, 1 for ongoing campaign"
             ),
         ),
         coreapi.Field(
             name='picture_status',
             required=False,
             location='query',
             schema=coreschema.Enum(
                 choices,
                 description=str(pformat(choices)),
                 title="Picture status",
             )
         )
     ]
Example #3
0
class CheckAlphabet(APIView):
    '''
    simple APIView for alphacheck api
    '''
    schema = AutoSchema(manual_fields=[
        coreapi.Field(
            'case_insensitive',
            required=False,
            location='query',
            schema=coreschema.Boolean(),
        ),
    ])

    # pylint: disable=redefined-builtin, unused-argument
    def get(self, request, query, format=None):
        '''
        HTTP GET method that checks whether query contains all letters of the alphabet
        '''
        try:
            case_insensitive = json.loads(
                request.query_params.get('case_insensitive', 'false'))
        except json.JSONDecodeError:
            case_insensitive = False

        try:
            response = has_all_alphabet(query,
                                        case_insensitive=case_insensitive,
                                        version=request.version)
        except KeyError:
            raise Http404

        return Response({
            'response': response,
        })
Example #4
0
def _annotated_type_to_coreschema(
        annotated_type: type) -> coreschema.schemas.Schema:
    if annotated_type is bool or issubclass(annotated_type, schema.Boolean):
        return coreschema.Boolean()
    elif annotated_type is int or issubclass(annotated_type, schema.Integer):
        return coreschema.Integer()
    elif annotated_type is float or issubclass(annotated_type, schema.Number):
        return coreschema.Number()

    return coreschema.String()
 def get_schema_fields(self, view):
     return [
         coreapi.Field(
             name='is_paid',
             required=False,
             schema=coreschema.Boolean(
                 description='If true, returns only payments already paid'),
             location='query',
         )
     ]
Example #6
0
    def get_serializer_fields(self, path, method):
        fields = []
        if method == 'POST':
            fields = [
                coreapi.Field(name="group_id",
                              required=True,
                              location="form",
                              schema=coreschema.Integer(
                                  title="group", description="Id группы"),
                              description='group_id'),
                coreapi.Field(
                    name="title",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="title",
                                             description="Название задачи"),
                    description='Название задачи',
                ),
                coreapi.Field(
                    name="user",
                    required=True,
                    location="form",
                    schema=coreschema.Array(title="user",
                                            description="Юзеры в задаче"),
                    description='Юзеры в задаче',
                ),
            ]
        if method == 'PUT':
            fields = [
                coreapi.Field(name="done",
                              required=True,
                              location="form",
                              schema=coreschema.Boolean(
                                  title="done", description="Завершено"),
                              description='Завершено'),
                coreapi.Field(
                    name="title",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="title",
                                             description="Название задачи"),
                    description='Название задачи',
                ),
                coreapi.Field(
                    name="user",
                    required=True,
                    location="form",
                    schema=coreschema.Array(title="user",
                                            description="Юзеры в задаче"),
                    description='Юзеры в задаче',
                ),
            ]

        return fields
Example #7
0
def get_param_schema(annotated_type: typing.Type) -> coreschema.schemas.Schema:
    if issubclass(annotated_type, (bool, typesystem.Boolean)):
        return coreschema.Boolean()
    elif issubclass(annotated_type, int):
        return coreschema.Integer()
    elif issubclass(annotated_type, float):
        return coreschema.Number()
    elif issubclass(annotated_type, typesystem.Enum):
        enum = typing.cast(typing.Type[typesystem.Enum], annotated_type)
        return coreschema.Enum(enum=enum.enum)
    return coreschema.String()
Example #8
0
    def get_serializer_fields(self, path, method):

        extra_fields = []

        if method == 'PUT':
            extra_fields = [
                coreapi.Field(name='password',
                              required=False,
                              location='form',
                              schema=coreschema.String(
                                  description="New password",
                                  title='password',
                              )),
                coreapi.Field(
                    name='position',
                    required=False,
                    location='form',
                    type=coreschema.Integer,
                    schema=coreschema.Integer(
                        description=
                        "Device outlet position. Mandatory for changing outlet name, remove user or outlet status. Must be an integer. Only admins can remove user from outlet",
                        title="position")),
                coreapi.Field(
                    name='name',
                    required=False,
                    location='form',
                    schema=coreschema.String(
                        description=
                        "Change the outlet name in the position provided",
                        title='name')),
                coreapi.Field(
                    name='status',
                    required=False,
                    location='form',
                    type=coreschema.String,
                    schema=coreschema.String(
                        description=
                        "Turn on or off the remote server connected to the outlet position provided. Values accepted: \'on\' or \'off\'",
                        title='status')),
                coreapi.Field(
                    name='rempos',
                    required=False,
                    location='form',
                    schema=coreschema.Boolean(
                        description=
                        "Remove user from position. Only for admins. Values accepted: True or False (False by default)",
                        title='rempos',
                    )),
            ]

        manual_fields = super(CustomUserRestSchema,
                              self).get_serializer_fields(path, method)
        return manual_fields + extra_fields
Example #9
0
class EncounterListView(generics.ListAPIView):
    """
    List own encounters
    """
    pagination_class = LimitOffsetPagination
    serializer_class = EncounterSerializer

    def get_queryset(self):
        queryset = Encounter.objects.filter(accounts__user=self.request.user).order_by('-started_at')

        since = self.request.query_params.get('since', None)
        if since is not None:
            queryset = queryset.filter(started_at__gte=since)

        area_id = self.request.query_params.get('area_id', None)
        if area_id is not None:
            queryset = queryset.filter(area_id=int(area_id))

        success = self.request.query_params.get('success', None)
        if success is not None:
            queryset = queryset.filter(success=strtobool(success))

        return queryset

    schema = AutoSchema(manual_fields=[
        coreapi.Field(
            name="since",
            required=False,
            location='query',
            schema=coreschema.Integer(
                title="Since",
                description="Earliest time (UNIX timestamp)",
            ),
        ),
        coreapi.Field(
            name="area_id",
            required=False,
            location='query',
            schema=coreschema.Integer(
                title="Area ID",
                description="ID of the area where encounter took place",
            ),
        ),
        coreapi.Field(
            name="success",
            required=False,
            location='query',
            schema=coreschema.Boolean(
                title="Success",
                description="Return only successful or unsuccessful encounters",
            ),
        ),
    ])
Example #10
0
def get_param_schema(annotated_type: typing.Type) -> coreschema.schemas.Schema:
    schema_kwargs = {'description': getattr(annotated_type, 'description', '')}

    if issubclass(annotated_type, (bool, typesystem.Boolean)):
        return coreschema.Boolean(**schema_kwargs)
    elif issubclass(annotated_type, int):
        return coreschema.Integer(**schema_kwargs)
    elif issubclass(annotated_type, float):
        return coreschema.Number(**schema_kwargs)
    elif issubclass(annotated_type, typesystem.Enum):
        enum = typing.cast(typing.Type[typesystem.Enum], annotated_type)
        return coreschema.Enum(enum=enum.enum, **schema_kwargs)
    return coreschema.String(**schema_kwargs)
Example #11
0
def _annotated_type_to_coreschema(
        annotated_type: type) -> coreschema.schemas.Schema:
    if annotated_type is bool or issubclass(annotated_type, schema.Boolean):
        return coreschema.Boolean()
    elif annotated_type is int or issubclass(annotated_type, schema.Integer):
        return coreschema.Integer()
    elif annotated_type is float or issubclass(annotated_type, schema.Number):
        return coreschema.Number()
    elif issubclass(annotated_type, schema.Enum):
        enum = cast(Type[schema.Enum], annotated_type)
        return coreschema.Enum(enum=enum.enum)

    return coreschema.String()
Example #12
0
    def get_schema(self):
        if self.dtype == str:
            return coreschema.String(description=self.description)

        elif self.dtype == bool:
            return coreschema.Boolean(description=self.description)

        elif self.dtype == int:
            return coreschema.Integer(description=self.description)
        elif self.dtype == float:
            return coreschema.Number(description=self.description)

        elif self.dtype == list:
            return coreschema.Array(description=self.description)

        else:
            raise TypeError("Parameter must have type.")
Example #13
0
    def field_to_schema(self, field):
        import coreschema
        import django.forms as django_forms
        from django.utils.encoding import force_str
        title = force_str(field.label) if field.label else ''
        description = force_str(field.help_text) if field.help_text else ''

        schema = None

        if isinstance(field, django_forms.MultipleChoiceField):
            schema = coreschema.Array(
                items=coreschema.Enum(enum=list(field.choices)),
                title=title,
                description=description)
        elif isinstance(field, django_forms.ChoiceField) and not isinstance(
                field, django_forms.ModelChoiceField):
            choices = list(
                map(
                    lambda choice: choice[0]
                    if isinstance(choice, tuple) else choice, field.choices))
            choices.remove('')
            schema = coreschema.Enum(enum=choices,
                                     title=title,
                                     description=description)
        elif isinstance(field, django_forms.BooleanField):
            schema = coreschema.Boolean(title=title, description=description)
        elif isinstance(field,
                        (django_forms.DecimalField, django_forms.FloatField)):
            schema = coreschema.Number(title=title, description=description)
        elif isinstance(field, django_forms.IntegerField):
            schema = coreschema.Integer(title=title, description=description)
        elif isinstance(field, django_forms.DateField):
            schema = coreschema.String(title=title,
                                       description=description,
                                       format='date')
        elif isinstance(field, django_forms.DateTimeField):
            schema = coreschema.String(title=title,
                                       description=description,
                                       format='date-time')
        elif isinstance(field, django_forms.JSONField):
            schema = coreschema.Object(title=title, description=description)

        return schema or coreschema.String(title=title,
                                           description=description)
Example #14
0
    def get_serializer_fields(self, path, method):
        fields = []
        if method in ['PUT', 'POST']:
            fields = [
                coreapi.Field(
                    name="title",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="title",
                                             description="title"),
                    description='Название группы',
                ),
                coreapi.Field(
                    name="description",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="description",
                                             description="description"),
                    description='Описание',
                ),
                coreapi.Field(
                    name="category",
                    required=True,
                    location="form",
                    schema=coreschema.Integer(title="category",
                                              description="category"),
                    description='ID категории',
                ),
                coreapi.Field(
                    name="is_public",
                    required=True,
                    location="form",
                    schema=coreschema.Boolean(title="is_public",
                                              description="is_public"),
                    description='Группа публичная',
                ),

            ]

        return fields
Example #15
0
 def get_schema_fields(self, view):
     super().get_schema_fields(view)
     return [
         coreapi.Field(
             name="state",
             required=False,
             location="query",
             schema=coreschema.Boolean(
                 title="Campaign state",
                 description="'draft', 'started' or 'closed'",
             ),
         ),
         coreapi.Field(
             name="picture__state",
             required=False,
             location="query",
             schema=coreschema.Enum(
                 Picture.STATES,
                 description=str(pformat(Picture.STATES)),
                 title="Picture state",
             ),
         ),
     ]
Example #16
0
            "nresults",
            required=False,
            location="query",
            schema=coreschema.Integer(
                description="Maximum number of journeys to return, default "
                "10. (e.g. 20)"),
            description="Maximum number of journeys to return, default 10. "
            "(e.g. 20)",
            example="20",
        ),
        coreapi.Field(
            "expand_journey",
            required=False,
            location="query",
            schema=coreschema.Boolean(
                description="Expands the resulting journey into a full "
                "journey object"),
            description="Expands the resulting journey into a full "
            "journey object",
        ),
    ],
    description="Return the timetabled vehicle journeys expected for a given "
    "stop identified by _stop_id_ from a specific date and time "
    "identified by _datetime_from_ (optional, default = now). "
    "\n\n"
    "All results are paginated based on _nresults_ and a _next_ "
    "attribute is returned containing the URL to use to retrieve "
    "more results. The pagination can return up to _nresults_ "
    "or less if there are no more results for a day, for example.")

Example #17
0
 def get_schema_fields(self, view):
     fields = [
         coreapi.Field(name=self.category_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Integer(
                           title='Category',
                           description=force_str(
                               self.category_query_description))),
         coreapi.Field(name=self.sub_category_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Integer(
                           title='Sub Category',
                           description=force_str(
                               self.sub_category_query_description))),
         coreapi.Field(name=self.author_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Integer(
                           title='Author',
                           description=force_str(
                               self.author_query_description))),
         coreapi.Field(name=self.title_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.String(
                           title='Title',
                           description=force_str(
                               self.title_query_description))),
         coreapi.Field(name=self.content_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.String(
                           title='Title',
                           description=force_str(
                               self.category_query_description))),
         coreapi.Field(name=self.audio_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Boolean(
                           title='Has Audio',
                           description=force_str(
                               self.audio_query_description))),
         coreapi.Field(name=self.from_year_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Integer(
                           title='From Year',
                           description=force_str(
                               self.from_year_query_description))),
         coreapi.Field(name=self.to_year_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Integer(
                           title='To Year',
                           description=force_str(
                               self.to_year_query_description))),
         coreapi.Field(name=self.sort_query_param,
                       required=False,
                       location='query',
                       schema=coreschema.Enum(
                           title='Sort by',
                           description=force_str(
                               self.sort_query_description),
                           enum=[
                               'publish_date',
                               'add_date',
                               'author',
                               'has_audio',
                               'pages',
                               'downloads',
                               'reads',
                               'rate',
                               '-publish_date',
                               '-add_date',
                               '-author',
                               '-has_audio',
                               '-pages',
                               '-downloads',
                               '-reads',
                               '-rate',
                           ])),
     ]
     return fields
Example #18
0
                location='path',
                required=True,
                schema=coreschema.Integer())
      ]),
 'set_complete':
 Link(url='/todo/{ident}/',
      action='PUT',
      fields=[
          Field(name='ident',
                location='path',
                required=True,
                schema=coreschema.Integer()),
          Field(name='complete',
                location='query',
                required=False,
                schema=coreschema.Boolean())
      ]),
 'set_percent_complete':
 Link(url='/todo/{ident}/percent_complete',
      action='PUT',
      fields=[
          Field(name='ident',
                location='path',
                required=True,
                schema=coreschema.Integer()),
          Field(name='percent_complete',
                location='query',
                required=False,
                schema=coreschema.Number())
      ]),
 'set_category':
Example #19
0
jsonschema = coreschema.RefSpace({
    'Schema': coreschema.Object(
        properties={
            # Meta
            'id': coreschema.String(format='uri'),
            '$schema': coreschema.String(format='uri'),
            'title': coreschema.String(),
            'description': coreschema.String(),
            'default': coreschema.Anything(),
            'definitions': coreschema.Ref('SchemaMap'),
            # Type
            'type': coreschema.Ref('SimpleTypes') | coreschema.Array(items=coreschema.Ref('SimpleTypes'), min_items=1, unique_items=True),
            # Number validators
            'minimum': coreschema.Number(),
            'maximum': coreschema.Number(),
            'exclusiveMinimum': coreschema.Boolean(default=False),
            'exclusiveMaximum': coreschema.Boolean(default=False),
            'multipleOf': coreschema.Number(minimum=0, exclusive_minimum=True),
            # String validators
            'minLength': coreschema.Integer(minimum=0, default=0),
            'maxLength': coreschema.Integer(minimum=0),
            'pattern': coreschema.String(format='regex'),
            'format': coreschema.String(),
            # Array validators
            'items': coreschema.Ref('Schema') | coreschema.Ref('SchemaArray'), # TODO: default={}
            'additionalItems': coreschema.Boolean() | coreschema.Ref('Schema'),  # TODO: default={}
            'minItems': coreschema.Integer(minimum=0, default=0),
            'maxItems': coreschema.Integer(minimum=0),
            'uniqueItems': coreschema.Boolean(default=False),
            # Object validators
            'properties': coreschema.Ref('SchemaMap'),
Example #20
0
expected = Schema(url='/schema/', content={
    'list_todo': Link(
        url='/todo/',
        action='GET',
        description='list_todo description',
        fields=[Field(name='search', location='query', required=False, schema=coreschema.String())]
    ),
    'add_todo': Link(
        url='/todo/',
        action='POST',
        description='add_todo description\nMultiple indented lines',
        fields=[
            Field(name='id', required=False, location='form', schema=coreschema.Integer()),
            Field(name='text', required=False, location='form', schema=coreschema.String()),
            Field(name='complete', required=False, location='form', schema=coreschema.Boolean()),
            Field(name='percent_complete', required=False, location='form', schema=coreschema.Number()),
            Field(name='category', required=False, location='form', schema=coreschema.Enum(enum=['shop', 'chore']))
        ]
    ),
    'show_todo': Link(
        url='/todo/{ident}/',
        action='GET',
        fields=[Field(name='ident', location='path', required=True, schema=coreschema.Integer())]
    ),
    'set_complete': Link(
        url='/todo/{ident}/',
        action='PUT',
        fields=[
            Field(name='ident', location='path', required=True, schema=coreschema.Integer()),
            Field(name='complete', location='query', required=False, schema=coreschema.Boolean())
Example #21
0
class GoodsManageViewSet(viewsets.ViewSet):
    '''二手物品相关服务,需认证 错误码42xxx'''
    authentication_classes = [JWTAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    schema = CustomSchema(
        manual_fields={
            'POST:/goods/publish/': [
                coreapi.Field("title",
                              required=True,
                              location="form",
                              description='标题 品类品牌型号都是买家喜欢搜索的'),
                coreapi.Field("description",
                              required=True,
                              location="form",
                              description='描述宝贝的转手原因、入手渠道和使用感受'),
                coreapi.Field(
                    "images",
                    required=True,
                    location="form",
                    description='照片,每一项以 goodspublish 开头,多项之间以英文分号分隔'),
                coreapi.Field("isNew",
                              required=True,
                              location="form",
                              description='是否 全新宝贝',
                              schema=coreschema.Boolean()),
                coreapi.Field("knife",
                              required=True,
                              location="form",
                              description='是否 可小刀',
                              schema=coreschema.Boolean()),
                coreapi.Field(
                    "price", required=True, location="form", description='价格'),
                coreapi.Field("category",
                              required=True,
                              location="form",
                              description='分类,只有一级分类'),
                coreapi.Field("tags",
                              required=True,
                              location="form",
                              description='标签,以井号(#)分隔'),
            ],
            'POST:/goods/status/': [
                coreapi.Field("gid",
                              required=True,
                              location="form",
                              description='二手物品发布信息唯一标识 GID'),
                coreapi.Field(
                    "status",
                    required=True,
                    location="form",
                    description='改变状态:normal-重新发布、delete-删除、removed-下架、sold-出售。'
                ),
            ],
            'POST:/goods/collect/': [
                coreapi.Field("gid",
                              required=True,
                              location="form",
                              description='二手物品发布信息唯一标识 GID'),
                coreapi.Field("status",
                              required=True,
                              location="form",
                              description='收藏:normal;取消收藏:delete'),
            ],
            'GET:/goods/collection/': [],
            'POST:/goods/comment/': [
                coreapi.Field("gid",
                              required=True,
                              location="form",
                              description='二手物品发布信息唯一标识 GID'),
                coreapi.Field("toUser",
                              required=False,
                              location="form",
                              description='回复的用户的 UID'),
                coreapi.Field("comment",
                              required=True,
                              location="form",
                              description='评论内容'),
            ],
            'POST:/goods/comment/delete/': [
                coreapi.Field("cid",
                              required=True,
                              location="form",
                              description='评论信息唯一标识'),
            ],
        })

    @action(methods=['post'], detail=False)
    def publish(self, request, format=None):
        '''发布二手物品信息'''
        user = request.user
        # 获取及检查参数
        params = [
            'title', 'description', 'images', 'isNew', 'knife', 'price',
            'category', 'tags'
        ]
        title, description, images, isNew, knife, price, category, tags = get_dict_values(
            request.data, params)
        if check_none(title, description, images, isNew, knife, price,
                      category, tags):
            raise ParseError('缺少参数:' + ', '.join(params))
        # status 默认为 normal

        # 检查标签,将新标签存入数据库,旧标签使用次数加一
        tags_arr = tags.split('#')
        for tag in tags_arr:
            try:
                record_tag = GoodsTags.objects.get(name=tag)
                record_tag.using = record_tag.using + 1
                record_tag.save()
            except GoodsTags.DoesNotExist:
                record_tag_new = GoodsTags(name=tag,
                                           types='diy',
                                           using=1,
                                           createUser=user)
                record_tag_new.save()
        # 将分类标签使用次数加一
        try:
            record_category = GoodsTags.objects.get(name=category)
            record_category.using = record_category.using + 1
            record_category.save()
        except GoodsTags.DoesNotExist:
            pass

        # 反序列化数据
        publish_params = {
            'uid': user,
            'title': title,
            'description': description,
            'images': images,
            'isNew': isNew,
            'knife': knife,
            'price': price,
            'category': category,
            'tags': tags,
        }
        record_publish = PublishGoodsSerializers(data=publish_params)
        if not record_publish.is_valid():
            errors = record_publish.errors
            return Response(res_format(errors, code=42001, msg='发布信息格式错误'))
        record_publish.save()
        return Response(
            res_format({'gid': record_publish.data['gid']}, msg='发布成功'))

    @action(methods=['post'], detail=False)
    def status(self, request, format=None):
        '''更改二手物品信息发布状态'''
        user = request.user
        # 获取及检查参数
        params = ['gid', 'status']
        gid, status = get_dict_values(request.data, params)
        if check_none(gid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查是否是更新合法的图书状态
        status_dict = {
            'normal': '重新发布',
            'delete': '删除',
            'sold': '出售',
            'removed': '下架'
        }
        if status not in status_dict:
            return Response(
                res_format(None, code=42002, msg='未知的切换状态 ' + status))
        try:
            # 查询当前状态
            record = PublishGoods.objects.get(gid=gid)
            # 判断这本书是不是该用户发布的
            if record.uid != user:
                return Response(res_format(None, code=42003,
                                           msg='无法操作别人发布的物品'))
            # 检查发布信息的系统状态
            if record.systemStatus != 'normal':
                return Response(
                    res_format(None, code=42004, msg='该物品的系统状态异常,无法操作'))
            # 出售后只可以进行删除
            if record.status == 'sold' and status != 'delete':
                return Response(
                    res_format(None, code=42005, msg='不可对已出售的物品进行其他操作'))
            # 检查无误,可以切换状态了
            record.status = status
            record.save()
            return Response(res_format(None, msg=status_dict[status] + '物品成功'))
        except PublishGoods.DoesNotExist:
            return Response(res_format(None, code=42006, msg='无相关物品信息'))

    @action(methods=['post'], detail=False)
    def collect(self, request, format=None):
        '''收藏二手物品信息'''
        user = request.user
        # 获取及检查参数
        params = ['gid', 'status']
        gid, status = get_dict_values(request.data, params)
        if check_none(gid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查是否是更新合法的图书状态
        status_dict = {'normal': '收藏', 'delete': '取消收藏'}
        if status not in status_dict:
            return Response(
                res_format(None, code=42006, msg='收藏状态错误 ' + status))
        # 查询信息
        try:
            record_goods = PublishGoods.objects.get(gid=gid)
            if record_goods.uid == user:
                return Response(res_format(None, code=42008,
                                           msg='无法收藏自己发布的物品'))
        except PublishGoods.DoesNotExist:
            return Response(res_format(None, code=42009, msg='无相关物品信息'))
        # 检查收藏状态
        try:
            record = CollectGoods.objects.get(uid=str(user), gid=gid)
            record.status = status
            record.save()
        except CollectGoods.DoesNotExist:
            record_new = CollectGoods(uid=user,
                                      gid=record_goods,
                                      status=status)
            record_new.save()
        return Response(res_format(None, msg=status_dict[status] + '成功'))

    @action(detail=False)
    def collection(self, request, format=None):
        '''查询已收藏的二手物品信息'''
        user = request.user
        record = CollectGoods.objects.filter(uid=str(user)).filter(
            status='normal').filter(gid__status='normal').filter(
                gid__systemStatus='normal').order_by('-updateTime')
        result = CollectGoodsSerializers(record, many=True).data
        return Response(res_format(result))

    @action(methods=['post'], detail=False)
    def comment(self, request, format=None):
        '''给二手物品信息留言'''
        user = request.user
        # 评论频率限制
        # 每分钟 3 条,每小时 30 条,每天 200 条
        now = datetime.datetime.now()
        limit_minute = now - datetime.timedelta(minutes=1)
        limit_hour = now - datetime.timedelta(hours=1)
        limit_day = now - datetime.timedelta(hours=24)
        record_limit = CommentGoods.objects.filter(commentUserInfo=user)
        if len(record_limit.filter(createTime__gt=limit_minute)) >= 3:
            return Response(
                res_format('Minute Limit', code=42010, msg='留言失败,请过一会儿再来'))
        if len(record_limit.filter(createTime__gt=limit_hour)) >= 30:
            return Response(
                res_format('Hour Limit', code=42011, msg='留言失败,请过一会儿再来'))
        if len(record_limit.filter(createTime__gt=limit_day)) >= 100:
            return Response(
                res_format('Day Limit', code=42012, msg='留言失败,请过一会儿再来'))
        # 获取及检查参数
        params = ['gid', 'comment']
        gid, comment = get_dict_values(request.data, params)
        if check_none(gid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查评论信息
        if len(comment) == 0:
            return Response(res_format(None, code=42013, msg='评论不能为空'))
        # 获取信息
        try:
            record_goods = PublishGoods.objects.get(gid=gid)
        except PublishGoods.DoesNotExist:
            return Response(res_format(None, code=42014, msg='评论失败,无法获取物品信息'))
        # 获取回复别人评论的别人的用户信息
        to_user = request.data.get('toUser', None)
        if to_user is not None:
            try:
                record_to_user = AccountBasic.objects.get(uid=to_user)
            except AccountBasic.DoesNotExist:
                record_to_user = None
        else:
            record_to_user = None
        # 保存评论
        record = CommentGoods(commentUserInfo=user,
                              toUserInfo=record_to_user,
                              goodsInfo=record_goods,
                              comment=comment)
        record.save()
        result = CommentGoodsSerializers(record).data
        return Response(res_format(result))

    @action(methods=['post'], detail=False, url_path='comment/delete')
    def comment_delete(self, request, format=None):
        '''删除留言'''
        user = request.user
        cid = request.data.get('cid', None)
        if cid is None:
            return Response(res_format(None, code=42015, msg='删除评论失败'))
        # 查询评论
        try:
            record = CommentGoods.objects.get(cid=cid, commentUserInfo=user)
        except CommentGoods.DoesNotExist:
            return Response(res_format(None, code=42016, msg='删除评论失败,未找到相关评论'))
        # 删除
        record.status = 'delete'
        record.save()
        return Response(res_format(None))
Example #22
0
class CMSAuthToken(viewsets.GenericViewSet):
    """Implements retrieving of Token."""

    # permission_classes = (IsAuthenticated,)

    # from rest_framework.schemas.inspectors import AuthoSchema
    schema = ManualSchema(
        fields=[
            coreapi.Field(
                "username",
                required=True,
                location="form",
                schema=coreschema.String(
                    description="username required to create or retrieve token"
                ),
            ),
            coreapi.Field(
                "password",
                required=True,
                location="form",
                schema=coreschema.String(
                    description="password required to create or retrieve token"
                ),
            ),
            coreapi.Field(
                "renew",
                required=False,
                location="query",
                schema=coreschema.Boolean(
                    description=
                    "set to true to retrieve a new token invalidating old one if it exists."
                ),
                description="password required to create or retrieve token",
            ),
        ],
        description="Gets or Creates a Token for the given user.",
    )

    # def get(self, request):

    # if request.user.is_authenticated:

    # token =

    def retrieve(self, request, **kwargs):

        username = request.data.get("username", None)
        password = request.data.get("password", None)
        renew = request.data.get("renew", False)
        """Returns token for logged in user."""

        if request.user.is_authenticated:
            if renew:
                try:
                    token = Token.objects.get(user=request.user)
                    token.delete()
                except ObjectDoesNotExist as e:
                    # Nothing to renew
                    pass

            token, created = Token.objects.get_or_create(user=request.user)
            return Response(data={"token": token.key},
                            status=status.HTTP_200_OK)

        else:
            return Response(data={"error": "Not Authorized"},
                            status=status.HTTP_401_UNAUTHORIZED)
Example #23
0
    def get_serializer_fields(self, path, method):
        fields = []
        if method == 'POST':
            fields = [
                coreapi.Field(name="group_id",
                              required=True,
                              location="form",
                              schema=coreschema.Integer(
                                  title="group", description="Id группы"),
                              description='group_id'),
                coreapi.Field(
                    name="title",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="title",
                                             description="Название покупки"),
                    description='Название покупки',
                ),
                coreapi.Field(
                    name="price",
                    required=True,
                    location="form",
                    schema=coreschema.Number(title="price",
                                             description="Цена"),
                    description='Цена',
                ),
                coreapi.Field(
                    name="comment",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="comment",
                                             description="Комментарий"),
                    description='Комментарий',
                ),
                coreapi.Field(
                    name="user",
                    required=True,
                    location="form",
                    schema=coreschema.Array(title="user",
                                            description="Юзеры в покупке"),
                    description='Юзеры в покупке',
                ),
            ]
        if method == 'PUT':
            fields = [
                coreapi.Field(name="done",
                              required=True,
                              location="form",
                              schema=coreschema.Boolean(
                                  title="done", description="Завершено"),
                              description='Завершено'),
                coreapi.Field(
                    name="title",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="title",
                                             description="Название покупки"),
                    description='Название покупки',
                ),
                coreapi.Field(
                    name="price",
                    required=True,
                    location="form",
                    schema=coreschema.Number(title="price",
                                             description="Цена"),
                    description='Цена',
                ),
                coreapi.Field(
                    name="comment",
                    required=True,
                    location="form",
                    schema=coreschema.String(title="comment",
                                             description="Комментарий"),
                    description='Комментарий',
                ),
                coreapi.Field(
                    name="user",
                    required=True,
                    location="form",
                    schema=coreschema.Array(title="user",
                                            description="Юзеры в покупке"),
                    description='Юзеры в покупке',
                ),
            ]

        return fields
Example #24
0
 coreschema.Anything(),
 "definitions":
 coreschema.Ref("SchemaMap"),
 # Type
 "type":
 coreschema.Ref("SimpleTypes")
 | coreschema.Array(items=coreschema.Ref("SimpleTypes"),
                    min_items=1,
                    unique_items=True),
 # Number validators
 "minimum":
 coreschema.Number(),
 "maximum":
 coreschema.Number(),
 "exclusiveMinimum":
 coreschema.Boolean(default=False),
 "exclusiveMaximum":
 coreschema.Boolean(default=False),
 "multipleOf":
 coreschema.Number(minimum=0, exclusive_minimum=True),
 # String validators
 "minLength":
 coreschema.Integer(minimum=0, default=0),
 "maxLength":
 coreschema.Integer(minimum=0),
 "pattern":
 coreschema.String(format="regex"),
 "format":
 coreschema.String(),
 # Array validators
 "items":
Example #25
0
class BookManageViewSet(viewsets.ViewSet):
    '''图书管理相关服务 需认证 错误码23xxx'''
    authentication_classes = [JWTAuthentication]
    permission_classes = [permissions.IsAuthenticated]

    schema = CustomSchema(
        manual_fields={
            'POST:/book/publish/': [
                coreapi.Field("description",
                              required=True,
                              location="form",
                              description='用户描述,不可为空,最多 300 字'),
                coreapi.Field("price",
                              required=True,
                              location="form",
                              description='出售价格'),
                coreapi.Field("images",
                              required=True,
                              location="form",
                              description='图书图片'),
                coreapi.Field("knife",
                              required=True,
                              location="form",
                              description='是否可小刀',
                              schema=coreschema.Boolean()),
                coreapi.Field("phase",
                              required=True,
                              location="form",
                              description='品相,L10/L9/L7/L5'),
                coreapi.Field("status",
                              required=True,
                              location="form",
                              description='发布状态,normal:正常;draft:草稿'),
                coreapi.Field("bookISBN",
                              required=True,
                              location="form",
                              description='图书 ISBN 码'),
                coreapi.Field("categoryL1",
                              required=True,
                              location="form",
                              description='图书类别,大类'),
                coreapi.Field("categoryL2",
                              required=True,
                              location="form",
                              description='图书类别,小类'),
            ],
            'POST:/book/status/': [
                coreapi.Field("bid",
                              required=True,
                              location="form",
                              description='图书发布信息唯一标识 BID'),
                coreapi.Field(
                    "status",
                    required=True,
                    location="form",
                    description='改变状态:normal-重新发布、delete-删除、removed-下架、sold-出售。'
                ),
            ],
            'POST:/book/collect/': [
                coreapi.Field("bid",
                              required=True,
                              location="form",
                              description='图书发布信息唯一标识 BID'),
                coreapi.Field("status",
                              required=True,
                              location="form",
                              description='收藏:normal;取消收藏:delete'),
            ],
            'GET:/book/collection/': [],
            'POST:/book/comment/': [
                coreapi.Field("bid",
                              required=True,
                              location="form",
                              description='图书发布信息唯一标识 BID'),
                coreapi.Field("toUser",
                              required=False,
                              location="form",
                              description='回复的用户的 UID'),
                coreapi.Field("comment",
                              required=True,
                              location="form",
                              description='评论内容'),
            ],
            'POST:/book/comment/delete/': [
                coreapi.Field("cid",
                              required=True,
                              location="form",
                              description='评论信息唯一标识'),
            ],
        })

    @action(methods=['post'], detail=False, url_path='publish')
    def publish(self, request, format=None):
        '''发布图书信息'''
        user = request.user
        # 获取及检查参数
        params = [
            'description', 'price', 'images', 'knife', 'phase', 'status',
            'bookISBN', 'categoryL1', 'categoryL2'
        ]
        description, price, images, knife, phase, status, bookISBN, categoryL1, categoryL2 = get_dict_values(
            request.data, params)
        if check_none(description, price, images, knife, phase, status,
                      bookISBN, categoryL1, categoryL2):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 发布状态,normal:正常;draft:草稿
        if status not in ['normal', 'draft']:
            return Response(res_format(None, code=23003, msg='发布失败,发布状态错误'))
        # 检查发布信息中是否有 bookInfo,如果有就是用户完善的信息
        # 没有就通过 ISBN 查询图书信息
        user_isbn_info = request.data.get('bookInfo', None)
        if user_isbn_info is None:
            dataSource = 'douban'
            try:
                record_isbn = ISBNInfo.objects.get(isbn=bookISBN)
                isbn_info = ISBNInfoSerializers(record_isbn).data
            except ISBNInfo.DoesNotExist:
                return Response(
                    res_format(None, code=23001, msg='发布失败,请重新扫描 ISBN 码获取信息'))
        else:
            dataSource = 'user'
            # 将空字符串设置为 None
            for key in user_isbn_info:
                if user_isbn_info[key] == '':
                    user_isbn_info[key] = None
            # 序列化数据,并校验
            isbn_info_serializer = ISBNInfoSerializers(data=user_isbn_info)
            if not isbn_info_serializer.is_valid():
                return Response(
                    res_format(None, code=23011, msg='完善的图书信息格式错误,请修改'))
            else:
                isbn_info = isbn_info_serializer.data
        # 发布信息模块
        publish_params = {
            'uid':
            user,
            'bookTitle':
            (isbn_info['title'] if isbn_info['title'] is not None else '') +
            (' : ' + isbn_info['subtitle']
             if isbn_info['subtitle'] is not None else ''),
            'bookAuthor':
            isbn_info['author'],
            'bookCover':
            isbn_info['cover'],
            'bookPress':
            isbn_info['press'],
            'bookPublishYear':
            isbn_info['publishYear'],
            'bookPrice':
            isbn_info['price'],
            'bookIntroduction':
            isbn_info['introduction'][:512]
            if isbn_info['introduction'] else None,
            'bookRatingValue':
            isbn_info['ratingValue'],
            'dataSource':
            dataSource
        }
        # 如果该图书没有标题,就设为 None
        if publish_params['bookTitle'] == '':
            publish_params['bookTitle'] = None
        publish_params.update(request.data)
        record_publish = PublishBookSerializers(data=publish_params)
        if not record_publish.is_valid():
            errors = record_publish.errors
            return Response(res_format(errors, code=23002, msg='发布信息格式错误'))
        record_publish.save()
        return Response(
            res_format({'bid': record_publish.data['bid']}, msg='发布成功'))

    @action(methods=['post'], detail=False, url_path='status')
    def status(self, request, format=None):
        '''更新图书状态,normal-重新发布、delete-删除、removed-下架'''
        user = request.user
        # 获取及检查参数
        params = ['bid', 'status']
        bid, status = get_dict_values(request.data, params)
        if check_none(bid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查是否是更新合法的图书状态
        status_dict = {
            'normal': '重新发布',
            'delete': '删除',
            'sold': '出售',
            'removed': '下架'
        }
        if status not in status_dict:
            return Response(
                res_format(None, code=23006, msg='未知的切换状态 ' + status))
        try:
            # 查询当前图书状态
            record = PublishBook.objects.get(bid=bid)
            # 判断这本书是不是该用户发布的
            if record.uid != user:
                return Response(res_format(None, code=23005,
                                           msg='无法操作别人发布的图书'))
            # 检查图书发布信息的系统状态
            if record.systemStatus != 'normal':
                return Response(
                    res_format(None, code=23007, msg='该图书的系统状态异常,无法操作'))
            # 出售后的图书只可以进行删除
            if record.status == 'sold' and status != 'delete':
                return Response(
                    res_format(None, code=23019, msg='不可对已出售的图书进行其他操作'))
            # 检查无误,可以切换状态了
            record.status = status
            record.save()
            return Response(res_format(None, msg=status_dict[status] + '图书成功'))
        except PublishBook.DoesNotExist:
            return Response(res_format(None, code=23004, msg='无相关图书信息'))

    @action(methods=['post'], detail=False, url_path='collect')
    def collect(self, request, format=None):
        '''收藏/取消收藏图书'''
        user = request.user
        # 获取及检查参数
        params = ['bid', 'status']
        bid, status = get_dict_values(request.data, params)
        if check_none(bid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查是否是更新合法的图书状态
        status_dict = {'normal': '收藏', 'delete': '取消收藏'}
        if status not in status_dict:
            return Response(
                res_format(None, code=23008, msg='收藏状态错误 ' + status))
        # 查询图书信息
        try:
            record_book = PublishBook.objects.get(bid=bid)
            if record_book.uid == user:
                return Response(res_format(None, code=23010,
                                           msg='无法收藏自己发布的图书'))
        except PublishBook.DoesNotExist:
            return Response(res_format(None, code=23009, msg='无相关图书信息'))
        # 检查图书收藏状态
        try:
            record = CollectBook.objects.get(uid=str(user), bid=bid)
            record.status = status
            record.save()
        except CollectBook.DoesNotExist:
            record_new = CollectBook(uid=user, bid=record_book, status=status)
            record_new.save()
        return Response(res_format(None, msg=status_dict[status] + '成功'))

    @action(detail=False, url_path='collection')
    def collection(self, request, format=None):
        '''获取我的收藏信息'''
        user = request.user
        record = CollectBook.objects.filter(uid=str(user)).filter(
            status='normal').filter(bid__status='normal').filter(
                bid__systemStatus='normal').order_by('-updateTime')
        result = CollectBookOverviewSerializers(record, many=True).data
        return Response(res_format(result))

    @action(methods=['post'], detail=False, url_path='comment')
    def comment(self, request, format=None):
        '''对图书信息发表评论'''
        user = request.user
        # 评论频率限制
        # 每分钟 3 条,每小时 30 条,每天 200 条
        now = datetime.datetime.now()
        limit_minute = now - datetime.timedelta(minutes=1)
        limit_hour = now - datetime.timedelta(hours=1)
        limit_day = now - datetime.timedelta(hours=24)
        record_limit = CommentBook.objects.filter(commentUserInfo=user)
        if len(record_limit.filter(createTime__gt=limit_minute)) >= 3:
            return Response(
                res_format('Minute Limit', code=23016, msg='留言失败,请过一会儿再来'))
        if len(record_limit.filter(createTime__gt=limit_hour)) >= 30:
            return Response(
                res_format('Hour Limit', code=23017, msg='留言失败,请过一会儿再来'))
        if len(record_limit.filter(createTime__gt=limit_day)) >= 100:
            return Response(
                res_format('Day Limit', code=23018, msg='留言失败,请过一会儿再来'))
        # 获取及检查参数
        params = ['bid', 'comment']
        bid, comment = get_dict_values(request.data, params)
        if check_none(bid, status):
            raise ParseError('缺少参数:' + ', '.join(params))
        # 检查评论信息
        if len(comment) == 0:
            return Response(res_format(None, code=23012, msg='评论不能为空'))
        # 获取图书信息
        try:
            record_book = PublishBook.objects.get(bid=bid)
        except PublishBook.DoesNotExist:
            return Response(res_format(None, code=23013, msg='评论失败,无法获取图书信息'))
        # 获取回复别人评论的别人的用户信息
        to_user = request.data.get('toUser', None)
        if to_user is not None:
            try:
                record_to_user = AccountBasic.objects.get(uid=to_user)
            except AccountBasic.DoesNotExist:
                record_to_user = None
        else:
            record_to_user = None
        # 保存评论
        record = CommentBook(commentUserInfo=user,
                             toUserInfo=record_to_user,
                             bookInfo=record_book,
                             comment=comment)
        record.save()
        result = CommentBookInfoSerializers(record).data
        return Response(res_format(result))

    @action(methods=['post'], detail=False, url_path='comment/delete')
    def comment_delete(self, request, format=None):
        '''删除图书评论'''
        user = request.user
        cid = request.data.get('cid', None)
        if cid is None:
            return Response(res_format(None, code=23014, msg='删除评论失败'))
        # 查询评论
        try:
            record = CommentBook.objects.get(cid=cid, commentUserInfo=user)
        except CommentBook.DoesNotExist:
            return Response(res_format(None, code=23015, msg='删除评论失败,未找到相关评论'))
        # 删除
        record.status = 'delete'
        record.save()
        return Response(res_format(None))
Example #26
0
class UserView(ModelViewSetNoDelete):
    queryset = User.objects.all()
    permission_classes = [AllowAny]
    filterset_class = UserFilters

    def get_serializer_class(self):
        if self.request.method == "GET":
            return UserSerializer
        else:
            return UserSerializerPost

    def get_permissions(self):
        """
       Instantiates and returns the list of permissions that this view requires.
       """
        if self.action == "create" or self.action == "reset_password":
            permission_classes = [AllowAny]
        else:
            permission_classes = [IsAuthenticated]
        return [permission() for permission in permission_classes]

    @action(
        methods=["get"],
        detail=False,
        url_path="current",
        schema=ManualSchema(
            fields=[],
            description="Get the data from the currently logged user"),
    )
    def get_current_user_data(self, request: Request):
        """
        Get the data from the currently logged user
        """
        return Response(data=UserSerializerCurrentUser(request.user).data)

    @action(
        methods=["get"],
        detail=True,
        url_path="getaddresses",
        schema=ManualSchema(
            description="Gets all addresses from a user",
            fields=[
                coreapi.Field(
                    "id",
                    required=True,
                    location="path",
                    schema=coreschema.Integer(),
                    description="User ID",
                ),
                coreapi.Field(
                    "active",
                    required=False,
                    location="query",
                    schema=coreschema.Boolean(),
                    description="Active addresses",
                ),
            ],
        ),
    )
    def get_addresses(self, request: Request, pk: int):
        user = self.get_object()
        active = request.query_params.get("active", None)
        addresses_queryset = user.addresses.all().select_related(
            "neighborhood", "neighborhood__city", "neighborhood__city__state")

        if active is not None:
            active = str_to_boolean(active)
            addresses_queryset = addresses_queryset.filter(active=active)

        return Response(
            data=UserAddressSerializer(addresses_queryset, many=True).data)

    @action(
        methods=["patch"],
        detail=True,
        url_path="changeaddressstatus",
        schema=ManualSchema(
            description="Updates the status of an address from the given user",
            fields=[
                coreapi.Field(
                    "id",
                    required=True,
                    location="path",
                    schema=coreschema.Integer(),
                    description="User ID",
                ),
                coreapi.Field(
                    "address_id",
                    required=False,
                    location="form",
                    schema=coreschema.Integer(),
                    description="Adress' ID",
                ),
                coreapi.Field(
                    "active",
                    required=False,
                    location="form",
                    schema=coreschema.Boolean(),
                    description="New value for the address' active attribute",
                ),
            ],
        ),
    )
    def change_address_status(self, request: Request, pk: int):
        user = self.get_object()
        address_id = get_param_or_400(request.data, "address_id", int)
        active = get_param_or_400(request.data, "active", bool)

        address = user.addresses.get(id=address_id)
        address.active = active
        address.save()

        return Response()

    @action(
        methods=["post"],
        detail=True,
        url_path="addaddress",
        schema=ManualSchema(
            description="Add a new addresses to the given user",
            fields=[
                coreapi.Field(
                    "id",
                    required=True,
                    location="path",
                    schema=coreschema.Integer(),
                    description="User ID",
                ),
                coreapi.Field(
                    "neighborhood_id",
                    required=False,
                    location="form",
                    schema=coreschema.Integer(),
                    description="Neighborhood' ID",
                ),
                coreapi.Field(
                    "address",
                    required=False,
                    location="form",
                    schema=coreschema.String(max_length=150),
                    description="State' ID",
                ),
                coreapi.Field(
                    "zip",
                    required=False,
                    location="form",
                    schema=coreschema.String(max_length=8),
                    description="ZIP code",
                ),
            ],
        ),
    )
    @transaction.atomic
    def add_address(self, request: Request, pk: int):
        user = self.get_object()
        neighborhood_id = get_param_or_400(request.data, "neighborhood_id",
                                           int)
        address = get_param_or_400(request.data, "address", str)
        zip_code = get_param_or_400(request.data, "zip", str)

        addresses_queryset = UserAddress.objects.all().select_related(
            "neighborhood", "neighborhood__city", "neighborhood__city__state")
        new_address = addresses_queryset.create(
            neighborhood_id=neighborhood_id,
            address=address,
            zip_code=zip_code)
        user.addresses.add(new_address)
        user.save()

        return Response(data=UserAddressSerializer(new_address).data)

    @action(
        methods=["patch"],
        detail=True,
        url_path="updateaddress",
        schema=ManualSchema(
            description="Updates a user address",
            fields=[
                coreapi.Field(
                    "id",
                    required=True,
                    location="path",
                    schema=coreschema.Integer(),
                    description="User ID",
                ),
                coreapi.Field(
                    "user_address_id",
                    required=False,
                    location="form",
                    schema=coreschema.Integer(),
                    description="User address ID",
                ),
                coreapi.Field(
                    "neighborhood_id",
                    required=False,
                    location="form",
                    schema=coreschema.Integer(),
                    description="Neighborhood' ID",
                ),
                coreapi.Field(
                    "address",
                    required=False,
                    location="form",
                    schema=coreschema.String(max_length=150),
                    description="State' ID",
                ),
                coreapi.Field(
                    "zip",
                    required=False,
                    location="form",
                    schema=coreschema.String(max_length=8),
                    description="ZIP code",
                ),
            ],
        ),
    )
    @transaction.atomic
    def update_address(self, request: Request, pk: int):
        user = self.get_object()
        address_id = get_param_or_400(request.data, "user_address_id", int)
        neighborhood_id = get_param_or_400(request.data, "neighborhood_id",
                                           int)
        address = get_param_or_400(request.data, "address", str)
        zip_code = get_param_or_400(request.data, "zip", str)

        user_address = user.addresses.get(id=address_id)
        user_address.neighborhood_id = neighborhood_id
        user_address.zip_code = zip_code
        user_address.address = address
        user_address.save()

        return Response()

    @action(
        methods=["post"],
        detail=False,
        url_path="resetpassword",
        schema=ManualSchema(
            description="User e-mail",
            fields=[
                coreapi.Field(
                    "email",
                    required=True,
                    location="form",
                    schema=coreschema.String(),
                    description="User e-mail",
                ),
            ],
        ),
    )
    @transaction.atomic
    def reset_password(self, request: Request):
        user = User.objects.all()
        email = get_param_or_400(request.data, "email", str)

        try:
            user_reset_pass = user.get(email=email)
            if user_reset_pass:
                new_pass = generate_new_pass(user_reset_pass)
                user_reset_pass.set_password(new_pass)
                user_reset_pass.save()

                email_render_data = {
                    'user': user_reset_pass.first_name,
                    'new_password': new_pass
                }
                user_reset_pass.send_email(
                    'emails/user_reset_password.html', email_render_data,
                    'Conta Comigo APP - Recuperação de Senha')
                return Response(
                    data=UserNewPasswordSerializer(user_reset_pass).data)
                # return Response(data={"password": new_pass})

        except Exception as ex:
            raise ValueError(f"There is no register for {email}: {ex}")

        return Response()