models.py
class Employees(models.Model):
emp_no = models.IntegerField(primary_key=True)
birth_date = models.DateField()
first_name = models.CharField(max_length=14)
last_name = models.CharField(max_length=16)
gender = models.CharField(max_length=1)
hire_date = models.DateField()
class Meta:
managed = False
db_table = 'employees'
class Salaries(models.Model):
emp_no = models.ForeignKey(Employees, models.DO_NOTHING, db_column='emp_no',related_name='salaries', primary_key=True)
salary = models.IntegerField()
from_date = models.DateField()
to_date = models.DateField()
class Meta:
managed = False
db_table = 'salaries'
unique_together = (('emp_no', 'from_date'),)
Mysql raw query:
SELECT `employees`.`emp_no`, `employees`.`birth_date`, `employees`.`first_name`, `employees`.`last_name`, `employees`.`gender`, `employees`.`hire_date`,
(
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'salary', `salaries`.`salary`,
'from_date', `salaries`.`from_date`,
'to_date', `salaries`.`to_date`
)
) FROM `salaries` WHERE (`employees`.`emp_no` = `salaries`.`emp_no`)
) as salaries
FROM `employees`
INNER JOIN `salaries` root_salaries ON `root_salaries`.`salary` > 60000
WHERE `employees`.`emp_no` = `root_salaries`.`emp_no` LIMIT 100 OFFSET 100
Output for raw query:
[
{
"emp_no": 10017,
"birth_date": "1958-07-06",
"first_name": "Cristinel",
"last_name": "Bouloucos",
"gender": "F",
"hire_date": "1993-08-03",
"salaries": [
{
"salary": 71380,
"to_date": "1994-08-03",
"from_date": "1993-08-03"
},
{
"salary": 75538,
"to_date": "1995-08-03",
"from_date": "1994-08-03"
}
]
},
{
"emp_no": 10018,
"birth_date": "1954-06-19",
"first_name": "Kazuhide",
"last_name": "Peha",
"gender": "F",
"hire_date": "1987-04-03",
"salaries": [
{
"salary": 55881,
"to_date": "1988-04-02",
"from_date": "1987-04-03"
},
{
"salary": 59206,
"to_date": "1989-04-02",
"from_date": "1988-04-02"
},
{
"salary": 61361,
"to_date": "1990-04-02",
"from_date": "1989-04-02"
}
]
}
]
My question is how to generate the above raw query using Django ORM.
Thanks.
Views.py
query_set = Employees.objects.filter(salaries__salary__gt=60000).annotate(
salaries_1=Subquery(
Salaries.objects.filter(emp_no=OuterRef('emp_no'), salary__gt=60000).values(
salaries=JSONArrayAgg(JSONObject(
salary=F('salary'),
from_date=F('from_date'),
to_date=F('to_date')
))))
).distinct()[100:200]
employee_ser = EmployeesWithSalaryGroupSerializer(query_set, many=True)
data = employee_ser.data
Serializers.py
class EmployeesWithSalaryGroupSerializer(serializers.Serializer):
emp_no = serializers.IntegerField()
birth_date = serializers.DateField()
first_name = serializers.CharField()
last_name = serializers.CharField()
gender = serializers.CharField()
hire_date = serializers.DateField()
salaries_1 = serializers.JSONField()
def to_representation(self, instance):
ret = super(EmployeesWithSalaryGroupSerializer, self).to_representation(instance=instance)
ret['salaries'] = json.loads(instance.salaries_1)
ret.pop('salaries_1')
return ret
Related
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 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
}
},
]
},
]
}
I am new in Django rest API. I create an API for my project where user can get data from the system via API. I serialize data and pass also but I also want to count the result and pass that value too.
my view.py is here
def categorySearch(request, slug):
itemViewCategory = Item.objects.raw('''select *, company.slug as companySlug, company.name as companyName,
field.id as fieldId, field.name as fieldName, category.name as categoryName from company
inner join category on company.business_type = category.id inner join category_field on
category_field.category_id = category.id inner join custom_field as field on category_field.field_id = field.id
where category.id = (select id from category where slug= %s) and field.name LIKE %s order by company.name ''', [slug, product])
itemViewCategoryCount = Item.objects.raw(
'''select *, COUNT(company.name) as companyCount from company inner join category on
company.business_type = category.id where category.id = (select id from category where slug= %s)
order by company.name ''', [slug])
results = []
for val in itemViewCategory:
place_json = {}
place_json['name'] = val.name
place_json['email'] = val.email
place_json['address'] = val.address
results.append(place_json)
return JsonResponse(results, safe=False)
where its return data like this
[
{
"name": "Washing Plants",
"email": "ababil.washing#yahoo.com",
"address": "ababil.washing#yahoo.com"
},
{
"name": "Washing Plants",
"email": "info#dekkoisho.com",
"address": "Holding # 79/1, Chandra, Kaliakoir"
},
{
"name": "Washing Plants",
"email": "aznmery90#yahoo.com",
"address": "79/8/2 Bibir Bagicha ( 4 No. Gate )\r\nNorth Jatrabari, Dhaka-1205."
},
]
But I want this type of data formate
{
"statuscode": "0",
"message": "Success",
"data": [
{
"companyName": "Adorn Knitwear Ltd.",
"phone": "01713047421",
"city": "Dhaka"
},
{
"companyName": "Adury Apparels Ltd.",
"phone": "029333274",
"city": "Dhaka"
},
{
"companyName": "Advance World Ltd.",
"phone": "01711537851",
"city": "Dhaka"
},
{
"companyName": "Afaku Apparels Ltd.",
"phone": "01711869977",
"city": "Dhaka"
}
],
"common": {
"totalCompany": "104",
}
}
Now how can I format my data like this?
for val in itemViewCategory:
place_json = {}
place_json['name'] = val.name
place_json['email'] = val.email
place_json['address'] = val.address
results.append(place_json)
final_result = {}
final_result['data'] = results
final_result["statuscode"] = 0
final_result["message"] = "success"
return JsonResponse(final_result,safe=False)
I have struggling in this error unknown column error.
I have 3 table the following are
Marketplace --- One to Many relationship (marketplace has many products.)
Product --- One to One relationship (Product belongs to marketplace)
Country -- One to many relationship (Country has many products.)
The sample JSON given below :
[{
"id": 1,
"name": "XYZ Name",
"code": "XYZCODE",
"Products": [
{
"id": 150,
"product_name": "ABC",
"product_location": 19,
"state_id": 24,
"city": "California",
"Country": {
"id": 19,
"name": "USA"
}
},
{
"id": 154,
"product_name": "DEF",
"product_location": 19,
"state_id": 24,
"city": "New York",
"Country": {
"id": 19,
"name": "USA"
}
}
]
}]
If am query city and Country name inside the Country table getting following error in sequelize
{
"code": "ER_BAD_FIELD_ERROR",
"errno": 1054,
"sqlState": "42S22",
"sqlMessage": "Unknown column 'Products->Country.name' in 'on clause'",
"sql": "SELECT `MarketplaceType`.`id`, `MarketplaceType`.`name`, `MarketplaceType`.`code`, `Products`.`id` AS `Products.id`, `Products`.`product_name` AS `Products.product_name`, `Products`.`product_location` AS `Products.product_location`, `Products`.`state_id` AS `Products.state_id`, `Products`.`city` AS `Products.city`, `Products->Country`.`id` AS `Products.Country.id`, `Products->Country`.`name` AS `Products.Country.name` FROM `marketplace_type` AS `MarketplaceType` LEFT OUTER JOIN `product` AS `Products` ON `MarketplaceType`.`id` = `Products`.`marketplace_type_id` AND `Products`.`status` = 1 AND `Products`.`marketplace_id` = 1 AND (`Products`.`city` = 'California' OR `Products->Country`.`name` = 'California') LEFT OUTER JOIN `country` AS `Products->Country` ON `Products`.`product_location` = `Products->Country`.`id` WHERE `MarketplaceType`.`status` = 1 AND `MarketplaceType`.`marketplace_id` = 1;"
}
AND MYSQL Query are following :
SELECT `MarketplaceType`.`id`, `MarketplaceType`.`name`, `MarketplaceType`.`code`, `Products`.`id` AS `Products.id`, `Products`.`product_name` AS `Products.product_name`, `Products`.`product_location` AS `Products.product_location`, `Products`.`state_id` AS `Products.state_id`, `Products`.`city` AS `Products.city`, `Products->Country`.`id` AS `Products.Country.id`, `Products->Country`.`name` AS `Products.Country.name` FROM `marketplace_type` AS `MarketplaceType` LEFT OUTER JOIN `product` AS `Products` ON `MarketplaceType`.`id` = `Products`.`marketplace_type_id` AND `Products`.`status` = 1 AND `Products`.`marketplace_id` = 1 AND (`Products`.`city` = 'California' OR `Products->Country`.`name` = 'California') LEFT OUTER JOIN `country` AS `Products->Country` ON `Products`.`product_location` = `Products->Country`.`id` WHERE `MarketplaceType`.`status` = 1 AND `MarketplaceType`.`marketplace_id` = 1;
ORM Query using sequelize :
var marketplaceTypeQueryObj = {};
var productCountQueryParames = {};
marketplaceTypeQueryObj['status'] = status["ACTIVE"];
marketplaceTypeQueryObj['marketplace_id'] = marketplace['WHOLESALE'];
productCountQueryParames['status'] = status["ACTIVE"];
productCountQueryParames['marketplace_id'] = marketplace['WHOLESALE'];
if (req.query.origin) {
productCountQueryParames['$or'] = [{
city: req.query.origin
}, {
'$Products.Country.name$': req.query.origin
}, {
'$Products.State.name$': req.query.origin
}];
}
console.log('productCountQueryParames', productCountQueryParames);
model['MarketplaceType'].findAll({
where: marketplaceTypeQueryObj,
include: [{
model: model['Product'],
where: productCountQueryParames,
include: [{
model: model['Country'],
attributes: ['id', 'name']
}, {
model: model['State'],
attributes: ['id', 'name']
}],
attributes: ['id', 'product_name', 'product_location', 'state_id', 'city'],
required: false
}],
attributes: ['id', 'name', 'code']
})
Change
attributes: ['id', 'product_name', 'product_location', 'state_id', 'city'],
to
attributes: ['id', 'product_name', 'product_location', 'state_id', 'city','country_id'],
Add country id in your product model attributes
How can i select a name column from another table instead of id ,
example :
class Attendance(db.Model):
__tablename__ = 'zk_attendance'
id = db.Column(db.Integer,primary_key=True)
uid = db.Column(db.Integer,db.ForeignKey('zk_users.uid'))
date = db.Column(db.Date)
time = db.Column(db.Time)
device = db.Column(db.Integer,db.ForeignKey('devices.id'))
user = db.relationship('Users',backref=db.backref('user', lazy='dynamic'))
class Users(db.Model):
__tablename__ = 'zk_users'
uid = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String)
And if i want to select all attendance :
#app.route('/api/attendance/<string:date_from>/<string:date_to>',methods=['GET'])
def get_attend_date_date(date_from,date_to):
data = db.session.query(Attendance).filter(Attendance.date.between(date_from,date_to)).order_by(Attendance.date,Attendance.time)
attendance_schema = AttendanceSchema(many=True)
data = attendance_schema.dump(data).data
return jsonify({'attendance':data})
OUTPUT
{
"attendance": [
{
"Device": 4,
"date": "2016-01-18",
"id": 18805,
"time": "00:49:00",
"user": 30025
},
{
"Device": 4,
"date": "2016-01-18",
"id": 18902,
"time": "00:49:00",
"user": 30045
},
BUT
am getting the user uid , i want to return the user.name
Am using flask_marshmallow to serialize the data before send it as josn , to be able send the user name , i have to nest the name from the users schema as the following :
class UsersSchema(ma.Schema):
name = fields.String(dump_only=True)
class AttendanceSchema(ma.Schema):
date = fields.Date(dump_only=True)
user = fields.Nested(UsersSchema)