Thursday, June 24, 2021

Re: Specifying a database connection for ManyToMany add()

Thanks Mike!

My hesitation with directly manipulating that table is that there seems to be a lot of additional logic(validation, triggering signals, etc.) in add() besides insertion into the through table. However, I don't think I am relying on any of that functionality, so it should be ok to do it directly.

For context, I want to run migrations against a particular database. Any queries performed in RunPython operations need to specify that database's alias, otherwise they use the router which would direct them to use a different database than the one specified to the migrate command.

On Thursday, June 24, 2021 at 6:07:21 AM UTC+2 Mike Dewhirst wrote:
On 23/06/2021 7:18 pm, Jayanth Shankar wrote:
>
> Hi,
>
> I am trying to add items to a ManyToMany relationship, but I would
> like to make the operation use a particular database connection, like
> one might do when calling save() on a model instance. However, looking
> at the source for ManyToMany.add(), the function defaults to checking
> the router's for_write connection.
>
> class B(models.Model):
> ...
>
> class A(models.Model):
> b = models.ManyToManyField(B)
> ...
>
> ideally, I would like to modify the many to many field as follows...
> a = A(id=0)
> for b in B.objects.all():
>     a.b.add(b, using="aconnection")
>
> but this does not work. As far Is there an alternative way to insert
> an object into the ManyToMany relationship(where a db alias can be
> specified) besides add?

Not sure I understand what you are trying to do but it is possible to
manage the many-to-many yourself. Django makes a table to connect A and
B without your needing to specify it as a model.

If you write a model to represent that table you can add other fields to
it and use its save() method to perform all sorts of magic.

For example, I have chemicals and products.

class Chemical(models.Model):

    products = models.ManyToManyField(

        "Product",

        blank=True,

        through="ChemicalProducts",

        through_fields=("chemical", "product"),

        related_name="products",

    )


class ChemicalProducts(models.Model):

    chemical = models.ForeignKey(

        "Chemical",

        on_delete=models.CASCADE,

        related_name="base_chemical",

        null=True,

        blank=True,

    )

    product = models.ForeignKey(

        "Product",

         on_delete=models.CASCADE,

        null=True,

        blank=True,

    )

    # other fields and methods follow here

If I did not write the ChemicalProducts model, Django would make it
anyway. But because I have named the through table and it exists Django
doesn't bother.

This means I can write queries which insert m2m connections without
using 'add'.

However, I don't know because I haven't looked at the docs or the Django
source, whether you can use a callable for the 'through' table or even
specify the db_alias for it. I have only ever used the default myself.

HTH

Mike



>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/a49409db-5b9a-48cd-818f-6645caa184e9n%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/a49409db-5b9a-48cd-818f-6645caa184e9n%40googlegroups.com?utm_medium=email&utm_source=footer>.


--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Just
ask and I'll send it to you. Your email software can handle signing.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/41434ce6-ae74-4eaf-8537-9be8aa9bcdd2n%40googlegroups.com.

No comments:

Post a Comment