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


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.