কেন জ্যাঙ্গোর প্রিফেট_ রিলেটেড () কেবল সমস্ত () এর সাথে কাজ করে এবং ফিল্টার করে না ()?


90

ধরুন আমার কাছে এই মডেলটি রয়েছে:

class PhotoAlbum(models.Model):
    title = models.CharField(max_length=128)
    author = models.CharField(max_length=128)

class Photo(models.Model):
    album = models.ForeignKey('PhotoAlbum')
    format = models.IntegerField()

এখন যদি আমি দক্ষতার সাথে অ্যালবামের একটি উপসেটে ফটোগুলির একটি উপসেট দেখতে চাই। আমি এটি এরকম কিছু করি:

someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
    somePhotos = a.photo_set.all()

এটি কেবলমাত্র দুটি ক্যোয়ারী করে, যা আমি প্রত্যাশা করি (একটি অ্যালবামগুলি পেতে এবং তারপরে একটি যেমন ফটোআলবাম_আইডি ইন ফটোতে নির্বাচন করুন *) one

সবকিছু দুর্দান্ত।

তবে আমি যদি এটি করি:

someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
    somePhotos = a.photo_set.filter(format=1)

তারপরে এটি কি এক টন অনুসন্ধান করে WHERE format = 1! আমি কি কিছু ভুল করছি বা জ্যাঙ্গো যথেষ্ট স্মার্ট নয় এটি বুঝতে পেরে এটি ইতিমধ্যে সমস্ত ফটো এনেছে এবং সেগুলি পাইথনে ফিল্টার করতে পারে? আমি শপথ করে বলছি যে কোথাও ডকুমেন্টেশনে পড়েছি যে এটি করার কথা ...


উত্তর:


168

জ্যাঙ্গো ১.6 এবং তার আগে, অতিরিক্ত প্রশ্নগুলি এড়ানো সম্ভব নয়। prefetch_relatedকল কার্যকরভাবে ফলাফল ক্যাশে a.photoset.all()queryset প্রতিটি অ্যালবাম জন্য। তবে a.photoset.filter(format=1)এটি একটি আলাদা ক্যোয়ারসেট, সুতরাং আপনি প্রতিটি অ্যালবামের জন্য একটি অতিরিক্ত ক্যোয়ারী উত্পন্ন করবেন।

এটি prefetch_relatedডক্সে ব্যাখ্যা করা হয়েছে । filter(format=1)সমতূল্য filter(spicy=True)

দ্রষ্টব্য যে আপনি তার পরিবর্তে অজগরগুলিতে ফটো ফিল্টার করে সংখ্যা বা কোয়েরিগুলি হ্রাস করতে পারবেন:

someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
    somePhotos = [p for p in a.photo_set.all() if p.format == 1]

জাজানো ১. 1.-তে, এমন একটি Prefetch()বস্তু রয়েছে যা আপনাকে এর আচরণ নিয়ন্ত্রণ করতে দেয় prefetch_related

from django.db.models import Prefetch

someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related(
    Prefetch(
        "photo_set",
        queryset=Photo.objects.filter(format=1),
        to_attr="some_photos"
    )
)
for a in someAlbums:
    somePhotos = a.some_photos

কীভাবে Prefetchঅবজেক্টটি ব্যবহার করবেন সে সম্পর্কে আরও উদাহরণের জন্য prefetch_relatedডক্স দেখুন।


8

ডক্স থেকে :

... সর্বদা কোয়েরীসেটসের মতো, পরবর্তী কোনও শৃঙ্খলাবদ্ধ পদ্ধতি যা কোনও পৃথক ডাটাবেস কোয়েরিকে বোঝায় তা পূর্ববর্তী ক্যাশেড ফলাফলগুলিকে উপেক্ষা করবে এবং একটি নতুন ডাটাবেস ক্যোয়ারী ব্যবহার করে ডেটা পুনরুদ্ধার করবে। সুতরাং, আপনি যদি নিম্নলিখিত লিখেন:

pizzas = Pizza.objects.prefetch_related('toppings') [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]

... তারপরে পিজ্জা.টপিংসস.ল () পূর্বনির্ধারণ করা হয়েছে তা আপনাকে সাহায্য করবে না - বাস্তবে এটি কার্য সম্পাদনকে ক্ষতি করে, যেহেতু আপনি একটি ডেটাবেস কোয়েরি করেছেন যা আপনি ব্যবহার করেন নি। তাই সাবধানতার সাথে এই বৈশিষ্ট্যটি ব্যবহার করুন!

আপনার ক্ষেত্রে, "a.photo_set.filter (ফর্ম্যাট = 1)" একটি নতুন ক্যোয়ারির মতো আচরণ করা হয়।

তদতিরিক্ত, "ফটো_সেট" হ'ল বিপরীত চেহারা - সম্পূর্ণ আলাদাভাবে ব্যবস্থাপকের মাধ্যমে প্রয়োগ করা হয়।


photo_setউপস্থাপন করা যেতে পারে, পাশাপাশি, সঙ্গে .prefetch_related('photo_set')। আপনি যেমন ব্যাখ্যা করেছেন তেমন বিষয়গুলি অর্ডার করুন।
রিসাদিনহা

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.