I have a model like this:
class InvoiceItem(models.Model):
book = models.ForeignKey(Book, on_delete=models.PROTECT)
invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT, related_name='items')
title = models.CharField(max_length=100, null=True, blank=True)
price = models.IntegerField(null=True, blank=True)
discount = models.IntegerField(blank=True, default=0)
totalprice = models.IntegerField(null=True, blank=True)
count = models.IntegerField(null=True, blank=True)
and I want to calculate discount from book's discount table
How can I do it?
should I calculate it in models?
Here we can create property for override models fields like this (without override save() method)
class InvoiceItem(models.Model):
book = models.CharField(max_length=100)
invoice = models.PositiveIntegerField()
title = models.CharField(max_length=100, null=True, blank=True)
og_price = models.IntegerField(null=True, blank=True)
sell_price = models.IntegerField(null=True, blank=True)
discount = models.IntegerField(blank=True, default=0)
discounted_price = models.IntegerField(blank=True, default=0)
count = models.IntegerField(null=True, blank=True)
#property
def discounted_price(self):
return ((self.og_price*self.discount)/100)
#property
def sell_price(self):
return ((self.og_price - self.discounted_price))
with override save() method
class InvoiceItem(models.Model):
book = models.CharField(max_length=100)
invoice = models.PositiveIntegerField()
title = models.CharField(max_length=100, null=True, blank=True)
og_price = models.IntegerField(null=True, blank=True)
sell_price = models.IntegerField(null=True, blank=True)
discount = models.IntegerField(blank=True, default=0)
discounted_price = models.IntegerField(blank=True, default=0)
count = models.IntegerField(null=True, blank=True)
#property
def dis_price(self):
print((self.og_price*self.discount)/100)
return ((self.og_price*self.discount)/100)
#property
def selling_price(self):
print(self.og_price - self.dis_price)
return (self.og_price - self.dis_price)
def save(self, *args, **kwargs):
self.sell_price = self.selling_price
self.discounted_price = self.dis_price
super(InvoiceItem, self).save(*args, **kwargs)
Output
You need to fill only those fields
NOTE: here i changed two fields for data adding in database
book = models.CharField(max_length=100)
invoice = models.PositiveIntegerField()
If you want to calculate it before saving, or when it enter form admin panel or from any place you can override Save method in django model
Or you can calculate from view for example and insert it on saving
Save method example:
class MyModel(models.Model):
...
def save(self, *args, **kwargs):
here you can get field value and insert it in any field you want
Related
Currently I am able to upload only 1 image per product.
My Model
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True,
default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
numReviews = models.IntegerField(null=True, blank=True, default=0)
price = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
This is my serializer
class ProductSerializer(serializers.ModelSerializer):
reviews = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Product
fields = '__all__'
def get_reviews(self, obj):
reviews = obj.review_set.all()
serializer = ReviewSerializer(reviews, many=True)
return serializer.data
This is the views file
#api_view(['GET'])
def getProduct(request, pk):
product = Product.objects.get(_id=pk)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
I am trying to also upload the images to a folder which has same product name if possible.
In order to upload multiple images for each product you have to modify your model as you have already designed. Let's see:
Your Product model should look like this-
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, null=True, blank=True)
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
mum_of_reviews = models.IntegerField(null=True, blank=True,
default=0)
price = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
stock_counter = models.IntegerField(null=True, blank=True,
default=0)
created_at = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
Let's create a new model to add multiple images for each product-
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL,
null=True, related_name='product_images')
image = models.ImageField(null=True, blank=True,
default='/placeholder.png')
Let's write the serializer for them
class ProductImageSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields = '__all__'
class ProductRetriveSerializer(serializers.ModelSerializer):
reviews = serializers.SerializerMethodField(read_only=True)
images = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Product
fields = '__all__'
def get_reviews(self, obj):
reviews = obj.review_set.all()
serializer = ReviewSerializer(reviews, many=True)
return serializer.data
def get_images(self, obj):
images = obj.product_images.all()
return ProductImageSerializer(images, many=True)
class ProductCreationSerializer(serializers.ModelSerializer):
images = ProductImageSerializer(many=True, required=False)
class Meta:
model = Product
fields = '__all__'
Let's write the API for creating a product with multiple images
class ProductCreateAPIView(APIView):
parser_classes = (FormParser, MultiPartParser)
serializer = ProductCreationSerializer
#transaction.atomic
def post(self, request, format=None):
images = request.data.get('images', [])
request.data.pop('images')
serialized_data = self.serializer(data=request.data)
product_obj = None
if serialized_data.is_valid():
product_obj=Product.objects.create(**serialized_data.validated_data)
if product_obj and len(images) > 0:
for image_data in images:
image_data['product_id'] = str(product_obj._id)
product_image_serialized_data = ProductImageSerializer(data=image_data)
if product_image_serialized_data.is_valid(raise_exception=True):
product_image_obj = ProductImage.objects.create(**product_image_serialized_data.validated_data)
# Write your necessary code if needed
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
I have at least tried to make you understand the way you will upload multiple images.Best of luck :)
I am making a app for one kindergarten in my city. I have kids model and payment model.
For updating kid I am using class based view generic UpdateView and for creating a payment i am using form and function view. I have not problems with payment form when I am using a different template but when I try to put it on the same template, payment form is not showing up and it's not working. Is it possible to have payment form on same template as UpdateView class ? I am using UpdateView class as profile page and I would like to have payment form on the same page. Please help. Thanks
models:
class Kids(models.Model):
name = models.CharField(max_length=100, blank=True, null=True)
city_birthday = models.CharField(max_length=100, blank=True, null=True)
custom_id = models.CharField(max_length=100 ,blank=True, null=True)
gender = models.CharField(max_length=100, choices=gender_choices, null=True, blank=True)
address = models.CharField(max_length=250, null=True, blank=True)
contact_phone = models.CharField(max_length=100, blank=True, null=True)
family_size = models.IntegerField(null=True, blank=True)
living_with = models.CharField(max_length=100, choices=living_choices, null=True, blank=True)
number_of_preschool_kids_in_family = models.IntegerField(null=True, blank=True)
kid_already_been_in_kindergarten = models.CharField(max_length=100, choices=preschool_choices,
null=True, blank=True ,default=False)
father_name = models.CharField(max_length=100, blank=True, null=True)
father_education_level = models.CharField(max_length=200, blank=True, null=True)
father_company = models.CharField(max_length=200, blank=True, null=True)
mother_name = models.CharField(max_length=100, blank=True, null=True)
mother_education_level = models.CharField(max_length=200, blank=True, null=True)
mother_company = models.CharField(max_length=200, blank=True, null=True)
parent_notes = models.CharField(max_length=500, blank=True, null=True)
program_choice = models.CharField(max_length=100, choices=kindergarten_program_choice, null=True,
blank=True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
class Payment(models.Model):
user = models.ForeignKey(Kids, on_delete=models.CASCADE, blank=True, null=True)
bank_paper_id = models.IntegerField(null=True, blank=True)
payment_date = models.CharField(max_length=100, null=True, blank=True)
paid = models.FloatField(null=True, blank=True)
need_to_pay = models.FloatField(null=True, blank=True)
notes = models.CharField(max_length=500, blank=True, null=True)
def __str__(self):
return self.user.name
views:
class UpdateKidView(UpdateView):
model = Kids
fields = '__all__'
template_name = 'vrtic/update_kid.html'
success_url = reverse_lazy('vrtic:kids')
def create_payment(request, pk):
kid = Kids.objects.get(id=pk)
payment_form = PaymentForm()
if request.method == 'POST':
payment_form = PaymentForm(request.POST)
if payment_form.is_valid():
payment = payment_form.save(commit=False)
payment.user = kid
payment_form.save()
return redirect('vrtic:kids')
context = {
'payment_form': payment_form,
'kid': kid
}
return render(request, 'vrtic/update_kid.html', context)
form:
class PaymentForm(forms.ModelForm):
class Meta:
model = Payment
fields = '__all__'
class UpdateKidView(UpdateView):
model = Kids
form_class = KidsForm
second_form_class = PaymentForm
template_name = 'vrtic/update_kid.html'
success_url = reverse_lazy('vrtic:kids')
def get_context_data(self, **kwargs):
context = super(UpdateKidView, self).get_context_data(**kwargs)
context['form'] = self.form_class(instance=self.get_object())
context['second_form'] = self.second_form_class()
return context
def post(self, request, **kwargs):
kids_form = self.form_class(request.POST, request.FILES, instance=self.get_object())
if kids_form.is_valid():
kid = kids_form.save()
payment_form = self.second_form_class(request.POST)
...
Not the happiest solution, but u got the idea, if need more help contact me to explain on Serbian, not sure how are the rules here for languages : )
I want to create a Model in which I can store the same models as for example in a folder there can be several folders.
I tried like this:
class Service(models.Model):
name = models.TextField(default="")
price = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.name
class ServiceType(models.Model):
services_types = models.ManyToManyField(ServiceType, null=True, blank=True)
services = models.ManyToManyField(Service, null=True, blank=True)
name = models.TextField(default="")
But it didn't work. How can this problem be solved?
If you want to reference same model then you have to use quotation 'ModelName' like this.
So your code will be like:
class Service(models.Model):
name = models.TextField(default="")
price = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.name
class ServiceType(models.Model):
services_types = models.ManyToManyField('ServiceType', null=True, blank=True)
services = models.ManyToManyField(Service, null=True, blank=True)
name = models.TextField(default="")
How can I display all related values from my model and display in template as one?
class DentalProcedures(models.Model):
id = models.AutoField(primary_key=True)
patient = models.ForeignKey(PatientInfo, on_delete=models.CASCADE, null=True, blank=True)
proc_date = models.DateField(null=True, blank=True)
proc_tooth_no = models.CharField('Tooth No./s', max_length=10, null=True, blank=True)
procedure = models.CharField('Procedure', max_length=200, null=True, blank=True)
amount_charged = models.IntegerField('Amount Charged', null=True, blank=True)
class DentalPayment(models.Model):
id = models.AutoField(primary_key=True)
procedureid = models.ForeignKey(DentalProcedures, on_delete=models.CASCADE, null=True, blank=True)
patient = models.ForeignKey(PatientInfo, on_delete=models.CASCADE, null=True, blank=True)
amount_paid = models.IntegerField('Amount Paid', null=True, blank=True)
date_paid = models.DateField(null=True, blank=True)
I want to display the patient summary of payment including the, procedure name, amount charged and payment details.
View
class DentalPaymentDetailView(DetailView):
context_object_name = "payment_detail"
model = PatientInfo
template_name = "patient/procedure_payment_detail.html"
def get_context_data(self, **kwargs):
context = super(DentalPaymentDetailView, self).get_context_data(**kwargs)
payment = DentalPayment.objects.filter(patient=self.kwargs['pk'])
context["payment"] = payment.DentalProcedures_set.all()
return context
If you have some logic to provide the patient_id, try this
context["payment"] = DentalPayment.objects.filter(patient_id=patient_id).values('procedureid__procedure', 'procedureid__amount_charged', 'amount_paid', 'date_paid')
to get total amount paid,
from django.db.models import Sum
total_amount = DentalPayment.objects.filter(patient_id=patient_id).aggregate(tota_amount_paid=Sum('amount_paid'))
here is my code :
class Invitation(models.Model):
#other fields here
Code = models.CharField(max_length=128, null=True, blank=True)
Tags = models.ManyToManyField("CategorieInvitation", null=True, blank=True)
Tags = models.ManyToManyField("Usage", null=True, blank=True)
Note = models.CharField(max_length=128, null=True, blank=True)
Used = models.BooleanField(default=False, blank=True)
SendTo = models.EmailField(null=True, blank=True)
# a revoir
def post_save(self, model_instance, add):
if self.Code.__len__() == 0 :
self.Code = generate_invitation(1)[0]
self.save()
how to replace Code with the result of generate_invitation if Code is blank or null even if created in django-admin interface ?
regards
Bussiere
For what you are trying to do it's probably easier and more efficient to override the save method.
class Invitation(models.Model):
#other fields here
code = models.CharField(max_length=128, null=True, blank=True)
tags = models.ManyToManyField("CategorieInvitation", null=True, blank=True)
tags2 = models.ManyToManyField("Usage", null=True, blank=True)
note = models.CharField(max_length=128, null=True, blank=True)
used = models.BooleanField(default=False, blank=True)
send_to = models.EmailField(null=True, blank=True)
# a revoir
def save(self, *args, **kwargs):
if not self.code:
self.code = generate_invitation(1)[0]
super(Invitation, self).save(*args, **kwargs)
By the way post_save is not something that should be a model instance method.
See: https://docs.djangoproject.com/en/1.4/ref/signals/#signals