django: use model methods without create instance - django

I have a Model Product with business methods. My model contains relationship with Models Item and Dealer.
Let's say my Product is serialized as / can be created from:
{
"name": "productA",
"items": [2,3,13],
"dealer": [1,2]
}
I can for instance run Product.simulate():
class Product(Models):
....
def simulate(self):
```dummy function to illustrate```
return sum(i.price for i in self.items.all()) / len(i.dealer.all())
I would like to be able to compute Product.simulation with values in a dictionnary without creating Product instance. I have multiple signals and batch operation on Product Model I dont want to run on the only for simulation objects.
I could create a for_simulation attribute on Product and specify on my signals / batch operation to don't run on those instances but it seems do lead to duplicate code and be forgotten on some signals / batch.
On the other hand, I could rewrite all my methods in Product, Item, Dealer to work with dict as input but there's a lot of them.
Is there a better way to achieve my goal ? Ideally I would like to be able to do something like:
p = Product({
"name": "productA",
"items": [2,3,13],
"dealer": [1,2]
})
p.simulation()
I cannot: my instances need to be saved to build relationships.

Related

Serializing Many to Many DRF

So I have predefined database structure like this:
User:
id
User_1:
user_=ForeignKey(User)
User_2:
user_1=ForeignKey(User_1)
Something:
owner=ForeignKey(User_2)
users=ManyToMany(User_2)
Well, I need to fill the table Something. Short story is that from front end I receive the ids of model User but to store I need User_2. One way I see right now is to write custom create method is serializer and do all manually.
Are there other ways to solve it?
And is it correct to use serializers.PrimaryKeyRelatedField to deal with ForeignKey when payload has next format?
{
"user": 1
}

Django Rest Framework: Disable save in update

It is my first question here, after reading the similar questions I did not find what I need, thanks for your help.
I am creating a fairly simple API but I want to use best practices at the security level.
Requirement: There is a table in SQL Server with +5 million records that I should ONLY allow READ (all fields) and UPDATE (one field). This is so that a data scientist consumes data from this table and through a predictive model (I think) can assign a value to each record.
For this I mainly need 2 things:
That only one field is updated despite sending all the fields of the table in the Json (I think I have achieved it with my serializer).
And, where I have problems, is in disabling the creation of new records when updating one that does not exist.
I am using an UpdateAPIView to allow trying to allow a bulk update using a json like this (subrrogate_key is in my table and I use lookup_field to:
[
{
"subrrogate_key": "A1",
"class": "A"
},
{
"subrrogate_key": "A2",
"class": "B"
},
{
"subrrogate_key": "A3",
"class": "C"
},
]
When using the partial_update methods use update and this perform_update and this finally calls save and the default operation is to insert a new record if the primary key (or the one specified in lookup_field) is not found.
If I overwrite them, how can I make a new record not be inserted, and only update the field if it exists?
I tried:
Model.objects.filter (subrrogate_key = ['subrrogate_key']). Update (class = ['class])
Model.objects.update_or_create (...)
They work fine if all the keys in the Json exist, because if a new one comes they will insert (I don't want this).
P.S. I use a translator, sorry.
perform_update will create a new record if you passed a serializer that doesn't have an instance. Depending on how you wrote your view, you can simply check if there is an instance in the serializer before calling save in perform_update to prevent creating a new record:
def perform_update(self, serializer):
if not serializer.instance:
return
serializer.save()
Django implements that feature through the use of either force_update or update_fields during save().
https://docs.djangoproject.com/en/3.2/ref/models/instances/#forcing-an-insert-or-update
https://docs.djangoproject.com/en/3.2/ref/models/instances/#specifying-which-fields-to-save
https://docs.djangoproject.com/en/3.2/ref/models/instances/#saving-objects
In some rare circumstances, it’s necessary to be able to force the
save() method to perform an SQL INSERT and not fall back to doing an
UPDATE. Or vice-versa: update, if possible, but not insert a new row.
In these cases you can pass the force_insert=True or force_update=True
parameters to the save() method.
model_obj.save(force_update=True)
or
model_obj.save(update_fields=['field1', 'field2'])

Associating multiple items with a single REST call

I am using the Loopback framework, and have modelA which is in a many-to-many relation with modelB.
I want to know if it's possible to relate multiple items from modelB to modelA.
There is currently a way to relate one item with this call:
/modelA/{id}/modelB/rel/{fk}
Is there any way to perform this in a bulk operation?
If I understand your question correctly, I think you can simply do it through a filter. ModelA has many modelBs, Let me assume the relation name is 'modelBs'
modelA.find({
where: [your filter option on model A]
include: {
relation: 'modelBs',
scope: {
[your filters on model B]
}
}
})
in restful way:
/modelAs?filter[include]=modelBs&filter[where]....
The official documentation may help: https://docs.strongloop.com/display/public/LB/Querying+data
It seems to be HasManyThrough model.
I believe your model names starts with lowercase but ideally it should be ModelA and ModelB and their instances can then be saved in modelA and modelB variables.
In order to use add method, you will need to first find instance of ModelA first using ModelA.findById which you can save in modelA variable and then use the following code:
modelA.modelBs.add(modelBFieldsObject, function(err, patient) {
...
});
where modelBs should be the name of relation in the ModalA.json file as in
"relations": {
"modelBs": {
"type": "hasMany",
"model": "ModelB",
"foreignKey": "modelAId",
"through": "ModelAModelB",
"keyThrough": "modelBId"
}
...
I think it should be allowed to pass an array of modelBFieldsObject to create multiple instances as in
modelA.modelBs.add([modelBFieldsObject, modelBFieldsObject], function(err, patient) {
...
});
Tip: For clarity, name your models beginning with upper case letter and their instance variable in camelCase format.
References: Methods added to the model.

How to set conditions on "through" model defined by "hasManyThrough" relation in Loopback

I defined 3 models in Loopback: job, contact and job_contact(through model) and using hasManyThrough relations defined below relation:
job has many contact through job_contact.
and I used the code below to find contacts by job through job_contact
job.findById(id, {
include: {
relation:'contact',
where :{deleted: false}, // no working here
scope:{
where:{deleted: false} // here will add condition on contact table
}
}
})
Someone got any ideas? How can I put conditions on "through" model, job_contact model, in this case?
I have found it is not possible to interact with the through model with filters on queries the two other models. If you want to access the through model you need to query it independently.
See part More Info at the bottom of the answer here and the linked github discussion.

Converting JSON to model instance in Django

What's the best way in django to update a model instance given a json representation of that model instance.
Is using deserialize the correct approach? Are there tutorials available out there?
The best approach would be to utilize one of the existing Django applications that support serializing model instances to and from JSON.
In either case, if you parse the JSON object to a Python dictionary, you can basically use the QuerySet.update() method directly.
So, say you get a dictionary where all the keys map to model attributes and they represent the values you'd want to update, you could do this:
updates = { # Our parsed JSON data
'pk': 1337,
'foo': 'bar',
'baz': 192.05
}
id = updates.pop('pk') # Extract the instance's ID
Foo.objects.filter(id=id).update(**updates) # Update the instance's data