2011-09-20 26 views
24

Tôi có người quản lý tùy chỉnh. Tôi muốn sử dụng nó cho các đối tượng liên quan. Tôi đã tìm thấy use_for_related_fields trong tài liệu. Nhưng nó không làm việc theo cách tôi đã sử dụng nó:Cách sử dụng trình quản lý tùy chỉnh với các đối tượng liên quan?

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() 

tôi đã sử dụng nó cho một mô hình:

>>> post = PostPages.default_manager.filter(image_gallery__isnull=False).distinct().randomize() 

Và cố gắng làm tương tự với m2m đối tượng liên quan:

>>> post.image_gallery.randomize() 

Đã xảy ra lỗi:

AttributeError: 'ManyRelatedManager' object has no attribute 'randomize' 

có thể sử dụng trình quản lý tùy chỉnh theo cách tôi đã làm không? Nếu vậy, làm thế nào để bạn làm cho nó hoạt động?

Sửa

mô hình của tôi:

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() 

Trả lời

18

Thiết use_for_related_fields-True trên người quản lý sẽ làm cho nó có sẵn trên tất cả các mối quan hệ mà chỉ - mô hình mà bạn định nghĩa quản lý này là người quản lý mặc định . Đây là tài liệu here

class MyManager(models.Manager): 
    use_for_related_fields = True 
    # ... 

Tôi cho rằng bạn có nó chỉ kích hoạt trên mô hình PostPages của bạn, không phải trên mô hình Gallery của bạn (hoặc bất kỳ mô hình được gọi đó là tham chiếu thông qua post_image_gallery). Nếu bạn muốn có chức năng bổ sung trên trình quản lý hiện thực này, bạn cần thêm trình quản lý mặc định tùy chỉnh với use_for_related_fields = True vào kiểu Gallery của mình!

+0

tôi xác định người quản lý trong cả hai mô hình. Nếu tôi hiểu đúng, 'đối tượng' có nghĩa là người quản lý mặc định. Xem chỉnh sửa câu hỏi, tôi đã thêm các mô hình trong đó. – I159

+0

Trình quản lý _first_ được xác định trở thành trình quản lý mặc định, cho dù nó được gọi là 'đối tượng' hay không ... –

+0

Uoo hooo! Nó hoạt động! Nhiều khả năng có một số sai lầm rất ngu ngốc. Bởi vì bây giờ nó là ok. – I159

17

Đối với đầy đủ của chủ đề này, Django 1,7 (cuối cùng) hỗ trợ using a custom reverse manager, vì vậy bạn có thể làm một cái gì đó như thế (chỉ cần sao chép từ các tài liệu django):

 
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() 
2

Ngoài ra, trong bộ quản lý tùy chỉnh, hãy chắc chắn để truy cập queryset qua self.get_query_set() phương pháp proxy khi thực hiện bộ lọc tùy chỉnh được gọi là từ người quản lý có liên quan: sử dụng

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() 

mẫu:

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() 
2

Trong django 2.0 use_for_related_fields được depricated https://docs.djangoproject.com/en/2.0/releases/1.10/#manager-use-for-related-fields-and-inheritance-changes

Bạn nên sử dụng base_manager_namehttps://docs.djangoproject.com/en/2.0/ref/models/options/#django.db.models.Options.base_manager_name

đây được cập nhật tài liệu 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' 
+0

'base_manager_name' hy vọng tên của người quản lý được đề cập dưới dạng một chuỗi chứ không phải là cá thể. Xem [this] (https://github.com/django/django/blob/8dc675d90f14a84ef95f16c7cc8100d9a04459b3/tests/custom_managers/models.py#L158). – Nobilis

+0

@Nobilis cảm ơn, đã sửa –

Các vấn đề liên quan