how select column in flask sqlalchemy - mysql

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)

Related

Django - Raw query to ORM

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

How to serialize nested objects with related 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

How to Left Join Model (or) Table in DRF

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
}
},
]
},
]
}

Django rest API formatting data

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)

How to match a top level array in json with specs2

In specs2 you can match an array for elements like this:
val json = """{"products":[{"name":"shirt","price":10, "ids":["1", "2", "3"]},{"name":"shoe","price":5}]}"""
def aProductWith(name: Matcher[JsonType], price: Matcher[JsonType]): Matcher[String] =
/("name").andHave(name) and /("price").andHave(price)
def haveProducts(products: Matcher[String]*): Matcher[String] =
/("products").andHave(allOf(products:_*))
json must haveProducts(
aProductWith(name = "shirt", price = 10) and /("ids").andHave(exactly("1", "2", "3")),
aProductWith(name = "shoe", price = 5)
)
(Example taken from here: http://etorreborre.github.io/specs2/guide/SPECS2-3.0/org.specs2.guide.Matchers.html)
How do I do the same thing i.e. match the contents of products if products is a root element in the json? What should haveProducts look like?
val json = """[{"name":"shirt","price":10, "ids":["1", "2", "3"]},{"name":"shoe","price":5}]"""
You can replace /("products").andHave(allOf(products:_*)) with have(allOf(products:_*)) like this:
val json = """[{"name":"shirt","price":10, "ids":["1", "2", "3"]},{"name":"shoe","price":5}]"""
def aProductWith(name: Matcher[JsonType], price: Matcher[JsonType]): Matcher[String] =
/("name").andHave(name) and /("price").andHave(price)
def haveProducts(products: Matcher[String]*): Matcher[String] = have(allOf(products:_*))
json must haveProducts(
aProductWith(name = "shirt", price = 10) and /("ids").andHave(exactly("1", "2", "3")),
aProductWith(name = "shoe", price = 5)
)