2

I am using flask with flask-restplus and sqlalchemy.

My rest API function looks like the following:

@ns.route('/user')
class UsersCollection(Resource):

    @jwt_optional
    @permissions.user_has('admin_view')
    @ns.marshal_list_with(user_details)
    def get(self):
        """
        Returns list of users.
        """

        users = User.query.all()

        return users

I am willing to add additional data to users collection which should be returned by the API. Some of this data may be stored in other DB tables, while other is stored in memory.

What I am usually doing is something like this:

@ns.route('/user')
class UsersCollection(Resource):

    @jwt_optional
    @permissions.user_has('admin_view')
    @ns.marshal_list_with(user_details)
    def get(self):
        """
        Returns list of users.
        """

        users = User.query.all()

        # Add additional data
        for user in users:
          user.activity = UserActivity.query ...  # from DB 
          user.online_status = "Active" # Taken somewhere from memory

        return users

Obviously I don't like this approach of adding data to the User object on the fly. But what is the best design pattern to achieve it?

4
  • Well the only thing that comes to my mind would be having additional class that would contain user, his activities and his status. Commented Jan 14, 2018 at 10:48
  • I was actually reading about using marshmallow and defining another class, but don't have too much experience with it and I am not sure this is the right choice.... Commented Jan 14, 2018 at 10:51
  • Sorry for late answer, was busy, I don't have much experience working in Python but if I had similar problem in kotlin or java I would definitely make another class. Python has ability to add functionality to instances which you are using right now, I'm not sure if that is considered best practice, for me its a bit odd, but if your project is small keep it this way, its simple and understandable, if you have to add more functionalities then make class which wraps all needed data together. Commented Jan 15, 2018 at 10:43
  • Another option would be inheritance but I prefer composition because it isn't tight coupled, you can easily add or remove things without changing your code much. Commented Jan 15, 2018 at 10:44

1 Answer 1

1

About the design pattern, I recommend a DAO and Service approach, here's a good and short article about it: https://levelup.gitconnected.com/structuring-a-large-production-flask-application-7a0066a65447

About the models User/Activity relationship, I presume you have a mapped Activity model. If this is a One to One relationship, in the User model create a activityId field for the FK field and a activity relation where your ORM (I'll assume SQLAlchemy) will retrieve when user.activity is accessed.

class Activity(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    descrption = db.Column(db.String(255))

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    activity = db.relationship(Activity)
    activityId = db.Column(db.Integer, db.ForeignKey(Activity.id))

If you have a Many to Many relationship you'll have to create a third class called ActivityUser to map the relation

class ActivityUser(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    activity = db.relationship(Activity, lazy=True)
    user = db.relationship(User, lazy=True)
    activityId = db.Column(db.ForeignKey(Activity))
    userId = db.Column(db.ForeignKey(User))

and you can retrieve the user activities like this (again assuming you use SQLAlchemy):

ActivityUser.query.filter(ActivityUser.userId == user.id).all()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.