জ্যাঙ্গোতে কীভাবে গতিশীলভাবে একটি ওআর ক্যোয়ারী ফিল্টার রচনা করবেন?


107

একটি উদাহরণ থেকে আপনি একাধিক বা ক্যোরি ফিল্টার দেখতে পাবেন:

Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))

উদাহরণস্বরূপ, এর ফলাফলগুলি:

[<Article: Hello>, <Article: Goodbye>, <Article: Hello and goodbye>]

তবে, আমি একটি তালিকা থেকে এই ক্যোয়ারী ফিল্টারটি তৈরি করতে চাই। কিভাবে যে কি?

যেমন [1, 2, 3] -> Article.objects.filter(Q(pk=1) | Q(pk=2) | Q(pk=3))


4
আপনি এটি দু'বার জিজ্ঞাসা করেছেন বলে মনে হচ্ছে: stackoverflow.com/questions/852404
— ডমিনিক রজার

এই নির্দিষ্ট ব্যবহারের ক্ষেত্রে আপনি সম্ভবত Article.objects.filter(pk__in=[1, 2, 3])আধুনিক জ্যাঙ্গো ব্যবহার করতে চাইবেন , তবে প্রশ্নটি এখনও প্রাসঙ্গিক যদি আপনি ওআর কিউ অবজেক্টকে একসাথে আরও কিছুটা উন্নত করতে চান।
— বেরুইক

উত্তর:


166

আপনি নীচে আপনার প্রশ্নের শৃঙ্খলা করতে পারে:

values = [1,2,3]

# Turn list of values into list of Q objects
queries = [Q(pk=value) for value in values]

# Take one Q object from the list
query = queries.pop()

# Or the Q object with the ones remaining in the list
for item in queries:
    query |= item

# Query the model
Article.objects.filter(query)

4
ধন্যবাদ! আমি যা খুঁজছিলাম এটি এটিই ছিল :) আপনি কী করতে পারবেন তা জানেন না | =
— জ্যাক হা

23
আপনি কোয়েরিটি আরম্ভ করতে পারেন:
— ক্যোরি

5
আপনি ** field 'ক্ষেত্রের নাম': মান}: কোয়েরিগুলি = [প্রশ্ন (**
— field 'ফিল্ডের নাম

4
আপনি যদি উপরের মতো alচ্ছিক শর্ত যুক্ত করতে চান তবে কীভাবে আপনি জ্যাঙ্গোর সাথে কাঁচা প্রশ্ন তৈরি করতে পারেন?
— ব্যবহারকারী

এটি আমার পক্ষে কাজ করে নি, কেন জানি না। কোয়েরিগুলি আমার জন্য শূন্য ফলাফল ফেরায়
— মেহরান নুরি

83

আরও জটিল প্রশ্নগুলি তৈরি করার জন্য Q () অবজেক্টের ধ্রুবক Q.OR এবং Q.AND এ বিল্ট (যুক্ত) পদ্ধতি যুক্ত করে ব্যবহার করার বিকল্প রয়েছে:

list = [1, 2, 3]
# it gets a bit more complicated if we want to dynamically build
# OR queries with dynamic/unknown db field keys, let's say with a list
# of db fields that can change like the following
# list_with_strings = ['dbfield1', 'dbfield2', 'dbfield3']

# init our q objects variable to use .add() on it
q_objects = Q(id__in=[])

# loop trough the list and create an OR condition for each item
for item in list:
    q_objects.add(Q(pk=item), Q.OR)
    # for our list_with_strings we can do the following
    # q_objects.add(Q(**{item: 1}), Q.OR)

queryset = Article.objects.filter(q_objects)

# sometimes the following is helpful for debugging (returns the SQL statement)
# print queryset.query

12
আমার মতো এই থ্রেডে আগতদের জন্য, আমি মনে করি এই উত্তরটিকে শীর্ষ উত্তর হিসাবে বিবেচনা করা উচিত। এটি গৃহীত উত্তরের চেয়ে বেশি জ্যাঙ্গোসেক। ধন্যবাদ!
— থেছান্না

5
আমি বিতর্ক করব যে বিল্টিন ওআরএ্যান্ড অপারেটরগুলি (| এবং &) ব্যবহার করা আরও অজগর। q_objects |= Q(pk=item)
— ববোর্ট

পারফেক্ট! ধন্যবাদ!
— আরএল শ্যাম

4
লক্ষণীয় যে, যদি listখালি হয়ে যায় তবে আপনি তার সমতুল্য ফিরে আসবেন Article.objects.all()। Article.objects.none()যদিও সেই পরীক্ষায় ফিরে এসে প্রশমিত করা সহজ ।
— Wil

4
@Wil আপনার কাছে আরম্ভ করতে পারেন q_objectsসঙ্গে Q(id__in=[])। এটি সর্বদা ব্যর্থ হবে যদি না কোনও কিছু দিয়ে ওআরড হয় এবং ক্যোয়ারী অপ্টিমাইজার এটি সুন্দরভাবে পরিচালনা করে না।
— জনাথন রিচার্ডস

45

পাইথনের হ্রাস ফাংশনটি ব্যবহার করে ডেভ ওয়েবের উত্তর লেখার একটি ছোট্ট উপায় :

# For Python 3 only
from functools import reduce

values = [1,2,3]

# Turn list of values into one big Q objects  
query = reduce(lambda q,value: q|Q(pk=value), values, Q())  

# Query the model  
Article.objects.filter(query)  

দেখে মনে হচ্ছে "বিল্টিন" কমানো সরানো হয়েছে এবং এর সাথে প্রতিস্থাপন করা হয়েছে functools.reduce। উত্স
— lsowen

ধন্যবাদ @ নীচু, স্থির।
— টম ভিনার 20

এবং operator.or_ল্যাম্বদার পরিবর্তে এটি ব্যবহার করা সম্ভব ।
— আইজিনিইন

38
from functools import reduce
from operator import or_
from django.db.models import Q

values = [1, 2, 3]
query = reduce(or_, (Q(pk=x) for x in values))

ঠিক আছে, তবে কোথা operatorথেকে এসেছে?
— এমপিস্কোর 13

4
@ এমপিসকোর: প্রতিটি পাইথন মডিউল হিসাবে একই জায়গা: আপনি এটি আমদানি করেন।
— ইগনাসিও ওয়াজকেজ-আব্রামস

4
হাস্যকর. আসলেই আমার প্রশ্ন ছিল: আমি কোন মডিউল / গ্রন্থাগারে এটি খুঁজে পেতে পারি? গুগল খুব একটা সাহায্য করেনি।
— এমপিস্কোর

ওহ, আমি ভেবেছিলাম এটি কোনও ধরণের জ্যাঙ্গো ওআরএম অপারেটর। আমাকে কত নির্বোধ, ধন্যবাদ!
— এমপিস্কোর 14

20

সম্ভবত এটি বিবৃতিতে এসকিএল ব্যবহার করা ভাল better

Article.objects.filter(id__in=[1, 2, 3])

দেখুন queryset API উল্লেখ ।

আপনার যদি গতিশীল যুক্তি দিয়ে সত্যই জিজ্ঞাসা করা দরকার, আপনি এর মতো কিছু করতে পারেন (কুরুচিপূর্ণ + পরীক্ষিত নয়):

query = Q(field=1)
for cond in (2, 3):
    query = query | Q(field=cond)
Article.objects.filter(query)

4
আপনিও ব্যবহার করতে পারেনquery |= Q(field=cond)
— ববোর্ট

8

দস্তাবেজগুলি দেখুন :

>>> Blog.objects.in_bulk([1])
{1: <Blog: Beatles Blog>}
>>> Blog.objects.in_bulk([1, 2])
{1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
>>> Blog.objects.in_bulk([])
{}

মনে রাখবেন যে এই পদ্ধতিটি কেবলমাত্র প্রাথমিক কী দেখার জন্য কাজ করে, তবে এটি আপনি যা করার চেষ্টা করছেন তা মনে হয়।

সুতরাং আপনি যা চান তা হ'ল:

Article.objects.in_bulk([1, 2, 3])

6

যদি আমরা কোন ডিবি ক্ষেত্রটি প্রোগ্রামের ভিত্তিতে সেট করতে চাই যে আমরা কোয়েরি করতে চাই:

import operator
questions = [('question__contains', 'test'), ('question__gt', 23 )]
q_list = [Q(x) for x in questions]
Poll.objects.filter(reduce(operator.or_, q_list))

6

সমাধান যা ব্যবহার করে reduceএবং or_অপারেটরগুলি গুণক ক্ষেত্রগুলি দ্বারা ফিল্টার করে।

from functools import reduce
from operator import or_
from django.db.models import Q

filters = {'field1': [1, 2], 'field2': ['value', 'other_value']}

qs = Article.objects.filter(
   reduce(or_, (Q(**{f'{k}__in': v}) for k, v in filters.items()))
)

পিএস fএকটি নতুন ফর্ম্যাট স্ট্রিং আক্ষরিক। এটি পাইথন ৩.6 এ প্রবর্তিত হয়েছিল


4

আপনি Q = অবজেক্টস ব্যবহার করে প্রোগ্রামটিকে কোয়েরি আপডেট করার জন্য | = অপারেটরটি ব্যবহার করতে পারেন।


4
এই কোথাও নথিভুক্ত করা হয়? আমি গত 15 মিনিট ধরে অনুসন্ধান করছি এবং এটিই আমি খুঁজে পেতে পারি।
— wobbily_col

আমাদের ইন্ডাস্ট্রির মতো অনেক কিছু, এটি স্ট্যাকওভারফ্লোতে নথিভুক্ত করা হয়েছে!
— ক্রিস

2

এটি একটি গতিশীল পিকে তালিকার জন্য:

pk_list = qs.values_list('pk', flat=True)  # i.e [] or [1, 2, 3]

if len(pk_list) == 0:
    Article.objects.none()

else:
    q = None
    for pk in pk_list:
        if q is None:
            q = Q(pk=pk)
        else:
            q = q | Q(pk=pk)

    Article.objects.filter(q)

আপনি এর q = Q()পরিবর্তে ব্যবহার করতে পারেন q = None, তারপরে এই if q is Noneধারাটি সরিয়ে ফেলুন - কিছুটা কম দক্ষ তবে কোডের তিনটি লাইন মুছে ফেলতে পারেন। (কোয়েরিটি চালানো হলে খালি কিউ পরে মিশে যায়))
— ক্রিস

1

আরেকটি বিকল্প আমি সম্প্রতি পর্যন্ত সচেতন ছিল না - QuerySetএছাড়াও অগ্রাহ্য &, |, ~, ইত্যাদি অপারেটর। অন্যান্য উত্তরগুলি যে ও কিউ অবজেক্টগুলি এই প্রশ্নের আরও ভাল সমাধান তবে আগ্রহ / যুক্তির স্বার্থে আপনি এটি করতে পারেন:

id_list = [1, 2, 3]
q = Article.objects.filter(pk=id_list[0])
for i in id_list[1:]:
    q |= Article.objects.filter(pk=i)

str(q.query)ধারাটিতে থাকা সমস্ত ফিল্টার সহ একটি ক্যোয়ারী ফিরিয়ে দেবে WHERE।


1

লুপের জন্য:

values = [1, 2, 3]
q = Q(pk__in=[]) # generic "always false" value
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)

হ্রাস করুন:

from functools import reduce
from operator import or_

values = [1, 2, 3]
q_objects = [Q(pk=val) for val in values]
q = reduce(or_, q_objects, Q(pk__in=[]))
Article.objects.filter(q)

এ দুটিই সমান Article.objects.filter(pk__in=values)

valuesখালি থাকার সময় আপনি কী চান তা বিবেচনা করা গুরুত্বপূর্ণ important Q()প্রারম্ভিক মান হিসাবে অনেক উত্তর সবকিছু ফিরিয়ে দেবে । Q(pk__in=[])একটি ভাল শুরু মান। এটি সর্বদা ব্যর্থ হওয়া কিউ অবজেক্ট যা অপটিমাইজার (এমনকি জটিল সমীকরণের জন্য) খুব সুন্দরভাবে পরিচালনা করে।

Article.objects.filter(Q(pk__in=[]))  # doesn't hit DB
Article.objects.filter(Q(pk=None))    # hits DB and returns nothing
Article.objects.none()                # doesn't hit DB
Article.objects.filter(Q())           # returns everything

আপনি যদি খালি হয়ে সমস্ত কিছু ফিরিয়ে দিতে চান তবে সেই আচরণটি নিশ্চিত করার জন্য valuesআপনার উচিত এবং উচিত ~Q(pk__in=[]):

values = []
q = Q()
for val in values:
    q |= Q(pk=val)
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # only Tolkien

q &= ~Q(pk__in=[])
Article.objects.filter(q)                     # everything
Article.objects.filter(q | author="Tolkien")  # everything

এটি মনে রাখা জরুরী যে Q()এটি কিছুই নয় , সর্বদা-উত্তরকারী কিউ অবজেক্ট নয়। এর সাথে জড়িত যে কোনও ক্রিয়াকলাপ এটিকে পুরোপুরি ফেলে দেবে।


0

সহজ ..
থেকে django.db.models আমদানি কিউ আমদানি করুন আপনি মডেল আরগস = (কিউ (দৃশ্যমানতা = 1) | (কিউ (দৃশ্যমানতা = 0) এবং কিউ (ব্যবহারকারী = স্ব। ব্যবহারকারীর)) # টিপল প্যারামিটার = {} # ডিডিক অর্ডার = 'create_at' সীমা = 10

Models.objects.filter(*args,**parameters).order_by(order)[:limit]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.