J'ai un gestionnaire personnalisé. Je veux l'utiliser pour des objets connexes. J'ai trouvé se_for_related_fields dans la documentation. Mais cela ne fonctionne pas comme je l'ai utilisé:
class RandomQueryset(models.query.QuerySet):
def randomize(self):
count = self.count()
random_index = random.randint(0, count - 1)
return self.all()[random_index]
class RandomManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
return RandomQueryset(self.model, using=self._db)
def randomize(self):
return self.get_query_set().randomize()
Je l'ai utilisé pour un modèle:
>>> post = PostPages.default_manager.filter(image_gallery__isnull=False).distinct().randomize()
Et j'ai essayé de faire de même avec un objet lié à m2m:
>>> post.image_gallery.randomize()
Vous avez une erreur:
AttributeError: 'ManyRelatedManager' object has no attribute 'randomize'
Est-il possible d'utiliser un gestionnaire personnalisé comme je l'ai fait? Si oui, comment le faites-vous fonctionner?
Mes modèles:
class ShivaImage(models.Model, ImageResizing):
image = models.ImageField(upload_to='img')
slide_show = models.BooleanField()
title = models.CharField(max_length=100)
text = models.TextField(max_length=400)
ordering = models.IntegerField(blank=True, null=True)
objects = RandomManager()
class PostPages(models.Model):
image_gallery = models.ManyToManyField(ShivaImage, blank=True,
related_name='gallery',)
# all the other fields...
objects = RandomManager()
Réglage use_for_related_fields
à True
sur le gestionnaire le rendra disponible sur toutes les relations qui pointent vers le modèle sur lequel vous avez défini ce gestionnaire comme le gestionnaire par défaut. Ceci est documenté ici
class MyManager(models.Manager):
use_for_related_fields = True
# ...
Je suppose que vous ne l'avez activé que sur votre modèle PostPages
, pas sur votre modèle Gallery
(ou quel que soit le modèle appelé qui est référencé par post_image_gallery
). Si vous souhaitez avoir des fonctionnalités supplémentaires sur ce gestionnaire de realtion, vous devez ajouter un gestionnaire par défaut personnalisé avec use_for_related_fields = True
à votre modèle Gallery
!
Pour compléter le sujet, Django 1.7 (enfin) prend en charge en utilisant un gestionnaire inverse personnalisé , donc vous pouvez faire quelque chose comme ça (juste en copiant depuis le Django docs):
from Django.db import models
class Entry(models.Model):
objects = models.Manager() # Default Manager
entries = EntryManager() # Custom Manager
b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()
Dans Django 2.0 use_for_related_fields
est obsolète https://docs.djangoproject.com/en/2.0/releases/1.10/#manager-use-for-related-fields-and-inheritance-changes
Tu devrais utiliser base_manager_name
: https://docs.djangoproject.com/en/2.0/ref/models/options/#Django.db.models.Options.base_manager_name
Documents mis à jour: https://docs.djangoproject.com/en/2.0/topics/db/managers/#using-managers-for-related-object-access
class MyModel(models.Model):
field1 = ...
field2 = ...
special_manager = MyManager()
class Meta:
base_manager_name = 'special_manager'
De plus, dans le gestionnaire personnalisé, assurez-vous d'accéder au jeu de requêtes via la méthode proxy self.get_query_set () lors de l'implémentation de filtres personnalisés à appeler à partir du gestionnaire associé:
class EventManager(models.Manager):
use_for_related_fields = True
def visible_events(self):
today = datetime.date.today()
# don't do this !!!
# unsuitable for related managers as could retrieve extraneous objects
# qs = super(EventManager, self).get_query_set()
# Use queryset proxy method as follows, instead:
qs = self.get_query_set()
qs = qs.filter(visible_from__lte=today, visible_to__gte=today)
return qs
class Event(models.Model):
visible_from = models.DateField(_(u'visible from'), null=False, blank=False)
visible_to = models.DateField(_(u'visible to'), null=False, blank=False)
concepts = models.ManyToManyField(Concept, through='ConceptEventRegistration')
objects = EventManager()
Exemple d'utilisation:
my_concept = Concept.objects.get(id=1)
# retrieve all events related to the object
my_concept.event_set.all()
# retrieve all visible events related to the object
my_concept.event_set.visible_events()