From 4327e1b7e3c49c5404608b9a4ce8f43a0d346c84 Mon Sep 17 00:00:00 2001 From: abondar Date: Sun, 28 Apr 2024 16:16:06 +0300 Subject: [PATCH] Link to docs --- README.rst | 281 +---------------------------------------------------- 1 file changed, 2 insertions(+), 279 deletions(-) diff --git a/README.rst b/README.rst index 2650b5d..fe578a3 100644 --- a/README.rst +++ b/README.rst @@ -54,284 +54,7 @@ To install with poetry: poetry add django-copyist -Basic usage +Usage ----------- -.. warning:: - For more comfortable reading - read it in docs - https://abondar.github.io/django-copyist/quickstart.html - -Assuming you have following models in your Django app: - -.. code-block:: python - - from django.db import models - - - class Company(models.Model): - name = models.CharField(max_length=100) - address = models.CharField(max_length=100) - - - class Project(models.Model): - name = models.CharField(max_length=100) - company = models.ForeignKey( - Company, related_name="projects", on_delete=models.CASCADE - ) - - - class Employee(models.Model): - name = models.CharField(max_length=100) - company = models.ForeignKey( - Company, related_name="employees", on_delete=models.CASCADE - ) - - - class Counterpart(models.Model): - name = models.CharField(max_length=100) - external_id = models.IntegerField() - project = models.ForeignKey( - Project, related_name="counterparts", on_delete=models.CASCADE - ) - - - class Task(models.Model): - name = models.CharField(max_length=100) - description = models.TextField() - - assignee = models.ForeignKey( - Employee, related_name="tasks", on_delete=models.CASCADE - ) - project = models.ForeignKey(Project, related_name="tasks", on_delete=models.CASCADE) - counterparts = models.ManyToManyField(Counterpart, related_name="tasks") - - -And you want to create full copy of company with all nested data, but also want it to be created with different name and address. -In this case you should write following ModelCopyConfig - -.. code-block:: python - - from django_copyist.config import ( - ModelCopyConfig, - TAKE_FROM_ORIGIN, - MakeCopy, - UpdateToCopied, - FieldCopyConfig, - CopyActions, - ) - from example.demo.models import ( - Project, - Counterpart, - Task, - Company, - Employee, - ) - - - config = ModelCopyConfig( - model=Company, - filter_field_to_input_key={"id": "company_id"}, - field_copy_actions={ - "name": FieldCopyConfig( - action=CopyActions.TAKE_FROM_INPUT, - input_key="new_company_name", - ), - "address": FieldCopyConfig( - action=CopyActions.TAKE_FROM_INPUT, - input_key="new_company_address", - ), - "projects": MakeCopy( - ModelCopyConfig( - model=Project, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "counterparts": MakeCopy( - ModelCopyConfig( - model=Counterpart, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "external_id": TAKE_FROM_ORIGIN, - }, - ) - ), - }, - ) - ), - "employees": MakeCopy( - ModelCopyConfig( - model=Employee, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - }, - ) - ), - }, - compound_copy_actions=[ - ModelCopyConfig( - model=Task, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "description": TAKE_FROM_ORIGIN, - "counterparts": UpdateToCopied(Counterpart), - "project": UpdateToCopied(Project), - "assignee": UpdateToCopied(Employee), - }, - ) - ], - ) - -And then you can execute copy action like this: - -.. code-block:: python - - from django_copyist.copy_request import CopyRequest - from django_copyist.copyist import CopyistConfig, Copyist - - copy_request = CopyRequest( - config=CopyistConfig([config]), - input_data={ - "company_id": company_id, - "new_company_name": new_company_name, - "new_company_address": new_company_address, - }, - confirm_write=False, - ) - result = Copyist(copy_request).execute_copy_request() - -With this, all company data should be copied. -That seems like a lot to take in, so let's break it down to what exactly happens here: - -1. We define a `ModelCopyConfig` for the `Company` model. - -.. code-block:: python - - config = ModelCopyConfig( - model=Company, - filter_field_to_input_key={"id": "company_id"}, - ... - -`ModelCopyConfig` is a class that defines how to copy a model. It takes the model class as the first argument and a dictionary that maps the filter field to the input key. This is used to find the object to copy. - -2. Next we define `field_copy_actions` for the `Company` model. - -.. code-block:: python - - field_copy_actions={ - "name": FieldCopyConfig( - action=CopyActions.TAKE_FROM_INPUT, - input_key="new_company_name", - ), - "address": FieldCopyConfig( - action=CopyActions.TAKE_FROM_INPUT, - input_key="new_company_address", - ), - "projects": MakeCopy( - ModelCopyConfig( - model=Project, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "counterparts": MakeCopy( - ModelCopyConfig( - model=Counterpart, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "external_id": TAKE_FROM_ORIGIN, - }, - ) - ), - }, - ) - ), - "employees": MakeCopy( - ModelCopyConfig( - model=Employee, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - }, - ) - ), - ... - -`field_copy_actions` is a dictionary that maps the field name to a `FieldCopyConfig` object. - -The `FieldCopyConfig` object defines how to copy the field. In this case, we take the `name` and `address` fields from the input data. - -`TAKE_FROM_ORIGIN` is a shortcut for creating `FieldCopyConfig` with `CopyActions.TAKE_FROM_ORIGIN` action, which takes value for new object from original object. - -We also define how to copy the `projects` and `employees` fields. - -We use the `MakeCopy` action to copy the related objects. -`MakeCopy` is a shortcut for creating `FieldCopyConfig` with `CopyActions.MAKE_COPY` action and reference to given model. -Nested `MakeCopy` automatically propagate parent id to child object. - -3. We define `compound_copy_actions` for the `Company` model. - -.. code-block:: python - - compound_copy_actions=[ - ModelCopyConfig( - model=Task, - field_copy_actions={ - "name": TAKE_FROM_ORIGIN, - "description": TAKE_FROM_ORIGIN, - "counterparts": UpdateToCopied(Counterpart), - "project": UpdateToCopied(Project), - "assignee": UpdateToCopied(Employee), - }, - ) - ... - -`compound_copy_actions` is a list of `ModelCopyConfig` objects that define how -to copy related objects that are not directly related to the model, or related through multiple relations that need to be created beforehand. - -`compound_copy_actions` are executed after all fields are copied. - -In this case, we define how to copy the `Task` model. We take the `name` and `description` fields from the original object. We also define how to copy the `counterparts`, `project`, and `assignee` fields. - -`UpdateToCopied` is a shortcut for creating `FieldCopyConfig` with `CopyActions.UPDATE_TO_COPIED` action and reference to given model. -It will search mapping of previously copied objects and update reference to copied object. - -4. We create a `CopyRequest` object with the `CopyistConfig` and input data. - -.. code-block:: python - - copy_request = CopyRequest( - config=CopyistConfig([config]), - input_data={ - "company_id": company_id, - "new_company_name": new_company_name, - "new_company_address": new_company_address, - }, - confirm_write=False, - ) - ... - -`CopyRequest` is a class that defines the copy request. It takes the `CopyistConfig` object, input data, and a boolean flag that indicates whether to confirm the write operation. - -`CopyistConfig` is a class that defines the configuration for the copy operation. It takes a list of `ModelCopyConfig` objects. - -`input_data` is a dictionary that contains the input data for the copy operation. It is later used in filtering or `TAKE_FROM_INPUT` actions. - -`confirm_write` is a boolean flag that indicates whether to confirm the write operation, -even if there are issues with matching objects in origin location with objects in target destination. -It is not used in this example, but you can read more about it in overview section of this documentation. - -5. We execute the copy request. - -.. code-block:: python - - result = Copyist(copy_request).execute_copy_request() - -`Copyist` is a class that executes the copy request. It takes the `CopyRequest` object as an argument. - -`execute_copy_request` method returns `CopyResult` object that contains information about the copy operation. Read more about it in overview section. - -And like this you have copied the company with all related data and can see and edit configuration in one place. - -Next steps ----------- - -This is just a basic example of how to use django-copyist. -It can do much more granular control on how it should execute copy, and you can read more about it in the documentation. - -https://abondar.github.io/django-copyist/overview.html +`See quickstart in docs `_