Is there a way to access child model class object from parent model class object or now what child model class does this parent model class object has?
Here are my model classes:
class Content(models.Model):
_name = 'content'
title = fields.Char(string='Title', required=False)
summary = fields.Char(string='Summary', required=False)
description = fields.Char(string='Description', required=False)
class Video(models.Model):
_name = 'video'
_inherits = {'content': 'content_id'}
duration = fields.Float(string='Duration', required=False)
class Image(models.Model):
_name = 'image'
_inherits = {'content': 'content_id'}
width = fields.Float(string='Width', required=False)
height = fields.Float(string='Height', required=False)
If I have an object of "Content" class say "content1" that has a child object "image1", is there a way to access that "image1" object from "content1" object or now that type of "content1" is "Image"?
Content can have many child classes in future so I don't want to query all the child classes.
In Odoo you can travel bi-direction but your models should have configured like that,
class Content(models.Model):
_name = 'content'
_rec_name='title'
title = fields.Char(string='Title', required=False)
summary = fields.Char(string='Summary', required=False)
description = fields.Char(string='Description', required=False)
video_ids : fields.One2many('video','content_id','Video')
image_ids : fields.One2many('image','content_id','Video')
class Video(models.Model):
_name = 'video'
_inherit = 'content'
duration = fields.Float(string='Duration', required=False)
content_id = fields.Many2one('content','Content')
class Image(models.Model):
_name = 'image'
_inherit = 'content'
width = fields.Float(string='Width', required=False)
height = fields.Float(string='Height', required=False)
content_id = fields.Many2one('content','Content')
And you can access functionality of child classes by calling in this way.
for video in content1.video_ids:
## you can access properties of child classes like... video.duration
for image in content1.image_ids:
print image.width
Similarly you can call the method of child classes the same way.
If your aim is to do something else then specify it with example.
Related
SerializerClass:
class VacancySerializer(serializers.ModelSerializer):
organization_small_name = serializers.CharField(source='organization.short_name', read_only=True)
class Meta:
model = Vacancy
fields = ['organization', 'description', 'specs', 'type', 'publication_date',
'is_published', 'withdrawal_data', 'organization_small_name', ]
read_only_fields = ['publication_date', 'is_published', 'withdrawal_data',]
ViewSet:
class VacancyViewSet(viewsets.ModelViewSet):
queryset = Vacancy.objects.all()
serializer_class = VacancySerializer
filter_backends = [filters.SearchFilter]
search_fields = ['organization_small_name']
...
Model:
class Vacancy(models.Model):
organization = models.OneToOneField(DictOrganization, on_delete=models.CASCADE, related_name='vacancies')
description = models.TextField('Описание')
specs = models.ManyToManyField(DictSpec, blank=True)
type = models.CharField('Тип', max_length=20, choices=VacancyType.choices(), default=VacancyType.PRACTICE.value)
publication_date = models.DateField('Дата публикации', null=True, blank=True)
is_published = models.BooleanField('Опубликовано', default=False)
withdrawal_data = models.DateField('Дата снятия с публикации', null=True, blank=True)
My goal is to make API search by 'organization_small_name' field
that is in VacancySerializer.
Server runs successfully, but as soon as i add ?search parameter, i get next error:
Why it doesn't recognize 'organization_small_name' field, even thought it is decribed in serializer, and how can i fix it?
I have created a parent model, which has a Selection field.
This pattern must be inherited from classes that offer a service, so in the child classes I use fields.Selection(selection_add = ....). Is it possible to create, in the parent class, an "empty" selection that will only fill with the selection fields of the models that inherit it?
Ex
class GenericService(models.Model):
_name = 'generic.service'
selection_type = fields.Selection(
[('select_type', _("Select an Account")),],default='select_type',
string=_("Service Type"),
required=True
class SpecificService(model.Model):
_inherit = 'generic.service'
selection_type = fields.Selection(
selection_add=[('sftp','SFTP')],
)
I would like to avoid adding a default field on the generic model selection, my alternative is to create a method that controls the insertion, but I would like to know if it could be avoided.
If you inherit like that _inherit without _name. Then you end up only with 1 model generic.service And all selection_add=[] added selections.
If you add
class GenericService(models.Model):
_name = 'generic.service'
selection_types = fields.Selection([], string="Service Type")
class SpecificServiceA(model.Model):
_inherit = 'generic.service'
selection_type = fields.Selection(
selection_add=[('sftp','SFTP')], required=True
)
class SpecificServiceB(model.Model):
_inherit = 'generic.service'
selection_type = fields.Selection(
selection_add=[('https','HTTPS')], required=True
)
you end up with model named "generic.service" and selections [('sftp','SFTP'), ('https','HTTPS')]
I believe strings and selection names are added automatically to translation list. no need for _()
You can also use Odoo's mixin feature, which is a bit like abstract types/classes. Following an example in context of your requirments:
class ServiceMixin(models.AbstractModel):
_name = "service.mixin"
def _get_type_selection(self):
""" Returns a 2-tuple list for type_selection field
Meant to be extended by inheriting models."""
return []
type_selection = fields.Selection(
selection="_get_type_selection", string="Type")
class ServiceA(models.Model):
_name = "service.a"
_inherit = ["service.mixin"]
def _get_type_selection(self):
""" Returns a 2-tuple list for type_selection field"""
return [('a', 'A'), ('b', 'B')]
class ServiceB(models.Model):
_name = "service.b"
_inherit = ["service.mixin"]
def _get_type_selection(self):
""" Returns a 2-tuple list for type_selection field"""
return [('a', 'A'), ('c', 'C')]
In database that will lead to 2 new tables: service_a and service_b. So you have really 2 new Odoo models, which aren't dependend on eachother.
I have a class named detail_base, and two other classes name flight_detail and tour_detail, the last two classes inherits from the first one, like this:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherits = 'detail_base'
age = fields.Integer('Tourist Age')
The problem is when I call the flight_detail and tour_detail in the same view, the browser can't handle the common attributes of both classes, If I assign 5 to tour_detail.fee, that number will be stored into flight_detail.fee.
It seems the problem is related to the attributes with the same name of different objects being siblings.
I will appreciate any help.
You should either use _inherit
class DetailBase(models.AbstractModel):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherit = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = 'detail_base'
age = fields.Integer('Tourist Age')
which should either create 3 database tables (detail_base as Model) or 2 database tables (AbstractModel).
Or you use _inherits like:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = {'detail_base': 'base_id'}
passport = fields.Char('Passport')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = {'detail_base': 'base_id'}
age = fields.Integer('Tourist Age')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
That will create 3 tables, and fee and passenger will be stored in detail_base table. Odoo will get it from there, because it is a sort of delegation inheritence.
use inherit:
1- inherit without _name :
inherit = 'model.name'
new_field = fields...
this add this field to the model.name
2- inherit with _name:
inherit = 'model.name'
_name = 'new.model'
here will create a new tabel in database with the same structure of model.name.
inherits: The delegation inheritance.
best example is res.users and res.partners user is a partener so when we create a res.users record we must create a res.partener that hold commun field like name, email, address ... and information related to users like passowrd and login are stored in res.users model and with type of inheritence you can access field of res.partener directly without having to create a related field. you can do user_record.name or .email or .address this will not be a problem.
i like to think of it as one2one relation.
_inherits = {model.name : many2one_field_id }
_name = 'new.model'
# m2o field should be required and ondelete = cascade
many2one_field_id = fields.Many2one('model.name', string='Label', required=True, ondelete="cascade")
so when you create a record of new.model all field that are in model.name will be stored in model.name.
I got models:
class Car:
name = models.CharField(max_length=50, blank=True, default='')
class Wheel:
name = models.CharField(max_length=50, blank=True, default='')
cars = models.ManyToManyField(Car)
and serializers:
class CarSerializer(serializers.ModelSerializer):
class Meta:
model = Car
fields = ('name')
class WheelSerializer(serializers.ModelSerializer):
cars = CarSerializer(many=True, required=False)
class Meta:
model = Wheel
fields = ('name', 'cars')
It's works fine with Wheel case, it's shows me wheels and cars inside them. But I want to call cars and see wheels inside Cars. It's possible? Thanks!
Solution is to create new serializers:
class CarSerializer(serializers.ModelSerializer):
class Meta:
model = Car
fields = ('name')
class WheelSerializer(serializers.ModelSerializer):
class Meta:
model = Wheel
fields = ('name', 'cars')
class CarWheelSerializer(serializers.ModelSerializer):
cars = CarSerializer(many=True, required=False)
class Meta:
....
and WheelCarSerializer same way.
I need help to set default value of purchase_ok field at product_template class in purchase module
thanks
You can simply set the default attribute like this:
class ProductTemplate(models.Model):
_inherit = 'product.template'
purchase_ok = fields.Boolean(
string='Selectable on purchase operations',
default=True,
)
Or you can use a lambda function like this:
class ProductTemplate(models.Model):
_inherit = 'product.template'
purchase_ok = fields.Boolean(
string='Selectable on purchase operations',
default=lambda self: self._get_default_purchase_ok(),
)
#api.model
def _get_default_purchase_ok(self):
value = True
# some operations
return value