How to get integer ID of Django Factory Boy object? - python

I have a factory boy factory that uses Django that I need to access the ID of the generated objects. However, whenever I attempt to get that ID, I receive TypeErrors. Any idea what I am missing?
# factories.py
class PartNoFactory(factory.django.DjangoModelFactory):
class Meta:
model = PartNo
id = factory.fuzzy.FuzzyInteger(1, 1000000, step=1)
# have also tried id = factory.Sequence(lambda n: n + 1)
# have also tried id = int(factory.Sequence(lambda n: n + 1)), which results in error "type Sequence cannot be assigned to paramater "_x"
# test_factories.py
def mock_child_part_nos(arg_1: PartNo) -> 'list[int]':
mock_part_no_one = PartNoFactory()
mock_part_no_two = PartNoFactory()
mock_part_no_three = PartNoFactory()
return [mock_part_no_one.id, mock_part_no_two.id, mock_part_no_three.id]
# if using FuzzyInteger: "Expression of type "list[FuzzyInteger]" cannot be assigned to return type "list[int]"
# if using Sequence: "Expression of type "list[Sequence]" cannot be assigned to return type "list[int]"

Related

Save and duplicate an instance in django

I have to define a function in order to duplicate an instance of my class Scenario.
I created an identical instance whose fields are identical except name and id, but when I save the new instance the original is deleted. Here is the code of the function:
def duplicate(scn):
attr_list = [field for field in Scenario._meta.get_fields() if isinstance(field,django.db.models.fields.Field)]
s = Scenario()
s.id = str(scn.id+10)
s.name='s_dup_of_' + scn.name
#print(Scenario.objects.all())
for a in attr_list:
if a.name!='name' and a.name!= 'id':
value = getattr(scn,a.name)
setattr(s,a.name,value)
#print(Scenario.objects.all())
#list_class = [Unit,HidroUnit,ThermalUnit,Arc,Flow,Fuel,Group,Loop,Machine,ModeVir,Node,Region,Reservoir,Solution,Station,Transitions,Tube]
list_class = [Unit,HidroUnit,ThermalUnit]
for myClass in list_class:
instance_list = myClass.objects.filter(scenario=scn)
attr_list = [field for field in myClass._meta.get_fields() if isinstance(field,django.db.models.fields.Field)]
for instance in instance_list:
inst_new = myClass()
for a in attr_list:
if a.name!='temporalobject_ptr':
value = getattr(instance,a.name)
setattr(inst_new,a.name,value)
inst_new.save()
#print(Scenario.objects.all())
s.save()
#print(Scenario.objects.all())
return None
For example, if I want to duplicate the scenario called s1 and to create the scenario s_dup_s1, and if I reproduce all lines of my duplicate function, then after I write s_dup_s1.save() the old instance s1 is deleted.
What can I do if I want s1 and s1_sup_s1 at the same time?
This is what happens when I run the code:
This doesn't work either:
Here's an easy hack to duplicate your instance:
You can rewrite your duplicate function as follows:
def duplicate(instance):
duplicate = Scenario.objects.get(pk=instance.pk)
duplicate.pk = None
duplicate.save()
return duplicate
This way your initial instance is preserved and you can do whatever you want with it. And, the function duplicate creates a duplicate of your instance, saves it and returns it.
Finally I find a solution. If you want to duplicate an instance s1 you have to set a new name and a new id and save it:
s1.id = scn.id+1
s1.name = scn.name + '_dup'
s1.save()
Of this way you will have both s1 and s1_dup.
The next works:
def duplicate(scn):
scn.id = scn.id+1
scn.name = scn.name + '_dup'
scn.save()
n = Scenario.objects.all().count()
s_new = Scenario.objects.all()[n-1]
list_class = [Unit,HidroUnit,ThermalUnit]
for myClass in list_class:
instance_list = myClass.objects.filter(scenario=scn)
attr_list = [field for field in myClass._meta.get_fields() if isinstance(field,django.db.models.fields.Field)]
for instance in instance_list:
instance.scenario = s_new
instance.num = instance.num + 1
instance.save()
return None

count the sales of a worker

I am trying to count the sales made by a worker but I get the following error when using the code mentioned below:
TypeError: object of type 'bool' has no len()
class Movement_type (models.Model):
_name = 'project_rc.movement_type'
_rec_name = 'movement_type'
type_movement = fields.Selection ([('purchase', 'Purchase'), ('sale', 'Sale'), ('merma', 'Merma')], string = "Movement type", required = True)
class Worker (models.Model):
_name = 'project_rc.worker'
_rec_name = 'name'
sales_counter = fields.Integer (string = "Sales made", compute = "get_sales_realized", store = True)
#api.depends('move_type_ids')
def get_sales_realized (self):
for rec in self:
rec.count_sale = len (rec.move_type_ids.mov_type == 'sale')
I'm not familiar with whatever framework you are using, but if you look at the error you are getting you can see that it is correct.
On line 3, you write rec.move_type_ids.mov_type == 'sale'. It doesn't matter what rec.move_type_ids.mov_type is, when you compare it to something with ==, the answer will either be True or False. It doesn't make sense to take the length of a boolean (t/f).
From the context, I'm guessing that rec.move_type_ids is a list of objects and you want to figure out how many of them have a mov_type property equal to 'sale'. If that's the case, then you could easily do that with a for loop:
sales = []
for thing in rec.move_type_ids:
if thing.type == 'sale':
sales.append(thing)
rec.count_sale = len(sales)
If you want to get a little fancier, you can do that with a filter function:
rec.count_sale = len(filter(lambda x: x.mov_type == 'sale', rec.move_type_ids))

Calculate a value from GraphQL and save it in Django models

I am trying to calculate a value from GraphQL. I am sending mutation to Django models but before save it I want to calculate this value with if statement (if the value is greater than 10 divide by 2, if is less than 10 multiply by 2).
I don't know where to add this function.
Here is my mutation in schema.py
class CreatePrice(graphene.Mutation):
price = graphene.Field(PriceType)
class Arguments:
price_data = PriceInput(required=True)
#staticmethod
def mutate(root, info, price_data):
price = Price.objects.create(**price_data)
return CreatePrice(price=price)
class Mutation(graphene.ObjectType):
create_product = CreateProduct.Field()
create_price = CreatePrice.Field()
schema = graphene.Schema(query = Query, mutation=Mutation)
And here is my Django model. Base price is calculated value and function name has two options(*2 or /2 it depends of initial value).
class Price(models.Model):
base_price = models.CharField(max_length = 20)
function_name = models.CharField(max_length = 20, choices = PROMO_FUNCTION)
def __str__(self):
return self.price_name
P.S. Sorry for bad English. Thanks!
I don't know why you are using CharField for base_price. So, I suggest you to do this:
#staticmethod
def mutate(root, info, price_data):
if int(price_data.base_price) >= 10:
price_data.base_price = str(int(price_data.base_price) / 2)
else:
price_data.base_price = str(int(price_data.base_price) * 2)
price = Price(base_price=price_data.base_price, function_name=price_data.function_name)
price.save()
return CreatePrice(price=price)
You can also create records in database by creating object and using save method on it.

Adding a new object to a class with user-input(input) in python

I am trying to add new objects to a class(emne) but the new instances of the class needs to be created using user input. So i need a way to be able to chose the name for the object and set some of the values of the objects with user input.
I have already tried to create a function that passes the value of the user input into a x = emner(x) to create it but it only returns:
AttributeError: 'str' object has no attribute 'fagKode'
so i think my issue is that the value of the input is created as a string so that it is not understood as a way to create the function
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne():
nyttEmne = input("test:")
nyttEmne=Emne(nyttEmne)
expected result is that the code creates a new instance of the class.
If by choosing a name you mean your fagKode attribute, what you need is:
fagKode = input('Enter code: ')
Emne(fagKode)
You're adding the instances of Enme to the list in the constructor, so you don't need to save them to a variable.
Alternatively, you can handle that in the function:
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
def leggTilEmne():
nyttEmne = input("test:")
enme.append(Emne(nyttEmne))
I'm not sure what exactly you are asking, since you haven't responded to the comments. So,
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne(self, value): # <--- is this what you want
self.nyttEmne= Emne(value)
This is an example of when to use a class method. __init__ should not be appending to a global variable, though. Either 1) have the class method append to a class attribute, or 2) have it return the object and let the caller maintain a global list.
emne = []
class Emne:
emne = []
def __init__(self, fag_kode):
self.fag_kode = fag_kode
self.karakter = ""
#classmethod
def legg_til_emne_1(cls):
nytt_emne = input("test:")
cls.emne.append(cls(nytt_emne))
#classmethod
def legg_til_emne_2(cls):
nyttEmne = input("test:")
return cls(nyttEmne)
Emne.legg_til_emne_1() # Add to Emne.emne
e = Emne.legg_til_emne_2()
emne.append(e)

Django random value for Model field

So I am able to generate a random id using uuid
So far so good
But when I try to database i get same value
def f():
d = uuid4()
str = d.hex
return str[0:16]
class Q(models.Model):
a = models.CharField(max_length=150)
b = models.IntegerField(max_length=25)
c = models.IntegerField(max_length=32 , default=0)
d = models.ManyToManyField(Ans , related_name='aa')
e = models.CharField(max_length=18 , default = f() ,unique=True )
class Ans(models.Model):
sub = models.CharField(max_length=150)
-----------------------------------------------------------------
And I'm inserting like this
def ins(request):
t =random.randint(0, 1000)
p = Q(a = t , b=0 , c=0)
p.save()
return HttpResponse('Saved')
Just curious what the hell is happening here
Side note: If I set e.unique = False I get 2-3 with the same e values before I get a new
UUID values
You should not call the function that you are passing to default:
e = models.CharField(max_length=18, default=f, unique=True)
FYI, according to docs, you should pass a value or a callable:
The default value for the field. This can be a value or a callable
object. If callable it will be called every time a new object is
created.

Categories

Resources