Home > Blockchain >  Python Unknown Error : Attribute Error with MongoDB database
Python Unknown Error : Attribute Error with MongoDB database

Time:05-24

I have written a programme and I have tried to spilt my programme into multiple python files. But it returns unknown Attribute Error which I did not know how to solve.

There are five parts for my codes. The first part is called Database, which is my own database with some non-real data.

from pymongo import MongoClient
from bson import ObjectId

client = MongoClient(
    sample.com   # I hide my MongoDB account in here for security reason
)

db = client.Peter

user = db['User']
tx = db['Transaction']

db.User.drop()
db.Transaction.drop()

# Create
creative = [{'name': 'Peter', 'balance': 52642},
            {'name': 'Mary', 'balance': 57127},
            {'name': 'John', 'balance': 9000},
            {'name': 'Terry', 'balance': 29000},
            {'name': 'Tom', 'balance': 350000},
            {'name': 'Jason', 'balance': 21000},
            {'name': 'Ken', 'balance': 41400},
            {'name': 'Eva', 'balance': 21600}]

fake_record = [{'name': 'Peter', 'Transaction Type': 'Revenue', 'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Mary', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Mary', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'John', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'John', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'John', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Terry', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Terry', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Terry', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Terry', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Tom', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Tom', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Tom', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Jason', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Jason', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Jason', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Ken', 'Transaction Type': 'Revenue',
                   'Transaction Category': 'Food', 'Transaction amount': 52642},
               {'name': 'Eva', 'Transaction Type': 'Revenue', 'Transaction Category': 'Food', 'Transaction amount': 52642}]

db.User.insert_many(creative)
db.Transaction.insert_many(fake_record)

Part 2, the file below is my main programme.

from database import user, tx
import getpass
import inquirer
import time
from view import View
from store import Store


def main():
    print("Welcome to The Goldman Sachs Group Banking System !!!")
    p = getpass .getpass("Please enter your password : ")
    if (p == 'sunday'):
        view1 = View()
        view1.first_page()


if __name__ == '__main__':
    main()

Part 3, the codes below is my view programme, it contains all the screens (pages) that I have. The User of this programme will go through some of the pages below if they run this programme, and I will let them to select some of the options that I have given to them.

import inquirer
import time
from model import Player
from database import user, tx
from store import Store
import route


class View:
    def __init__(self) -> None:
        self.player = Player()
        self.route = route.Route()
        self.store = Store()

    def first_page(self) -> None:
        # Question Section
        questions = [
            inquirer.List('page_1_result',
                          message="What do you want to do?",
                          choices=['Continue With Existing User',
                                   'Create New Player'],
                          ),
        ]
        answer = inquirer.prompt(questions)

        # Answer Section
        if answer['page_1_result'] == 'Continue With Existing User':
            self.current_user = self.player.enterOldPlayers()
        else:
            self.current_user = self.player.createNewPlayer()
        self.store.setUserName(self.current_user)
        # Routing
        self.route.goTo1()

    def second_page(self):
        # Question Section
        print(f"Hello {str(self.store.getUserName())},\n")
        questions = [
            inquirer.List('Please Choose Action',
                          message=f"What do you want to do?",
                          choices=['View all transaction',
                                   'Add Tansaction',
                                   'Back to previous page'],
                          ),
        ]
        answer1 = inquirer.prompt(questions)

        # Answer Section
        if answer1['Please Choose Action'] == 'Add Tansaction':
            self.route.goTo("Page 3 c1")
        elif answer1['Please Choose Action'] == 'View all transaction':
            self.route.goTo("Page 4")
        else:
            self.route.goTo("Page 1")

    def third_page(self):
        questions = [
            inquirer.List('Please Choose a type',
                          message="Please Choose a type",
                          choices=['Revenue',
                                   'Expense',
                                   'Back to previous page'],
                          ),
        ]
        self.transaction_type = answer1 = inquirer.prompt(questions)
        # Back to second page if they chosen this answer
        if answer1['Please Choose a type'] == 'Back to previous page':
            self.route.goTo("Page 2")
        self.route.goTo("Page 3__v2")

    def third_page_v2(self):
        questions = [
            inquirer.List('Please Choose a category',
                          message="Please Choose a category",
                          choices=['Food',
                                   'Transportation',
                                   'Rent',
                                   'Back to previous page'],
                          ),
        ]
        self.transaction_category = answer1 = inquirer.prompt(questions)
        if answer1['Please Choose a category'] == 'Back to previous page':
            self.route.goTo("Page 3")
        else:
            self.route.goTo("Page 3__v3")

    def third_page_v3(self):
        self.amount = float(
            input('Please enter a amount for the transaction:'))
        if self.amount != '':
            self.route.goTo("Page 3__v4")

    def third_page_v4(self):
        dummy1 = user.find_one({'name': self.store.getUserName()})
        questions = [
            inquirer.List('Confirm',
                          message="Did you confirmed all the data inputed is correct?",
                          choices=['Yes',
                                   'No, bring me back to the previous page', ]
                          ),
        ]
        answer1 = inquirer.prompt(questions)
        if answer1['Confirm'] == 'Yes':
            tx.insert_one(
                # transaction_type['Please Choose a type'] << This line was used to obtained the value
                {'name': dummy1['name'],
                    'Transaction Type': self.transaction_type['Please Choose a type'],
                    'Transaction Category': self.transaction_category['Please Choose a category'],
                    'Transaction Amount': self.amount}
            )
            # Update Balance
            balance = dummy1['balance']
            if self.transaction_type['Please Choose a type'] == 'Revenue':
                balance  = self.amount
                user.update_one({'name': dummy1['name']}, {
                                "$set": {'balance': (balance)}})
            else:
                balance -= self.amount
                user.update_one({'name': dummy1['name']}, {
                                "$set": {'balance': (balance)}})
                # TODO: ADD A {} in that set of data
            print(
                f"You have entered a entry with ---> {self.transaction_type['Please Choose a type']}, {self.transaction_category['Please Choose a category']}, {self.amount}")

            print("The database has been updated, you will be sent to the first page")
            time.sleep(1.5)
            self.route.goTo("Page 1")
        else:
            self.route.goTo("Page 3__v2")

    def fourth_page(self):
        transactions = tx.find({'name': self.store.getUserName()})
        for transaction in transactions:
            print(transaction)
        print("All transaction has been shown from the database.")
        time.sleep(1.5)
        questions = [
            inquirer.List('back_or_not',
                          message="Do you want to go back to previous page?",
                          choices=['Yes',
                                   'No, bring me back to the first page', ]
                          ),
        ]
        answer1 = inquirer.prompt(questions)
        self.go_back_or_not = answer1
        if self.go_back_or_not['back_or_not'] == 'Yes':
            self.route.goTo("Page 2")
        else:
            self.route.goTo("Page 1")

Part 4, the codes below is my routes, it tells which page the User of this programme will go if they run this programme.

import view


class Route:

    def goTo(self, temp):
        if temp == "Page 2":
            self.user1 = view.View().current_user
            self.screen = view.View().second_page()
            return self.screen

        if temp == "Page 3":
            self.transaction_type = view.View().third_page()
            return self.transaction_type

        if temp == "Page 4":
            self.go_back_or_not = view.View().fourth_page()
            return self.go_back_or_not

        if temp == "Page 1":
            self.screen = view.View().first_page()
            return self.screen

        if temp == "Page 3__v2":
            self.transaction_category = view.View().third_page_v2()
            return self.transaction_category

        if temp == "Page 3__v3":
            self.screen = view.View().third_page_v3()
            return self.screen

        if temp == "Page 3__v4":
            self.screen = view.View().third_page_v4()
            return self.screen

    def goTo1(self):
        self.screen = view.View().second_page()
        return self.screen

Part 5, the codes below is called the model. It is to let the user decide whether to "use a old player" or "to create a new user" when they run this programme. Just a simple functions for this part.

from database import user, tx
import inquirer


class Player:
    def createNewPlayer(self):
        balance = 0
        name = str(input('Please enter a name for the new user:').capitalize())
        balance = float(
            input('Please enter a balance amount for the new User:'))
        new_user = {"name": name, "balance": balance}

        user.insert_one(new_user)
        return name

    def enterOldPlayers(self):
        users = user.find().sort("name")
        questions = [
            inquirer.List('user_selected',
                          message="Select a User",
                          choices=[user['name'] for user in users]
                          ),
        ]
        answer1 = inquirer.prompt(questions)
        return answer1['user_selected']

Part 6, the codes below called store. I want this part serves as a server. If the user input some variable. I want to save all the variables here. And whenever I wanted to call back those variable, I can call all the variables in this part.

For example, when the user run this programme, they need to select a player (i.e. an account). And then I want to save the account name that they have selected, and print their name out in every page of this programme.

class Store:
    def __init__(self) -> None:
        pass

    def setUserName(self, username):
        self.username = username

    def getUserName(self):
        return self.username

Here comes the problem: When I tried to run the App.py (The main part of my programme), it shows "AttributeError: 'Store' object has no attribute 'username'" in the file called "Store", which the the codes in part 6. That is, line 9, in "getUserNamereturn self.username".

I have a little bit idea of why this Error will happen. It is probably because I have clear the variable that I have stored when I run the code in part 3 of my code in the line "self.store = Store()".

Since I deliberately separate a very big file into multiple files, just like these example. If I want to keep these six part of files that I have , what should I do to solve this problem?

I know that in Java Script, there is a system called "state management" can solve this problem. But I don't know how to solve it in Python.

Thank you very much!

CodePudding user response:

It is good practice to set any class attributes in the __init__ method of your class.

If you don't do this, and reference the attribute before it is set, you will get an AttributeError.

This code is a bit safer; if you try and get the username before it it set, it will return None, which is a big clue that you haven't set the username.

class Store:
    def __init__(self) -> None:
        self.username = None

    def setUserName(self, username):
        self.username = username

    def getUserName(self):
        return self.username
  • Related