I generate model with Model Generator and then (afterward) add a new table and new foreign keys relations.
Is it possible to update the existing model with model generator?
Or do I need to edit the code manually when I add a new table?
Have a look at the gii-template-collection and it's FullModel template.
It generates by default two classes for your models, BaseModel and Model. Best-practice for me is to add my custom functions, behaviors, scopes, etc... to Model and leave BaseModel untouched.
If you have changes in your database schema, just re-generate the BaseModel class.
No you can't edit the existing model with Gii tool. You will have to either manually update the model or generate a new one.
Related
Is there a straight forward process to copy a module to a new module name with its own dependencies?
In my example I need to create a module very similar to the EVENTS module, but I also need the EVENTS module in its original form.
I figure the easiest way is to copy the events module to a new module name and then make my changes to it.
yes, you can do that... but you have to refactor the MODULE name, MODELS name, VIEWS(form,tree,action) name DIFFERENT from EVENT modules. So ur EVENT modules didn't get pile up.
Don't do that, it's a very bad idea.
Inheritance is what you want
What you want to do is create a new module with the module event as a dependency of your module. Then you can create new views that inherit existing views using the this in the view definitions:
<field name="inherit_id" ref="xml_id_of_view" />
Then all the model class that you need to update have to inherit the existing models as explained in ORM Inheritance. You'll have choice between 3 ways on inheritance:
creating a new model from an existing one, adding new information to the copy but leaving the original module as-is
extending models defined in other modules in-place, replacing the previous version
delegating some of the model’s fields to records it contains
# 1.
class Event(models.Model):
_name = "new_event"
_inherit = "event.event"
# 2.
class Event(models.Model):
_inherit = "event.event"
# 3.
class Holiday(models.Model):
_name = "event.holiday"
_inherits = {
"event.event": "event_id"
}
event_id = fields.Many2one("event.event")
I won't go into details on the 3 possible ways on inheritance to keep it short but.
Will copy the model definition to a new model so you essentially have the same thing as if you copied the code including extensions from other dependencies loaded before inheriting the model.
Will just extend the model adding new functions, will essentially share data but can be avoided by adding a type and correctly filtering models. For example you'd want a type on events to keep them separated logically while keeping them in the same table. This has the advantage to keep things together. So if you want to display multiple types of events in a calendar it will be possible.
This will create a new table having some of the data kept in a different table and new data inside the new model table. In other words when you create this new model, you'll create this model and the one being delegated. One example is having an Event and having an Holiday. The holiday type would remain in its table and you could list all holidays, but each holiday would be link to an event with a date and so on. It's a bit like inheritance method 2 with a type except that data is being isolated in different tables. For example, the holidays will be visible inside the calendar event.event but won't display anything defined in event.holiday as event.event has no idea what's an event.holiday. (for example, res.users -> res.partner is using this method).
With that said, method 2 doesn't really have any cost to implement in speed, method 1 will also be fast as data is kept in its own table but if a module extend the model and isn't in your dependency tree, the changes made to the model won't be visible so it's not 100% copying the schema.
Method 3 is good when you want to keep data normalized where each table own the data it needs to exist and the whole data of the model can be spanned across multiple tables with an implicit one2one relationship.
Also inheritance of views
Also, you can inherit views to create a new views by setting primary=True.
Documentation on views
View matching
if a view is requested by (model, type), the view with the right model and type, mode=primary and the lowest priority is matched
when a view is requested by id, if its mode is not primary its closest parent with mode primary is matched
Setting a view as primary essentially tell odoo to consider it as a top view so it doesn't extend the view it inherits but create a new view with the extension. This can be used with new models being created to prevent custom changes to affect the views of models that don't have the extension.
You can change the model of the view to handle a different model. For example, the holiday model could be handled by inheriting the event.event view and setting the model as event.holiday and changing the type of the view to primary=True. Any other module extending this new view will not have any effect on the parent event.event views.
Why not copying a whole module:
Now as to why copying an existing module is a bad idea. When you copy a module, you're taking the maintenance of the code on yourself. So any changes from one version to an other or bug fixed in the event module will not be present in your module unless you manually maintain change of code in the event module into your one.
Then you may think it's fine and can get away with it but the moment you'll want to upgrade from let say odoo12 to odoo13. Your module will have to be ported and if you want to rollback your change to create a module that extends the event module like explained above. You'll have to remember exactly which commit you forked the module from. Otherwise you'll have a hard time making a diff and seeing what changes you did introduce and how to port it to odoo13. If you only create a module that extends events, you'll have to port your changes and if you're lucky, you won't have to change anything as since odoo8-10 things didn't change much in some modules so moving from one to an other version is usually straight forward but if you copy you're adding a lot of work in the future for nothing.
Also, this is all based on personal experience after I had to work on projects and modules developed from outsourced companies. Some of the people "developing" the modules did exactly what you're trying to achieve and it costed us so much time to extract the changes made by this company to the PointOfSale which resulted in a module with a few lines of code. The module prevented us from installing the actual point of sale, and the module I had to fix was based from a very old version of the PoS missing critical bug fixes.
It simply isn't worth it.
I have a custom model mymodule.contacts which inherits from res.partner because I new a few extra fields. I would like my records that I add to mymodule.contacts to be visible in the other Odoo modules, sans my extra fields .. i.e. the fields in my model which inherit from res.partner are the only ones that possibly could be visible in the other Odoo models and that's fine. so for example, the Invoice module uses the res.partner model. My model inherits from res.partner. However since Odoo should create my model as a new table in Postgres, I dont think any of my contact data in my custom model will be visible to the Invoices module, despite inheriting from res.partner, because the actual data is in a different Postgres table. Are my assumptions correct?
It really depends on the kind of inheritance you're doing. If you do a simple inheritance with
_inherit = res.partner
To add new fields to the res.partner model, then Yes the new fields would be available to any model that has links to res.partner
On the other hand if you do a polymorphic inheritance with
_inherits = res.partner
Or you specify a _name while inheriting, A new table would be created in postgres with the attributes of the old model and your new fields won't be available to other models that inherit res.partner.
I think what you're really looking for is _inherits, it creates a new table for you. The default data for res.partner would still be stored in it's table but the new data would be stored in the new table you specified, so other models would never get to know of the new fields you added.
There is a great visualization here on the types of inheritance in Odoo.
https://www.odoo.com/forum/how-to/developers-13/whats-the-difference-between-inherit-and-inherits-52205
When you inherit a model, you simply gain its characteristics so that you can build on it. The inherited model or any other model will not have any visibility to your model unless its connected. The extra fields you add to your extension model will not be visible to any other model unless you connect them with many2one ,one2many or many2many fields.
I want to rename a property, sortOrder:
to sequence, within an NSManagedObject class.
(example illustration only)
And have followed the steps of Lightweight Migration.
The challenge is that the Lightweight Migration doesn't actually affect the NSManagedObject class (FormItems).
So the code still uses the sortOrder property. I can run a refactor-rename through XCode to change the code, but will that then break my backwards DB compatibility due to the renaming within the class?
What am I misunderstanding here?
Lightweight migration should work as expected. This statement
The challenge is that the Lightweight Migration doesn't actually affect the NSManagedObject class (FormItems).
is not necessarily true. It LW migration should affect all changed entities.
You can refactor your code to use the new name and
Create a new model version.
Make the changes to the property after changing to the new model version.
Make sure the persistent store has the right options.
NSMigratePersistentStoresAutomaticallyOption and
NSInferMappingModelAutomaticallyOption
As described by #Mundi, you need to create a new model version.
After that, you need to rename sortOrder as sequence in your code.
In mapping model, value expression for attribute "sequence" would be $source.sortOrder. This will retain all previous values after migration.
I need some help as I seem not to be able to grasp the concept.
In a framework, namely Yii, we create models that correspond to database tables. We extend them from CActiveRecord.
However, if I want to create a class that will get some data from other models but then will do all the computations based on those results and do something with them... then how do I proceed?
I want to clearly divide the responsibility so I don't want put all the calculations in source db based models. Basically the idea is that it will be taking some stuff from some models and then updating another models with the results of the calculations.
What do I do?
Keep all the calculations in some controller and use required models? (Hesitant about this because there is a rule to keep controller slim)
Create a none db model and then work from there (how?)?
Do something else (what?)?
Thanks for any help!
For you to use the Yii interpretation of Model, you will have to create class, which depends on CModel. It is an abstract class, thus you will be required to implement attributeNames() method.
To use other "Models" with this new structure, you will need to inject them in constructor, or right after your custom model has been created.
In real MVC model is a layer, which mostly contains two sets of classes with specific responsibilities: domain business logic and data access operations. Objects which are responsible for Domain Business Logic have no clue where the information is stored and where it comes from. Or even if there is such a thing as "database".
This video might explain a bit: https://vimeo.com/21173483
I'm using DropCreateDatabaseIfModelChanges DB initializer class in Entity-framework-4.2. Problem is it creates a new database and old data is lost. I used seed method of this class to enter some new values. But in that way I cannot preserve my old data.
Does anyone know a way to drop and create a DB when model changes, without losing existing data?
Thank you.
No it is not possible with built-in database initializers and writing custom initializer preserving data would be very complex task. As alternative you can use Code First Migrations instead of initializers. Migrations allows incremental development of your database.