Flask MVC with Circular Dependency (dependency injection?)

Question:

I’m trying to create models to form the mvc in flask but it’s marked as a circular dependency (db in init), I even removed the models to test and put them in for the controllers to use the bank, but the result was the same, what could I do to create the model of the user in user and use the db defined in app > __init__.py without circular dependency.

Github: https://github.com/HenriqueBuzin/resaber

enter image description here

__init__.py

import os
from flask import Flask
from flask_pymongo import PyMongo
from app.routes.site import site
from app.routes.admin import admin

app = Flask(__name__)

app.config["MONGO_URI"] = (f'mongodb://'
                           f'{os.environ["MONGO_USERNAME"]}'
                           f':{os.environ["MONGO_PASSWORD"]}'
                           f'@{os.environ["MONGO_HOSTNAME"]}:27017'
                           f'/{os.environ["MONGO_DATABASE"]}?authSource=admin')
mongodb_client = PyMongo(app)
db = mongodb_client.db

app.secret_key = os.urandom(32).hex()

app.template_folder = 'views'

app.register_blueprint(site)

app.register_blueprint(admin)

app.static_folder = 'static'

app > controllers > AdminController.py

from flask import render_template, redirect, url_for, request, session
from app import db

def get():

    user_count = db.users.count_documents({})

    if user_count == 0:
        return redirect(url_for('admin/config'))

    return render_template('admin/index.html')

def post():
    email = request.form['email']
    password = request.form['password']

    user = db.users.find_one({'email': email, 'password': password})

    if user:
        session['user_id'] = str(user['_id'])
        return redirect(url_for('admin_page'))

    return render_template('admin/index.html', error='Credenciais inválidas')

app > routes > admin.py

from flask import Blueprint
from app.controllers.admin import (AdminController, AdminPageController,
                                   ConfigAdminController,
                                   RegisterUserAdminController)

admin = Blueprint('admin', __name__, url_prefix='/admin')

@admin.route('/', methods=['GET'])
def admin_index_get():
    return AdminController.get()

@admin.route('/', methods=['POST'])
def admin_index_post():
    return AdminController.post()

@admin.route('/admin_page', methods=['GET'])
def admin_page():
    return AdminPageController.get()

@admin.route('/config', methods=['GET'])
def admin_config():
    return ConfigAdminController.get()

@admin.route('/cadastrar_usuario', methods=['GET'])
def admin_register_user():
    return RegisterUserAdminController.get()
Asked By: Henrique Buzin

||

Answers:

I managed to create an __init__ in the models that has PyMongo()

models > __init__

from flask_pymongo import PyMongo

mongo = PyMongo()

models > user

from app.models import mongo

class User:
    def __init__(self):
        self.mongo = mongo
        self.db = self.mongo.db
        self.collection = self.db.users
    
    def users_count(self):
        user_count = self.collection.count_documents({})
        return user_count

    def insert_user(self, email, password):
        result = self.collection.insert_one({"email": email, "password": password})
        
        if result.inserted_id:
            return str(result.inserted_id)
        else:
            return None
            
    def find_user_by_credentials(self, email, password):
        user = self.collection.find_one({"email": email, "password": password})
        if user:
            user['_id'] = str(user['_id'])
        return user

controller > UserController

from flask import render_template, redirect, url_for, request, session
from app.models.user import User

def get():
    user_instance = User()
    user_count = user_instance.users_count()

    if user_count == 0:
        return redirect(url_for('admin.admin_config_get'))

    return render_template('admin/index.html')

def post():
    email = request.form['email']
    password = request.form['password']

    user_instance = User()

    # Chame o método find_user_by_credentials para verificar se o usuário existe
    existing_user = user_instance.find_user_by_credentials(email, password)

    if existing_user:
        session['user_id'] = existing_user['_id']
        return redirect(url_for('admin.admin_page'))

    return render_template('admin/index.html', error='Credenciais inválidas')

__init__

import os
from flask import Flask
from app.routes.site import site
from app.routes.admin import admin
from app.models import mongo
from app.seeders import Seeder

def create_app():

    app = Flask(__name__)

    app.secret_key = os.urandom(32).hex()

    app.template_folder = 'views'

    app.static_folder = 'static'

    app.config['UPLOAD_FOLDER'] = 'static/pdfs'

    app.register_blueprint(site)

    app.register_blueprint(admin)

    app.config["MONGO_URI"] = (f'mongodb://'
                           f'{os.environ["MONGO_USERNAME"]}'
                           f':{os.environ["MONGO_PASSWORD"]}'
                           f'@{os.environ["MONGO_HOSTNAME"]}:27017'
                           f'/{os.environ["MONGO_DATABASE"]}?authSource=admin')

    mongo.init_app(app)

    seeder = Seeder()
    
    seeder.seed_all_data()
    
    return app

app = create_app()

Now I’m going to work on improving security

Answered By: Henrique Buzin