0

I use flask-marshmallow and mongoengine.

Also flask-restplus for my API server.

Here is my api.py

class BoardSchema(ma.Schema):
    class Meta:
        fields = ('no', 'title', 'body', 'tags', 'created_at', 'views')

board_schema = BoardSchema()
boards_schema = BoardSchema(many=True)


class ArticleList(Resource):
    def get(self):
        articles = Board.objects.all()
        return boards_schema.jsonify(articles)

model.py

from datetime import datetime
from mongoengine import *
from config import DB_NAME


connect(DB_NAME)


class Board(Document):
    d = datetime.now()
    date = "{}-{}-{}".format(d.year, d.month, d.day)

    no = SequenceField()
    title = StringField(required=True)
    body = StringField(required=True)
    tags = ListField(StringField())
    likes = ListField(StringField())
    views = ListField(StringField())
    password = StringField(required=True)
    created_at = DateTimeField(default=date)
    updated_at = DateTimeField(default=date)

When I access to /article, it's result like this ->

{
  "body": "123", 
  "created_at": "2018-08-20T00:00:00+00:00", 
  "no": 1, 
  "tags": [
    "MySQL", 
    "C"
  ], 
  "title": "\ud14c\uc2a4\ud2b8", 
  "views": [
    "127.0.0.1"
  ]
}

in "views", ip will be added who read article.

But I want to count of all the list of views and include it to my result.

The result I wanted is here.

{
  "body": "123", 
  "created_at": "2018-08-20T00:00:00+00:00", 
  "no": 1, 
  "tags": [
    "MySQL", 
    "C"
  ], 
  "title": "\ud14c\uc2a4\ud2b8", 
  "views": 20
}

I'm new at flask-marshmallow so I'm so confused how can I solve this issue.

Thanks.

Hide
  • 3,199
  • 7
  • 41
  • 83
  • Firstly shall views by StringField type? It will be easier if it would be integer. – bc291 Aug 20 '18 at 12:26
  • I don't see you logic/endpoint for viewing single article, but you can just increment views like so: `single_article = Board.objects.first()` `single_article.views = single_article.views + 1` – bc291 Aug 20 '18 at 12:26
  • It is perhaps IntField, so declare `views = IntField() ` – bc291 Aug 20 '18 at 12:28
  • @needtobe `views` must be `StringField` inside of `ListField`. Because every viewer's ip address will be stored at the views fields. So, one ip can increase one view count. – Hide Aug 20 '18 at 12:40
  • @needtobe So, I want to count all of views and represent it to my result. – Hide Aug 20 '18 at 12:42
  • Oh I see. Then you can alter views field right before dumping it using schema customization. – bc291 Aug 20 '18 at 12:45

3 Answers3

0

Maybe you can try like this:

class BoardSchemaCustom(ma.ModelSchema):
    class Meta:
        model = Board

    views = ma.fields.method(deserialize="_custom_serializer")

    def _custom_serializer(self, obj):
        return len(obj.views)

Create instance of your custom schema:

custom_board_schema = BoardSchemaCustom()

and dump it:

dump, errors = custom_board_schema.schema.dump(Board.query.first())
>>> dump
bc291
  • 1,071
  • 11
  • 23
  • 1
    Maybe flask-marshmallow doesn't have `ModelSchema` attribute. I run after write your code, it throw `AttributeError: 'Marshmallow' object has no attribute 'ModelSchema'` errors at `class BoardSchemaCuston(ma.ModelSchema):` – Hide Aug 21 '18 at 06:25
  • Flask-marshmallow has ModelSchema attribute, look here (https://flask-marshmallow.readthedocs.io/en/latest/) – bc291 Aug 21 '18 at 06:35
  • Try like this: `from flask_marshmallow import Marshmallow` `ma = Marshmallow(app)` and then `ma.ModelSchema` – bc291 Aug 21 '18 at 06:37
  • My code already same with your code. But it throw errors. In the docs, that example use sqlalchemy. But my db is mongodb. Maybe it occured errors? – Hide Aug 21 '18 at 06:43
  • No, I don't thing so, for mongo: https://github.com/touilleMan/marshmallow-mongoengine/blob/master/docs/tutorial.rst – bc291 Aug 21 '18 at 06:44
  • In that example, Not `flask-marshmallow` but `marshmallow-mongoengine`. To implement your code to works, I have to install `marshmallow-mongoengine` instead of `flask-marshmallow`. – Hide Aug 21 '18 at 08:04
  • That was just for presentation purposes, `flask_marshmallow` has `ma.ModelSchema` field too, but if it's not working you may try to use it in `marshmallow-mongoengine` manner and pip install that one. – bc291 Aug 21 '18 at 08:26
0

i've got the same problem. and my code works after installing marshmallow-sqlalchemy

pip install marshmallow-sqlalchemy

see from offical documentation https://flask-marshmallow.readthedocs.io/en/latest/

0

Below snippet would also work:

class BoardSchemaCustom(ma.ModelSchema):
    class Meta:
        model = Board

    views = ma.fields.Function(lambda obj: len(obj.views))