I am trying to test my AnimalShelter.py code in Jupyter Notebook but I keep getting the error that the 'create' attribute is not there. Did I miss something? I have it defined in the code but no matter what I change it still says it is not there.
AnimalShelter.py code:
import pymongo
from pymongo import MongoClient
from bson.objectid import ObjectId
class AnimalShelter(object):
""" CRUD operations for Animal collection in MongoDB """
def __init__(self, username, password):
#Initializing the MongoClient. This helps to access the MongoDB databases and collections.
self.client = MongoClient('mongodb://%s:%s#localhost:45344' % (username, password))
#where xxxx is your unique port number
self.database = self.client['AAC']
#Complete this create method to implement the C in CRUD.
def create(self, data):
if data is not None:
insert = self.database.animals.insert(data) #data should be dictionary
else:
raise Exception("Nothing to save, because data parameter is empty")
#Create method to implement the R in CRUD.
def read(self, searchData):
if searchData:
data = self.database.animals.find(searchData, {"_id": False})
else:
data = self.database.animals.find({}, {"_id": False})
return data
#Create method to implement U in CRUD.
def update(self, searchData, updateData):
if searchData is not None:
result = self.database.animals.update_many(searchData, {"$set": updateData})
else:
return "{}"
return result.raw_result
#Create method to implement D in CRUD.
def delete(self, deleteData):
if deleteData is not None:
result = self.database.animals.delete_many(deleteData)
else:
return "{}"
return result.raw_result
The test code I am trying to use to see that CRUD is functioning properly:
from AnimalShelter import AnimalShelter
data = {}
query = {}
test_class = AnimalShelter()
#test each function in the AnimalShelter class
response = test_class.create(data)
assert response
response = test_class.read(data)
assert response
response = test_class.update(data)
assert response
response = test_class.delete(data)
assert response
I am at a loss. I am new to Jupyter Notebook with the whole testing thing and I figured this was the simplest way to test the attributes before making a different test for specific data from the python code but either way I still get that the create attribute doesn't exist!
I created a slightly altered version of your code for easy testing and got the error that no username and password were being passed to the AnimalShelter constructor.
class AnimalShelter(object):
""" CRUD operations for Animal collection in MongoDB """
def __init__(self, username, password):
print("constructor")
#Complete this create method to implement the C in CRUD.
def create(self, data):
print("create")
#Create method to implement the R in CRUD.
def read(self, searchData):
print("read")
#Create method to implement U in CRUD.
def update(self, searchData, updateData):
print("update")
#Create method to implement D in CRUD.
def delete(self, deleteData):
print("delete")
test_class = AnimalShelter("user", "pass")
data = {}
test_class.create(data)
test_class.read(data)
test_class.update(data, {})
test_class.delete(data)
Could your error be because you didn't pass these variables when constructing the test_class object? Upon passing "user" and "pass", I got the expected output:
constructor
create
read
update
delete
Related
I recently created an update method that changes the value of a key labeled age_upon_outcome in a Mongo database. It successfully updates the data in my database, but instead of returning a dictionary in JSON format, it returns a cursor. How can return the data in JSON format instead of cursor? Here is my code:
testing_script.ipynb
from animal_shelter import AnimalShelter
# now need to create the object from the class
shelter = AnimalShelter("aacuser","Superman")
data = {"age_upon_outcome":"2 years","animal_type":"Dog","breed":"Dachshund","color":"Black and tan","name":"Rhonda","outcome_subtype":"Partner","outcome_type":"Adopt","sex_upon_outcome":"Female"}
new_values = {"$set": {"age_upon_outcome":"3 years"}}
# if shelter.create(data):
# print("Animal added")
# else:
# print("Failed to add animal")
# Calls the read function
# shelter.read(data)
# Calls the update function
shelter.update(data, new_values)
output
<pymongo.cursor.Cursor at 0x7fb32a753f60>
animal_shelter.py
from pymongo import MongoClient
from bson.objectid import ObjectId
class AnimalShelter(object):
""" CRUD operations for Animal collection in MongoDB """
def __init__(self,username,password):
# Initializing the MongoClient. This helps to
# access the MongoDB databases and collections.
# init to connect to mongodb without authentication
self.client = MongoClient('mongodb://localhost:55996')
# init connect to mongodb with authentication
# self.client = MongoClient('mongodb://%s:%s#localhost:55996/?authMechanism=DEFAULT&authSource=AAC'%(username, password))
self.database = self.client['AAC']
# Complete this create method to implement the C in CRUD.
def create(self, data):
if data is not None:
self.database.animals.insert(data) # data should be dictionary
return True # Tells whether the create function ran successfully
else:
raise Exception("Nothing to save ...")
# Create method to implement the R in CRUD.
def read(self, data):
return self.database.animals.find_one(data) #returns only one
# Update method to implement the U in CRUD.
def update(self, data, new_values):
if self.database.animals.count(data):
self.database.animals.update(data, new_values)
return self.database.animals.find({"age_upon_outcome":"3 years"})
else:
raise Exception("Nothing to update ...")
I have tried using this code within the update method:
return self.database.animals.find_one(data)
I was expecting an updated dictionary, but it just returns the original dictionary.
I'm trying to create the CRUD operations in MongodB, but is unable to create the delete operations in this. the code below is for the animal shelter where I'm inserting the data first and then in the reading the data using the find keyword, I'm just confused about the delete operation, as i want to delete - say all the row. then how to use the
deletemany()
from pymongo import MongoClient
class AnimalShelter(object):
""" CRUD operations for Animal collection in MongoDB """
def __init__(self, username, password):
# Initializing the MongoClient. This helps to
# access the MongoDB databases and collections.
if username and password:
self.client = MongoClient('mongodb://%s:%s#localhost:27017' % (username, password))
else:
self.client = MongoClient('mongodb://localhost:27017')
self.database = self.client['AAC']
# Complete this create method to implement the C in CRUD.
def create(self, data):
if data is not None:
insert = self.database.animals.insert(data) # data should be dictionary
if insert!=0:
return True
else:
return False
else:
raise Exception("Nothing to save, because data parameter is empty")
# Create method to implement the R in CRUD.
def read(self,criteria=None):
# criteria is not None then this find will return all rows which matches the criteria
if criteria:
# {'_id':False} just omits the unique ID of each row
data = self.database.animals.find(criteria,{"_id":False})
else:
#if there is no search criteria then all the rows will be return
data = self.database.animals.find( {} , {"_id":False})
return data
# The delete method in CRUD
(missing)
I have a simple flask app that does CRUD operations. I have a python module where I defined all functions and they all work fine; I can create, read, update and delete. I added a retrieve method where I call find() and it does retrieve the cursor. The problem is I can't get it to populate the data, all I get is an empty array []. I looped through the cursor and I used loads and dumps from bson.json_util, but I get the same result. Here is what the class looks like:
from pymongo import MongoClient
class AnimalShelter(object):
def __init__(self, username, password):
# Access the MongoDB databases and collections.
self.client = MongoClient('localhost', ####)
self.db = self.client['project']
self.username = username
self.password = password
# Create
def create(self, data):
if data is not None:
return self.db.collection.insert(data)
else:
print("Nothing to save, because data parameter is empty")
return False
# Read
...
# Update
...
# Delete
...
# Retrieve
def retrieve(self, data, projection):
if data is not None:
return self.db.collection.find(data, projection)
else:
return False
In the test file, I have:
animals = AnimalShelter(username, password)
try:
dog = dumps(list(animals.retrieve({"animal_type": "Dog", "name": "Flow"}, {"_id": False})))
print(dog)
except:
print("Unable to find the outcome")
Any help would be appreciated!
my issue is that I am saving dict objects with MongoEngine:
class MongoRecord(DynamicDocument):
record_id = SequenceField(primary_key = True)
class SimpleMongo(object):
def __init__(self, *args, **kwargs):
"""
Very simple dict-like Mongo interface
"""
if PY_VERSION == 2:
self.iterattr = 'iteritems'
else:
self.iterattr = 'items'
self.debug = DEBUG
self.dict_type = type(dict())
self.dbname = kwargs.get('dbname', 'untitled')
self.collection_name = kwargs.get('collection', 'default')
self.ip = kwargs.get('ip', '127.0.0.1')
self.port = kwargs.get('port', 27017)
self.dbconn = connect(self.dbname, host=self.ip, port=self.port)
drop = kwargs.get('drop', False)
if drop:
self.dbconn.drop_database(self.dbname)
def put(self, data):
"""
Put dict
"""
assert type(data) == self.dict_type
record = MongoRecord()
record.switch_collection(self.collection_name)
generator = getattr(data, self.iterattr)
__res__ = [setattr(record, k, v) for k,v in generator()] # iteritems() for Python 2.x
record.save()
but when trying to access them:
def get(self):
record = MongoRecord()
record.switch_collection(self.collection_name)
return record.objects
getting
mongoengine.queryset.manager.QuerySetManager object, not an iterator.
So, what is the proper way to get my data back from Mongo being saved as DynamicDocument?
The problem isn't that MongoRecordis a DynamicDocument or that it contains a dict. You would get the same result with a regular Document. Your problem is with querying, you should change record.objects to MongoRecord.objects to get a cursor.
Regarding your usage of switch_collection()...
If MongoRecord documents will be saved to a collection with the same name, at most times, you can define this like below, and you don't have to use switch_collection() when a collection with that name is being queried.
class MongoRecord(DynamicDocument):
record_id = SequenceField(primary_key = True)
meta = {'collection': 'records'}
In case you do want to retrieve MongoRecord documents from a collection which isn't called 'records', and you want to define a function for this (which can give an UnboundLocalError), you can do it like this (source):
from mongoengine.queryset import QuerySet
def get(self):
new_group = MongoRecord.switch_collection(MongoRecord(), self.collection_name)
new_objects = QuerySet(MongoRecord, new_group._get_collection())
all = new_objects.all()
# If you would like to filter on an MongoRecord attribute:
filtered = new_objects.filter(record_id=1)
return all
I have the following example code which uses either MongoEngine and Peewee as DB backends.
import mongoengine, peewee
from mongomodels import *
from mysqlmodels import *
class Parser(object):
def __init__(self, line, dbBackend):
if dbBackend in ["MongoDB","MySQL"]:
self.line = line
self.DB = dbBackend
user = self.createUser()
car = self.createCar(user)
parking = self.createParking(car)
else:
raise Exception()
def createUser(self):
if self.DB == "MongoDB":
newUserID = self._createMongoUser(self.line['firstname'], self.line['lastname'], '...')
else:
newUserID = self._createMySQLUser(self.line['firstname'], self.line['lastname'], '...')
return newUserID
def _createMongoUser(self, firstname, lastname, '...'):
try:
_user = MongoUserModel.objects.get(firstname=firstname, lastname=lastname)
except mongoengine.errors.DoesNotExist as e:
user = MongoUserModel(firstname=firstname, password)
_user = user.save()
finally:
return _user
def _createMySQLUser(self, firstname, lastname, '...'):
try:
_user = MySQLUserModel.get(MySQLUserModel.fistname == firstname, MySQLUserModel.lastname == lastname )
except Exception as e:
user = MySQLUserModel(fistname=fistname, lastname=lastname)
_user = user.save()
finally:
return _user
def createCar(self, user):
pass
def createParking(self, car):
pass
Is there any good practice / trick / module to keep my code DRY and to avoid redefining two methods to create my Models?
Should I can create a new abstraction class 'UserModel' as does PDO in PHP?
This is something I went through recently - I swapped from a mongo backend to postgres. When I set up the original project I had some models and a DataLayer. The datalayer (dl) had quite a simple interface that I used throughout my app.
# note: this is half python / half pseudocode
class Model1(object):
__collection__ = 'model1'
__tablename__ = 'model1'
# field definitions etc
class MongoDataLayer(object):
def __init__(self, mongo_db_connection):
self.conn = mongo_db_connection
def load(self, model, conditions):
raw = self.conn[model.__collection__].find(...)
return model(**raw)
def persist(self, obj):
self.conn[obj.__collection__].save(obj.as_dict())
class SQLDataLayer(object):
def __init__(self, sa_session_factory):
self.Session = sa_session_factory
self.session = self.Session()
def load(self, model, conditions):
return self.session.query(model).find_by(conditions).one() # ...etc
def persist(self, obj):
self.conn[obj.__collection__].save(obj)
# connections - mongo and postgres (I use SQLAlchemy)
dl_mongo = MongoDataLayer(db...)
dl_sql = SQLDataLayer(Session...)
# using them - you don't care which one you have
m = dl_mongo.load(models.Model1)
dl_mongo.persist(m)
m = dl_sql.load(models.Model1)
dl_sql.persist(m)
In my app I load up the dl in the initial load and then inject it into the app whenever data access needs to happen. The app itself then knows about models but not the details of how to load / save them.
Maybe not the best way to do it but it's worked well for me. Would be interested to hear how other people deal with it.