Check constraint on django - django

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'
)
]

Related

django filter data and make union of all data points to assignt to a new data

My model is as follows
class Drawing(models.Model):
drawingJSONText = models.TextField(null=True)
project = models.CharField(max_length=250)
Sample data saved in drawingJSONText field is as below
{"points":[{"x":109,"y":286,"r":1,"color":"black"},{"x":108,"y":285,"r":1,"color":"black"},{"x":106,"y":282,"r":1,"color":"black"},{"x":103,"y":276,"r":1,"color":"black"},],"lines":[{"x1":109,"y1":286,"x2":108,"y2":285,"strokeWidth":"2","strokeColor":"black"},{"x1":108,"y1":285,"x2":106,"y2":282,"strokeWidth":"2","strokeColor":"black"},{"x1":106,"y1":282,"x2":103,"y2":276,"strokeWidth":"2","strokeColor":"black"}]}
I am trying to write a view file where the data is filtered based on project field and all the resulting queryset of drawingJSONText field are made into one data
def load(request):
""" Function to load the drawing with drawingID if it exists."""
try:
filterdata = Drawing.objects.filter(project=1)
ids = filterdata.values_list('pk', flat=True)
length = len(ids)
print(list[ids])
print(len(list(ids)))
drawingJSONData = dict()
drawingJSONData = {'points': [], 'lines': []}
for val in ids:
if length >= 0:
continue
drawingJSONData1 = json.loads(Drawing.objects.get(id=ids[val]).drawingJSONText)
drawingJSONData["points"] = drawingJSONData1["points"] + drawingJSONData["points"]
drawingJSONData["lines"] = drawingJSONData1["lines"] + drawingJSONData["lines"]
length -= 1
#print(drawingJSONData)
drawingJSONData = json.dumps(drawingJSONData)
context = {
"loadIntoJavascript": True,
"JSONData": drawingJSONData
}
# Editing response headers and returning the same
response = modifiedResponseHeaders(render(request, 'MainCanvas/index.html', context))
return response
I runs without error but it shows a blank screen
i dont think the for function is working
any suggestions on how to rectify
I think you may want
for id_val in ids:
drawingJSONData1 = json.loads(Drawing.objects.get(id=id_val).drawingJSONText)
drawingJSONData["points"] = drawingJSONData1["points"] + drawingJSONData["points"]
drawingJSONData["lines"] = drawingJSONData1["lines"] + drawingJSONData["lines"]

How to execute a function when a variable's value is changed?

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))

Change a series I have been given

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?

how to compare related Sum with a value itself

class Investor(Model):
name = CharField(max_length=16)
class Project(Model):
plan_finance = IntegerField()
class ProjectProcess(Model):
project = OneToOneField('Project')
investors = ManyToManyField('Investor')
class InvestShip(Model):
project = ForeignKey('Project')
investor = ForeignKey('Investor')
invest_amount = IntegerField()
How to find the Project which have already finished being financed , in other words, the money received from investors' > plan_finance.
You can use annotation on the related set and then filter on it.
from django.db.models import Sum
Project.objects.annotate(invested_sum=Sum('investship_set__invest_amount')).filter(invested_sum__gte=plan_finance)

Can we execute a SQL like query using User defined Manager in Django?

Below is my model details
class QuesManager(db.Manager):
def with_counts(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
SELECT Q.question, Q.title, Q.qid, V.up_qid, V.down_qid
FROM Question Q, Votes_ques V
WHERE Q.qid=V.qid
ORDER BY 3 DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(question=row[0], title=row[1], up_vote=row[2], down_vote=row[3])
result_list.append(p)
return result_list
class dummy(db.Model):
obj = QuesManager()
class Question(db.Model):
userid = db.CharField(max_length=50)
posted = db.DateTimeField(auto_now=True)
question = db.TextField(max_length=500)
qid = db.AutoField(primary_key=True)
title = db.TextField(max_length=80)
tags = db.ManyToManyField('Tags')
class Votes_ques(db.Model):
qid = db.ForeignKey('Question')
up_qid = db.IntegerField()
down_qid = db.IntegerField()
from mysite.answers.models import dummy
from mysite.answers.models import Votes_ques
from mysite.answers.models import Question
Does, Vote = dummy.obj.all() will give all result set of the query inside the QuesManager class. Anyone have any idea on this...
Thanks!
Perhaps you're simply looking for this:
questions = Question.objects.all()
for question in questions:
votes = question.votes_ques_set.all()