from sqlalchemy import Column, Integer, String, Boolean, Float, DateTime, ForeignKey
from sqlalchemy.orm import relationship, reconstructor
from app import utils
import datetime
import pandas
from base import Base
from series import Series
class ConstantSeries(Series):
__tablename__ = 'constantseries'
# ID Primary Key (linked to parent)
id = Column(Integer, ForeignKey('series.id'), primary_key=True)
# The value of this series to be returned for all periods.
value = Column(Float)
__mapper_args__ = {'polymorphic_identity': 'constantseries'}
def GetData(self, scenario, periods):
"""Get data values for the specified periods.
"""
return pandas.Series(data=[self.value]*len(periods), index=periods)
I have been given the code above but I want to be able to change it so that I can have a series that has different values depending on what day it is. For example if it is a weekday I have a value of 100 and for a weekend have a value of 200
Can you tell me how you are calling the above code and what it currently returns?
It seems that the GetData function just returns a data structure, i.e. it returns the structure of a Column for every period, but no actual data.
What's not shown here is how the actual data in the Columns is populated and accessed.
You could loop through your periods and build the Series data according to the day e.g if periods contained ['mon','tue','wed','thu','fri','sat','sun']
def GetData(self, scenario, periods):
mydata = {}
for p in periods:
if p in ['sat','sun']:
e[p] = 200
else:
e[p] = 100
return pandas.Series(mydata, index=periods)
Then calling GetData should return something like
'mon' 100
'tue' 100
...
'sat' 200
'sun' 200
but thats not the structure you want and i dont think its how the Getdata function is being used.
def GetData(self, scenario, periods):
rtn = {}
for timest, val in cap.GetData(base_scenario,utils.enumerate_periods(start,end,'H','CET')).iteritems():
if timest.weekday_name in ['Saturday', 'Sunday']:
rtn[timest.weekday_name] = (0.72 * val)
#0.46*2574
else:
rtn[timest.weekday_name] = (1.0 * val)
return [rtn]
#Define ConstantSeries class
#I have made no changes here, just what you already had
class ConstantSeries(Series):
__tablename__ = 'constantseries'
# ID Primary Key (linked to parent)
id = Column(Integer, ForeignKey('series.id'), primary_key=True)
# The value of this series to be returned for all periods.
value = Column(Float)
__mapper_args__ = {'polymorphic_identity': 'constantseries'}
def GetData(self, scenario, periods):
"""Get data values for the specified periods.
"""
return pandas.Series(data=[self.value]*len(periods), index=periods)
#End of class definition
#Define new special Cap2Series class
class Cap2Series(Series):
#I'm not sure how tablename is used so be aware, might need to put constantseries as before
__tablename__ = 'cap2series'
# ID Primary Key (linked to parent)
id = Column(Integer, ForeignKey('series.id'), primary_key=True)
# The value of this series to be returned for all periods.
value = Column(Float)
#Same as above, I'm not sure how this is used so be aware, might need to put constantseries as before
__mapper_args__ = {'polymorphic_identity': 'cap2series'}
#Define GetData method of our new special class
def GetData(self, scenario, periods):
#instantiate new ConstantSeries instance called cap when you call GetData
cap = (ConstantSeries(value=self.value))
rtn = {}
for timest, val in cap.GetData(scenario, periods).iteritems():
if timest.weekday_name in ['Saturday', 'Sunday']:
rtn[timest.weekday_name] = (0.72 * val)
#0.46*2574
else:
rtn[timest.weekday_name] = (1.0 * val)
return pandas.Series(data=rtn, index=periods)
#End of class definition
#Instantiate new Cap2Series instance called cap2
cap2 = Cap2Series(1647)
#Call GetData method of cap2 instance
cap2.GetData(base_scenario, utils.enumerate_periods(start,end,'H','CET')).plot()
#Is this something like what you're trying to do?
Related
I have two models
class Order(models.Model):
ord_number:str
ord_date: date
ord_ref: str Null=True
ord_qty: Decimal
ord_desc: str
timestamp: datetime
created: datetime
Class OrderLines(models.Model):
order: FK(Order)
driver: FK(Driver)
truck: FK(Truck)
ord_qty: Decimal
loaded_quantity: Decimal
loading_date: date
My schemas on posting will be like this
OrderCreateBase = create_schema(Order, exclude=("id", "timestmap", "created"))
OrderLineCreateBase = create_schema(OrderLines, exclude=("id))
class OrderCreateSchema(OrderCreateBase):
order_lines = List[OrderLineCreateBase]
Json data to be used on creating like this
"ord_number: "AB123",
"order_date: Date(01/01/2021),
"ord_ref" Null,
"ord_qty": Decimal("10_000"),
"ord_desc" "Sample Order",
"order_lines"[
{"order_id": 1,
"driver_id: 23,
"truck_id": 12,
"ord_qty": Decimal("10_000"),
"loaded_quantity": Decimal("8_000") <----#,
"loading_date": Date(01/01/2021)},
{"order_id": 1,
"driver_id: 13,
"truck_id": 17,
"ord_qty": Decimal("10_000"),
"loaded_quantity": Decimal("9_000") <----#,
"loading_date": Date(01/01/2021)}]
}
I want check constraint that will ensure total loaded quantity(loaded_quantity) per order will be <= to ordered_quantity (ord_qty)
currently my create endpoint is like this
#router.post(
"/ilr/{ilr_id}/instrunctions",
response={HTTPStatus.CREATED: Message, HTTPStatus.BAD_REQUEST: Message},
tags=["ilrs instructions"],
summary=_("create loading request instructions"),
description=_("API to create ilr instructions lines"),
url_name="create_ilr_instructions",
)
#transaction.atomic()
def create_ilr_instrunctions(request, ilr_id: int, payload: ILRLineCreateSchema):
data = payload.dict()
ilr = get_object_or_404(ILR, id=ilr_id, status=0)
data["request"] = ilr
data["order_date"] = ilr.ilr_date
# get existing lines total volume
total_volume = ILRLine.objects.filter(request=ilr).aggregate(total_volume=Sum("quantity"))
if ilr.quantity < total_volume.get("total_volume") + data.get("quantity"): <-----#
return HTTPStatus.BAD_REQUEST, {
"detail": [{"msg": f"Total loading quantities will be higher than ordered quantity"}]
}
try:
with transaction.atomic():
ILRLine.objects.create(**data)
.....
How can I force it on database level using check constraint? I don't want to override model save
You can try CheckConstraint.check
from django.db.models import CheckConstraint, Q, F
class OrderLines(models.Model):
...
class Meta:
constraints = [
CheckConstraint(
check=Q(loaded_quantity__lte=F('ord_qty')),
name='quantity_check'
)
]
In Odoo 10, I want to change the value of a variable when the forecasted quantity of a product is changed. I tried using the #api.onchange decorator, but it doesn't work. The forecasted quantity change, but the variable keeps the same value. I have this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default = False)
#api.onchange('virtual_available')
def qtychanged(self):
self.was_changed = True
_logger.info('Product_Qty_Cahnged: %s',str(self.virtual_available))
In this code, if the forecasted quantity of a product would change, the variable was_changed should be set to True, but nothing happens.
After that, I tried to overwrite the write method for my custom class, like this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default=False)
#api.multi
def write(self, values):
if values['virtual_available']:
values['was_changed'] = True
# THE FOLLOWING LINES WERE IN THE ORIGINAL WRITE METHOD
res = super(MyProduct, self).write(values)
if 'standard_price' in values:
self._set_standard_price(values['standard_price'])
return res
But still, I have the same result. I can't seem to get that flag to change. So, any ideas?
Try this:
class MyProduct(models.Model):
_inherit = 'product.product'
was_changed = fields.Boolean(default = False)
#api.onchange('virtual_available')
def qtychanged(self):
self.write({'was_changed': True})
_logger.info('Product_Qty_Cahnged: %s',str(self.virtual_available))
I want to get the parent class values with each child values? How can I identify child objects to fetch?
I have the Django model structure like this.
class Category(models.Model):
name = models.CharField(max_length=80)
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
category = models.ForeignKey('Category')
class PizzaRestaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
class PastaRestaurant(Place):
extra = models.CharField(max_length=80)
When we do operation we may save the object like below. And it saved into the db as i expected. two entry in the Place table and each entry in each child object table.
a = Category()
a.name = "pasta"
b = Category()
b.name = "pizza"
a.save()
b.save()
x = PastaRestaurant()
x.address = "Pasta Address"
x.name = "Pastamonia"
x.extra = "some extra"
x.category = a
y = PizzaRestaurant()
y.address = "Pizza Address"
y.name = "Dominos"
y.serves_hot_dogs = 1
y.serves_pizza = 0
y.category = b
x.save()
y.save()
Now I need to access the like this
p = Place.objects.get(id=1)
How can I know, which objects/attributes belongs to the place objects?
So when I fetch the place with common attributes and should be able get the corresponding child objects values also.
Or any other model design work for my need?
If you want to access the child model's attributes you need to fetch it as that model, i e PizzaRestaurant or PastaRestaurant, otherwise you will only get a Place object.
If you need to get all Places regardless of subclass take a look at InheritanceManager from django-model-utils. Using this you can implement overloaded operations to perform subclass-specific actions.
django-polymorphic does this beautifully, improving the abilities to work with model inheritance like so:
from polymorphic.models import PolymorphicModel
class Place(PolymorphicModel):
...
class PizzaRestaurant(Place):
...
class PastaRestaurant(Place:
...
>>> some_place = Place.objects.create(name="Walmart")
>>> some_pizza_place = PizzaRestaurant.objects.create(name="Slice King", address="101 Main St., Bismarck, ND", category = Category.objects.first(),serves_pizza=True)
>>> some_pizza_place.instance_of(PizzaPlace)
True
>>> PizzaRestaurant.objects.all()
queryset<['Slice King',]>
>>> Place.objects.all()
queryset<['Walmart', 'Slice King',]>
I am not sure exactly how achieve this.
I have a model defined as
class Post(ndb.Model):
author_key = ndb.KeyProperty(kind=Author)
content = ndb.StringProperty(indexed=False)
created = ndb.DateTimeProperty(auto_now_add=True)
title = ndb.StringProperty(indexed=True)
topics = ndb.StructuredProperty(Concept, repeated=True)
concise_topics = ndb.ComputedProperty(get_important_topics())
#classmethod
def get_important_topics(cls):
cls.concise_topics = filter(lambda x: x.occurrence > 2, cls.topics)
return cls.concise_topics
I like to set the value of concise_topics (Which is on the same type as topics) to a subset acheived via get_important_topics method. This should happen the moment the topics property has been set.
How do I define the "concise_topics" property in the Post class ?
With class method, you don't have access to the instance values. And also you shouldn't call the function, only pass it to the computed property, and let it call by itself.
class Post(ndb.Model):
author_key = ndb.KeyProperty(kind=Author)
content = ndb.StringProperty(indexed=False)
created = ndb.DateTimeProperty(auto_now_add=True)
title = ndb.StringProperty(indexed=True)
topics = ndb.StructuredProperty(Concept, repeated=True)
def get_important_topics(self):
return filter(lambda x: x.occurrence > 2, self.topics)
concise_topics = ndb.ComputedProperty(get_important_topics)
As far as I remember the computed property is set on each put call, so your topics should be already there by that time.
I am very new to Python so I assume I am doing something terribly wrong, but I don't see what and Google has not helped this far too. What is wrong with this ?
def lookup_permille(name):
# TODO: implement a permille lookup table
return 0
def lookup_known_product(name):
# TODO: implement a known product lookup table
return 0
class ProductEntry:
def __init__(self, source, name, price, volume, permille = lookup_permille(name), known_product_id = lookup_known_product(name), category = 0):
self.source = source
self.name = name
self.price = price
self.volume = volume
self.permille = permille
self.price_per_permille = self.permille / self.price;
self.category = category
self.known_product_id = known_product_id
Calling the constructor of ProductEntry fails with:
def __init__(self, source, name, price, volume, permille = lookup_permille(name), known_product_id = lookup_known_product(name), category = 0):
NameError: name 'name' is not defined
The expressions defining default arguments are evaluated when the function is defined, not when it is called. At the point when __init__ is being defined, name does not exist, so it cannot be used in an expression to calculate a default argument.
The usual way to do something like this is to have a stand-in value as your default argument, and replace it with whatever value you actually want inside the body of your function.
def __init__(self, source, name, price, volume,
permille=None, known_product_id=None, category=0):
if permille is None:
permille = lookup_permille(name)
if known_product_id is None:
known_product_id = lookup_known_product(name)
...