Importance of active_ids and active_id in odoo - odoo

What are the key roles of active_ids and active_id in development ?
I want to know Advantages and Limitations of that functionality provided by odoo.
In certain case what we can do if I can not get the active_ids in context while opening wizard from other model's list view ?
Here is the action which I used to open my wizard from list view of product.product model.
<act_window name="Calculate Product Price"
res_model="wizard.main"
src_model="product.product"
view_mode="form"
view_type="form"
target="current"
multi="True"
key2="client_action_multi"
id="action_product_price_calculator_ept"
view_id="view_product_calculator_wizard"/>
Here is my python code to get active ids.
#api.model
def default_get(self, fields):
context = self.env.context
res = super(wizard_main, self).default_get(fields)
product_ids = context.get('active_ids',[])
if not product_ids:
return res
#### few more lines will be added here
return res

Related

How write a Django REST APIView POST request with a condition?

I am trying to create a post request for a game api. The game implies that a user can label a picture. A label entered once is a tagging, a label entered twice for the same resource is a tag.
This is how I am trying to create a Tagging so far:
saved_tagging = Tagging.objects.create(user_id=current_user_id,
gameround=gameround,
resource=random_resource,
tag='tag newwww',
created=datetime.now(),
score=score,
origin=origin
)
tagging_serializer = TaggingSerializer(saved_tagging)
At the moment I am getting the ValueError: Cannot assign "'tag newwww'": "Tagging.tag" must be a "Tag" instance.
Is there any way that I can avoid this?
Here are also my models and the relevant serializer.
models.py
class Tag(models.Model):
name = models.CharField(max_length=256)
language = models.CharField(max_length=256)
objects = models.Manager()
def create(self, validated_data):
tag_data = validated_data.pop('tag')
Tag.objects.create(**tag_data)
return tag_data
def __str__(self):
return self.name or ''
class Tagging(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
gameround = models.ForeignKey(Gameround, on_delete=models.CASCADE, related_name='taggings')
resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name='taggings')
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, related_name='tagging')
created = models.DateTimeField(editable=False)
score = models.PositiveIntegerField(default=0)
origin = models.URLField(max_length=256, blank=True, default='')
objects = models.Manager()
def create(self, validated_data):
tag_data = validated_data.pop('tag')
tagging = Tagging.objects.create(**validated_data)
Tag.objects.create(name=tagging, **tag_data)
return tagging
def __str__(self):
return str(self.tag) or ''
serializers.py
class TaggingSerializer(serializers.ModelSerializer):
tag = StringRelatedField()
resource = ResourceSerializer(read_only=True)
gameround = GameroundSerializer(read_only=True)
class Meta:
model = Tagging
fields = ('id', 'tag', 'gameround', 'created', 'score', 'resource', 'origin')
def create(self, validated_data):
return Tagging.objects.create(**validated_data)
def to_representation(self, data):
data = super().to_representation(data)
return data
tag must be a Tag Instance !
So... you can do this in two ways (in my opinion).
First you can create a Tag object in your view and than pass this object to tag value in your Tagging create method.
Or create a service layer on your app, and create a custom create method for your model. This in my opinion is superior because your a centralizing your rules in one method instead of in one view.
Ex.:
services/tag_service.py
def create(user_id,gameround,resource,tag,...origin):
if not isinstance(tag, Tag):
#create your tag model based on the String passed
your_new_tag_object = Tag.objects.create(tag=tag, ...)
# Here your create others rules too for model creation
# Return your model .create method
return Tagging.objects.create(user_id=user_id,...tag=your_new_tag_object,...)
And Than use this new create method inside your POST serializer.
from services import tag_service
class TaggingSerializer(serializers.ModelSerializer):
# your normal serializer here
def create(self, validated_data):
return tag_service.create(**validated_data)

Reference field does not render on frontend in Odoo

I have added this to my model:
ref_doc_id = fields.Reference(selection='_referencable_models', string='Reference Document')
#api.model
def _referencable_models(self):
models = self.env['ir.model'].search([('field_id.name', '=', 'message_ids')])
return [(x.model, x.name) for x in models]
And the field to a view:
<field name="ref_doc_id"/>
The field seems to be loaded on frontend but it doesn't show the dropdown. Am I doing something wrong?

How to set a fixed value of particular column to user in POST API in Django?

I am using DRF for creating API, using basic APIView. Below are the models and views.
models.py
from django.db import models
from django.utils import timezone
class PizzaOrder(models.Model):
name = models.CharField(max_length=120)
size = models.CharField(default='MEDIUM')
customer_name = models.CharField(max_length=120)
customer_address = models.TextField()
ordered_time = models.DateTimeField(default=timezone.now)
Now, I need two things in that.
First - I want to set STATUS as 'open' in the database while ordering pizza. User isn't able to see the STATUS column while saving.
Second - I want to get all orders, but it should show STATUS to the user now.
view.py
class PizzaOrderView(APIView):
def get(self, request):
orders = PizzaOrder.objects.all()
serializer = ArticleSerializer(orders, many=True)
return Response({"orders": serializer.data})
def post(self, request):
orders = request.data.get('orders')
serializer = ArticleSerializer(data=orders)
if serializer.is_valid(raise_exception=True):
article_saved = serializer.save()
What should I do to get my all two requirements?
First of all if you want to save status in the database you must include it as one of the fields in your model. I would also suggest adding the choices enumeration so that nothing unwanted can end up in database as a status (note that you can add any other choice besides open and closed):
class PizzaOrder(models.Model):
...
OPEN = 'open'
CLOSED = 'closed'
TYPE_CHOICES = (
(OPEN, 'Open'),
(CLOSED, 'Closed'),
)
status = models.CharField(max_length=120, choices=STATUS_CHOICES, default=OPEN)
Next thing to know is that the way data is presented to the user depends mostly on your serializers (would be useful if you could include those in your question aswell). So for serializing the PizzaOrder data you can use two different serializers (one which includes the status field, and one which does not):
class PizzaOrderSerializer(serializers.ModelSerializer):
class Meta:
model = PizzaOrder
fields = '__all__'
class PizzaOrderWithoutStatusSerializer(serializers.ModelSerializer):
class Meta:
model = PizzaOrder
fields = ['name', 'size', 'customer_name', 'customer_address', 'ordered_time']
you can user one serializer just just using the one serializer
class PizzaOrderSerializer(serializers.ModelSerializer):
class Meta:
model = PizzaOrder
fields = '__all__'
read_only_fields = ('status',)

How to update a db row from an action in Flask-appbuilder and SQLAInterface

I am building a app using flask-appbuilder and I have an action that runs a function and I want to update the row in the table with the output of function. Can't work out how to do it. Any help? Thanks
#action("prospect", "Prospect", "off we go", "fa-rocket")
def prospect(self, items):
if isinstance(items, list):
for a in items:
out = self.myfunction(a.name)
#Need to update the table with output
#anyideas?
self.update_redirect()
else:
print "nothing"
return redirect(self.get_redirect())
I'm assuming this is a View that is related to a model. If this is the case, you relate the model to the view using Flask-AppBuilder SQLAInterface class.
This class allows you to interact with the item in the database.
This class has an 'edit' method that let's you update the item.
Let's say your model is like the one below:
class Contact(Model):
id = Column(Integer, primary_key=True)
name = Column(String(50), unique = True, nullable=False)
Let's say you want to implement an action that capiltalizes the contact name, and you want to be able to do it on the the 'List' and 'Show' views. This is one way to do it:
class ContactView(ModelView):
datamodel = SQLAInterface(Contact)
#action("capitalize",
"Capitalize name",
"Do you really want to capitalize the name?")
def capitalize(self, contacts):
if isinstance(contacts, list):
for contact in contacts:
contact.name = contact.name.capitalize()
self.datamodel.edit(contact)
self.update_redirect()
else:
contacts.name = contacts.name.capitalize()
self.datamodel.edit(contacts)
return redirect(self.get_redirect())
You can check other SQLAInterface methods here.

How to modify many to many field in wizard?

I have model contains many to many assign_to_id, I want to modify that field in wizard form through escalte_to method when user trigger escalate button
Model:
class Incident(models.Model):
_name = 'itmangement.incident'
assigned_to_id = fields.Many2one('hr.employee', string="Assigned To",domain="[('department_id', '=', dep_id)]",required=True)
Wizard model
class Escalate(models.TransientModel):
escalated_to = fields.Many2one('hr.employee', string="Escalated To", required=True)
#api.one
def escalate(self):
incident_obj = self.env['itmangement.incident']
record = incident_obj.browse(self._context.get('active_ids'))
record.write({'state': 'escalated'})
class Escalate(models.TransientModel):
escalated_to = fields.Many2one('hr.employee', string="Escalated To", required=True)
#api.one
def escalate(self):
object_id = self.env.context.get('active_id')
for object in self.env['itmangement.incident'].browse(object_id) and self.escalated_to:
object.assigned_to_id = self.escalated_to.id