Реализация паттерна MVC в Python

Сложности в понимании паттерна MVC и его практической реализации на Python. Пытаюсь ради интереса создать консольную ATM, где пользователь условно создает себе счета и карты, привязанные к ним, а заодно и закрепить практику MVC паттерна.

controllers.py

from abc import ABC, abstractmethod, abstractproperty, abstractclassmethod, abstractstaticmethod

from models import ATMModel
from views import ABC_ATMView


class ABC_ATMController(ABC):
    pass


class ATMController(ABC_ATMController):
    model: ATMModel
    view: ABC_ATMView

    def __init__(self, model: ATMModel, view: ABC_ATMView):
        self.model = model
        self.view = view

    def entry_point(self):
        menu = self.view.show_entry_point()
        if menu.chosen == "1":
            form = self.view.show_sign_in_form()
        elif menu.chosen == "2":
            form = self.view.show_sign_up_form()

views.py

from abc import ABC, abstractmethod, abstractproperty, abstractclassmethod, abstractstaticmethod
from os import system, name

from mixin import SignInDTO, SignUpDTO, MenuChoice


class ABC_ATMView(ABC):
    @abstractmethod
    def show_entry_point(self) -> MenuChoice: ...

    @abstractmethod
    def show_sign_in_form(self) -> SignInDTO:  ...

    @abstractmethod
    def show_sign_up_form(self) -> SignUpDTO: ...


class ATMViewTerminal(ABC_ATMView):
    @staticmethod
    def get_input(input_title: str = None, allowed_values: list = None):
        value = input(f"{input_title + ': ' if input_title else '>>> '}")
        if allowed_values:
            while value not in allowed_values:
                value = input(f"Неверное значение: ")
        return value

    @staticmethod
    def clear():
        if name == 'nt':
            _ = system('cls')
        else:
            _ = system('clear')

    @staticmethod
    def draw_header(custom_title: str = None):
        print(f"{'='*15} {'ATM Bank' if not custom_title else custom_title} {'='*15}")

    @staticmethod
    def draw_option(n: int, option_title: str):
        return print(f"{n} > {option_title.capitalize()}")

    def show_entry_point(self):
        self.draw_header()
        self.draw_option(1, option_title="У меня есть аккаунт")
        self.draw_option(2, option_title="У меня нет аккаунта")
        choice = self.get_input(allowed_values=["1", "2"])

        self.clear()
        return MenuChoice(choices=["1", "2"], chosen=choice)

    def show_sign_in_form(self) -> SignInDTO:
        self.draw_header("Вход")
        login = self.get_input("Логин")
        password = self.get_input("Пароль")

        self.clear()
        return SignInDTO(login, hash(password))

    def show_sign_up_form(self) -> SignUpDTO:
        self.draw_header("Регистрация")
        login = self.get_input("Логин")

        password, password_c = "1", "2"
        while password != password_c:
            password = self.get_input("Пароль")
            password_c = self.get_input("Подтверждение пароля")

        self.clear()
        return SignUpDTO(login, hash(password), hash(password_c))

Проблема заключается в том, что я не могу понять кто, а точнее какой объект должен переключать view в зависимости от input'a ? Сейчас это делает ATMController в методе entry_point(), где в зависимости от input'a переключает формы, то есть форму входа и форму регистрации. Однако это делает ATMController зависимым от конкретной реализации View, а именно TerminalView, чего хочется избежать, но не знаю как...


Ответы (0 шт):