-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing base models/adapters for Nautobot side functionality. #153
Conversation
Is the goal here to get to dynamic pydantic models based on the underlying django models? Curious if you have explored https://github.com/jordaneremieff/djantic/? |
The inference of data types would be great but the inference of the full model would not. This does not conflict with anything that @lampwins indicated, but just want to be clear of the intention as auto discovery of the whole model would be problematic given how complex Nautobot's data model is. |
This looks interesting. I will give usage of this a quick exploration, it may serve to make the model definition even simpler. @itdependsnetworks your point is very valid, djantic appears to allow usage with |
docs/user/developing_jobs.md
Outdated
|
||
### Putting it Together in a Job | ||
|
||
Develop a Job class, derived from either the `nautobot_ssot.jobs.base.DataSource` or `DataTarget` classes provided by this plugin, and implement the adapters to populate the self.source_adapter and self.target_adapter that are used by the built-in implementation of sync_data. This sync_data method is an opinionated way of running the process including some performance data, more in next section, but you could overwrite it completely or any of the key hooks that it calls: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have trouble following this one, mind taking another crack at it?
docs/user/modelling.md
Outdated
|
||
## Many-to-one Relationships | ||
|
||
For many-to-one relationships (i.e. [foreign keys](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/) or [generic foreign keys](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/#generic-relations)) a slightly different approach is employed. We need to add a field on our model for each field that we need in order to uniquely identify our related object behind the many-to-one relationship. We can do this using a [familiar synta](https://docs.djangoproject.com/en/3.2/topics/db/queries/#lookups-that-span-relationships) of double underscore separated paths. Assuming we want to synchronize prefixes and associate them with locations, we may be faced with the problems that locations aren't uniquely identified by name alone, but rather need the location type as well, we can address this as follows. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For many-to-one relationships (i.e. [foreign keys](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/) or [generic foreign keys](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/#generic-relations)) a slightly different approach is employed. We need to add a field on our model for each field that we need in order to uniquely identify our related object behind the many-to-one relationship. We can do this using a [familiar synta](https://docs.djangoproject.com/en/3.2/topics/db/queries/#lookups-that-span-relationships) of double underscore separated paths. Assuming we want to synchronize prefixes and associate them with locations, we may be faced with the problems that locations aren't uniquely identified by name alone, but rather need the location type as well, we can address this as follows. | |
For many-to-one relationships (i.e. [foreign keys](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/) or [generic foreign keys](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/#generic-relations)) a slightly different approach is employed. We need to add a field on our model for each field that we need in order to uniquely identify our related object behind the many-to-one relationship. We can do this using a [familiar syntax](https://docs.djangoproject.com/en/4.2/topics/db/queries/#lookups-that-span-relationships) of double underscore separated paths. Assuming we want to synchronize `prefixes` and associate them with `locations`, we may be faced with the problems that locations aren't uniquely identified by name alone, but rather need the location type as well, we can address this as follows. |
docs/user/modelling.md
Outdated
location__location_type__name: str | ||
``` | ||
|
||
Now, on model `create` or `update`, the SSoT framework will dynamically pull in the location with the specified name and location type name, uniquely identifying the location and populating the foreign key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "how" is not immediately clear to me to for how to add a field on our model
is exactly constructed.
docs/user/modelling.md
Outdated
|
||
### Special Case: Generic Foreign Key | ||
|
||
In the case of a [generic foreign key](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/), we are faced with a problem. Normally, the [content type](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/) of a relationship field can be inferred from the model class. In the case of generic foreign keys however, this is not the case. In the example of the [IP address](https://docs.nautobot.com/projects/core/en/stable/models/ipam/ipaddress/?h=ip+address) model in Nautobot, the `assigned_object` field can point to either a device's or a VM's interface. We address this the following way: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of a [generic foreign key](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/), we are faced with a problem. Normally, the [content type](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/) of a relationship field can be inferred from the model class. In the case of generic foreign keys however, this is not the case. In the example of the [IP address](https://docs.nautobot.com/projects/core/en/stable/models/ipam/ipaddress/?h=ip+address) model in Nautobot, the `assigned_object` field can point to either a device's or a VM's interface. We address this the following way: | |
In the case of a [generic foreign key](https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/), we are faced with a problem. Normally, the [content type](https://docs.djangoproject.com/en/3.2/ref/contrib/contenttypes/) of a relationship field can be inferred from the model class. In the case of generic foreign key**s** however, this is not the case. In the example of the [IP address](https://docs.nautobot.com/projects/core/en/stable/models/ipam/ipaddress/?h=ip+address) model in Nautobot, the `assigned_object` field can point to either a device's or a VM's interface. We address this the following way: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand, why is it important to highlight the "s" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First you write:
In the case of a [generic foreign key]
Then you write:
In the case of generic foreign keys however
After reading that 5 times I am still not sure what two things are being compared. It seemed logical that you were comparing generic foreign key
to generic foreign keys
based on the paragraph structure ... but perhaps that is wrong?? So emphasis is my best guess at what is being stated as different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say a common theme is to be explicit, often by removing pronouns but in this case a bit different. It's very complex topic and I am not always understanding "what exactly" is being referred to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, this is wording problem. The "however" corresponds to the "normally", not to the "In the case of a [generic foreign key]". I will re-word this. Thanks!
I have put a full example into the "Develop Jobs" section of the docs with the latest revision |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with the PR even though I still added some comments in terms of documentation.
I think it makes sense to call into the bullpen and ask @glennmatthews to take a look? I don't fully understand everything that is happening here, with his experience building DiffSync, he likely has the best perspective. |
Similar approach and borrowing lots of ideas from #69 but with automatic inference.