django очистить поле manytomany

Django: Retrieving IDs of manyToMany fields quickly

I have the following model schema in Django (with Postgres).

Given a QuerySet of A, I would like to return a dictionary mapping each instance of A in the QuerySet to a list of id s of its related instances as quickly as possible.

I can surely iterate through each A and query the related field, but is there a more optimal way?

django очистить поле manytomany. Смотреть фото django очистить поле manytomany. Смотреть картинку django очистить поле manytomany. Картинка про django очистить поле manytomany. Фото django очистить поле manytomany

2 Answers 2

You can get pretty close like this:

This will give a mapping from pks of the current object to the instance itself, so you can iterate through as follows:

Or given an instance, you can do a fast lookup like so:

This method maps the instance ids to the related ids (indirectly) since you specifically requested a dictionary. If you aren’t doing lookups, you may want the following instead:

You may take note of the use of only to only pull the pks from the db. There is an open ticket to allow the use of values and (I presume) values_list in Prefetch queries. This would allow you to do the following.

You could of course optimize further, for example by using qs.only(‘related_insts’) on the primary queryset, but make sure you aren’t doing anything with these instances— they’re essentially just expensive containers to hold your related_ids.

I believe this is the best that’s available for now (without custom queries). To get to exactly what you want, two things are needed:

With these two things in place (and continuing the above example) you could do the following to get exactly what you requested:

I’ve left off some details explaining things, but it should be pretty clear from the documentation. If you need any clarification, don’t hesitate!

Источник

Django: How to annotate M2M or OneToMany fields using a SubQuery?

I have Order objects and OrderOperation objects that represent an action on a Order (creation, modification, cancellation).

Conceptually, an order has 1 to many order operations. Each time there is an operation on the order, the total is computed in this operation. Which means when I need to find an attribute of an order, I just get the last order operation attribute instead, using a Subquery.

The simplified code

The issue

Computing total is easy as it’s a simple value. However, when there is a M2M or OneToMany field, this method does not work. For example, using the example above, let’s add this field:

Writing something like the following does NOT work as it returns only 1 foreign key (not a list of all the FKs):

The purpose

The whole purpose is to allow a user to search among all orders, providing a list or articles in input. For example: «Please find all orders containing at least article 42 or article 43», or «Please find all orders containing exactly article 42 and 43», etc.

If I could get something like:

That would solve my issue.

My current idea

values() and values_list() are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. This metaphor falls apart when dealing with many-to-many and other multivalued relations (such as the one-to-many relation of a reverse foreign key) because the “one row, one object” assumption doesn’t hold.

2 Answers 2

ArrayAgg will be great if you want to fetch only one variable (ie. name) from all articles. If you need more, there is a better option for that:

prefetch_related

The only caveat with that is that you will always get a list with one operation or an empty list when there are no operations for selected order.

Then you can just use order.last_operation[0].ordered_articles to get all ordered articles for particular order. You can add prefetch_related(‘ordered_articles’) to first queryset to have improved performance and less queries on database.

django очистить поле manytomany. Смотреть фото django очистить поле manytomany. Смотреть картинку django очистить поле manytomany. Картинка про django очистить поле manytomany. Фото django очистить поле manytomany

To my surprise, your idea with ArrayAgg is right on the money. I didn’t know there was a way to annotate with an array (and I believe there still isn’t for backends other than Postgres).

You can then filter the resulting queryset using the ArrayField lookups:

‘DISTINCT’ is needed only if the operation may contain duplicate articles.

Looking at your posted code more closely, you’ll also have to filter on the one OrderOperation you are interested in; the query above looks at all operations for the relevant order.

Источник

Updating an ManyToMany field with Django rest

I’m trying to set up this API so I can use a «PUT» to update one/many «TAG»s on an item in the model «MOVIE». Tags is an M2M on MOVIE. I am posting on the PK of the item in movie.

My httpie work (returns a 200OK) but nothing gets created. When I post the whole JSON (using fetch) it just creates the TAG but no M2M relationship on MOVIE (link).

2 Answers 2

After verifying that the serializer method is called, maybe you should write a test for it using drf test api client to be able to easily spot errors: http://www.django-rest-framework.org/api-guide/testing/#apiclient

django очистить поле manytomany. Смотреть фото django очистить поле manytomany. Смотреть картинку django очистить поле manytomany. Картинка про django очистить поле manytomany. Фото django очистить поле manytomany

Okay. I promised to come back when I figured it out. This probably isn’t completely data-safe as django hasn’t yet validated the incoming data so I’m making some assumptions in my relative ignorance of python and django. If anyone who’s smarter than I am can expand this answer, please hit me up.

note: I am a firm adherent to the Clean Code standard of writing software. It has served me well over the years. I know it’s not meta for Python code, but without small, tightly focused methods, it felt sloppy.

Views.py

You have to clear the related objects yourself before you can add new ones if you can’t have dupes. It’s the only way I could find to delete m2m reliably for my use case. I needed to ensure there were no duplicates and I expect an atomic model. Your mileage may vary.

Serializers.py

You have to hook the to_internal_value serializer method to get the data you need since the validator ignores m2m fields.

Utils.py

Test.py

Adjust urls as necessary for this to work. The logic should be correct but may need some tweaking to correctly reflect your models and serializers. It’s more complex because we have to create the json data for the APIClient to send with the put request.

Источник

Documentation

Many-to-many relationships¶

In this example, an Article can be published in multiple Publication objects, and a Publication has multiple Article objects:

What follows are examples of operations that can be performed using the Python API facilities.

Create a few Publications :

You can’t associate it with a Publication until it’s been saved:

Associate the Article with a Publication :

Adding a second time is OK, it will not duplicate the relation:

Adding an object of the wrong type raises TypeError :

Create and add a Publication to an Article in one step using create() :

Article objects have access to their related Publication objects:

Publication objects have access to their related Article objects:

Many-to-many relationships can be queried using lookups across relationships :

The count() function respects distinct() as well:

Reverse m2m queries are supported (i.e., starting at the table that doesn’t have a ManyToManyField ):

Excluding a related item works as you would expect, too (although the SQL involved is a little complex):

Adding via the ‘other’ end of an m2m:

Adding via the other end using keywords:

Removing Publication from an Article :

And from the other end:

Relation sets can be set:

Relation sets can be cleared:

And you can clear from the other end:

Recreate the Article and Publication we have deleted:

Источник

Using the following related models (one blog entry can have multiple revisions):

4 Answers 4

I think you are misunderstanding the nature of a ManyToMany relationship. You talk about «the corresponding BlogEntry» being deleted. But the whole point of a ManyToMany is that each BlogEntryRevision has multiple BlogEntries related to it. (And, of course, each BlogEntry has multiple BlogEntryRevisions, but you know that already.)

As Of Django 2.0

The ForeignKey initializer now requires you to specify the on_delete parameter:

I had this exact use-case today:

For this, I’m using a ManyToManyRelationship.

My use-case was: if I delete the last entry of a particular author, then this author should be deleted as well.

The solution can be achieved using the pre_delete signal:

Simply use the clear() method to remove related objects since Django uses a through model to specify the relationships the clear method removes all related BlogEntryRevision

You can use a custom model manager, but the documentation seems to indicate that it does do something like this already and I can’t recall exactly what this means:

The delete method, conveniently, is named delete(). This method immediately deletes the object and has no return value. Example:

You can also delete objects in bulk. Every QuerySet has a delete() method, which deletes all members of that QuerySet.

For example, this deletes all Entry objects with a pub_date year of 2005:

Keep in mind that this will, whenever possible, be executed purely in SQL, and so the delete() methods of individual object instances will not necessarily be called during the process. If you’ve provided a custom delete() method on a model class and want to ensure that it is called, you will need to «manually» delete instances of that model (e.g., by iterating over a QuerySet and calling delete() on each object individually) rather than using the bulk delete() method of a QuerySet.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *