সম্পত্তি দ্বারা ফিল্টার


98

মডেল সম্পত্তি দ্বারা জ্যাঙ্গো ক্যোয়ারসেট ফিল্টার করা সম্ভব?

আমার মডেলটিতে আমার একটি পদ্ধতি রয়েছে:

@property
def myproperty(self):
    [..]

এবং এখন আমি এই সম্পত্তি হিসাবে ফিল্টার করতে চান:

MyModel.objects.filter(myproperty=[..])

এটি কি কোনওভাবে সম্ভব?


এটি এসকিউএএলএলকেমিতে রয়েছে: ডকসস.সকলালকিমি.আর.ইন / স্লেস্ট / হরফ / এক্সটেনশনস / হাইব্রিড এইচটিএমএল এবং আপনি পিকিপিপিথন.আর.পিপি / আলডজেমির মাধ্যমে এসকিএএলএলচেমির সাথে জ্যাঙ্গো সংযোগ করতে পারেন তবে আমি সন্দেহ করি যে এই দুটি সংযুক্ত হতে পারে আপনি যেভাবে চান সেভাবে
রাত্রি

উত্তর:


79

নাহ। জ্যাঙ্গো ফিল্টারগুলি এসকিউএল উত্পন্ন করে ডাটাবেস স্তরে কাজ করে। পাইথন বৈশিষ্ট্যের উপর ভিত্তি করে ফিল্টার করতে, সম্পত্তিটি মূল্যায়নের জন্য আপনাকে পাইথনের মধ্যে বস্তুটি লোড করতে হবে - এবং সেই সময়ে, আপনি এটি লোড করার জন্য ইতিমধ্যে সমস্ত কাজ শেষ করেছেন।


4
দুর্ভাগ্য যে এই বৈশিষ্ট্যটি প্রয়োগ করা হয়নি, ফলসেটটি তৈরি হওয়ার পরে কমপক্ষে ম্যাচিং অবজেক্টগুলিকে ফিল্টার আউট করা একটি আকর্ষণীয় এক্সটেনশন হবে be
schneck

4
অ্যাডমিনে এটি মোকাবেলা কিভাবে? কিছুটা কর্মক্ষেত্র আছে?
andilabs

41

আমি আপনার মূল প্রশ্নটি ভুল বোঝাবুঝি করছি তবে পাইথনটিতে একটি ফিল্টার বিল্টইন রয়েছে।

filtered = filter(myproperty, MyModel.objects)

তবে তালিকা অনুধাবন ব্যবহার করা আরও ভাল :

filtered = [x for x in MyModel.objects if x.myproperty()]

বা আরও ভাল, একটি জেনারেটর এক্সপ্রেশন :

filtered = (x for x in MyModel.objects if x.myproperty())

16
এটি একবার পাইথন অবজেক্ট পেলে এটি ফিল্টার করতে কাজ করে, তবে সে জ্যাঙ্গো কোয়েরি সেট.ফিল্টার সম্পর্কে জিজ্ঞাসা করছে, যা এসকিউএল অনুসন্ধানগুলি তৈরি করে।
গ্লেন মেইনার্ড

4
ঠিক আছে, তবে উপরে বর্ণিত হিসাবে, আমি আমার ডাটাবেস ফিল্টারটিতে সম্পত্তিটি যুক্ত করতে চাই। ক্যোয়ারীর পরে ফিল্টারিং হ'ল আমি এড়াতে চাই।
schneck

20

@ দ্যগ্রিমসায়েন্টিস্টের প্রস্তাবিত কার্যবিবরণী বন্ধ করে আপনি ম্যানেজার বা ক্যোয়ারীসেটে তাদের সংজ্ঞায়িত করে পুনরায় ব্যবহার / শৃঙ্খলা / রচনা করে এই "স্কয়ার বৈশিষ্ট্যগুলি" তৈরি করতে পারেন:

একজন পরিচালক সহ:

class CompanyManager(models.Manager):
    def with_chairs_needed(self):
        return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))

class Company(models.Model):
    # ...
    objects = CompanyManager()

Company.objects.with_chairs_needed().filter(chairs_needed__lt=4)

একটি ক্যোয়ারীসেট সহ:

class CompanyQuerySet(models.QuerySet):
    def many_employees(self, n=50):
        return self.filter(num_employees__gte=n)

    def needs_fewer_chairs_than(self, n=5):
        return self.with_chairs_needed().filter(chairs_needed__lt=n)

    def with_chairs_needed(self):
        return self.annotate(chairs_needed=F('num_employees') - F('num_chairs'))

class Company(models.Model):
    # ...
    objects = CompanyQuerySet.as_manager()

Company.objects.needs_fewer_chairs_than(4).many_employees()

আরও জানতে https://docs.djangoproject.com/en/1.9/topics/db/managers/ দেখুন। নোট করুন যে আমি ডকুমেন্টেশনটি বন্ধ করে দিচ্ছি এবং উপরেরটি পরীক্ষা করেছি না।


14

দেখে মনে হচ্ছে টীকা সহ এফ () ব্যবহার করা এটির সমাধান হবে।

এটি দ্বারা ফিল্টার হচ্ছে না @property, যেহেতু Fঅজগরগুলিকে পাইথন আনার আগে ডাটাবেসে কথা হয়। তবে সম্পত্তি হিসাবে ফিল্টার চাওয়ার আমার কারণটি দুটি পৃথক ক্ষেত্রের সরল পাটিগণিতের ফলাফলের দ্বারা অবজেক্টগুলিকে ফিল্টার করতে চেয়েছিল তবে এখনও এটি একটি উত্তর হিসাবে এখানে রেখেছি।

সুতরাং, লাইন বরাবর কিছু:

companies = Company.objects\
    .annotate(chairs_needed=F('num_employees') - F('num_chairs'))\
    .filter(chairs_needed__lt=4)

সম্পত্তিটি সংজ্ঞায়িত করার পরিবর্তে:

@property
def chairs_needed(self):
    return self.num_employees - self.num_chairs

তারপরে সমস্ত বস্তু জুড়ে একটি তালিকা বোধগম্য করা।


5

আমারও একই সমস্যা ছিল এবং আমি এই সহজ সমাধানটি বিকাশ করেছি:

objects_id = [x.id for x in MyModel.objects.all() if x.myProperty == [...]]
MyModel.objects.filter(id__in=objects_id)

আমি জানি এটি সর্বাধিক পারফরম্যাটিক সমাধান নয়, তবে আমার হিসাবে সাধারণ ক্ষেত্রে সহায়তা করতে পারে


3

দয়া করে কেউ আমাকে সংশোধন করুন, তবে আমি অনুমান করি যে আমি একটি সমাধান পেয়েছি, কমপক্ষে আমার নিজের ক্ষেত্রে for

আমি সেই সমস্ত উপাদানগুলির সাথে কাজ করতে চাই যাদের সম্পত্তিগুলির সমান সমান ... যাই হোক না কেন।

তবে আমার বেশ কয়েকটি মডেল রয়েছে এবং এই রুটিনটি সমস্ত মডেলের জন্য কাজ করা উচিত। এবং এটি করে:

def selectByProperties(modelType, specify):
    clause = "SELECT * from %s" % modelType._meta.db_table

    if len(specify) > 0:
        clause += " WHERE "
        for field, eqvalue in specify.items():
            clause += "%s = '%s' AND " % (field, eqvalue)
        clause = clause [:-5]  # remove last AND

    print clause
    return modelType.objects.raw(clause)

এই সার্বজনীন সাবরুটিনের সাহায্যে আমি সেই সমস্ত উপাদান নির্বাচন করতে পারি যা আমার নির্দিষ্ট 'নির্দিষ্ট' (সংখ্যার নাম, সম্পত্তি মূল্য) সংমিশ্রণের অভিধানের সমান।

প্রথম প্যারামিটারটি একটি (মডেল। মডেল) নেয়,

দ্বিতীয় অভিধানের মতো: {"সম্পত্তি1": "77", "সম্পত্তি 2": "12"}

এবং এটি একটি এসকিউএল বিবৃতি তৈরি করে

SELECT * from appname_modelname WHERE property1 = '77' AND property2 = '12'

এবং এই উপাদানগুলির উপর একটি কোয়েরি সেট দেয় returns

এটি একটি পরীক্ষার ফাংশন:

from myApp.models import myModel

def testSelectByProperties ():

    specify = {"property1" : "77" , "property2" : "12"}
    subset = selectByProperties(myModel, specify)

    nameField = "property0"
    ## checking if that is what I expected:
    for i in subset:
        print i.__dict__[nameField], 
        for j in specify.keys():
             print i.__dict__[j], 
        print 

এবং? আপনি কি মনে করেন?


সাধারণত এটি চারপাশে একটি শালীন কাজ মনে হয়। আমি এটি আদর্শ বলব না, তবে প্রতিবার যখনই এর মতো কিছু প্রয়োজন হয় তখন আপনি পাইপিআই থেকে ইনস্টল করা প্যাকেজগুলির জন্য মডেলটি সংশোধন করার জন্য একটি ভাণ্ডার তৈরি করতে প্রহার করে।
hlongmore

আর এখন যে আমি সময় এটির সাথে একটি বিট খেলতে হবে করেছি: এই পদ্ধতির বাস্তব downside হয় যে querysets .raw () দ্বারা ফিরে হয় পূর্ণাঙ্গ querysets, যা দিয়ে আমি বলতে চাচ্ছি সেখানে queryset পদ্ধতি অনুপস্থিত হয় নয়:AttributeError: 'RawQuerySet' object has no attribute 'values'
hlongmore

1

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে এখানে ঝাঁপিয়ে পড়া ব্যক্তিদের জন্য আমি নীচের প্রশ্নটি পড়তে এবং আপেক্ষিক উত্তরটি দরকারী বলে মনে করি:

জ্যাঙ্গো ১.৪-এ অ্যাডমিন ফিল্টার কীভাবে কাস্টমাইজ করা যায়


4
এই উত্তরটি ঝাপটানকারীদের জন্য - এই লিঙ্কটি হ'ল জাজানো অ্যাডমিনে তালিকা ফিল্টারগুলি "সিম্পললিস্টফিলার" ব্যবহার করে প্রয়োগ করার তথ্য to দরকারী, তবে খুব নির্দিষ্ট ক্ষেত্রে বাদে প্রশ্নের উত্তর নয়।
jenniwren

0

এছাড়া দ্বারা queryset টীকা যে সম্পত্তি পেতে / সেট যুক্তিবিজ্ঞান নকল, প্রস্তাবিত যেমন হিসাবে ব্যবহার করা সম্ভব হতে পারে @rattray এবং @thegrimmscientist , সাথেproperty । এটি পাইথন স্তরের এবং উভয় ক্ষেত্রেই কিছু কাজ করতে পারে ডাটাবেস স্তর ।

ত্রুটিগুলি সম্পর্কে নিশ্চিত নন: উদাহরণের জন্য এই এসও প্রশ্নটি দেখুন ।


আপনার কোড পর্যালোচনা প্রশ্ন লিঙ্ক একটি বিজ্ঞপ্তি দেয় যে এটি স্বেচ্ছায় এর লেখক দ্বারা সরানো হয়েছিল। কোডের লিঙ্ক সহ, বা কোনও ব্যাখ্যা সহ, আপনার উত্তরটি এখানে আপডেট করার বিষয়ে আপনি কি আপত্তি জানবেন বা কেবল নিজের উত্তরটি সরিয়ে ফেলবেন?
hlongmore

@ হোলংমোর: এর জন্য দুঃখিত। এই প্রশ্নটি এসও-তে স্থানান্তরিত হয়েছিল। আমি উপরের লিঙ্কটি ঠিক করেছি।
djvg
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.