these are my models
class Countries(models.Model):
Name = models.CharField(max_length=100)
Language = models.IntegerField()
Population = models.IntegerField(default=0)
class World(models.Model):
Languages_spoken = model.Charfield(max_length=12000)
World_population = models.IntegerField(default=0)
I am trying to add Population of all instances in Countries to sum and show on World_population field on class World
What I have tried
class World(models.Model):
Languages_spoken = model.Charfield(max_length=12000)
World_population = models.IntegerField(default=0)
def save(self, *args, **kwargs):
self.World_population = Countries.objects.get(Population) # I know this is not correct
super(World,self).save()
Give this a shot:
from django.db.models import Sum
Countries.objects.aggregate(total_population=Sum('Population'))
More info on aggregation here
You can use Sum() here,
self.World_population = Countries.objects.aggregate(Sum('Population'))
https://docs.djangoproject.com/en/2.1/topics/db/aggregation/
Related
Environment is Python and Django3
I want to make api which retrieve the data from multiple model class.
I have models like this , each CountryStat has Country.
class Country(models.Model):
code = models.CharField(max_length=3,unique=True)
name = models.CharField(max_length=50)
class CountryStat((models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE,null=True)
date = models.DateField(null=True,blank =True)
stat = models.IntegerField()
Now I want to get the latest Coutry Stat for each Country.
So I made the serializer for Country
class CountrySerializer(serializers.ModelSerializer):
latest_stat = serializers.SerializerMethodField()
class Meta:
model = Country
fields = ('id','code','latest_stat')
def get_latest_stat(self,obj):
# how can I get the latest stat from CountryStat model ????
Is this the correct idea or how can I make it??
You should define a custom latest_stat attribute on your model:
class Country(models.Model):
code = models.CharField(max_length=3,unique=True)
name = models.CharField(max_length=50)
def latest_stat(self):
return self.countrystat_set.order_by('-date').first()
For example, I have three Models in django:
class Car(models.Models):
range = models.DecimalField()
speed = models.DecimalField()
def __str__(self):
return self.speed
class Group_of_Cars(models.Models):
name = models.CharField()
starting_city = models. CharField()
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Arrival_time(models.Models):
Location_of_ArrivalPoint = models.CharField()
Last_known_location_of_CarGroup = models.CharField()
Group_of_Cars = models.ForeignKey(Group_of_Cars)
def function(self):
"Get speed of the "Car" in "Group_of_Cars"
def __str__(self):
return self. Location_of_ArrivalPoint
This is an example of what I want to do, not my actual models. The idea is for the user to input a series of values for the type of "Cars" such as speed and range. I'd like "Cars" to be selected when defining parameters for "a Group_of_Cars". What I'm not sure how to do is how to get the speed of the car, for the Group_of_Cars for which I need to calculate an arrival time (Group_of_Cars consists of one type of car and I'd like 'Arrival_time' to be its own table).
Thank you for any input.
models.py
from django.db import models
# Create your models here.
class Car(models.Model):
range = models.DecimalField(decimal_places=2,max_digits=5)
speed = models.DecimalField(decimal_places=2,max_digits=5)
def __str__(self):
return str(self.speed)
class Group_of_Cars(models.Model):
name = models.CharField(max_length=50)
starting_city = models. CharField(max_length=50)
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Arrival_time(models.Model):
Location_of_ArrivalPoint = models.CharField(max_length=50)
Last_known_location_of_CarGroup = models.CharField(max_length=50)
Group_of_Cars = models.ForeignKey(Group_of_Cars, on_delete=models.CASCADE)
def function(self):
# "Get speed of the "Car" in "Group_of_Cars"
return self.Group_of_Cars.car.all()
def __str__(self):
return self. Location_of_ArrivalPoint
In views.py
from django.shortcuts import render
from core.models import Arrival_time
from django.http import HttpResponse
# Create your views here.
def home(request):
arp = Arrival_time.objects.get(Location_of_ArrivalPoint='Newyork')
for i in arp.function():
print(i)
return HttpResponse()
Currently my models are:
class Workout(models.Model):
date = models.DateField()
routine = models.ForeignKey('Routine')
def __str__(self):
return '%s' % self.date
class Routine(models.Model):
name = models.CharField(max_length=255)
exercises = models.ManyToManyField('Exercise')
def __str__(self):
return self.name
class Exercise(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
I want the user to be able to create a new entry specified by a date(Workout). They can also create routines(Routine), associated with the date and filled with different exercises(Exercise) which they can also create.
Here is the part I can't figure out.
I want the user, when adding a new exercise, to be able to choose whether it is a strength exercise or cardio exercise. Strength exercises will have fields like: #of sets, reps, and weight. Where as carido will have fields like length and speed.
I am unclear on how to relate the two types of exercises to the Exercise class.
The most common way of doing this, is to create a generic relationship, such as:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Exercise(models.Model):
name = models.CharField(max_length=255)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
info = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.name
class StrengthExercise(models.Model):
sets, reps, weight = (...)
class CardioExercise(models.Model):
length, speed = (...)
Example use:
>>> from app_name.models import Exercise, CardioExercise
>>> exercise_info = CardioExercise.objects.create(length=600, speed=50)
>>> exercise = Exercise(name="cardio_exercise_1", info=exercise_info)
>>> exercise.save()
>>> exercise.info.length
600
>>> exercise.info.__class__.__name__
'CardioExercise'
OBS: Make sure you have 'django.contrib.contenttypes' in your INSTALLED_APPS (enabled by default).
edit: I completely rewrote the question as the original one didn't clearly explain my question
I want to run a function which is specific to each particular model instance.
Ideally I want something like this:
class MyModel(models.Model):
data = models.CharField(max_length=100)
perform_unique_action = models.FunctionField() #stores a function specific to this instance
x = MyModel(data='originalx', perform_unique_action=func_for_x)
x.perform_unique_action() #will do whatever is specified for instance x
y = MyModel(data='originaly', perform_unique_action=func_for_y)
y.perform_unique_action() #will do whatever is specified for instance y
However there is no datatype FunctionField. Normally this would be solvable with inheritance, and creating subclasses of MyModel, maybe like this:
class MyModel(models.Model):
data = models.CharField(max_length=100)
perform_unique_action = default_function
class MyModelX(MyModel):
perform_unique_action = function_X
class MyModelY(MyModel):
perform_unique_action = function_Y
x = MyModelX(data='originalx')
x.perform_unique_action() #will do whatever is specified for instance x
y = MyModelY(data='originaly')
y.perform_unique_action() #will do whatever is specified for instance y
Unfortunately, I don't think I can use inheritance because I am trying to access the function this way:
class MyModel(models.Model):
data = models.CharField(max_length=100)
perform_unique_action = default_function
class SecondModel(models.Model):
other_data = models.IntegerField()
mymodel = models.ForeignKey(MyModel)
secondmodel = SecondModel.objects.get(other_data=3)
secondmodel.mymodel.perform_unique_action()
The problem seems to be that I don't know what type the foreign key is going to be in SecondModel if I override the perform_unique_action in subclasses.
Can I access MyModel from SecondModel as a foreign key and still have a unique function for each instance of MyModel?
This works for me. I haven't tested it, but you should be able to create another class and override their methods and it'll work. Check the class Meta line, it'll treat it as an abstract class. Here's an example of my actual classes that I'm working on right now.
EDIT: Added VoteComment class and tested it. It works as expected!
class Vote(models.Model):
VOTE_ENUM = (
(VoteEnum.DOWN_VOTE, VoteEnum.toString(VoteEnum.DOWN_VOTE)),
(VoteEnum.NONE, VoteEnum.toString(VoteEnum.NONE)),
(VoteEnum.UP_VOTE, VoteEnum.toString(VoteEnum.UP_VOTE)),
)
question = models.ForeignKey(Question, null=False, editable=False, blank=False)
voter = models.ForeignKey(User, blank=False, null=False, editable=False)
vote_type = models.SmallIntegerField(default=0, null=False, blank=False, choices=VOTE_ENUM)
class Meta:
abstract = True
def is_upvote(self):
return self.vote_type > 0
def is_downvote(self):
return self.vote_type < 0
class VoteAnswer(Vote):
answer = models.ForeignKey(Answer, null=False, editable=False, blank=False)
class Meta:
unique_together = (("voter", "answer"),) # to prevent user from voting on the same question/answer/comment again
def __unicode__(self):
vote_type = "UP" if vote_type > 0 else ("DOWN" if vote_type < 0 else "NONE")
return u"{0}: [{1}] {2}".format(user.username, vote_type, answer.text[:32])
def is_upvote(self):
return "FOO! "+str(super(VoteAnswer, self).is_upvote())
class VoteComment(Vote):
comment = models.ForeignKey(Comment, null=False, editable=False, blank=False)
class Meta:
unique_together = (("voter", "comment"),) # to prevent user from voting on the same question/answer/comment again
def __unicode__(self):
vote_type = "UP" if vote_type > 0 else ("DOWN" if vote_type < 0 else "NONE")
return u"{0}: [{1}] {2}".format(user.username, vote_type, comment.text[:32])
def is_upvote(self):
return "BAR!"
I came up with two ways of having a specific function defined for each object. One was using marshal to create bytecode which can be stored in the database (not a good way), and the other was by storing a reference to the function to be run, as suggested by Randall. Here is my solution using a stored reference:
class MyModel(models.Model):
data = models.CharField(max_length=100)
action_module = models.CharField(max_length=100)
action_function = models.CharField(max_length=100)
class SecondModel(models.Model):
other_data = models.IntegerField()
mymodel = models.ForeignKey(MyModel)
secondmodel_obj = SecondModel.objects.get(other_data=3)
#The goal is to run a function specific to the instance
#of MyModel referred to in secondmodel_obj
module_name = secondmodel_obj.mymodel.action_module
func_name = secondmodel_obj.mymodel.action_function
module = __import__(module_name)
func = vars(module)[func_name]
func()
Thanks to everyone who replied, I couldn't have got to this answer if it weren't for your help.
You could achive some similar behavior overriding the save method. And providing special callbacks to your instances.
Something like:
def default_function(instance):
#do something with the model instance
class ParentModel(model.Model):
data = models.CharField()
callback_function = default_function
def save(self, *args, **kwargs):
if hasattr(self, 'callback_function'):
self.callback_function(self)
super(ParentModel, self).save(*args, **kwargs)
class ChildModel():
different_data = models.CharField()
callback_function = other_fun_specific_to_this_model
instance = ChildModel()
#Specific function to this particular instance
instance.callback_function = lambda inst: print inst.different_data
instance.save()
You can write endpoints on your server and limit their access to just your self. Then store in each model instance corresponding url. For example:
views.py
def funx_x(request):
pass
def func_y(request):
pass
models.py:
class MyModel(models.Model):
data = models.CharField(max_length=100)
perform_unique_action = models.URLField()
and then:
x = MyModel(data='originalx', perform_unique_action='http://localhost/funx_x')
requests.post(x.perform_unique_action)
i dont know whether i understand u correct or not. but you can check out this example here.
Example:
A string representing an attribute on the model. This behaves almost the same as the callable, but self in this context is the model instance. Here's a full model example:
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')
How do I create a dynamic field on a model?
Let's say I'm writing an application related to the stock market. I make a purchase on one day and sometime later I want to check the gain (or loss) based on today's price. I'd have a model like this:
class Purchase(models.Model):
ticker = models.CharField(max_length=5)
date = models.DateField()
price = models.DecimalField(max_digits=20, decimal_places=3)
quantity = models.IntegerField()
What I'd like to do is define a model something like this:
class PurchaseGain(Purchase):
gain = models.DecimalField(max_digits=20, decimal_places=3)
class Meta:
proxy = True
So that I could do this:
todays_price = get_price_from_webservice(ticker)
for p in PurchaseGain.objects.get_purchase_gain(todays_price):
print '%s bought on %s for a gain of %s' % (p.ticker, p.date, p.gain)
Where p.gain is dynamically computed based on the input to get_purchase_gain. Rather than just constructing dictionaries on the fly I want to use a model, because I'd like to pass this around and generate forms, save changes, etc from the instance.
I tried creating a derived QuerySet, but that led to a circular dependency, because Purchase needed to know about the QuerySet (through a custom manager) and the QuerySet returned an iterator that needed to instantiate a PurchaseGain, which was derived from Purchase.
What options do I have?
Thanks,
Craig
Why not add a gain() method to your model?
class Purchase(models.Model):
ticker = models.CharField(max_length=5)
date = models.DateField()
price = models.DecimalField(max_digits=20, decimal_places=3)
quantity = models.IntegerField()
def gain(self, todays_price=None):
if not todays_price:
todays_price = get_price_from_webservice(self.ticker)
result_gain = todays_price - self.price
return result_gain
Then you can pretty much do what you want:
for p in Purchase.objects.all():
print '%s bought on %s for a gain of %s' % (p.ticker, p.date, p.gain())
Creating a proxy class is what confused me. By just adding attributes to a Purchase, I was able to accomplish what I wanted.
class PurchaseQuerySet(QuerySet):
def __init__(self, *args, **kwargs):
super(PurchaseQuerySet, self).__init__(*args, **kwargs)
self.todays_price = None
def get_with_todays_price(self, todays_price):
self.todays_price = todays_price
cloned = self.all()
cloned.todays_price = todays_price
return cloned
def iterator(self):
for p in super(PurchaseQuerySet, self).iterator():
p.todays_price = self.todays_price
yield p
class PurchaseManager(models.Manager):
def get_query_set(self):
return PurchaseQuerySet(self.model)
def __getattr__(self, name)
return getattr(self.get_query_set(), name)
class Purchase(models.Model):
ticker = models.CharField(max_length=5)
date = models.DateField()
price = models.DecimalField(max_digits=20, decimal_places=3)
quantity = models.IntegerField()
objects = PurchaseManager()
#property
def gain(self):
return self.todays_price - self.price
Now I can do:
for p in Purchase.objects.filter(ticker=ticker).get_with_todays_price(100):
print p
print p.gain