Circular Import with app models - python

I have an app in two different models, The error is 'cannot import name sku', which i believe is because of a circular import. How can I still reference this app.model without referencing the model import the way I am currently.
Model PurchaseOrderDetail
App Purchase_order
from product.models import InventoryTransaction
class PurchaseOrderDetail(AuditMixin, models.Model):
purchase_order = models.ForeignKey(PurchaseOrder,
on_delete=models.PROTECT)
sku = models.ForeignKey(Sku, on_delete=models.PROTECT)
qty_received = models.IntegerField(default=0, null=True, blank=True)
reason_code = models.IntegerField(default=0, null=True, blank=True)
def _get_sku_code(self):
return self.sku.sku_code
def _set_sku_code(self, value):
tenant = self.purchase_order.tenant
sku = Sku.objects.get(tenant=tenant, sku_code=value)
self.sku = sku
sku_code = property(_get_sku_code, _set_sku_code)
def calc_received(self):
# calculate sum of qty_received from inventory_transactions
sum_quantity = InventoryTransaction.objects.filter(
sku=self.sku,
po_number=self.purchase_order,
transaction_type='100'
).aggregate(
quantity_sum=Sum(F('quantity'))
)
return sum_quantity
Model Inventorytransaction
app Product
from purchase_order.models import PurchaseOrderDetail
class InventoryTransaction(models.Model):
tenant = models.ForeignKey(Tenant)
po_number = models.CharField(max_length=100)
inventory_transaction = models.ForeignKey(PurchaseOrderInventoryTransaction)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# update the PO detail with the qty_received
obj = PurchaseOrderDetail.objects.get(
purchase_order=self.po_number,
sku=self.inventory_transaction.sku
)
obj.qty_received = obj.calc_received()
obj.save()

If you don't want this problem to appear, simply import your PurchaseOrderDetails inside your def save function.
def save(self, *args, **kwargs):
from purchase_order.models import PurchaseOrderDetail
...

Related

Django - How to get self.id instance when creating new object

I am working with two classes, when i save the first one it will automatic create the other one, the field called "transaction" should be filled by self.id.
But i get this error message:
NOT NULL constraint failed: portfolios_portfoliotoken.transaction_id
this is the code that i am using:
PortfolioToken.objects.create(transaction=self.id, portfolio=self.portfolio, date=self.date, total_today_brl=self.total_cost_brl+last.total_today_brl, order_value=self.total_cost_brl)
More details is possible to see below:
class Transaction(models.Model):
id = models.AutoField(primary_key=True)
date = models.DateField(("Date"), default=date.today)
portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, default=1)
total_cost_brl = models.FloatField(editable=False)
...
def save(self, *args, **kwargs):
self.share_cost_brl = round(self.share_cost_brl, 2)
self.total_cost_brl = round(self.shares_amount * self.share_cost_brl, 2)
...
PortfolioToken.objects.create(transaction=self.id, portfolio=self.portfolio, date=self.date, total_today_brl=self.total_cost_brl+last.total_today_brl, order_value=self.total_cost_brl)
super(Transaction, self).save(*args, **kwargs)
class PortfolioToken(models.Model):
portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE, default=1)
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
total_today_brl = models.FloatField()
order_value = models.FloatField()
date = models.DateField(("Date"), default=date.today)
...
You should first call super().save(*args, **kwargs) to save the transaction, and then you can use this to construct the PortfolioToken:
class Transaction(models.Model):
# …
def save(self, *args, **kwargs):
# …
super().save(*args, **kwargs)
PortfolioToken.objects.create(
transaction_id=self.id,
portfolio=self.portfolio,
date=self.date,
total_today_brl=self.total_cost_brl+last.total_today_brl,
order_value=self.total_cost_brl
)

unable to auto-fill data during update in dependent dropdowns

So I have been following this tutorial related to dependent dropdowns which can be found here and I seem to have gotten stuck at the last part the else if statement and am unable to implement the same in my project
postlog models.py:
from django.db import models
# Create your models here.
class FlightNum(models.Model):
fl_no =models.CharField(max_length=5,primary_key=True)
def __str__(self):
return self.fl_no
class Destination(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl1')
dest= models.CharField(max_length=15,blank=True)
def __str__(self):
return self.dest
class Parking(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl2')
park_bay= models.CharField(max_length=3)
def __str__(self):
return self.park_bay
class DepartureTime(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl3')
dep_time= models.CharField(max_length=9)
def __str__(self):
return self.dep_time
class Flight(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE, primary_key=True, related_name='fl4')
park_bay= models.ForeignKey(Parking, on_delete=models.CASCADE)
dest= models.ForeignKey(Destination, on_delete=models.CASCADE)
dep_time= models.ForeignKey(DepartureTime, on_delete=models.CASCADE)
inbound= models.CharField(max_length=15,blank=True)
airline= models.CharField(max_length=15)
arr_time= models.TimeField()
status models.py:
from django.db import models
from postlog.models import FlightNum,Destination,Parking,DepartureTime
# Create your models here.
class FlightStatus(models.Model):
CLEANING_CHOICES = (
('Yes', 'Yes'),
('No','No'),
)
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fli_no',primary_key=True)
park_bay= models.ForeignKey(Parking,on_delete=models.CASCADE,related_name='parki_bay')
catering= models.CharField(max_length=9)
fuel= models.IntegerField()
pas_cnt= models.IntegerField()
dest= models.ForeignKey(Destination,on_delete=models.CASCADE,related_name='desti',null=True)
dep_time=models.ForeignKey(DepartureTime,on_delete=models.CASCADE,related_name='dept_time')
Cleaning = models.CharField( max_length=3, choices=CLEANING_CHOICES)
status forms.py:
from django.forms import ModelForm
from status.models import FlightStatus
from postlog.models import FlightNum,Destination,Parking,DepartureTime
class StatusForm(ModelForm):
class Meta:
model = FlightStatus
fields = ('fl_no', 'park_bay', 'catering', 'fuel', 'pas_cnt', 'dest','dep_time', 'Cleaning')
labels = {
'fl_no': ('Flight Number'),
'park_bay': ('Parking Bay'),
'catering': ('Catering'),
'fuel': ('Fuel'),
'pas_cnt': ('Passenger Count'),
'dest': ('Destination'),
'dep_time': ('Departure Time'),
'Cleaning': ('Cleaning'),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['park_bay'].queryset = Parking.objects.none()
self.fields['dest'].queryset = Destination.objects.none()
self.fields['dep_time'].queryset = DepartureTime.objects.none()
if 'fl_no' in self.data:
try:
flightid = int(self.data.get('fl_no'))
self.fields['park_bay'].queryset = Parking.objects.filter(fl_no=flightid).order_by('park_bay')
self.fields['dest'].queryset = Destination.objects.filter(fl_no=flightid).order_by('dest')
self.fields['dep_time'].queryset = DepartureTime.objects.filter(fl_no=flightid).order_by('dep_time')
except (ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.park_bay_set.order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.park_bay_set.order_by('dep_time')
so if anyone could help me fix this part:
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.park_bay_set.order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.dep_time_set.order_by('dep_time')
I would really appreciate it
The error says there's no park_bay_set attribute for FlightNum, because you specified related_name='fl4' for your fl_no field inside your Flight model. Also, up to this point you are in a Flight instance, so you need one more relation to reach the park bays. Your status forms.py should be like this:
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.fl4.park_bay.all().order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.fl4.park_bay.all().order_by('dep_time')
Here's a diagram of how your models are currently related, not sure if this is exactly what you want, you might want to take a look and see if a normalization is needed.

Why am I getting core.Model.none?

I'm working on a django based backend.
I have a Submentor model. This model is going to have a list of names associated with it. So, I made a model called List. they both have a manytoMany relationship. Now, I made another model called names. This has a ManytoMany relationship with List. The list will have many names. Each Submentor will have one List each.
After coding when I try to add a value in The list from admin console I get core.Name.none instead of the name in my Submentors list.
What am I doing wrong?
code of models :-
class Names(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,blank=True,null=True)
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class SAccepted_list(models.Model):
saccepted_name = models.ManyToManyField(Names,blank =True, related_name='saccepted_name')
def __str__(self):
return str(self.saccepted_name)
class SPending_list(models.Model):
spending_name = models.ManyToManyField(Names,blank =True, related_name='spending_name')
def __str__(self):
return str(self.spending_name)
class SRejected_list(models.Model):
srejected_name = models.ManyToManyField(Names,blank =True, related_name='srejected_name')
def __str__(self):
return str(self.srejected_name)
class SubMentor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
mentee_pref_count = models.IntegerField(default=3, verbose_name='Preferred mentee count')
rating = GenericRelation(Rating, related_query_name='Submentor')
skills = models.ManyToManyField(Skill, blank=True, related_name='subskills')
courses = models.ManyToManyField(Course, blank=True, related_name='subcourses')
projects = models.ManyToManyField(Project, blank=True, related_name='subprojects')
saccepted_list = models.ManyToManyField(SAccepted_list,blank=True,related_name='saccepted_list')
spending_list = models.ManyToManyField(SPending_list, blank=True,related_name='spending_list')
srejected_list = models.ManyToManyField(SRejected_list, blank=True,related_name='srejected_list')
def __str__(self):
return self.user.get_full_name()
def get_mentee_count(self, *args, **kwargs):
if self.trainees.exists():
return self.trainees.count()
else:
return 0
class Accepted_list(models.Model):
accepted_name = models.ManyToManyField(Names,blank =True, related_name='accepted_name')
# saccepted_name = models.ManyToManyField(Names,blank =True, related_name='saccepted_name')
def __str__(self):
return str(self.accepted_name)
class Pending_list(models.Model):
pending_name = models.ManyToManyField(Names,blank =True, related_name='pending_name')
# spending_name = models.ManyToManyField(Names,blank =True, related_name='spending_name')
def __str__(self):
return str(self.pending_name)
class Rejected_list(models.Model):
rejected_name = models.ManyToManyField(Names,blank =True, related_name='rejected_name')
# srejected_name = models.ManyToManyField(Names,blank =True, related_name='srejected_name')
def __str__(self):
return str(self.rejected_name)
class Mentor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
score = models.FloatField(default=0, blank=True, null=True)
mentee_pref_count = models.IntegerField(default=5, verbose_name='Preferred menteee count')
rating = GenericRelation(Rating, related_query_name='mentor')
skills = models.ManyToManyField(Skill, blank=True, related_name='skills')
accepted_list = models.ManyToManyField(Accepted_list,blank=True,related_name='accepted_list')
pending_list = models.ManyToManyField(Pending_list, blank=True,related_name='pending_list')
rejected_list = models.ManyToManyField(Rejected_list, blank=True,related_name='rejected_list')
def __str__(self):
return self.user.get_full_name()
def get_mentee_count(self, *args, **kwargs):
if self.trainees.exists():
return self.trainees.count()
else:
return 0
picture of me adding names direct through admin console:-
Thank you.
Ok, I solved my problem. It was wrong of me in the first place to use m2m and then another to make a list.
Instead I used only 1 m2m relationship with Lists and then made a property of them to be charfield. Now it's working properly.
Thanks :)

Manager object has no attribute 'save'

In my serializers.py I have a OrderCreateSerializer:
class OrderCreateSerializer(ModelSerializer):
data_params = serializers.DictField() # 根据产品数据模型不同而异
class Meta:
model = Order
fields = (
"product_describe", # 产品描述 (购买xx产品 + 参数)
"billing_type", # 计费类型 ("包年包月")
"data_params", # 数据
)
def create(self, validated_data):
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
validated_data["order_num"] = generateOrderNum(userid=user.id)
validated_data["order_status"] = "未支付"
validated_data["order_status"] = "未支付"
data_dic = validated_data.pop("data_params") #
# data_dic["data"]["profile"]
validated_data["buytime"] = data_dic["data"]["buytime"]
validated_data["count"] = data_dic["data"]["count"]
validated_data["paytype"] = ""
validated_data["cost"] = ""
validated_data["account"] = user.account
return Order.objects.save(**validated_data) # this is the line 57
When I save the validated_data, it report the bellow error:
Manager object has no attribute 'save'
My Order model is like bellow, there is many fields in it :
class Order(models.Model):
"""
订单
"""
order_num = models.CharField(max_length=128, unique=True) # 订单编号
order_status = models.CharField(max_length=12) # 订单状态 "未支付", "已支付,未完成", "已完成", "已经删除","其他"
product_describe = models.TextField() # 产品描述
billing_type = models.CharField(max_length=16) # 计费类型
buytime = models.CharField(max_length=16) # 比如:1月 永久
count = models.IntegerField() # 购买数量
paytype = models.CharField(max_length=16) # 支付方式(支付包,微信,xxx)
cost = models.DecimalField(max_digits=8, decimal_places=2, default=0.00) # 费用(需要花费多少钱)
account = models.ForeignKey(to=Account) # 所属账户
ctime = models.DateTimeField(auto_now_add=True) # 创建时间
uptime = models.DateTimeField(auto_now=True) # 更新时间
def __str__(self):
return self.product_describe
def __unicode__(self):
return self.product_describe
I don't know why there is the Manager object here.
You're calling save on the manager (ie, objects)
return Order.objects.save(**validated_data)
You call save on models.
I assume you're trying to create the model, in which case you want create.
return Order.objects.create(**validated_data)
Order.objects is an instance of the Manager class. The save method is a method of the model class.
Try:Order(**validated_data).save()

how django 'auto_now' ignore the update of specified field

i have a model, like this:
name = models.CharField(max_length=255)
modify_time = models.DateTimeField(auto_now=True)
chasha = models.CharField(max_length=255)
stat = models.CharField(max_length=255)
Usually, 'modify_time' will be updated when i update 'name', 'chasha', 'stat' field. But, I just did not want the 'modify_time' been updated when i update 'stat'. how can i do that?
thanks.
Use a custom save method to update the field by looking at a previous instance.
from django.db import models
from django.utils import timezone as tz
class MyModel(models.Model):
name = models.CharField(max_length=255)
modify_time = models.DateTimeField(null=True, blank=True)
chasha = models.CharField(max_length=255)
stat = models.CharField(max_length=255)
def save(self, *args, **kwargs):
if self.pk: # object already exists in db
old_model = MyModel.objects.get(pk=self.pk)
for i in ('name', 'chasha'): # check for name or chasha changes
if getattr(old_model, i, None) != getattr(self, i, None):
self.modify_time = tz.now() # assign modify_time
else:
self.modify_time = tz.now() # if new save, write modify_time
super(MyModel, self).save(*args, **kwargs) # call the inherited save method
Edit: remove auto_now from modify_time like above, otherwise it will be set at the save method.

Categories