كيف يمكنني إجراء تصفية الاستعلام في قوالب جانغو

StackOverflow https://stackoverflow.com/questions/223990

  •  03-07-2019
  •  | 
  •  

سؤال

أحتاج إلى إجراء استعلام تمت تصفيته من داخل قالب Django، للحصول على مجموعة من الكائنات المكافئة لرمز python ضمن طريقة عرض:

queryset = Modelclass.objects.filter(somekey=foo)

في القالب الخاص بي أود أن أفعل

{% for object in data.somekey_set.FILTER %}

لكن يبدو أنني لا أستطيع معرفة كيفية كتابة FILTER.

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

المحلول

وأنت لا تستطيع أن تفعل هذا، والذي هو حسب التصميم. المؤلفون إطار جانغو تهدف إلى فصل صارم للقانون العرض التقديمي من منطق البيانات. نماذج الترشيح هو منطق البيانات، وإخراج HTML هو منطق العرض.

وهكذا كان لديك العديد من الخيارات. أسهل هو أن تفعل الترشيح، ثم تمرير نتيجة لrender_to_response. أو هل يمكن أن يكتب طريقة في النموذج الخاص بك بحيث يمكنك القول {% for object in data.filtered_set %}. وأخيرا، يمكن أن تكتب كلمة دلالية القالب الخاص بك، على الرغم من أن في هذه الحالة المحددة أنصح ضد ذلك.

نصائح أخرى

وأنا فقط إضافة علامة قالب إضافية مثل هذا:

@register.filter
def in_category(things, category):
    return things.filter(category=category)

وبعد ذلك يمكنني القيام به:

{% for category in categories %}
  {% for thing in things|in_category:category %}
    {{ thing }}
  {% endfor %}
{% endfor %}

أواجه هذه المشكلة بشكل منتظم وغالبًا ما أستخدم الحل "إضافة طريقة".ومع ذلك، هناك بالتأكيد حالات لا تعمل فيها "إضافة طريقة" أو "حسابها في العرض" (أو لا تعمل بشكل جيد).على سبيل المثالعندما تقوم بتخزين أجزاء القالب مؤقتًا وتحتاج إلى بعض حسابات قاعدة البيانات غير التافهة لإنتاجها.لا ترغب في القيام بعمل قاعدة البيانات إلا إذا كنت بحاجة إلى ذلك، ولكنك لن تعرف ما إذا كنت بحاجة إلى ذلك حتى تتعمق في منطق القالب.

بعض الحلول الممكنة الأخرى:

  1. استخدم علامة القالب {% expr <expression> كـ <var_name> %} الموجودة في http://www.djangosnippets.org/snippets/9/ التعبير هو أي تعبير Python قانوني مع سياق القالب الخاص بك باعتباره نطاقك المحلي.

  2. قم بتغيير معالج القالب الخاص بك.جينجا 2 (http://jinja.pocoo.org/2/) له بناء جملة مطابق تقريبًا للغة قالب Django، ولكن مع توفر قوة Python الكاملة.كما أنها أسرع.يمكنك القيام بذلك بالجملة، أو يمكنك قصر استخدامه على القوالب التي أنت نعمل عليها، لكن استخدم قوالب Django "الأكثر أمانًا" للصفحات التي يحتفظ بها المصمم.

ويمكن حل هذه مع علامة مهمة:

from django import template

register = template.Library()

@register.assignment_tag
def query(qs, **kwargs):
    """ template tag which allows queryset filtering. Usage:
          {% query books author=author as mybooks %}
          {% for book in mybooks %}
            ...
          {% endfor %}
    """
    return qs.filter(**kwargs)

والخيار الآخر هو أنه إذا كان لديك التصفية التي تريدها دائما التطبيقية، إضافة <لأ href = "https://docs.djangoproject.com/en/1.4/topics/db/managers/#custom- مدراء "> مدير مخصص على هذا النموذج في السؤال الذي ينطبق دائما مرشح للنتائج التي تم إرجاعها.

وخير مثال على هذا هو نموذج Event، حيث 90٪ من الاستعلامات تفعله على النموذج الذي تريد الذهاب الى شيء من هذا القبيل Event.objects.filter(date__gte=now)، أي كنت مهتما بشكل طبيعي في Events التي يتم القادمة. هذا من شأنه أن تبدو مثل:

class EventManager(models.Manager):
    def get_query_set(self):
        now = datetime.now()
        return super(EventManager,self).get_query_set().filter(date__gte=now)

وفي النموذج:

class Event(models.Model):
    ...
    objects = EventManager()

ولكن مرة أخرى، وهذا ينطبق على مرشح واحد ضد جميع الاستفسارات الافتراضية القيام به على نموذج Event وهكذا ليست مرنة بما أن بعض من الأساليب المذكورة أعلاه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top