Odoo change field attribute through extension - python

In Odoo there is a file addons/website_quote/models/sale_order.py which has a class SaleOrder. It has a field
website_description = fields.Html('Description', sanitize_attributes=False, translate=html_translate)
I would like this field to become not translatable, since every time the user saves a record he (the user) gets message "Update translations". Which annoyed the user.
website_description = fields.Html('Description', sanitize_attributes=False, translate=False)
To achieve this I would create another class that inherits SaleOrder and has this line
website_description = fields.Html('Description', sanitize_attributes=False, translate=False)
Is this right way to change field's attribute?

You don't need to recreate all field attributes again with the new API:
from odoo import models, fields
class SaleOrder(models.Model):
_inherit = "sale.order"
website_description = fields.Html(translate=False)
That should be enough.

Related

fetch value from two fields (Date and Monetary) and convert it in text in Odoo

I have two fields in Sale order, i need to get values from each one change its value in text and display in another field in custom model
Two fiedls in sale.order module:
amount_total = fields.Monetary(string="Total", store=True, compute='_compute_amounts', tracking=4)
date_order = fields.Datetime()
and this is my code so far:
from odoo import fields, models, api
from odoo.exceptions import ValidationError
import random
readonly_fields_states = {
state: [('readonly', True)]
for state in {'sale', 'done', 'cancel'}
}
class SaleOrder(models.Model):
_inherit = "sale.order"
test = fields.Many2one(string="Test",
comodel_name='sale.order',
default=lambda x: random.randint(1, 10),
states=readonly_fields_states,
)
#api.constrains('test')
def check_test_length(self):
for rec in self:
if rec.test:
if len(rec.test) > 50:
raise ValidationError('Длина текста строки "test" должна быть меньше 50 символов!')
else:
pass
The goal is: get data from fields turn its type into text and display that data in fiedl test when the two from sale.order is changed. For now i get only names S00001, S00002.. etc.
I have no working solution. I have tried various fucntion but non of them seems to work or i doing something wrong. I realise that my case bit unclear thats because i can`t wrap my head around it. So ask me whatever needed if you want to help.
You can use odoo related field attribute.
In your custom model add a relational field with sale.order and then create related fields.
sale_order_id = fields.Many2one(comodel_name="sale.order")
sale_order_amount_total = fields.Monetary(related="sale_order_id.amount_total")
sale_order_date_order = fields.Datetime(related="sale_order_id.date_order")
Now in custom model views you'll be able to use created fields.
<field name="sale_order_amount_total" />
<field name="sale_order_date_order" />
Note that these fields will be directly related to your Many2one model instance (sale.order record)
Good practice is to set them to readonly=True
In case you are going to execute queries in your custom models using your related fields, you should consider using store=True as attribute.
For example
sale_order_amount_total = fields.Monetary(
related="sale_order_id.amount_total",
store=True,
readonly=True
)

how to read value from field of another model?

I am working with odoo 10 and have created a few fields, and have the following problem:
I created my own field (x_order_bestelldatum) in the module sale.order. When I confirm an offer, I enter the effective order date in this field.
Now, when I create an invoice, I want to read the x_order_bestelldatum field of the module sale.order in module account.invoice so that I can print the order date on the invoice.
How can I read out the field x_order_bestelldatum from model sale.order in model account.invoice?
Here is my code in file models.py, but it does not work:
from odoo import models, fields, api
class felder_saleorder(models.Model):
_inherit = 'sale.order'
x_order_bestelldatum = fields.Date(string="Bestelldatum")
class felder_invoice(models.Model):
_inherit = 'account.invoice'
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",related='sale_order.x_order_bestelldatum')
x_lieferdatum = fields.Date(string="Lieferdatum")
That does not work (the field x_bestelldatum remains empty):
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",related='sale_order.x_order_bestelldatum')
Well lets not do it your way plus I can't get it how you are doing it.
So, I am suggesting some other possibilities which might help you.
First lets talk about the sale order field whom you named as 'sale_order'.
There are two possible options with which you are entering data in the sale_order field.
1). Automatically through python
2). Manually by selecting from the list.
In case of entering data Manually you should use onchange function:
#api.onchange('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
In Case if you are automatically entering data through python then you can use monetary or create function to fill the field.
Create function:
#api.model
def create(self, vals):
new_record = super(felder_invoice, self).create(vals)
if new_record.sale_order:
new_record.x_bestelldatum = new_record.sale_order.x_order_bestelldatum
return new_record
Compute Funtion:
First you need to amend your field deceleration in py file like that
x_bestelldatum = fields.Date(string="Bestelldatum",compute="get_order_date")
Then you need to create a compute function for that:
#api.one
#api.depends('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
You can get the order date by using above mentioned functions and willbe able to get its value in reports/prints.
Hope it helps.
Cheers!
Thank you for your answer.
I have tried a few variants, but it still does not work. The field 'x_bestelldatum' in the module 'account.invoice' will always be empty.
This is what my code looks like:
class felder_invoice(models.Model):
_inherit = 'account.invoice'
x_lieferdatum = fields.Date(string="Lieferdatum")
sale_order = fields.Many2one('sale.order','sale_order')
x_bestelldatum = fields.Date(string="Bestelldatum",compute="get_order_date")
#api.one
#api.depends('sale_order')
def get_order_date(self):
if self.sale_order:
self.x_bestelldatum = self.sale_order.x_order_bestelldatum
Is that right? Are all fields from 'sale.order' transferred to the new locale field 'sale_order'?
sale_order = fields.Many2one('sale.order','sale_order')

How to pass wizard fields ids in sale .order.line for Odoo10

I've inherited the sale.order.line and I've added a wizard (sale.pack.wizard) accesible from a button of sale.order form. Besides, I have a field test (One2many type) in the wizard. Now, I want to get the test field IDs in a method of sale.order.line model. So, how can I do this?
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
#api.depends('product_uom_qty', 'discount', 'price_unit', 'tax_id', 'product_id','price_subtotal')
def _compute_amount(self):
active_id = self.env.context.get('active_ids', []) or []
new = self.env['sale.pack.wizard'].browse(active_id)
#Here i want to show 'test' field id from wizard
class SalePackWizard(models.TransientModel):
_name = "sale.pack.wizard"
_description = "Sale Pack Wizard"
product_id = fields.Many2one('product.product', string="Product Pack", required=True, domain="[('is_pack','=',True)]")
test = fields.One2many('product.gold','service',string="Pack Products",change_default=True, default=_onchange_action_product_add )
You cannot achieve your purpose in that way. You have to take into account that there is a scheduled action in Odoo (AutoVacuum osv_memory objects) which removes every transient model record each 30 minutes (by default). This means that if you were able to get the wizard test field value, even so, it would only return any value the 30 minutes after the wizard was opened for the first time.
So, what I'd do in your case, is to create a new field in sale.order.line model which stores the info you need of the wizard. Then, I'd create a button in the wizard, and when you click on this button, execute a method which fills in the new sale.order.line field with the info you need.

How to modify field rendering behaviour based on state of other fields of model in django

Let's assume that I have following models:
class ScoutBook(models.Model):
troop = models.ForeignKey('Dictionary', limit_choices_to={'type' : 'Troop'}, related_name='+', blank=True, null=True)
class Dictionary(models.Model):
name = models.CharField(max_length=CHAR_FIELD_MAX_LEN, verbose_name="Nazwa")
active = models.BooleanField(verbose_name="Aktywny")
type = models.CharField(max_length=CHAR_FIELD_MAX_LEN, choices=DICTIONARY_CHOICES)
and I want to implement following logic:
when creating ScoutBook allow users to select only active troops, and when editing allow to select active troops or allow user to leave value unchanged (even if the troop is inactive). If I use limit_choices_to = {..., 'active' = True} troop that is inactive is absent from combo box in django admin.
So to be clear: let's assume that there are four troops in this system: Troop1, Troop2 and InactiveTroop, InactiveTroop2. On model creation I would like user to be able to choose Troop1 and Troop2. If model has troop field set to InactiveTroop2, I would like user to be able to choose between InactiveTroop2, Troop1 and Troop2.
I was looking at the django forms api and I didn't found obvious way do this. Moreover, in the application I'm developing there will be many such fields and many such models --- so solution must be pain free. I would rather not create new Form class for every model. I will be using mostly django admin to enable editing the database, and some read only views that will just list entries.
Ideally I would like to encapsulate this functionality in some custom field --- but fields have access to model instance on validate and save phase --- so I dont have access to it when I produce formfield.
This sounds like something you want to do in a form, not in the object itself. Create a ModelForm and override the ModelChoiceField like this:
from django import forms
class ScoutBookForm(forms.ModelForm):
troop = forms.ModelChoiceField(queryset=Troop.objects.filter(active=True))
class Meta:
model = ScoutBook
You can also override the clean method of ScoutBook to ensure it cannot ever be saved with an inactive Troop, though that may have some unintended consequences (e.g., you wouldn't be able to update a ScoutBook in the admin if the troop had gone inactive at some point in the past).
Well I had to hook into ModelForm creation. Attached Form inspects it's fields and if specific conditions are met it replaces model field queryset.
class DictionayModelForm(ModelForm):
def __init__(self, *largs, **kwargs):
super(DictionayModelForm, self).__init__(*largs, **kwargs)
if self.instance and self.instance.pk is not None:
for f in self.instance._meta.fields:
if isinstance(f, models.ForeignKey) and issubclass(f.rel.to, Dictionary):
model_field = self.fields[f.name]
value = getattr(self.instance, f.name, None)
if value and value not in model_field.choices:
model_field.queryset = Dictionary.objects.filter(Q(**f.rel.limit_choices_to) | Q(id = value.id))

Django - Get ContentType model by model name (Generic Relations)

I'm thinking about this for a while now,
I'm creating a chat application, in chat.models a class Room is specified, however, a Room can be related to anything in my project, since it uses a generic relation in it's foreign key.
Is there a way to know which model that Room is related knowing only the models name?
Like:
ctype = 'user'
related_to_user = Room.objects.filter(content_type=ctype)
The problem I'm having is, the code below is in a view:
doc = get_object_or_404(Document, id=id)
# get *or create* a chat room attached to this document
room = Room.objects.get_or_create(doc)
If I don't want to use Document model, if I want a model associated to a string, a string that can be anything, without having to write tons of if's to get a specific Model for the specific string. Is there a way to find a model just by it's 'name'?
Thanks
http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#methods-on-contenttype-instances
user_type = ContentType.objects.get(app_label="auth", model="user")
user_type = ContentType.objects.get(model="user")
# but this can throw an error if you have 2 models with the same name.
Very similar to django's get_model
from django.db.models import get_model
user_model = get_model('auth', 'user')
To use your example exactly:
ctype = ContentType.objects.get(model='user')
related_to_user = Room.objects.filter(content_type=ctype)

Categories

Resources