python - نماذج Django - كيفية تصفية عدد من ForeignKey الكائنات




3 Answers

يبدو وكأنه وظيفة extra .

A.objects.extra(
    select={
        'b_count': 'SELECT COUNT(*) FROM yourapp_b WHERE yourapp_b.a_id = yourapp_a.id',
    },
    where=['b_count < 2']
)

إذا كان العدد B هو الشيء الذي تحتاج إليه في كثير من الأحيان كمعيار تصفية أو طلب ، أو يجب أن يتم عرضه في طرق عرض القوائم ، يمكنك التفكير في عدم التسوية عن طريق إضافة حقل b_count إلى نموذج A واستخدام الإشارات لتحديثه عند إضافة B أو تم الحذف:

from django.db import connection, transaction
from django.db.models.signals import post_delete, post_save

def update_b_count(instance, **kwargs):
    """
    Updates the B count for the A related to the given B.
    """
    if not kwargs.get('created', True) or kwargs.get('raw', False):
        return
    cursor = connection.cursor()
    cursor.execute(
        'UPDATE yourapp_a SET b_count = ('
            'SELECT COUNT(*) FROM yourapp_b '
            'WHERE yourapp_b.a_id = yourapp_a.id'
        ') '
        'WHERE id = %s', [instance.a_id])
    transaction.commit_unless_managed()

post_save.connect(update_b_count, sender=B)
post_delete.connect(update_b_count, sender=B)

الحل الآخر هو إدارة علامة الحالة على كائن A عند إضافة أو إزالة ب.

B.objects.create(a=some_a)
if some_a.hidden and some_a.b_set.count() > 1:
    A.objects.filter(id=some_a.id).update(hidden=False)

...

some_a = b.a
some_b.delete()
if not some_a.hidden and some_a.b_set.count() < 2:
    A.objects.filter(id=some_a.id).update(hidden=True)

لديّ عارضتان ( A و ( B ، وهما على النحو التالي:

class A(models.Model):
  title = models.CharField(max_length=20)
  (...)

class B(models.Model):
  date = models.DateTimeField(auto_now_add=True)
  (...)
  a = models.ForeignKey(A)

الآن لدي بعض الكائنات A و B ، وأرغب في الحصول على استعلام يحدد جميع الكائنات التي تحتوي على أقل من 2 B تشير إليها.

A شيء مثل تجمع شيء ، والمستخدمين (B) الانضمام إلى تجمع. إذا كان هناك 1 أو 0 انضم فقط ، لا ينبغي عرض التجمع على الإطلاق.

هل من الممكن مع تصميم نموذج من هذا القبيل؟ أو ينبغي لي أن تعديل ذلك قليلا؟




نوصي بتعديل تصميمك ليشمل بعض حقول الحالة على A.

القضية هي واحدة من "لماذا؟" لماذا يحتوي A على <2 B و Why A have> = 2 B's. هل لأن المستخدم لم يدخل شيئًا؟ أو لأنهم حاولوا ومدخلاتهم كان بها أخطاء. أم هو لأن القاعدة <2 لا تنطبق في هذه الحالة.

استخدام وجود أو غياب مفتاح خارجي يحد من المعنى إلى - جيد - الحاضر أو ​​الغائب. ليس لديك أي طريقة لتمثيل "لماذا؟"

أيضا ، لديك الخيار التالي

[ a for a in A.objects.all() if a.b_set.count() < 2 ]

هذا يمكن أن يكون الثمن لأنه يجلب كل A بدلا من قوة قاعدة البيانات للقيام بهذا العمل.

تعديل: من التعليق "سيتطلب مني مراقبة انضمام المستخدم / مغادرة المستخدم لحضور أحداث تجمع".

لا "تشاهد" أي شيء - فأنت تقدم واجهة برمجة تطبيقات تعمل على ما تحتاج إليه. هذه هي الفائدة الأساسية لنموذج جانغو. وإليك طريقة واحدة ، مع وسائل explict في فئة A

class A( models.Model ):
    ....
    def addB( self, b ):
        self.b_set.add( b )
        self.changeFlags()
    def removeB( self, b ):
        self.b_set.remove( b )
        self.changeFlags()
    def changeFlags( self ):
        if self.b_set.count() < 2: self.show= NotYet
        else: self.show= ShowNow

يمكنك أيضًا تحديد Manager خاص لهذا ، واستبدال مدير b_set الافتراضي b_set الذي يحسب المراجع والتحديثات A




ماذا عن القيام بهذه الطريقة؟

queryset = A.objects.filter(b__gt=1).distinct()



Related

python django database-design