سؤال

ولقد حصلت على نموذج مثل هذا:

class Thing(models.Model):
    property1 = models.IntegerField()
    property2 = models.IntegerField()
    property3 = models.IntegerField()

class Subthing(models.Model):
    subproperty = models.IntegerField()
    thing = modelsForeignkey(Thing)
    main = models.BooleanField()

ولقد حصلت على وظيفة التي يتم تمريرها قائمة المرشحات حيث كل مرشح هو النموذج { 'نوع': شيء، "القيمة": س}. وتحتاج هذه الدالة لإرجاع مجموعة من النتائج اندينج جميع المرشحات معا:

final_q = Q()
for filter in filters:
        q = None
        if filter['type'] =='thing-property1':
            q = Q(property1=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property2=filter['value'])
        elif filter['type'] =='thing-property2':
            q = Q(property3=filter['value'])
        if q:
            final_q = final_q & q
return Thing.objects.filter(final_q).distinct()

وكل Subthing له خاصية منطقية "الرئيسية". كل شيء له (1) وSubthing 1 فقط حيث == الرئيسي صحيح.

وأنا الآن بحاجة إلى إضافة فلتر يقوم بإرجاع كافة الأمور التي لها Subthing حيث main==True وsubproperty==filter['value']

هل يمكنني القيام بذلك كجزء من وجوه Q أنا بناء؟ إن لم يكن إلا كيف؟ ومجموعة طلبات البحث أحصل قبل بلدي مرشح جديد يمكن أن تكون كبيرة جدا لذلك أود طريقة التي لا تنطوي على حلقات على النتائج.

هل كانت مفيدة؟

المحلول

وانها أسهل قليلا لفهم إذا كنت تعطي صراحة Subthings الخاص بك "related_name" في علاقتها شيء

class Subthing(models.Model):
    ...
    thing = models.ForeignKey(Thing, related_name='subthings')
    ...

والآن، يمكنك استخدام جانغو الانضمام بناء جملة لبناء كائن Q الخاص بك:

Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])

والعلاقة العكسية لها الاسم الافتراضي "subthing_set"، ولكن أجد أنه من الأسهل لمتابعة إذا كنت تعطيه اسما أفضل مثل 'subthings ".

نصائح أخرى

وعن طريق (بدلا من final_q=Q() في البداية)

final_q=Q(subthing_set__main=True)
sub_vals = map(lambda v: v['value'], filters)
if sub_vals:
    final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)

ويجب أن تحصل على ما تريد، ويمكنك أيضا ضبط حلقة لبناء قائمة sub_vals وتطبيقه بعد الحلقة.

وsubthing_set هو، وأضاف مجال آخر ذي صلة اضاف تلقائيا إلى شيء للوصول Subthings ذات الصلة.

ويمكنك تعيين اسم المتعلقة أخرى، منها مثلا.

thing=models.ForeignKey(Thing,related_name='subthings')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top