I cannot get the last measurement for each device based on the device's ID from the measurement. If someone can advise me on how to implement this?
Models
class Devices(models.Model):
deviceid = models.AutoField(db_column='deviceId', primary_key=True) # Field name made lowercase.
devicename = models.CharField(db_column='deviceName', unique=True, max_length=128) # Field name made lowercase
devicestatus = models.IntegerField(db_column='deviceStatus') # Field name made lowercase.
Class Meta:
managed = False
db_table = 'devices'
class Measurements(models.Model):
measurementid = models.AutoField(db_column='measurementId', primary_key=True) # Field name made lowercase.
deviceid = models.ForeignKey(Devices, models.DO_NOTHING, related_name="measurment_details", db_column='deviceId') # Field name made lowercase.
measurement = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
get_latest_by = 'measurementtime'
db_table = 'measurements'
Serializer
class MeasurmentsSerializer(serializers.ModelSerializer):
class Meta:
model = Measurements
fields = ('measurementid','measurement')
class DeviceSerializer(serializers.ModelSerializer):
latestmeasurment = serializers.SerializerMethodField()
count = 0
def get_latestmeasurment(self, obj):
qs = Measurements.objects.using('###').last()
serializer = MeasurmentsSerializer(instance=qs, many=False)
self.count = 1 + self.count
print(self.count , serializer.data )
return serializer.data
class Meta:
model = Devices
fields = ("devicename", 'latestmeasurment')
Views
class RetrieveAllDevicesView(viewsets.ModelViewSet):
http_method_names = ['get']
permission_classes = [permissions.IsAuthenticated]
serializer_class = DeviceSerializer
queryset = Devices.objects.using('###')
In serializer, you can see the count for primitive debug:
1 {'measurementid': 2942080, 'measurement': '35.0'}
2 {'measurementid': 2942080, 'measurement': '35.0'}
3 {'measurementid': 2942080, 'measurement': '35.0'}
4 {'measurementid': 2942080, 'measurement': '35.0'}
5 {'measurementid': 2942080, 'measurement': '35.0'}
6 {'measurementid': 2942080, 'measurement': '35.0'}
7 {'measurementid': 2942080, 'measurement': '35.0'}
8 {'measurementid': 2942080, 'measurement': '35.0'}
9 {'measurementid': 2942080, 'measurement': '35.0'}
10 {'measurementid': 2942080, 'measurement': '35.0'}
Response in JSON from view:
enter image description here
def get_latestmeasurment(self, obj):
device_measurements = obj.measurment_details.all()
last_measurement = device_measurements.order_by('id').last()
serializer = MeasurmentsSerializer(last_measurement)
return serializer.data
you get all measurments for each device and after sorting it you'll get the last one as your last_measurment
Related
I'm using Django Rest Framework.
Here is model:
class TimeSlot(models.Model):
date_start = models.DateTimeField(default=None, null=True, blank=True)
booked = models.BooleanField(default=False)
user = models.ForeignKey(User, related_name='time_slots', on_delete=models.SET_NULL, default=None)
Here is my serializer:
class CreateBookingSerializer(serializers.ModelSerializer):
class Meta:
model = TimeSlot
fields = ('id','booked','user',)
extra_kwargs = {'booked': {'required': True}}
Here is my view:
class CreateBookingViewSet(viewsets.ModelViewSet):
queryset = TimeSlot.objects.all()
serializer_class = CreateBookingSerializer
http_method_names = ['put']
def perform_update(self, serializer):
if (self.request.data['booked'] == 1):
serializer.save(user=self.request.user, booked=True)
I want to set booked to true only if the current value is False.
I'm using PUT method. so my url is /create_booking/id/
If I could get the id in my view, I would check the current booked value! How to get the id?
You can try to use self.kwargs['id'].
class CreateBookingViewSet(viewsets.ModelViewSet):
queryset = TimeSlot.objects.all()
serializer_class = CreateBookingSerializer
http_method_names = ['put']
def perform_update(self, serializer):
id = self.kwargs['id']
if (self.request.data['booked'] == 1):
serializer.save(user=self.request.user, booked=True)
I'm using Django 2.x.
I have two models
class AmountGiven(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.PROTECT)
amount = models.FloatField(help_text='Amount given to the contact')
interest_rate = models.FloatField(blank=True, default=None, null=True)
given_date = models.DateField(default=timezone.now)
total_due = models.FloatField(blank=True, default=0.0, editable=False)
class AmountReturned(models.Model):
amount_given = models.ForeignKey(AmountGiven, on_delete=models.CASCADE, blank=True)
amount = models.FloatField()
return_date = models.DateField(default=date.today)
Use case
There can be multiple records of the amount given to a contact
There can be multiple records of the returned amount for an amount given
Now, I want to get total_due amount for a particular contact. This includes
total_payable = total_given + interest
total_due = total_payable - total_returned
To calculate total_due and interest, I have defined few property methods in the AmountGiven model.
#property
def interest_to_pay(self):
if self.interest_rate:
simple_interest_amount = ...
return simple_interest_amount
return 0
#property
def total_payable(self):
return self.amount + self.interest_to_pay
#property
def amount_due(self):
total_due = self.total_payable - self.total_returned
self.total_due = total_due
self.save()
return total_due
#property
def total_returned(self):
returned_amount = self.amountreturned_set.aggregate(total_returned=Sum('amount'))['total_returned']
if not returned_amount:
returned_amount = 0
return returned_amount
In Contact model, there is a property method to get the total due amount for the contact.
#property
def amount_due(self):
total_due = 0
for due in self.amountgiven_set.all():
total_due += due.amount_due
return total_due
Query
ContactSerializer
class ContactMinSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = (
'id', 'first_name', 'amount_due', 'created', 'modified'
)
Since amount_due property is being used in the ContactSerializer, amount_due property is called everytime a contact is call and thus results in nested DB queries.
How can I optimise the above scenario in the application to reduce the DB queries while getting contact or list of contacts? Specially two properties amount_due and total_returned.
amount_due() updates the total_due field in the table, every time it is called.
Edit 2
class ContactViewSet(LoggingMixin, viewsets.ModelViewSet):
serializer_class = ContactMinSerializer
def get_queryset(self):
return Contact.objects.filter(user=self.request.user).annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
).order_by('first_name')
You're looking for annotations.
Your viewset should define a queryset as follows:
from django.db.models import F, Sum
Contact.objects.annotate(
total_due=Sum(
F('amountgiven_set__total_payable')
- F('amountgiven_set__total_returned')
)
)
Then define a MethodSerializer field on your serializer to account for it.
class ContactMinSerializer(serializers.ModelSerializer):
total_due = serializers.SerializerMethodField()
def get_total_due(self, obj):
return return self.total_due
class Meta:
model = Contact
fields = (
'id', 'first_name', 'created', 'modified',
'total_due',
)
This one is interesting to solve. I am building a module to register address for hospital, medical store and doctors. There is an abstracted model PrimaryAddress and a subclass called MedicalStorePrimaryAddress, and more subclasses will use the same abstracted model. I am using django rest framework to get the listings based on proximity (latitude, longitude and city). Now how could I filter it all using parent class, i.e PrimaryAddress model as I want to filter all the entities, i.e hospital, medical store and doctor nearby.
I have looked into django-polymorphic library but it doesnt help with geodjango and abstract class.
Any help suggestion is appreciated. Thanks
Here is the code sample:
# MODELS
class PrimaryAddress(gismodels.Model):
street = gismodels.CharField(max_length=255)
city = gismodels.CharField(max_length=60)
state = gismodels.CharField(max_length=100,
choices=settings.US_STATES,
default="CT")
landmark = gismodels.TextField()
latitude = gismodels.FloatField(null=True, blank=True)
longitude = gismodels.FloatField(null=True, blank=True)
location = gismodels.PointField(null=True, blank=True)
objects = gismodels.GeoManager()
def __unicode__(self):
return self.street
class Meta:
verbose_name = "Address"
verbose_name_plural = "Addresses"
abstract = True
def save(self, *args, **kwargs):
if self.latitude and self.longitude:
self.location = Point(self.longitude, self.latitude)
super(PrimaryAddress, self).save(*args, **kwargs)
class MedicalStoreAddress(PrimaryAddress):
medical_store = gismodels.OneToOneField(MedicalStore, related_name="medical_store_address",
on_delete=gismodels.CASCADE, null=True, blank=True)
# objects = gismodels.GeoManager()
def __unicode__(self):
return self.street
class Meta:
verbose_name = "Medical Store Address"
verbose_name_plural = "Medical Store Addresses"
def save(self, *args, **kwargs):
if self.latitude and self.longitude:
self.location = Point(self.longitude, self.latitude)
super(MedicalStoreAddress, self).save(*args, **kwargs)
# VIEW
class ProximityFilter(ListAPIView):
serializer_class = AddressSerializer
# authentication_classes = (authentication.TokenAuthentication, authentication.SessionAuthentication,)
# permission_classes = (permissions.IsAuthenticated,)
pagination_class = StandardResultsSetPagination
def get_queryset(self):
longitude = self.kwargs.get('longitude')
latitude = self.kwargs.get('latitude')
city = self.kwargs.get('city')
current_point = GEOSGeometry('POINT(%s %s)' % (longitude, latitude), srid=4326)
# raise
queryset = MedicalStoreAddress.objects.filter(city__iexact=city, location__distance_lte=(current_point, D(mi=700000000))).distance(
current_point).order_by('distance')
return queryset
# SERIALIZER
class AddressSerializer(HyperlinkedModelSerializer):
class Meta:
model = DoctorPrimaryAddress
fields = ('pk', 'street', 'latitude', 'longitude', 'city')
This paste expires on 2018-03-29 21:26:23. View raw. Remove now (Why am I seeing this?) Pasted through web.
The "Brand" object is foreign key of "company",they are ManytoMany relationship,and Brand object exists the field "company_Group"
the models are as follows:
class Brand(models.Model):
Company_Group = models.ManyToManyField(Company)
Brand_Group = models.CharField(u'Brand Group',max_length=255, default="")
Pref_Brand_Name_Flg = models.CharField(u'Preferred Name Flag',max_length=255, default="")
Pref_Brand_Name = models.CharField(u'Preferred Name',max_length=255, default="")
PrimaryContact = models.ForeignKey(UserRole, null=True, blank=True)
class Company(models.Model):
Pref_Company_Name_Flg = models.CharField(u'Preferred Name Flag',max_length=255, default="")
Pref_Company_Name = models.CharField(u'Preferred Name',max_length=255, default="")
Company_Type = models.CharField(u'Company Type',max_length=255, default="")
serializers
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = '__all__'
the Serializer as follows ,data_export_setting.Company_form_stand is the field as
class CompanySerializer(serializers.HyperlinkedModelSerializer):
Brand = BrandSerializer(source='brand', read_only=True)
class Meta:
model = Company
Company_form_stand=['id', 'Brand', 'Company_Type','Company_Name','company_Name_SC']
fields = data_export_setting.Company_form_stand
depth = 2
def create(self, validated_data):
return Company.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.__dict__.update(**validated_data)
instance.save()
return instance
the viewset are as follows
class BrandViewSet(viewsets.ModelViewSet):
queryset = Brand.objects.all()
serializer_class = BrandSerializer
model = Brand
def get_serializer(self, *args, **kwargs):
if 'data' in kwargs:
data = kwargs['data']
if isinstance(data, list):
kwargs['many'] = True
return super(BrandViewSet, self).get_serializer(*args, **kwargs)
class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
and I want to show the company objects with Brand objects ,however,it seems to ignore the brand object and its field
appreciate any help ,thanks
Try,
Brand = BrandSerializer(source='brand_set', read_only=True, many=True)
Since, you have defined the field relation as ManyToMany, more than one Brand objects are related to a single Company instance. By using the reverse relation, you can access them in your serializer, and many=True lets the serializer handle multiple objects in the relation.
My database:
User
-----------------------------------
id | name
-----------------------------------
1 | Phuong Vu
-----------------------------------
Profile
-----------------------------------
user_id | phone_number
-----------------------------------
1 | 123456
-----------------------------------
My models:
class User(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True)
phone_number = models.CharField(max_length=15, unique=True, blank=True)
My serializers:
class ProfileSerializer(serializers.ModelSerializer):
def validate(self, attrs):
##################################
# I want get current instance here
##################################
print self.instance
return attrs
class Meta:
model = Profile
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(many=False)
class Meta:
model = User
This is in my view, I called is_valid 2 times in 2 ways to test:
profile_data = {
'phone_number':'123456'
}
user = User.objects.get(pk=1)
profile = Profile.objects.get(user_id=1)
setattr(user, 'profile', profile)
data = {
'profile': profile_data
}
serializer = UserSerializer(
user,
data=data,
partial=True
)
# This said 'Profile phone number is exist'
# because ProfileSerialiser.instance is None
serializer.is_valid()
# This is fine because ProfileSerialiser.instance is not None
profile_serialiser = ProfileSerialiser(profile, data=profile_data, partial=True)
profile_serializer.is_valid()
After create serializer instance, UserSerializer.instance is not None but children ProfileSerializer.instance is None.
So how can I fix this issue? (Access to self.instance in ProfileSerializer after it has created via UserSerialiser)