changing django model filed data before saving to database - django

i want to update model field data before saving to database.
class mynumber(TimeStampedModel):
text = models.TextField(max_length=10000, null=True, blank=True)
number = models.DecimalField(default=0, max_digits=9, decimal_places=2)
#serializer file
class mynumberSerializer(serializers.ModelSerializer):
class Meta:
model = mynumber
fields = "__all__"
#view
class mynumberViewSet(CreateListMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
serializer_class = mynumberSerializer
queryset = mynumber.objects.all()
i want to divide number field by 2 before saving to database.
what should be the best approach?

One approach is overriding the def save() method of your model class mynumber.
def save() method is going to run when example_object.save() is invoked on an object and you can access it's fields like this before saving into database. So you can override the save() method of your model,
class Example(models.Model):
text= models.TextField(null=True, blank=True)
number = models.DecimalField(max_digits=None, decimal_places=None)
def save(self, *args, **kwargs):
self.number = self.number / 2
super(Example, self).save(*args, **kwargs)

Related

Queryset from non-related model in __init__ modelform method

I have two model classes. They are not related models (no relationship).
# models.py
class Model1(models.Model):
description = models.TextField()
option = models.CharField(max_length=64, blank=False)
def __str__(self):
return self.option
class Model2(models.Model):
name = models.CharField(max_length=64, blank=False)
def __str__(self):
return self.name
I have respective form from where I am submitting and saving data in my table. I want to use my Model2 data to fill-in 'option' field as select field, so I am introducing below init method.
# forms.py
class Model1Form(forms.ModelForm):
def __init__(self, *args, **kwargs):
all_options = Model2.objects.all()
super(Model1Form, self).__init__(*args, **kwargs)
self.fields['option'].queryset = all_options
class Meta:
model = Model1
fields = ('description', 'option')
It does not render the dropdown on my template, so I am wondering whether it is right way to address the issue (acknowledging that models are not related to each other).

Append an object to a list with django GenericViewSet

I wrote a many-to-many field for my model but when I try to write an updated view with generic-view-set don't append the new obj just replace it,how can I write to append the new obj to list, my model:
class Portfolio(models.Model):
name = models.CharField(max_length=50, blank=False, null=True, default='portfolio')
user = models.ForeignKey('accounts.User', on_delete=models.DO_NOTHING, related_name='investor')
assets = models.ManyToManyField(Assets, related_name='portfolio_assets')
def __str__(self):
return self.name
Serializer
class PortfolioUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Portfolio
fields = ['id', 'name']
View
class PortfolioAssetsUpdate(mixins.UpdateModelMixin, viewsets.GenericViewSet
):
queryset = Portfolio.objects.all()
serializer_class = PortfolioAssetsUpdateSerializer
def put(self, request, pk):
return self.update(request, pk)
Now my problem is when I update my portfolio, a new object replaces to old one, I need to append new to old,I really don't have any idea

Django update number of items on each save or delete

I am new to Django and still learning. I am looking to keep track of how many events I have under a test. My current model looks like
class Test(models.Model):
name = models.CharField(max_length=255)
description = models.CharField(max_length=255, blank=True)
num_of_events = models.IntegerField(default=0)
class Meta:
verbose_name = 'Test'
verbose_name_plural = 'Tests'
def __str__(self):
return self.name
class Event(models.Model):
name = models.CharField(max_length=255)
test = models.ForeignKey(Test,on_delete=models.CASCADE)
class Meta:
verbose_name = 'Event'
verbose_name_plural = 'Events'
def __str__(self):
return self.name
def save(self):
obj, created = Test.objects.update_or_create(name=self.test)
obj.num_of_events += 1
super().save()
def delete(self):
self.test.num_of_events -= 1
super().delete()
I thought I could just override the save() function but it does not update on the admin panel and still shows 0.
I am trying to figure out what I am doing wrong.
EDIT: admin.py
class TestAdmin(admin.ModelAdmin):
list_display = ('name', 'description', 'num_of_events')
fieldsets = [
(None, {'fields': ('name', 'description')})
]
class EventsAdmin(admin.ModelAdmin):
pass
class PropertyAdmin(admin.ModelAdmin):
list_display = ('name', 'property_type', 'expected_value')
admin.site.register(Test, TestAdmin)
admin.site.register(Event, EventsAdmin)
admin.site.register(Property, PropertyAdmin)
You forget to save the Test object. For example with:
class Event(models.Model):
# …
def save(self):
if self.test_id is not None:
obj = self.test
obj.num_of_events += 1
obj.save()
super().save()
def delete(self):
if self.test_id is not None:
self.test.num_of_events -= 1
self.test.save()
super().delete()
But regardless, storing the number of items is usually not a good idea. Say that you change the .test of a given Event, then you need to subtract from the old Test and add to the new Test. Furthermore ORM operations in bulk, like .update(..) circumvent .save() and signals, so it will be hard or impossible to keep this correct.
The point is that you do not need to store the number of Events. Indeed, you can simply obtain these with:
from django.db.models import Count
Test.objects.annotate(number_of_events=Count('event'))
The Test objects that arise from this queryset will have an extra attribute .number_of_events that contains the number of related Event ojbects.

How to filter or query using abstract parent class in Django model?

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.

Django Restful Api of ManytoMany models to show the foreign objects

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.