I would like to create small app using M-VC pattern in python. I am using PyCharm and my folder structure looks like this.
To avoid problem with cyclic references I am using import not from ... import.
Program executes without error when my viewController.py looks like this:
import model
class ViewController:
def initialize(self, mod):
self.model = mod
Adding model.Model expression inside initialize method results with an error: AttributeError: module 'model' has no attribute 'Model' Why it works in model.py with viewController.ViewController? And what is wrong?
[new]viewController.py
import model
class ViewController:
def initialize(self, mod:model.Model):
self.model = mod
Back/__init_.py
import model
import viewController
mModel = model.Model()
mVC = viewController.ViewController()
mModel.initializeApp(mVC)
model.py
import viewController
class Model():
def initializeApp(self, viewContr: viewController.ViewController):
self.vc = viewContr
self.vc.initialize(self)
Related
Multiple files in a project
db.py
Setup and handle firebase_admin connection
model.py
Abstract class for model CRUD
session.py, config.py...
Some classes extend models
main.py
Import files, coordinate them
main.py basically:
import db
class App():
....
main = App()
main.db = db.start(options)
model.py basically:
from abc import abstractmethod, ABC
class Model():
...
#abstractmethod
def gen_key(self):
pass
def create(self):
main.db.users_ref.set({
self.gen_key() : self.output_data()
})
but model.py cannot access main
I tried
global main
main = App()
in main.py, doesn't work.
Tried import main.py in model.py, got circular import error
Do I need to pass main to every single instance? Seemed so troublesome
I make model.py because I'm trying to make different parts of firebase more consistent. I learn this kind of things from PHP yii framework, it's for MySql, but make sense to me so I copy that kind of things.
You can see a gen_key in Model. I hope every "Table" have a gen_key method.
For example, Session.gen_key will return self.date
Config.key will return self.type+"_"+self.date
With that, I can just define the gen key rule, and run
record = new Session
record.date = today
record.save
Then things would automatically organise themselves in firebase
I'm trying to write a simple unit test to test an instance method of one of my models in Django. However my class initialises an external connection on __init__ which is not being patched even though I'm trying to target it.
Folder Structure:
- project/
- app1/
- tests/
- tests_models.py
- models.py
models.py:
from 3rdPartyPlugin import Bot
class MyClass:
def __init__(self, token):
self.bot = Bot(token)
def generate_buttons(self):
...
tests_models.py:
from django.test import TestCase
from unittest.mock import MagicMock, patch
from app1.models import MyClass
#patch('app1.models.3rdPartyPlugin.Bot')
class GenerateButtonsTestCase(TestCase):
def setUp(self):
self.tb = MyClass('', '', '')
def test_generates_button_correctly(self):
return True
I can't get past the setUp step because the initialisation of the class fails because it tries to reach out to that 3rdPartyPlugin module even though I patched it.
I've tried setting the patch to:
#patch('app1.models.3rdPartyPlugin.Bot')
#patch('app1.models.Bot')
#patch('app1.models.TB.Bot')
But all of the above still leads to the Bot being called. Any suggestions?
The problem is that Bot is already imported and read in models.py before you patch it.
Try to import the whole module instead:
import 3rdPartyPlugin
class MyClass:
def __init__(self, token):
self.bot = 3rdPartyPlugin.Bot(token)
def generate_buttons(self):
I eventually was able to solve this by moving the 3rdPartyPlugin code out of the initialiser and into an instance method on the class I was testing. This is how it looked in code:
models.py:
from 3rdPartyPlugin import Bot
class MyClass:
def __init__(self, token):
self.token = token
self.bot = self.bot()
def bot(self):
Bot(self.token)
tests_models.py:
from app1.models import MyClass
class GenerateButtonsTestCase(TestCase):
#patch('app1.models.MyClass.bot')
def setUp(self, _):
self.tb = MyClass('', '', '')
And after making the above changes, the patch correctly works and patches my use of Bot from the 3rdPartyPlugin. It's a bit messy but it works for me.
I am using Python 2.7, and have following code strucure
model
__init__.py
order.py
cart.py
That is, I define a package named model, and in this package, I define a module order, and I define a class in order.py
class MyOrder(object):
def __init__(self, name):
self.name = name
def getname(self):
return self.name
In the cart.py, the code is:
import model
x = model.order.MyOrder("Book")
print x.getname()
When I run it, it complains that AttributeError: 'module' object has no attribute 'order',
But the following is correct:
import model.order
x = model.order.MyOrder("Book")
print x.getname()
It looks that I can't import package (like import model) ?
If you want to have model automatically import order so it's available, you should do that in __init__.py. Simply put the following inside model/__init__.py:
from . import order
After that, you should be able to access model.order with just import model.
I created a controller in Pylot MVC and havent been able to figure out why it wont load the controller I created. I have it named appropriately. My controller is called courses.py, looks like so:
from system.core.model import Model
class Course(Controller):
def __init__(self):
super(Course, self).__init__()
def index(self):
return self.load_view('index')
My routes are set up and look right too
from system.core.router import routes
routes['default_controller'] = 'Courses'
I get this error when I try to run my server:
ImportError: No module named Courses
Any ideas on where I could have gone wrong?
Figured it out with help from a friend. I had two problems. One I named the controller class wrong. Should of been Courses like so.
from system.core.model import Model
class Courses(Controller):
def __init__(self):
super(Courses, self).__init__()
def index(self):
return self.load_view('index')
The other issue for anyone else who gets this same error is that the controller file itself has to be capitalized. I named my controller file courses.py and it had to be Courses.py.
I am trying to import a class in Python and after importing the class set a class variable as the imported class. I have searched Google as well as stackoverflow for an answer to this, but have not been able to find one.
For Example:
DB.py:
class DB:
def __init__(self):
#init sets up the db connection
def FetchAll():
#Fetchall fetches all records from database
Ex.py:
class Ex:
def __init__(self):
import DB.py as DB
self.db = DB.DB()
def FetchAll(self):
result_set = self.db.FetchAll()
I would like to be able to access the FetchAll() in the DB class from Ex class through a variable. I know in PHP this is possible by using "Protected" keyword in a class.
Thank you for any help you can offer.
Just
import DB
You provide a module name (that can be located given the current module search path), not a file name.
Check the tutorial for a beginner’s overview of how modules and imports work.
You can either just use the name of the class as the class variable:
import DB
class Ex:
# define methods
# call FetchAll with DB.FetchAll()
Or create a new class variable with the 'as' key:
import DB as x
class Ex:
# define methods
# call FetchAll with x.FetchAll()
And like the others are saying, import all modules at the top of the script.