Django: اكتشف العنصر في القائمة التي تم تحديدها

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

  •  07-07-2019
  •  | 
  •  

سؤال

أنا متأكد من أنني رأيت هذا السؤال على Stack Overflow من قبل ، لكنني لم أتمكن من العثور عليه في حياتي ، لذلك لا يذهب هنا.

لدي قائمة Django عادية تستخدم {% url %} وضع علامة وأسماء ثابتة لعناصر القائمة. الآن أريد أن يكون لدي نمط مختلف لعنصر القائمة الذي تم تحديده. ولكن يتم تقديم القائمة في القالب الأساسي ، فكيف يمكنني معرفة أي عنصر القائمة؟

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

المحلول

يمكنك بالتأكيد القيام بذلك مع بعض رمز القالب القبيح ، ولكن الطريقة الأكثر شهرة على مستوى العالم هي استخدام محدد CSS. هذا يتيح CSS القيام بكل العمل تلقائيًا لك.

وإليك كيف يعمل:

يمكنك ببساطة وضع معرف في جسمك اعتمادًا على الصفحة التي تقوم بها. ثم في CSS تفعل شيئًا كهذا:

#section-aboutme #nav-aboutme,
#section-contact #nav-contact
/* ... put one of these per body/menu item ... */
{
    font-color: red;
}

يمكنك وضع معرفات NAV-ABOUTME ، ومعرفات الاتصالات على كل من عناصر القائمة الخاصة بك.

سيتم تحديد النمط تلقائيًا بواسطة CSS اعتمادًا على معرف الجسم الموجود بداخله.

نصائح أخرى

عادةً ما أفعل ذلك بالطريقة التي اقترحها براين ، ولكن لاستيعاب قالب أعطاني المصمم الذي استخدم أكثر شيوعًا class="selected" الطريقة ، كتبت أ {٪ nav ٪} علامة قالب.

سيبدو قالب التنقل HTML الخاص بك شيئًا مثل:

{% block nav %}
<ul class="nav">
    <li{% if nav.home %} class="selected"{% endif %}><a href="/">Home</a></li>
    <li{% if nav.about %} class="selected"{% endif %}><a href="/about/">About</a></li>
</ul>
{% endblock %}

لتعيين التنقل في قالب الطفل ، افعل:

{% include "base.html" %}
{% load nav %}

{% block nav %}
{% nav "about" %}
{{ block.super }}
{% endblock %}

How about a custom tag which you use to generate your nav item?

The following takes the name of the url for which a nav item should be generated and the text it should display. It generates a li tag with a class of "selected" if the named url's path is the same as the current url (requires 'django.core.context_processors.request' in your TEMPLATE_CONTEXT_PROCESSORS). Within the li, it generates an a tag with the path of the url specified by the url_name. It has the contents specified by contents.

Obviously, this could be tweaked to generate different markup for the nav item, as required.

The rest can be done using CSS.

Advantages:

  • Easy to use

  • Little code required

  • DRY

  • Could be made to be more flexible

Disadvantages:

  • Requires 'django.core.context_processors.request'

  • Requires urls to be named e.g. urlpatterns = patterns('django.views.generic.simple', ... (r'^$', 'direct_to_template', {'template': 'index.html'}, 'index'), ... ). This could potentially be done differently (e.g. pass in url).

  • Doesn't cope with pages not exactly equal to the specified and therefore will not apply the selected class to the li when on a page lower in the url heirarchy. For example, if I'm on /products/, it will highlight the nav item directing to /products/. If I'm on /products/myProduct/, it will not highlight the /products/ link. This could be coded around, but it would force people to use sensible urls. For example, change the additionalAttrs assignment to additionalAttrs = ' class=selected' if (context['request'].path.startswith(path) and path != '/') or (context['request'].path == path) else ''.

Code:

from django import template
from django.core.urlresolvers import reverse

register = template.Library()

class NavNode(template.Node):
    def __init__(self, url_name, contents):
        self.url_name = url_name
        self.contents = contents

    def render(self, context):
        path = reverse(self.url_name)
        additionalAttrs = ' class=selected' if path == context['request'].path else ''
        return '<li'+additionalAttrs+'><a href="'+path+'">'+self.contents+'</a></li>'

@register.tag
def nav_link(parser, token):
    bits = token.split_contents()
    if len(bits) == 3:
        contents = bits.pop()
        url_name = bits.pop()
    else:
        raise template.TemplateSyntaxError, "%r tag requires a single argument" % bits[0]

    if contents[0] == contents[-1] and contents[0] in ('"', "'"):
        contents = contents[1:-1]

    return NavNode(url_name, contents)                

You can pass request.path to your template

from django.shortcuts import render_to_response
from django.template import RequestContext
return render_to_response('templ.html', {'page':request.path}, context_instance=RequestContext(request))

then use an ugly if template tag to add a CSS class to your menu item

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