I have the following code in my app:
models.py
class MainTable(Base):
__tablename__ = "main_table"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, unique=True, index=True, nullable=False)
owner = Column(String, index=True)
metas = relationship("ChildTable", back_populates="item")
class ChildTable(Base):
__tablename__ = "child"
id = Column(Integer, primary_key=True, index=True)
segment = Column(Integer)
name = Column(String)
main_name = Column(String, ForeignKey('main_table.name'), nullable=False)
item = relationship("MainTable", back_populates="metas")
__table_args__ = (UniqueConstraint('segment', 'main_name', name='_meta_for_main'),
)
And when I run my app, and create new obj in db:
{
"name": "string",
"owner": "string",
"metas": [
{
"segment": 0,
"name": "string",
"main_name": "string",
}
]
}
I get the following error:
AttributeError: 'MainMetaCreate' object has no attribute '_sa_instance_state'
schemas.py
class EnvironmentMetaBase(BaseModel):
segment: int
name: str
main_name: str
Haw you met the following problem?
Related
Using FastAPI I can't fetch all the data. For example I have this output :
Response body Download (but the items list is always empty):
[
{
"email": "mmm#gmail.com",
"id": 1,
"is_active": true,
"items": []
},
{
"email": "ee#gmail.com",
"id": 2,
"is_active": true,
"items": []
},
]
Endpoint are for example:
#app.get("/users/", response_model=list[schemas.User])
async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
users = crud.get_users(db, skip=skip, limit=limit)
return users
#app.get("/users/{user_id}", response_model=schemas.User)
async def read_user(user_id: int, db: Session = Depends(get_db)):
db_user = crud.get_user(db, user_id=user_id)
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user
I have the following schemas (database is PostgreSQL):
from pydantic import BaseModel
class ItemBase(BaseModel):
title: str
description: str | None = None
class ItemCreate(ItemBase):
pass
class Item(ItemBase):
id: int
owner: int
class Config:
orm_mode = True
class UserBase(BaseModel):
email: str
class UserCreate(UserBase):
password: str
class User(UserBase):
id: int
is_active: bool
items: list[Item] = []
class Config:
orm_mode = True
Database is postgresql
Models are (table users and table items):
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
class User(Base):
__tablename__ = "users"
__table_args__ = {'schema': 'socialcampaigns'}
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
is_active = Column(Boolean, default=True)
items_rel = relationship("Item", back_populates="owner_id_rel")
class Item(Base):
__tablename__ = "items"
__table_args__ = {'schema': 'socialcampaigns'}
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String, index=True)
owner = Column(Integer, ForeignKey("socialcampaigns.users.id"))
owner_id_rel = relationship("User", back_populates="items_rel")
Crud code is:
from sqlalchemy.orm import Session
from . import models, schemas
def get_user(db: Session, user_id: int):
return db.query(models.User).filter(models.User.id == user_id).first()
def get_users (db: Session, skip: int = 0, limit: int = 100):
return db.query(models.User).offset(skip).limit(limit).all()
How to solve it? How do I view the list of Items when viewing users?
I am new to FastAPI and SQL-Alchemy, I am having trouble creating a schema and relationship of the many-to-many table (association table).
Here is an example, a student can enroll in multiple courses and a single course can have multiple students thus making many-to-many relationship.
Database Models
class Student(Base):
__tablename__ = "student"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
class Course(Base):
__tablename__ = "course"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
class StudentCourse(Base):
__tablename__ = "student_course"
id = Column(Integer, primary_key=True, index=True)
student_id = Column(Integer, ForeignKey("student.id"), nullable=False)
course_id = Column(Integer, ForeignKey("course.id"), nullable=False)
What relation do I need to define and how to design a schema from which I can get the following responses:
Response 1
[
{
"id": 1,
"name": "Student A",
"courses": [
{
"id": 1,
"name": "Course A"
},
{
"id": 2,
"name": "Course B"
}
]
},
{
"id": 2,
"name": "Student B",
"courses": [
{
"id": 1,
"name": "Course A"
},
{
"id": 3,
"name": "Course C"
}
]
},
{...}
]
Response 2
[
{
"id": 1,
"name": "Course A",
"students": [
{
"id": 1,
"name": "Student A"
},
{
"id": 2,
"name": "Student B"
}
]
},
{
"id": 2,
"name": "Course B",
"students": [
{
"id": 1,
"name": "Student A"
},
]
},
{
"id": 3,
"name": "Course C",
"students": [
{
"id": 2,
"name": "Student B"
},
]
},
{...}
]
In my opinion, it is simpler and preferable to use an association table instead of an association object for this many-to-many relationship, since you don't need extra fields.
So, according to the documentation, your database models should be:
student_course = Table("student_course", Base.metadata,
Column("student_id", ForeignKey("student.id"), primary_key=True),
Column("course_id", ForeignKey("course.id"), primary_key=True))
class Student(Base):
__tablename__ = "student"
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
courses = relationship("Course",
secondary=student_course,
back_populates="students")
class Course(Base):
__tablename__ = "course"
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
students = relationship("Student",
secondary=student_course,
back_populates="courses")
and your pydantic models (schemas):
class Student(BaseModel):
id: int
name: str
class Config:
orm_mode = True
class Course(BaseModel):
id: int
name: str
class Config:
orm_mode = True
class StudentOut(Student):
courses: List[Course]
class CourseOut(Course):
students: List[Student]
where StudentOut and CourseOut are your response models
i am really new to DRM and i have to following problem
I have three related models. Now i want to for each sensor values to the related patient. My models look like:
class Sensor(models.Model):
sensor_name = models.CharField(max_length=200, primary_key=True)
sensor_refreshRate = models.FloatField()
sensor_prio = models.IntegerField(choices=[
(1, 1), (2, 2), (3, 3), (4, 4), ], default='1')
sensor_typ = models.CharField(
max_length=200,
choices=[
('bar', 'bar'), ('pie', 'pie'),
('line', 'line'), ('text', 'text'),
],
default='bar'
)
class Patient(models.Model):
firstName = models.CharField(max_length=200)
lastName = models.CharField(max_length=200)
age = models.IntegerField()
doctor = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sensor = models.ManyToManyField(Sensor)
class Value(models.Model):
value_date = models.DateTimeField(auto_now_add=True)
value = models.FloatField()
sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
Now i would like to send a JSON file which looks like:
[
{
"value": 445.0,
"sensor": "Pressure",
"patient": 3
},
{
"value": 478.0,
"sensor": "Temperature",
"patient": 3
}
]
Now i am not sure how to serialize my JSON.
Thanks in advance
your data models seems incomplete.
There's no link between the Value model and the Patient one.
So first I'd suggest to modify the Value model
class Value(models.Model):
value_date = models.DateTimeField(auto_now_add=True)
value = models.FloatField()
sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
then you could create a queryset
qs = Value.objects.filter(.....).values(
'patient_id', 'sensor__sensor_name', 'value'
)
and the write your serializer
I have two models Employee and AccessDr.
Employee Model=>
class Employee(models.Model):
empid = models.CharField(max_length=20, unique=True)
empname = models.CharField(max_length=50)
phone = models.CharField(max_length=20, blank=True)
token = models.ForeignKey(
Company, to_field='token', on_delete=models.CASCADE)
def __str__(self):
return "%s" % (self.empid)
class Meta:
managed = True
db_table = 'employee'
AccessDr Model=>
class AccessDr(models.Model):
empid = models.ForeignKey(
Employee, to_field='empid', on_delete=models.CASCADE)
_date = models.DateField()
_time = models.IntegerField()
device = models.CharField(max_length=5)
takey = models.CharField(max_length=3, default='00')
token = models.ForeignKey(
Company, to_field='token', on_delete=models.CASCADE)
def __str__(self):
return "%s %s" % (self.empid, self._date)
class Meta:
ordering = ['_date']
managed = True
db_table = 'tstrdoor'
I would like to return object when the request to AccessDr like SQL left join, Example json=>
{
empid:'',
empname:'', <=this one from employee model
phone:'', <=this one from employee model
_date:'',
_time:'',
.
.
}
How can I achieve that one?
have a look at this LEFT JOIN Django ORM
read this as well https://docs.djangoproject.com/en/2.2/topics/db/queries/#spanning-multi-valued-relationships
you can print query to look at how it translates to SQL by
Employes=AccessDr.objects.values('employee__empname','employee__phone')
print(Employes.query)
Are you using serializers in the views? in this case, you could create a serializer field
which will put agreement data as an array like this
class CustomerSerializer(serializers.ModelSerializer):
agreements = AgreementSerializer(many=True, read_only=True)
class Meta:
model = Customer
fields = [
'id',
'username',
'mail',
'fName',
'lName',
'fNameEng',
'lNameEng',
'personalId',
'phone',
'crmId', # "ID": "20995",
'agreements',
]
depth = 1
Are you using serializers in the views? in this case, you could create serializer field
which will put agreement data as an array like this
{
"id": 985,
"username": null,
"mail": "undefined",
"fName": "Merab",
"lName": "Dasv",
"fNameEng": "Merab",
"lNameEng": "Dasv",
"personalId": "01022342346003629",
"phone": "5912324234282331",
"crmId": 1439,
"agreements": [
{
"id": 884,
"signDate": "2015-04-16",
"accountDate": "2015-05-01",
"amount": 0,
"comBalance": -1445.0,
"status": 1,
"details": [
{
"square": 32.38,
"amount": 35.0,
"object": {
"id": 578,
"object": 2,
"block": 1,
"floor": 19,
"flat": "7",
"cadastre": "05.24.04.055.01.563",
"square": 32.38,
"pCounter": 25915123146,
"wCounter": 104412312435,
"accountDate": "2015-04-01T00:00:00",
"comBalance": -1445.0,
"comDeptAmount": 1895.0,
"rentDate": null,
"active": 1,
"finaAmount": 0,
"crmId": 0
}
},
]
},
]
}
class User(Base):
"""
users table
"""
__tablename__ = 'users'
__table_args__ = {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
id = Column(INTEGER, primary_key=True)
email = Column(String(64), nullable=False, unique=True)
password = Column(String(64), nullable=False)
name = Column(String(32), nullable=False)
last_login_time = Column(DateTime, default='')
last_login_ip = Column(String(32), default='')
create_time = Column(DateTime, nullable=False)
status = Column(SMALLINT, default=0)
role = relationship("Role",
secondary="role_user",
backref=backref('user'))
def __init__(self, email, password, name, last_login_time=now,
last_login_ip='0', create_time=now, status=0):
self.email = email
self.password = md5(password)
self.name = name
self.last_login_time = last_login_time
self.last_login_ip = last_login_ip
self.create_time = create_time
self.status = status
def __repr__(self):
return "<User('%s', '%s')>" % (self.name, self.email)
class Role(Base):
"""
roles table
"""
__tablename__ = 'roles'
__table_args__ = {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
id = Column(SMALLINT(5), primary_key=True)
name = Column(String(32), nullable=False, unique=True)
def __init__(self, name):
self.name = name
def __repr__(self):
return "<Role('%s', '%s')>" % (self.id, self.name)
class role_user(Base):
"""
role_user association table
"""
__tablename__ = 'role_user'
__table_args__ = {
'mysql_engine': 'InnoDB',
'mysql_charset': 'utf8'
}
user_id = Column(INTEGER, ForeignKey('users.id'), primary_key=True)
role_id = Column(SMALLINT(5), ForeignKey('roles.id'), primary_key=True)
def __init__(self, user_id, role_id):
self.user_id = user_id
self.role_id = role_id
when I create an user,I meet the error:
u1 = User(email='john#example.com', password='12345', name='john')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "<string>", line 2, in __init__
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/instrumentation.py", line 310, in _new_state_if_none
state = self._state_constructor(instance, self)
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/util/langhelpers.py", line 582, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/instrumentation.py", line 145, in _state_constructor
self.dispatch.first_init(self, self.class_)
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/event.py", line 409, in __call__
fn(*args, **kw)
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/mapper.py", line 2209, in _event_on_first_init
configure_mappers()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/mapper.py", line 2118, in configure_mappers
mapper._post_configure_properties()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/mapper.py", line 1242, in _post_configure_properties
prop.init()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/interfaces.py", line 231, in init
self.do_init()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/properties.py", line 1028, in do_init
self._setup_join_conditions()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/properties.py", line 1102, in _setup_join_conditions
can_be_synced_fn=self._columns_are_mapped
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/relationships.py", line 114, in __init__
self._determine_joins()
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/orm/relationships.py", line 180, in _determine_joins
consider_as_foreign_keys=consider_as_foreign_keys
File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.1dev-py2.6-linux-i686.egg/sqlalchemy/sql/util.py", line 345, in join_condition
b.foreign_keys,
AttributeError: type object 'role_user' has no attribute 'foreign_keys'
>>>
jiankong#ubuntu:~/git/admin-server$ python manage.py shell
Python 2.6.5 (r265:79063, Oct 1 2012, 22:07:21)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from apps.auth.models import User
>>> u1 = User(email='john#example.com', password='12345', name='john')
what can i do to solve the question? thank you !!
you've got conflicting names for role_user, in that there's a class called role_user and a table with the same name. So secondary="role_user" picks the class object first. Maybe state it like this:
relationship("Role", secondary="role_user.__table__")
EDIT: ideally you'd define "role_user" as a Table only, and define it before you do "secondary". Follow the example at http://docs.sqlalchemy.org/en/latest/orm/relationships.html#many-to-many.