How to remove all contents of database using MongoAlchemy - python

As title suggests, I want to remove all contents of the database. I'm making an application in Python using Flask and MongoAlchemy for database. I have the class People which models the documents. The structure is:
class People(db.Document):
Name = db.StringField()
Age = db.IntField()
Password = db.StringField()
Vms = db.AnythingField()
With the remove method I can delete only one document at once, based on the name or other detail, but I want to be able to delete them all at once.
This is my function for deleting a document, based on name.
def delete_document(name):
x = People.query.filter(People.Name == name).first()
x.remove()
Where People is the reference to the model class.

Apparently there is a easy way, using one of the built-in methods from Query class, remove_all. With the remove_all method you can get all the results from database in a list, and after that you can call the remove method on every instance. The code is posted below. Not sure if there is a more efficient way of doing this, so feel free to post it.
def deleteAll():
x = People.query.all()
for i in range(0, len(x)):
x[i].remove()

Related

Creating Object With A For Loop

Firstly, I do apologise as I'm not quite sure how to word this query within the Python syntax. I've just started learning it today having come from a predominantly PowerShell-based background.
I'm presently trying to obtain a list of projects within our organisation within Google Cloud. I want to display this information in two columns: project name and project number - essentially an object. I then want to be able to query the object to say: where project name is "X", give me the project number.
However, I'm rather having difficulty in creating said object. My code is as follows:
import os
from pprint import pprint
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('cloudresourcemanager', 'v1', credentials=credentials)
request = service.projects().list()
response = request.execute()
projects = response.get('projects')
The 'projects' variable then seems to be a list, rather than an object I can explore and run queries against. I've tried running things like:
pprint(projects.name)
projects.get('name')
Both of which return the error:
"AttributeError: 'list' object has no attribute 'name'"
I looked into creating a Class within a For loop as well, which nearly gave me what I wanted, but only displayed one project name and project number at a time, rather than the entire collection I can query against:
projects=[]
for project in response.get('projects', []):
class ProjectClass:
name = project['name']
projectNumber = project['projectNumber']
projects.append(ProjectClass.name)
projects.append(ProjectClass.projectNumber)
I thought if I stored each class in a list it might work, but alas, no such joy! Perhaps I need to have the For loop within the class variables?
Any help with this would be greatly appreciated!
As #Code-Apprentice mentioned in a comment, I think you are missing a critical understanding of object-oriented programming, namely the difference between a class and an object. Think of a class as a "blueprint" for creating objects. I.E. your class ProjectClass tells python that objects of type ProjectClass will have two fields, name and projectNumber. However, ProjectClass itself is just the blueprint, not an object. You then need to create an instance of ProjectClass, which you would do like so:
project_class_1 = ProjectClass()
Great, now you have an object of type ProjectClass, and it will have fields name and projectNumber, which you can reference like so:
project_class_1.name
project_class_1.projectNumber
However, you will notice that all instances of the class that you create will have the same value for name and projectNumber, this just won't do! We need to be able to specify values when we create each instance. Enter init(), a special python method colloquially referred to as the constructor. This function is called by python automatically when we create a new instance of our class as above, and is responsible for setting up all the fields of that class. Another powerful feature of classes and objects is that you can define a collection of different functions that can be called at will.
class ProjectClass:
def __init__(self, name, projectNumber):
self.name = name
self.projectNumber = projectNumber
Much better. But wait, what's that self variable? Well, just as before we were able reference the fields of our instance via the "project_class_1" variable name, we need a way to access the fields of our instance when we're running functions that are a part of that instance, right? Enter self. Self is another python builtin parameter that contains a reference to the current instance of the ProjectClass that is being accessed. That way, we can set fields on the instance of the class that will persist, but not be shared or overwritten by other instances of the ProjectClass. It's important to remember that the first argument passed to any function defined on a class will always be self (except for some edge-cases you don't need to worry about now).
So restructuring your code, you would have something like this:
class ProjectClass:
def __init__(self, name, projectNumber):
self.name = name
self.projectNumber = projectNumber
projects = []
for project in response.get('projects', []):
projects.append(ProjectClass(project["name"], project["projectNumber"])
Hopefully I've explained this well and given you a complete answer on how all these pieces fit together. The hope is for you to be able to write that code on your own and not just give you the answer!

How to check the existance of single Entity? Google App Engine, Python

Sorry for noobster question again.
But I'm trying to do some very easy stuff here, and I don't know how. Documentation gives me hints which do not work, or apply.
I recieve a POST request and grab a variable out of it. It says "name".
I have to search all over my entities Object (for example) and find out if there's one that has the same name. Is there's none, I must create a new Entity with this name. Easy it may look, but I keep Failing.
Would really appreciate any help.
My code currently is this one:
objects_qry = Object.query(Object.name == data["name"])
if (not objects_qry ):
obj = Object()
obj .name = data["name"]
obj .put()
class Object(ndb.Model):
name = ndb.StringProperty()
Using a query to perform this operation is really inefficient.
In addition your code is possibly unreliable, if name doesn't exist and you have two requests at the same time for name you could end up with two records. And you can't tell because your query only returns the first entity with the name property equal to some value.
Because you expect only one entity for name a query is expensive and inefficient.
So you have two choices you can use get_or_insert or just do a get, and if you have now value create a new entity.
Any way here is a couple of code samples using the name as part of the key.
name = data['name']
entity = Object.get_or_insert(name)
or
entity = Object.get_by_id(name)
if not entity:
entity = Object(id=name)
entity.put()
Calling .query just creates a query object, it doesn't execute it, so trying to evaluate is as a boolean is wrong. Query object have methods, fetch and get that, respectively, return a list of matching entities, or just one entity.
So your code could be re-written:
objects_qry = Object.query(Object.name == data["name"])
existing_object = objects_qry.get()
if not existing_object:
obj = Object()
obj.name = data["name"]
obj.put()
That said, Tim's point in the comments about using the ID instead of a property makes sense if you really care about names being unique - the code above wouldn't stop two simultaneous requests from creating entities with the same name.

Django Mongodb ListField not saving or updating

I am starting to create a webapp using Django and MongoDB. Everything is working fine when I create a model and save it into the Database. Now, I do a "Class.objects.get()" to get the object I need from my DB and I have one field called "media" which is a ListField(). I had tried doing either:
Concert.media.append(list)
or
Concert.media.extend(list)
and then
Concert.save()
This is my "Concert" object in my models.py:
class Concert(models.Model):
main_artist = models.CharField(max_length=50)
concert_id = models.AutoField(primary_key=True)
openers = ListField(EmbeddedModelField('Opener'))
concert_date = models.DateField()
slug = models.SlugField(unique=True)
media = ListField()
And when I go to see the results in does not update the object. No values where saved. If someone can help me I going to give a super cyber fist bump.
Concert is a class, not an instance. You can't save a class. You need to make an instance of the class and save that. Something like
c = Concert()
c.media.append(list)
c.save()
(btw, just as a note, list is a bad variable name because list is a type in python. Never use types as variable names (though everyone is guilty of this at one point or another, including me.))

Adding dynamic properties to datastore object

I'm relatively new to Python, coming from the PHP world. In PHP, I would routinely fetch an row, which would correspond to and object from the database, say User, and add properties to it before passing the user object to my view page.
For example, the user has properties email, name and id.
I get 5 users from the database and in a for loop, I assign a dynamic property to the user, say image.
This doesn't seem to work in Python/Google App Engine datastore models (I think it has to do more with the datastore model than python) in a for loop. It works within the for loop (meaning I can reference user.image within the for loop, but once the for loop ends, all of the objects seem to not have the new attribute image anymore.
Here is a code example:
# Model
Class User(ndb.Model):
email = ndb.StringProperty()
name = ndb.StringProperty()
# And then a function that returns a list of users
users = User.get_users()
user_list = []
# For loop
for user in user:
# For example, get image
user.image = Image.get_image(user.key)
user_list.append(user)
# If I print or log this user in the for loop, I see a result
logging.info(user.image) # WORKS!
for ul in user_list:
print ul.image # Results in None/ATTR Error
Can anyone explain to me why this is happening and how to achieve this goal?
I've searched the forms, but I couldn't find anything.
Try using Expando Model
Sometimes you don't want to declare your properties ahead of time. A
special model subclass, Expando, changes the behavior of its entities
so that any attribute assigned (as long as it doesn't start with an
underscore) is saved to the Datastore.

python in Google App Engine - having the class-instead-of-instance problem, but using db.Model so can't create init method

i am writing an app to compare products, using Python and GAE. The products will belong to a set of similar products, and the app calculates the best value in each set.
When i create a new product, it can be added to an existing set or a new set can be created.
When testing the app, the first set gets created just fine. I populate an instance of the set with the name of the product. I use a form on one web page to POST the data into the "suppbook" page. I'm still not clear on how a web page can be a class but that's a different question.
There's more code around all of this but I'm trying to make my question as clear as possible.
class Supp(db.Model):
name = db.StringProperty(multiline=False)
# a bunch of other attributes using Google's DB Model
class SuppSet(db.Model):
name = db.StringProperty(default='')
supp_list = set([])
# a bunch of other attributes using Google's DB Model
# i tried to add this after reading a few questions on SO but GAE doesn't like it
def __init__(self,):
self.name = 'NoName'
self.best_value = 'NoBestValue'
self.supp_list = set([])
Class Suppbook(webapp.RequestHandler):
def post(self):
supp = Supp()
suppSet = SuppSet()
...
supp.name = self.request.get('name')
supp.in_set = self.request.get('newset')
suppSet.name = supp.in_set
suppSet.supp_list.add(supp.name)
self.response.out.write('%s now contains %s<p>' % (suppSet.name,suppSet.supp_list))
This works well the first time around, and if I only use one SuppSet, I can add many supps to it. If I create another SuppSet, though, both suppSets will have the same contents for their supp_list. I have been looking through the questions on here and I think (know) I'm doing something wrong regarding class vs. instance attribute access. I tried to create an __init__ method for SuppSet but GAE complained: AttributeError: 'SuppSet' object has no attribute '_entity'
Also, I am using the GAE datastore to put() and get() the Supps and SuppSets, so I'm not clear why I'm not acting on the unique instances that I should be pulling from the DB.
I am not sure if I am providing enough information but I wanted to get started on this issue. Please let me know if more info is needed to help debug this.
I'm also open to the idea that i'm going about this completely wrong. I'm considering re-writing the whole thing, but I'm so close to being "finished" with basic functionality that I'd like to try to solve this issue.
Thanks
In your init you will need to call the super's init, db.Model has some important stuff to do in its init, you will have to match the signature.
However you likely shouldn't be setting up things like defaults in there. Try and just use the datastore Properties ability to set a default.
You've got some (I assume) typos in your code. Python is sensitive to case and white-space. The attribute names you use also don't match your defs, such as in_set. When possible, post actual working examples demonstrating your problem.
class Supp(db.Model):
name = db.StringProperty(multiline=False)
in_set = db.StringProperty(multiline=False)
# your other stuff ...
class SuppSet(db.Model):
name = db.StringProperty(default='')
supp_list = db.StringListProperty()
# your other stuff ...
# In Python, you need to explicitly call the parent's __init__ with your args.
# Note that this is NOT needed here.
def __init__(self, **kwargs):
db.Model.__init__(self, **kwargs)
class Suppbook(webapp.RequestHandler):
def post(self):
# This will create a NEW Supp and SuppSet every request,
# it won't fetch anything from the datastore.
# These are also NOT needed (included for explanation)
supp = Supp()
suppSet = SuppSet()
# It sounds like you want something like:
product_name = self.request.get('name')
product_set = self.request.get('newset')
# check for missing name / set:
if not product_name or not product_set:
# handle the error
self.error(500)
return
# Build the keys and batch fetch.
supp_key = db.Key.from_path('Supp', product_name)
suppset_key = db.Key.from_path('SuppSet', product_set)
supp, suppset = db.get([supp_key, suppset_key])
if not supp:
supp = Supp(key_name=product_name,
name=product_name)
if not suppset:
suppset = SuppSet(key_name=product_set,
name=product_set)
# Update the entities
supp.in_set = product_set
if product_name not in suppset.supp_list:
suppset.supp_list.append(product_name)
# Batch put...
db.put([supp, suppset])
self.response.out.write('%s now contains %s<p>' % (suppset.name, str(suppset.supp_list)))

Categories