Is it possible to sum values in fields of several objects?
class MyModel(model.Models): name = models.Charfield() amount = models.IntegerField()
Model
Object 1
Object 2
Object 3
Object 4
Object 5
Here i want the sum of "amount" in all the objects to use in my validation. If the total "amount" is correct, i want to save all objects.
How do i do this?
you can do it by creating a method (function in class) in the same model.
MyModel(models.Model):
...
def sum_of_all_amounts(self):
return (amount_1 + amount_2 ...)
you can call this function in the templating language by {{ MyModel.sum_of_all_amounts }}.
If you want to validate saving the model by the total amount then you can update the same function or make a method in which you can raise ValidationError if the total amount doesn't satisfy your needs.
If you don't know how to do that then you can ask me again by commenting on my answer.
Related
Sorry for the noobish question, but I am trying to make a simple stock management website with Django and I could not get this part to work.
I could not get the part where I register a certain amount of crates of soda and then when it gets taken away from the stock I want the web app to register it however amount less.
My model is as follows:
class Drink(models.Model):
category = models.CharField(max_length=100)
name = models.CharField(max_length=200, unique=True)
crate = models.IntegerField()
So if the stock manager registers 25 crates (crate) a certain drink (name) and then after some time takes 20 of the crates out for use, I want it to be able to register that 20 crates were taken out and that there are now 5 left. I want to do this on the front-end. I used this form to register a Drink object:
class CrateForm(forms.ModelForm):
class Meta:
model = Drink
fields = ["name", "category", "crate",]
labels = {'name': "Name", "crate": "Crate",}
So I guess my question is: how do I create a form that allows me to subtract whatever amount of crates I want to take out for use, and then registers the remaining amount back. It’s kind of like the CRUD stuff where it lets me update that specific field crate.
PS: it should also give me an error when I try to take out 60 crates when I only have 20 crates in the stock.
Like I said I am just getting started on Django and I am stuck here for good. Any ideas??
One of many ways: use an ordinary form.
class SoldCrateForm( forms.Form):
quantity_sold = forms.IntegerField( ...)
in a FormView, do the work in the form_valid method. A secondary question is how to know which Drink you are operating on. You could select it in the same form, or if it's already known you could pass it in the URL. I'll assume the latter, that it's been parsed in an URL definition as drink:
def form_valid(self, form):
drink = Drink.objects.get( pk = self.kwargs['drink'] )
stock = drink.crate
sold = form.cleaned_data['quantity_sold']
if sold > stock:
form.add_error('quantity_sold',
f'There are only {stock} crates in stock')
return self.form_invalid( self, form)
drink.crate = drink.crate - sold
drink.save()
return super().form_valid( self, form)
my model.py
class Main(models.Model):
name= ....
amount = models.PositiveIntegerField(default=40000)
In my views:
def mainf(request):
listmain = models.Main.objects.all()
for data in listmain:
value = data.amount * 5
calculated_data = data_and_value
context = {'main':calculated_data}
return render(request,'main/main.html',context)
How i can fetch fields from models and calculate some fileds and pass them(calculated_data) to my template?
For example i want to calculate salary base on hours. i want to fetch hours from database and calculate hours*500 and then send hours and salary to my template.
data_and_value can be object or anything. i want get this and send to my template
Either define them as properties on the model, or pass them through the context to the template.
If the value is based purely on fields in one model instance, it's good to define a property. For example,
class Thing( models.Model)
# Thing has height, width, depth fields
...
#property
def adjusted_volume(self):
return (self.height+10) * (self.width+10) * (self.depth+10)
In your template (and indeed in your code) you can now refer to {{ thing.adjusted_volume }}, assuming thing was included in the context, either explicitly, or by a class-based-view's context_object_name="thing"
Your question shows an example of passing the result of a computation that's not restricted to a single object instance to the template where you can refer to it as {{ main}} (But the code is incorrect, value gets repeatedly calculated and then thrown away in a loop, and data_and_value is not defined).
I want to get the numbers of values in Two ManyToMany Field and compain both to one Integer Field by function (def)
class Video(models.Model):
viewers = models.ManyToManyField(Account, related_name='video_views')
viewers_by_ip = models.ManyToManyField(UsersByIP, default='192.168.0.1', blank=True)
viewers_count = models.IntegerField('Here I want to get the number of both field')
You many do it without saving sum of count viewers_by_ip and viewers into database, actually you have to ways.
Make a property method that will calculate it pet each object:
class Video(models.Model):
#property
def total_viewes_count(self):
return self.viewers.count() + self.viewers_by_ip.count()
Add a annotation to queryset which getting model object for you:
from django.db.models import Count
Video.objects.annotate(
total_viewes_count=Count('viewers')+Count('viewers_by_ip')
).get(pk=<Video's primary key>)
in both cases you may use it in template like that:
{{ video.total_viewes_count }}
I have two models that go as follows (for simplicity's sake):
class Bank(models.Model):
name = models.CharField(max_length=250)
class Person(models.Model):
bank = models.ForeignKey(Bank)
savings = models.IntegerField()
debts = models.IntegerField()
def get_net_worth(self):
return self.savings - self.debts
And I want to write a method that lets me know the "total net worth" of the people in a bank, like:
class Bank(models.Model):
...
def get_net_worth(self):
return self.person_set.all().aggregate(Sum('get_net_worth'))
But of course Django complains that such field does not exist:
django.core.exceptions.FieldError: Cannot resolve keyword 'get_net_worth' into field.
Is there a way to achieve this without having to explicitly store the "net worth" in the database?
Edit:
In case you wonder, one can just do
def get_net_worth(self):
person_queryset = self.person_set.all()
return person_queryset.aggregate(Sum('savings'))['savings__sum'] - person_queryset.aggregate(Sum('debts'))['debts__sum']
But I do have to somehow use the get_net_worth method on every "Person".
Edit 2:
Just to clarify things up: These two are not my actual models, they are over-simplified examples of what I want to achieve, and what I essentially want to do is NOT to do arithmetic between two fields, but rather use a model's method as the field for the aggregate function (of course a method can do some more complex stuff before returning a value), therefore this one is not a duplicate of the other question.
I have model with field named "number". It's not the same as id, it's position while displayed on website, users can sort teams around.
I need something for default property of number. I think I should just count the number of positions in the database and add one, so if there are 15 positions inside db, the new team would be last on list and have "number" 16.
But I don't know how to do it, inside models.py file.
Inside views.py I would just use
Iteam.objects.count()
But what can I use inside model declaration? How can the model check itself?
Edit:
I tried do it as Joey Wilhelm suggested:
from django.db import models
class ItemManager(models.Manager):
def next_number(self):
return self.count() + 1
class Iteam(models.Model):
name = models.CharField()
objects = ItemManager()
number = models.IntegerField(default=objects.next_number())
Unfortunetly i get error:
AttributeError: 'NoneType' object has no attribute '_meta'
This is actually something you would want to do on a manager, rather than the model itself. The model should represent, and perform actions for, an individual instance. Whereas the manager represents, and performs actions for a collection of instances. So in this case you might want something like:
from django.db import models
class ItemManager(models.Manager):
def next_number(self):
return self.count() + 1
class Item(models.Model):
number = models.IntegerField()
objects = ItemManager()
That being said, I could see this leading to a lot of data integrity issues. Imagine the scenario:
4 items are created, with numbers 1, 2, 3, 4
Item 2 gets deleted
1 new item is created; this item now has a number of 4, giving you a duplicate
Edit:
The above approach will work only for pre-generating 'number', such as:
Iteam.objects.create(number=Iteam.objects.get_number(), name='foo')
In order to have it work as an actual default value for the field, you would need to use a less savory approach, such as:
from django.db import models
class Iteam(models.Model):
name = models.CharField()
number = models.IntegerField(default=lambda: Iteam.get_next_number())
#classmethod
def get_next_number(cls):
return cls.objects.count() + 1
I would still warn against this approach, however, as it still could lead to the data integrity issues mentioned above.