জ্যাঙ্গো: ডিবি তৈরির কোনও অবজেক্ট পান, বা কিছুই না মিললে 'কিছুই নয়'


101

এমন কোন জ্যাঙ্গো ফাংশন রয়েছে যা আমাকে কোনও ডাটাবেস ফর্মটি দেবে, বা কিছুই মিলছে না?

এখনই আমি এর মতো কিছু ব্যবহার করছি:

foo = Foo.objects.filter(bar=baz)
foo = len(foo) > 0 and foo.get() or None

তবে এটি খুব স্পষ্ট নয় এবং এটি সর্বত্র পাওয়া অগোছালো।


2
আপনি জানেন যে আপনি কেবল foo = foo [0] ব্যবহার করতে পারবেন যদি foo আর কিছুই না
ভিজিয়ান স্কেলু

2
পাইথনের একটি টার্নারি অপারেটর রয়েছে, আপনাকে বুলিয়ান অপারেটর ব্যবহার করতে হবে না। এছাড়াও, len(foo)খারাপ : " দ্রষ্টব্য: আপনি যা করতে চান তা সেটে রেকর্ডের সংখ্যা নির্ধারণ করে যদি কোয়েরিশেটে লেন () ব্যবহার করবেন না S (), এবং জাজানো সঠিকভাবে এই কারণে একটি গণনা () পদ্ধতি সরবরাহ করে । পুনর্লিখন:foo = foo[0] if foo.exists() else None
মোস্তফা.0x


1
@ mustafa.0x আমি মনে করি না এটি এখানে প্রযোজ্য। এখানে, গণনার জন্য অনুসন্ধান করা অন্য কোয়েরি চালাবে। তারপরে আসল ডেটা পেতে আমাদের আবার জিজ্ঞাসা থাকতে হবে। এটি এমন একটি ক্ষেত্রে যেখানে ফিল্টারিং এবং তারপরে গণনা আরও বোধগম্য হয় ... তবে ফিল্টারিং এবং কল করার চেয়ে বেশি বোধগম্য নয় first(): পি
মাইক্রনএক্সডি

উত্তর:


88

জাজানো 1.6 এ আপনি এটি ব্যবহার করতে পারেনfirst() Queryset পদ্ধতি। এটি ক্যোরিসেটের সাথে ম্যাচ করা প্রথম অবজেক্টটি বা কোনও মিলিত অবজেক্ট না থাকলে কিছুই দেয় না।

ব্যবহার:

p = Article.objects.order_by('title', 'pub_date').first()

19
এটি একটি ভাল উত্তর নয়, যদি একাধিক বস্তু পাওয়া যায় তবে MultipleObjectsReturned()উত্থাপিত হয় না, এখানে ডকুমেন্টেড হিসাবে । আপনি এখানে
স্লিপক্যাল

25
পছন্দ করুন first()কাজ ঠিক অনুমান হিসাবে। এটি ক্যোয়ারী ফলাফলের মধ্যে প্রথম অবজেক্টটি ফেরত দেয় এবং একাধিক ফলাফল পাওয়া গেলে তার যত্ন নেয় না। যদি আপনাকে একাধিক বস্তু ফিরে আসে তা পরীক্ষা করতে হয় তবে তার .get()পরিবর্তে ব্যবহার করা উচিত ।
সিজার কানাসা

7
[সম্পাদনা] ওপি .get()যেমন বলেছে, তার প্রয়োজনের জন্য উপযুক্ত নয়। এই প্রশ্নের সঠিক উত্তর নীচে @ কেপস্টর্ম দ্বারা পাওয়া যাবে এবং স্পষ্টতই এটি আরও উপযুক্ত উত্তর। filter()এইভাবে অপব্যবহারের ফলে অপ্রত্যাশিত পরিণতি হতে পারে, এমন কিছু যা ওপি সম্ভবত বুঝতে পারেনি (যদি আমি এখানে কিছু অনুপস্থিত না করি)
স্লিপাল

1
@ স্লিপাইকাল এই পদ্ধতির ফলে কোন অনিচ্ছাকৃত পরিণতি ঘটবে?
অশ্বারোহণ ফ্যাট 11

12
যদি আপনার ডাটাবেসের সীমাবদ্ধতাগুলি সঠিকভাবে বস্তুগুলির মধ্যে স্বতন্ত্রতা পরিচালনা না করে তবে আপনি এমন প্রান্তের ক্ষেত্রে আঘাত করতে পারেন যেখানে আপনার যুক্তিটি কেবলমাত্র একটি একক অবজেক্ট (যা প্রথম () দ্বারা নির্বাচিত) প্রত্যাশা করে, তবে বাস্তবে একাধিক বস্তু বিদ্যমান exist প্রথম () এর পরিবর্তে get () ব্যবহার করা আপনাকে উত্থাপনের মাধ্যমে সুরক্ষার জন্য একটি অতিরিক্ত স্তর দেয় MultipleObjectsReturned()। যদি ফলাফলটি ফেরত দেওয়া একাধিক বস্তু ফেরত প্রত্যাশিত না হয়, তবে এটির মতো আচরণ করা উচিত নয়। একটা ছিল দীর্ঘ এই সম্পর্কে বিতর্ক এখানে
sleepycal

139

এই কাজটি করার দুটি পদ্ধতি আছে;

try:
    foo = Foo.objects.get(bar=baz)
except model.DoesNotExist:
    foo = None

অথবা আপনি একটি মোড়ক ব্যবহার করতে পারেন:

def get_or_none(model, *args, **kwargs):
    try:
        return model.objects.get(*args, **kwargs)
    except model.DoesNotExist:
        return None

এটিকে কল করুন

foo = get_or_none(Foo, baz=bar)

8
এটি কার্যকারিতার জন্য ব্যতিক্রমগুলি ব্যবহার করছে - আমি এটি পছন্দ করি না - বেশিরভাগ ভাষায় এটি একটি খারাপ অভ্যাস। অজগর এ কেমন আছে?
পিসিভি

18
পাইথন পুনরাবৃত্তি এইভাবে কাজ করে (একটি স্টপআইটারেশন উত্থাপন করে) এবং এটি ভাষার মূল অংশ। আমি চেষ্টা / কার্যকারিতা বাদে প্রচুর ভক্ত নই, তবে এটি পাইথোনিক হিসাবে বিবেচিত বলে মনে হয়।
ম্যাট লুঙ্গো

4
@ পিসিভি: "বেশিরভাগ" ভাষা সম্পর্কে কোনও নির্ভরযোগ্য প্রচলিত জ্ঞান নেই। আমি মনে করি আপনি ব্যবহার করার ক্ষেত্রে কিছু নির্দিষ্ট ভাষা সম্পর্কে ভাবছেন তবে এই জাতীয় পরিমাণের সাথে সতর্ক হন। ব্যতিক্রমগুলি পাইথনের যে কোনও কিছু হিসাবে ধীর (বা "যথেষ্ট যথেষ্ট দ্রুত") হতে পারে। প্রশ্নে ফিরে যাওয়া - এটি কাঠামোর একটি ঘাটতি, তারা queryset1.6 এর আগে এটি করার জন্য কোনও পদ্ধতি সরবরাহ করেনি ! তবে এই নির্মাণের জন্য - এটি কেবল আনাড়ি। এটি "দুষ্ট" নয় কারণ আপনার প্রিয় ভাষার কিছু টিউটোরিয়াল লেখক এটি বলেছেন। গুগল চেষ্টা করুন: "অনুমতি চেয়ে ক্ষমা চাইতে"।
টমাসজ গ্যান্ডার

@ টমাসজান্ডার: হ্যাঁ, আপনার পছন্দের ভাষার টিউটোরিয়াল যাই বলুক না কেন এটি আনাড়ি এবং পড়া কঠিন difficult যখন আমি একটি ব্যতিক্রম দেখি তখন অনুমান করি যে মানহীন কিছু ঘটছে। পঠনযোগ্যতা গণনা। তবে আমি সম্মত হই যখন অন্য কোন যুক্তিসঙ্গত বিকল্প নেই, আপনার পক্ষে এটি করা উচিত এবং খারাপ কিছু ঘটবে না।
পিসিভি

@pcv getপদ্ধতিটি ফিরে আসার কথা নয় None, সুতরাং একটি ব্যতিক্রমটি বোঝা যায়। আপনি এটি এমন পরিস্থিতিতে ব্যবহার করার কথা ছিলেন যেখানে আপনি নিশ্চিত হন যে অবজেক্টটি সেখানে থাকবে / অবজেক্টটি সেখানে থাকার কথা "অনুমিত" রয়েছে। এছাড়াও এর মতো ব্যতিক্রমগুলি ব্যবহার করা 'ওকে' হিসাবে বিবেচিত হয় কারণ এটি ভাল it আপনি getএকটি পৃথক চুক্তি সহ একটি চান , তাই আপনি ব্যতিক্রমটি ধরেন এবং এটিকে দমন করেন, যা আপনার পরে পরিবর্তন।
ড্যান পাসারো

83

সোরকির উত্তরে কিছু নমুনা কোড যুক্ত করতে (আমি এটি একটি মন্তব্য হিসাবে যুক্ত করব, তবে এটি আমার প্রথম পোস্ট, এবং মন্তব্য দেওয়ার মতো যথেষ্ট খ্যাতি আমার নেই), আমি এই জাতীয় একটি get_or_none কাস্টম ম্যানেজার প্রয়োগ করেছি:

from django.db import models

class GetOrNoneManager(models.Manager):
    """Adds get_or_none method to objects
    """
    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except self.model.DoesNotExist:
            return None

class Person(models.Model):
    name = models.CharField(max_length=255)
    objects = GetOrNoneManager()

এবং এখন আমি এটি করতে পারি:

bob_or_none = Person.objects.get_or_none(name='Bob')

এটি খুব মার্জিত।
নোটসিমন

13

আপনি জ্ব্যাংগো বিরক্তিকর ব্যবহার করার চেষ্টা করতে পারেন (এটির আরও একটি কার্যকর কার্য রয়েছে!)

এটি দিয়ে এটি ইনস্টল করুন:

pip install django-annoying

from annoying.functions import get_object_or_None
get_object_or_None(Foo, bar=baz)

9

ফু কে এর কাস্টম ম্যানেজার দিন । এটি বেশ সহজ - আপনার কাস্টম ম্যানেজারে আপনার কোডটি ফাংশনে রাখুন, আপনার মডেলটিতে কাস্টম ম্যানেজার সেট করুন এবং এটিকে কল করুনFoo.objects.your_new_func(...)

আপনার যদি জেনেরিক ফাংশন প্রয়োজন হয় (এটি কোনও কাস্টম ম্যানেজারের সাথে নয় এমন কোনও মডেলটিতে ব্যবহার করার জন্য) আপনার নিজের লিখুন এবং এটিকে আপনার অজগর পথে এবং আমদানিতে কোথাও রাখুন, আর অগোছালো নয়।


4

এটি ম্যানেজারের মাধ্যমে করা বা জেনেরিক ফাংশনের মাধ্যমে, আপনি ট্রাই স্টেটমেন্টে 'মাল্টিপলঅবজেক্টস রিটার্নার্ড' ধরতেও পারেন, কারণ গেট () ফাংশন এটি বাড়িয়ে তুলবে যদি আপনার কাওয়ারগুলি একাধিক বস্তু পুনরুদ্ধার করে।

জেনেরিক ফাংশন উপর বিল্ডিং:

def get_unique_or_none(model, *args, **kwargs):
    try:
        return model.objects.get(*args, **kwargs)
    except (model.DoesNotExist, model.MultipleObjectsReturned), err:
        return None

এবং পরিচালকের মধ্যে:

class GetUniqueOrNoneManager(models.Manager):
    """Adds get_unique_or_none method to objects
    """
    def get_unique_or_none(self, *args, **kwargs):
        try:
            return self.get(*args, **kwargs)
        except (self.model.DoesNotExist, self.model.MultipleObjectsReturned), err:
            return None

এটি অন্যান্য উত্তরের সমস্ত সেরা পয়েন্ট ক্যাপচার বলে মনে হচ্ছে। খুব সুন্দর :)
এডওয়ার্ড নেওয়েল

@ এমসপাউডার, আমি যদি আর কোনওটিই না ফিরিয়ে দিতে চাই, তবে আমি একই পৃষ্ঠায় প্রদর্শিত "কোনও মিলবে না ডেটা" এর মতো একটি সতর্কতা বার্তাটি ফিরিয়ে দিতে চাই?
হালনা

0

এখানে সহায়িকার ফাংশনে একটি প্রকরণ রয়েছে যা আপনাকে QuerySetউদাহরণস্বরূপ বিকল্প হিসাবে পাস করতে দেয় , যদি আপনি মডেলটির allঅবজেক্টের ক্যোরিসেটের (যেমন উপস্থিত কোনও শিশু আইটেমের উপসেট থেকে ) অনন্য বস্তু (উপস্থিত থাকলে) পেতে চান মূল উদাহরণ):

def get_unique_or_none(model, queryset=None, *args, **kwargs):
    """
        Performs the query on the specified `queryset`
        (defaulting to the `all` queryset of the `model`'s default manager)
        and returns the unique object matching the given
        keyword arguments.  Returns `None` if no match is found.
        Throws a `model.MultipleObjectsReturned` exception
        if more than one match is found.
    """
    if queryset is None:
        queryset = model.objects.all()
    try:
        return queryset.get(*args, **kwargs)
    except model.DoesNotExist:
        return None

এটি দুটি উপায়ে ব্যবহার করা যেতে পারে, যেমন:

  1. obj = get_unique_or_none(Model, *args, **kwargs) হিসাবে previosuly আলোচনা
  2. obj = get_unique_or_none(Model, parent.children, *args, **kwargs)

-1

আমি মনে করি বেশিরভাগ ক্ষেত্রে আপনি কেবল ব্যবহার করতে পারেন:

foo, created = Foo.objects.get_or_create(bar=baz)

কেবলমাত্র যদি এটি সমালোচিত না হয় তবে Foo টেবিলটিতে একটি নতুন এন্ট্রি যুক্ত করা হবে (অন্যান্য কলামগুলির কোনও / ডিফল্ট মান থাকবে না)

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