Making SQLAlchemy records from a list - python

Fairly new to Python and very new to SQLAlchemy. Wondering how I can use a for loop to make multiple SQLAlchemy records from a list. Here's a very simplified version of what I have.
class ListItem(Base):
__tablename__ = list_items
id = Column(Integer, primary_key=True)
item = Column(String(50))
def list_to_ListItem(list_of_things):
for thing in list_of_things:
listitem = ListItem()
listitem.item = thing
I haven't yet run this because there's actually a lot more to my code that still needs to be worked out, but I'm under the impression that, instead of creating a record in list_items for each thing in list_of_things, this will simply create one record assigned to listitem that it will overwrite with every iteration of the for loop.
So how do I do this? Like I said, I'm fairly new to Python, but I've heard something about factory functions that I don't understand but which, at least in name, sounds promising for this problem. Thanks in advance!

List comprehension?
list_items = [ListItem(item=thing) for thing in list_of_things]

Related

Saving complex objects in SQLAlchemy

I'm new to SQLAlchemy and I'm trying to create a new item that includes a list of several sub-items (simple One-to-Many relation) using Flask-RESTful and Flask-SQLAlchemy. I'm trying to create both the item and sub-items simultaneously and I'm not clear on how SQLAlchemy is supposed to work.
class ItemModel(Model):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String(80))
sub_items = relationship('SubItemModel')
class SubItemModel(db.Model):
__tablename__ = 'sub_items'
id = Column(Integer, primary_key=True)
item_id = Column(Integer, ForeignKey('items.id'))
name = Column(String(80))
item = relationship('ItemModel')
I want to add an item along with several sub_items (through a POST route), but I'm having trouble wrapping my head around which objects to create first and how much SQLAlchemy will do automatically. I got something working by creating an item with no sub_items, creating the sub_items, and then re-saving the item with the sub_items. But this seems pretty clunky, particularly in cases where either the item or some of the sub_items might already exist.
My intuition is just to do something like this:
item = ItemModel(
name="item1",
sub_items=[{name: "subitem1"},{name: "subitem2"}])
session.add(self)
session.commit()
But it's not working (I'm getting errors about unhashable types), and it seems ...too simple, somehow. Like I should define the sub_item objects separately. But since they depend on the item_id I'm not sure how to do this.
I'm sure this has been answered before or explained in a simple tutorial somewhere but I haven't been able to find anything simple enough for me to understand. I'm hoping someone can walk me through the basics. (which parts are supposed to be magical and which parts do I still have to code manually...)
Thanks.
The "many" side of any SQLAlchemy relationship behaves like a standard Python list. You should be creating the SubItemModel objects directly and appending them to ItemModel:
item = ItemModel(name='item1')
subitem1 = SubItemModel(name='subitem1')
subitem2 = SubItemModel(name='subitem2')
item.sub_items.append(subitem1)
item.sub_items.append(subitem2)
or, to append multiple items at once, you can use the standard list extend method:
item = ItemModel(name='item1')
subitem1 = SubItemModel(name='subitem1')
subitem2 = SubItemModel(name='subitem2')
item.sub_items.extend([subitem1, subitem2])
You can, if you want, create the subitems directly when you're adding them:
item = ItemModel(name='item1')
item.sub_items.extend([SubItemModel(name='subitem1'), SubItemModel(name='subitem2')])
Whichever option you choose, you should be adding your created item object to the session, which will automatically include the new child records you've created:
session.add(item)
session.commit()
Voila, your item and subitems should all be inserted into the DB at once.

How to remove all contents of database using MongoAlchemy

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()

How to create and use a heap data structure

I am trying to create a python program that adds and removes names to a certain category. While I'm pretty sure the use a heap would be a good method for this program, I may be thinking of the wrong data structure. I'm still very new to programming and I am very unsure as what to do.
class table():
__slots__ = ('time','volunteers')
def mkTable(time,name):
tbl = table()
tbl.time = time
tbl.volumteers = name
return tbl
Does anyone have any advice?

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 query optimization: find a list of objects based on a many-to-one to a many-to-many

I have an ugly loop that is operating as a band-aid in Django that I'd like to optimize into a join. I've broken it down to the most basic structure to help simplify the problem. I'm hoping someone else has run into something like this before -- if not, I'll share the answer when I finally fix it.
To summarize
Object A has a non-symmetrical, many-to-many relationship with itself.
Object B has a many-to-one relationship with Object A.
Given an ObjectB, I need a set of other ObjectBs that are the children of the ObjectAs that are associated with our ObjectB's parent ObjectA.
I'm sure someone with more database experience could phrase that better (leave a comment if you have a better description of this association).
Here is a bare bones example of the structure I'm working with in Django, and the sort of loop that's running:
class ObjectA(models.Model):
object_a_rules = models.ManyToManyField("self", symmetrical=False, through='ObjectARule')
class ObjectARule(models.Model):
object_a_one = models.ForeignKey(ObjectA, related_name="object_a_before")
object_a_two = models.ForeignKey(ObjectA, related_name="object_a_after")
class ObjectB(models.Model):
object_a_association = models.ForeignKey(ObjectA)
def that_annoying_loop_i_mentioned(self):
object_a_rules_list = ObjectARule.objects.filter(object_a_one = self.object_a_association)
#A list of all of the ObjectARules that have the ObjectA this ObjectB is associated with
#as the first half of the many-to-many relationship.
object_b_list = ObjectB.objects.all()
#A list of all of the ObjectBs, may also be a filtered list
for object_a_rule in object_a_rules_list:
for object_b in object_b_list:
if (object_a_rule.object_a_two == object_b.object_a_association):
#if the second half of ObjectARule is the ObjectA of
#the ObjectB in this list, then do something with that ObjectB.
pass
How could Django get a list of ObjectBs through a join, so this painfully inefficient loop wouldn't have to run?
Given an ObjectB, I need a set of
other ObjectBs that are the children
of the ObjectAs that are associated
with our ObjectB's parent ObjectA.
If objb is the ObjectB you are given, you could do this as follows:
objects = ObjectB.objects.filter(object_a_association__object_a_rules=objb.object_a_association)
or alternatively,
objects = ObjectB.objects.filter(object_a_association__object_a_rules__objectb_set=objb)
See also Lookups that span relationships

Categories