Create object in flask - python

So basicaly I have this class:
class Grupa(db.Model):
__tablename__ = 'grupa'
id_grupy = db.Column(db.BigInteger, db.Sequence('grupa_seq'), primary_key=True)
nr_semestru = db.Column(db.SmallInteger)
rodzaj = db.Column(db.String(5))
nr_grupy = db.Column(db.SmallInteger)
dzien_tyg = db.Column(db.SmallInteger)
godz_rozp = db.Column(db.SmallInteger)
ilosc_godz = db.Column(db.SmallInteger)
czestatliwosc = db.Column(db.SmallInteger)
id_prowadzacego = db.Column(db.ForeignKey('prowadzacy.id_prowadzacego'))
id_przedmiotu = db.Column(db.ForeignKey('przedmiot.id_przedmiotu'))
id_sali = db.Column(db.ForeignKey('sala.id_sali'))
id_specjalnosci = db.Column(db.ForeignKey('specjalnosc.id_specjalnosci'))
id_studia = db.Column(db.ForeignKey('studia.id_studia'))
oferty = db.relationship('Oferta', backref='grupa')
def __repr__(self):
return '<Grupa(grupa={self.id_grupy!r})>'.format(self=self)
Now using flask I would like to create an object of it and add it to the database. I found the next example of:
from yourapp import User
me = User('admin', 'admin#example.com')
db.session.add(me)
db.session.commit()
The problem I have is
here
To be hones I was expecting giving params like "id_grupy" and so on and I have this. What is this classname and bases here?
P.S. That was really helpfull but now I got diffrent problem.
I go in for over my dataframe to extract it row by row and then add it to my database and there is that weird error
for row in df.iterrows():
dzien, godz, ilosc, tyg, id_naucz, id_sala, id_prz, rodz, grupa, id_st, sem, id_spec = row
As You see im trying to put this values from each row and error i get is :
dzien, godz, ilosc, tyg, id_naucz, id_sala, id_prz, rodz, grupa, id_st, sem, id_spec = row
ValueError: not enough values to unpack (expected 12, got 2)
Which is weird I just gave 12 values for him, why he got only 2 of them?

What you did is nice, but you need to add a __init__ function to your Grupa class in order to give attributes you want to your object :
def __init__(self, id_grupy, nr_semestru, rodzaj, ...):
self.id_grupy = id_grupy
self.nr_semetru = nr_semetru
self.rodzaj = rodzaj
...
(see an example here)
See ya !

Related

Is it a valid use-case to update a record fetched via a ForeignKeyField backref?

I'm on peewee 3.14.0 ... is it a valid use case to do something like this? This is ofc a toy example of my actual use-case:
class A(BaseModel):
id = BigAutoField(primary_key=True)
a1 = CharField()
class B(BaseModel):
a = ForeignKeyField(A, backref='bs')
b1 = CharField()
and then do something like:
a = A.select()...
for b in a.bs:
b.b1 = "doesn't work, this will insert a new record rather than update the existing"
b.save()
to cover this update use-case I need to do the following instead:
a = A.select()...
for b in a.bs:
q = (B.update({b1: "this however, works"}).where(B.a==a, ..))
q.execute()
Is there a way to fix the first approach or is it not covered by peewee?
It does not insert new records in this example. I think your example is either missing some important information or something else is missing.
class User(Base):
username = TextField()
class Tweet(Base):
user = ForeignKeyField(User, backref='tweets')
content = TextField()
db.create_tables([User, Tweet])
u = User.create(username='u1')
for j in range(2):
Tweet.create(user=u, content='t%s' % j)
u = User.get(User.username == 'u1')
for tweet in u.tweets:
tweet.content = tweet.content + '-x'
tweet.save()
for tweet in u.tweets:
print(tweet.content)
This correctly prints:
t0-x
t1-x

Django Can't save record with ForeinKey

I am familiar with the Django and I am using Django framework(2.2.2) in one of my website, But I am getting one weird issue for saving record with the foreign key:
I have following two models
class quick_note(models.Model):
note_id = models.AutoField(primary_key=True)
meeting_date = models.DateField(max_length=55)
title = models.TextField(blank = True,null=True)
headline = models.TextField(blank = True,null=True)
class quick_note_details(models.Model):
meeting_id = models.ForeignKey(quick_note,on_delete = models.CASCADE)
summary = models.TextField(default='',null=True)
Following is the code I have used for saving:
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id = 1)
quick_note_details_data.save()
Using this I am getting following error:
ValueError: Cannot assign "2": "quick_note_details.meeting_id" must be a "quick_note" instance.
Then, I have tried the following approach suggested in the following question,
Django: ValueError when saving an instance to a ForeignKey Field
quick_note_obj = quick_note.objects.get(note_id = note_id)
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id = quick_note_obj)
quick_note_details_data.save()
Using this I am getting following error:
django.db.utils.ProgrammingError: column "meeting_id_id" of relation "website_quick_note_details" does not exist
LINE 1: INSERT INTO "website_quick_note_details" ("meeting_id_id", "...
I don't have a column like meeting_id_id in the model anywhere, then why I am getting this error?
I have been searching for this long time, but didn't get any solution,
Hope I will get help here.
change meeting_id to meeting_id_id , try following
quick_note_details_data = quick_note_details(summary = summary_data,meeting_id_id = 1)
So, I had got my answer days back, so decided to answer so this will help people like me,
Basically, Django appends a suffix to the foreign_key columns,
e.g if your columns name is note ,Django will assume this as note_id,
So,To avoid this I had done only the following:
note_id = models.ForeignKey(quick_note,on_delete = models.CASCADE,db_column='note_id')
By using db_column property, now the foreign key will refer as note_id,
This solves my issue.

How to update object returned in query

So I'm a flask/sqlalchemy newbie but this seems like it should be a pretty simple. Yet for the life of me I can't get it to work and I can't find any documentation for this anywhere online. I have a somewhat complex query I run that returns me a list of database objects.
items = db.session.query(X, func.count(Y.x_id).label('total')).filter(X.size >= size).outerjoin(Y, X.x_id == Y.x_id).group_by(X.x_id).order_by('total ASC')\
.limit(20).all()
after I get this list of items I want to loop through the list and for each item update some property on it.
for it in items:
it.some_property = 'xyz'
db.session.commit()
However what's happening is that I'm getting an error
it.some_property = 'xyz'
AttributeError: 'result' object has no attribute 'some_property'
I'm not crazy. I'm positive that the property does exist on model X which is subclassed from db.Model. Something about the query is preventing me from accessing the attributes even though I can clearly see they exist in the debugger. Any help would be appreciated.
class X(db.Model):
x_id = db.Column(db.Integer, primary_key=True)
size = db.Column(db.Integer, nullable=False)
oords = db.relationship('Oords', lazy=True, backref=db.backref('x', lazy='joined'))
def __init__(self, capacity):
self.size = size
Given your example your result objects do not have the attribute some_property, just like the exception says. (Neither do model X objects, but I hope that's just an error in the example.)
They have the explicitly labeled total as second column and the model X instance as the first column. If you mean to access a property of the X instance, access that first from the result row, either using index, or the implicit label X:
items = db.session.query(X, func.count(Y.x_id).label('total')).\
filter(X.size >= size).\
outerjoin(Y, X.x_id == Y.x_id).\
group_by(X.x_id).\
order_by('total ASC').\
limit(20).\
all()
# Unpack a result object
for x, total in items:
x.some_property = 'xyz'
# Please commit after *all* the changes.
db.session.commit()
As noted in the other answer you could use bulk operations as well, though your limit(20) will make that a lot more challenging.
You should use the update function.
Like that:
from sqlalchemy import update
stmt = update(users).where(users.c.id==5).\
values(name='user #5')
Or :
session = self.db.get_session()
session.query(Organisation).filter_by(id_organisation = organisation.id_organisation).\
update(
{
"name" : organisation.name,
"type" : organisation.type,
}, synchronize_session = False)
session.commit();
session.close()
The sqlAlchemy doc : http://docs.sqlalchemy.org/en/latest/core/dml.html

SQLAlchemy: Dynamically loading tables from a list

I am trying to create a program that loads in over 100 tables from a database so that I can change all appearances of a user's user id.
Rather than map all of the tables individually, I decided to use a loop to map each of the tables using an array of objects. This way, the table definitions can be stored in a config file and later updated.
Here is my code so far:
def init_model(engine):
"""Call me before using any of the tables or classes in the model"""
meta.Session.configure(bind=engine)
meta.engine = engine
class Table:
tableID = ''
primaryKey = ''
pkType = sa.types.String()
class mappedClass(object):
pass
WIW_TBL = Table()
LOCATIONS_TBL = Table()
WIW_TBL.tableID = "wiw_tbl"
WIW_TBL.primaryKey = "PORTAL_USERID"
WIW_TBL.pkType = sa.types.String()
LOCATIONS_TBL.tableID = "locations_tbl"
LOCATIONS_TBL.primaryKey = "LOCATION_CODE"
LOCATIONS_TBL.pkType = sa.types.Integer()
tableList = ([WIW_TBL, LOCATIONS_TBL])
for i in tableList:
i.tableID = sa.Table(i.tableID.upper(), meta.metadata,
sa.Column(i.primaryKey, i.pkType, primary_key=True),
autoload=True,
autoload_with=engine)
orm.mapper(i.mappedClass, i.tableID)
The error that this code returns is:
sqlalchemy.exc.ArgumentError: Class '<class 'changeofname.model.mappedClass'>' already has a primary mapper defined. Use non_primary=True to create a non primary Mapper. clear_mappers() will remove *all* current mappers from all classes.
I cant use clear_mappers as it wipes all of the classes and the entity_name scheme doesn't seem to apply here.
It seems that every object wants to use the same class, although they all should have their own instance of it.
Does anyone have any ideas?
Well, in your case it *is the same Class you try to map to different Tables. To solve this, create a class dynamically for each Table:
class Table(object):
tableID = ''
primaryKey = ''
pkType = sa.types.String()
def __init__(self):
self.mappedClass = type('TempClass', (object,), {})
But I would prefer slightly cleaner version:
class Table2(object):
def __init__(self, table_id, pk_name, pk_type):
self.tableID = table_id
self.primaryKey = pk_name
self.pkType = pk_type
self.mappedClass = type('Class_' + self.tableID, (object,), {})
# ...
WIW_TBL = Table2("wiw_tbl", "PORTAL_USERID", sa.types.String())
LOCATIONS_TBL = Table2("locations_tbl", "LOCATION_CODE", sa.types.Integer())

SQLAlchemy - MappedCollection problem

I have some problems with setting up the dictionary collection in Python's SQLAlchemy:
I am using declarative definition of tables. I have Item table in 1:N relation with Record table. I set up the relation using the following code:
_Base = declarative_base()
class Record(_Base):
__tablename__ = 'records'
item_id = Column(String(M_ITEM_ID), ForeignKey('items.id'))
id = Column(String(M_RECORD_ID), primary_key=True)
uri = Column(String(M_RECORD_URI))
name = Column(String(M_RECORD_NAME))
class Item(_Base):
__tablename__ = 'items'
id = Column(String(M_ITEM_ID), primary_key=True)
records = relation(Record, collection_class=column_mapped_collection(Record.name), backref='item')
Now I want to work with the Items and Records. Let's create some objects:
i1 = Item(id='id1')
r = Record(id='mujrecord')
And now I want to associate these objects using the following code:
i1.records['source_wav'] = r
but the Record r doesn't have set the name attribute (the foreign key). Is there any solution how to automatically ensure this? (I know that setting the foreign key during the Record creation works, but it doesn't sound good for me).
Many thanks
You want something like this:
from sqlalchemy.orm import validates
class Item(_Base):
[...]
#validates('records')
def validate_record(self, key, record):
assert record.name is not None, "Record fails validation, must have a name"
return record
With this, you get the desired validation:
>>> i1 = Item(id='id1')
>>> r = Record(id='mujrecord')
>>> i1.records['source_wav'] = r
Traceback (most recent call last):
[...]
AssertionError: Record fails validation, must have a name
>>> r.name = 'foo'
>>> i1.records['source_wav'] = r
>>>
I can't comment yet, so I'm just going to write this as a separate answer:
from sqlalchemy.orm import validates
class Item(_Base):
[...]
#validates('records')
def validate_record(self, key, record):
record.name=key
return record
This is basically a copy of Gunnlaugur's answer but abusing the validates decorator to do something more useful than exploding.
You have:
backref='item'
Is this a typo for
backref='name'
?

Categories