Implementing CRUD in My Voting System API

Overview

The voting system API I implemented follows the CRUD (Create, Read, Update, Delete) paradigm, allowing users to interact with votes dynamically. This ensures users can upvote or downvote posts, update their votes, and remove votes when necessary. Below, I break down how each CRUD operation is handled within the API.


1. Create (POST) - Adding a Vote

The POST method allows users to upvote or downvote a post. If a vote already exists, it updates the vote instead of creating a duplicate.

Implementation:

@token_required()
def post(self):

    current_user = g.current_user
    data = request.get_json()

    if not data:
        return {'message': 'No input data provided'}, 400
    if 'post_id' not in data:
        return {'message': 'Post ID is required'}, 400
    if 'vote_type' not in data or data['vote_type'] not in ['upvote', 'downvote']:
        return {'message': 'Vote type must be "upvote" or "downvote"'}, 400

    existing_vote = Vote.query.filter_by(_post_id=data['post_id'], _user_id=current_user.id).first()
    if existing_vote:
        existing_vote._vote_type = data['vote_type']
        existing_vote.create()  # Commits update
        return jsonify(existing_vote.read())

    vote = Vote(data['vote_type'], current_user.id, data['post_id'])
    vote.create()
    return jsonify(vote.read())

Explanation:

  • The method retrieves the post_id and vote_type from the request body.
  • If a vote already exists, it updates the vote type.
  • If no vote exists, it creates a new one and commits it to the database.

2. Read (GET) - Retrieving Votes

The GET method allows users to retrieve all votes for a specific post, including the number of upvotes and downvotes.

Implementation:

class _POST_VOTES(Resource):
    def get(self):

        post_id = request.args.get('post_id')
        
        if not post_id:
            return {'message': 'Post ID is required as a query parameter'}, 400

        votes = Vote.query.filter_by(_post_id=post_id).all()
        upvotes = [vote.read() for vote in votes if vote._vote_type == 'upvote']
        downvotes = [vote.read() for vote in votes if vote._vote_type == 'downvote']

        result = {
            "post_id": post_id,
            "upvote_count": len(upvotes),
            "downvote_count": len(downvotes),
            "total_votes": len(votes),
            "upvotes": upvotes,
            "downvotes": downvotes
        }
        return jsonify(result)

Explanation:

  • The method extracts the post_id from the query parameters.
  • It fetches all votes associated with that post from the database.
  • It categorizes the votes into upvotes and downvotes and returns a JSON response containing vote counts.

3. Update (PUT) - Modifying a Vote

The PUT method allows users to update their existing votes (e.g., switching from an upvote to a downvote).

Implementation:

@token_required()
def put(self):

    current_user = g.current_user
    data = request.get_json()

    if not data:
        return {'message': 'No input data provided'}, 400
    if 'post_id' not in data:
        return {'message': 'Post ID is required'}, 400
    if 'vote_type' not in data or data['vote_type'] not in ['upvote', 'downvote']:
        return {'message': 'Vote type must be "upvote" or "downvote"'}, 400

    vote = Vote.query.filter_by(_post_id=data['post_id'], _user_id=current_user.id).first()
    if not vote:
        return {'message': 'Vote not found or not authorized to update this vote'}, 404

    vote.update(data['vote_type'])
    return jsonify(vote.read())

Explanation:

  • The method ensures that only authenticated users can modify their votes.
  • It checks whether the post_id and vote_type are provided in the request.
  • If a vote exists, it updates the vote type and commits the changes.

4. Delete (DELETE) - Removing a Vote

The DELETE method allows users to remove their vote from a post.

Implementation:

@token_required()
def delete(self):
    current_user = g.current_user
    data = request.get_json()

    if not data or 'post_id' not in data:
        return {'message': 'Post ID is required'}, 400

    vote = Vote.query.filter_by(_post_id=data['post_id'], _user_id=current_user.id).first()
    if vote is None:
        return {'message': 'Vote not found'}, 404

    vote.delete()
    return jsonify({"message": "Vote removed"})

Explanation:

  • The method verifies that the request contains a post_id.
  • It checks if the vote exists for the current user.
  • If found, the vote is removed from the database.

Conclusion

By implementing CRUD operations in this voting system, users can interact with votes efficiently while maintaining data integrity. This structured API ensures:

  • Create: Users can upvote/downvote posts.
  • Read: Vote counts and details can be retrieved.
  • Update: Users can change their vote type.
  • Delete: Users can remove their votes.