Django şablonlarında dizeleri nasıl birleştirebilirim?


191

Django şablon etiketinde bir dizeyi birleştirmek istiyorum, örneğin:

{% extend shop/shop_name/base.html %}

İşte shop_namebenim değişken ve bunu yolun geri kalanı ile birleştirmek istiyorum.

Varsayalım shop_name=example.comve sonucun uzatılmasını istiyorum shop/example.com/base.html.

Yanıtlar:


380

La kullan:

{% with "shop/"|add:shop_name|add:"/base.html" as template %}
{% include template %}
{% endwith %}

2
Genişletme etiketi yerine dahil etiketi kullandığından, bu cevap tarafından tamamen karıştırıldım, ancak görünüşe göre sadece çalışıyor. Yine de Ahsan'ın kendi cevabını da tavsiye ederim ama aynı zamanda çalışıyor ve (bence) anlamsal olarak daha doğru ve daha az karışıklık yaratıyor.
gitaarik

15
Bu işe yarayabilir, ancak django şablonlarındaki dizeleri birleştirmek için genel bir cevap olarak düşünülmemelidir. Bkz. Stackoverflow.com/a/23783666/781695
kullanıcı

Django belgelerinde belirtildiği gibi, "Tamsayılara zorlanabilen dizeler birleştirilecek, birleştirilmeyecek" Bu nedenle, örneğin, model nesnesinin birincil anahtarlarını birleştirmek istiyorsanız (benzersiz önbellek anahtarı oluşturmak için yararlı olabilir), iş.
zen11625

Bence bu hiç de kaçmıyor shop_name, bu yüzden tehlikeli.
Flimm

Dikkat edin, daha önce de belirtildiği gibi, bu sadece dizelerle çalışır! Çevirmek Eğer shop_namebir görünümde bağlamda geçirmeden önce en get_context_datakullanarak tercüme emin olun ugettextyerine ugettext_lazy.
Kim

111

addDizeler için kullanmayın , şöyle özel bir etiket tanımlamanız gerekir:

Bir dosya oluşturun: <appname>\templatetags\<appname>_extras.py

from django import template

register = template.Library()

@register.filter
def addstr(arg1, arg2):
    """concatenate arg1 & arg2"""
    return str(arg1) + str(arg2)

ve sonra @Steven'in dediği gibi kullanın

{% load <appname>_extras %}

{% with "shop/"|addstr:shop_name|addstr:"/base.html" as template %}
    {% include template %}
{% endwith %}

Kaçınma nedeni add:

Dokümanlara göre

Bu filtre ilk önce her iki değeri de tamsayılara zorlamaya çalışacaktır ... Tamsayılara zorlanabilen dizeler toplanır, birleştirilmez ...

Her iki değişken de tamsayı olursa, sonuç beklenmedik olur.


@ Register.filter (name = 'addstr') olmamalı mı?
seddonym

6
Bu en iyi yanıt olarak işaretlenmelidir çünkü Python tarafından tamsayı olarak zorlanabilen değerlerle doğru bir şekilde çalışmak.
zen11625

2
En çok "up" ile bir değil neden bu kadar biliyorum çünkü daha dont senin doğru cevap, " add" Yalnız sadece kullanmaz str()ilk etapta ve iş vermedi hiç benim için çözüm sorunsuz çalışır oysa
Olivier Pons

1
Cevabınız beni kurtardı!
Ljubisa Livac

6
Özel filtrenizi şablon dosyanızın en üstüne yüklemeyi unutmayın:{% load <appname>_extras %}
Susanne Peng

13

Klasör hiyerarşisini değiştirdim

/shop/shop_name/base.html için /shop_name/shop/base.html

ve sonra aşağıda işe yarayacaktı.

{% extends shop_name|add:"/shop/base.html"%} 

Şimdi base.html sayfasını genişletebilir.



3

addFiltreye bir göz atın .

Düzenleme: Filtreleri zincirleyebilirsiniz, böylece yapabilirsiniz "shop/"|add:shop_name|add:"/base.html". Ancak bu çalışmaz, çünkü argümanlardaki filtreleri değerlendirmek şablon etiketine bağlıdır ve genişletmez.

Sanırım bunu şablonlar içinde yapamazsınız.


bu işe yaramayacak. yolun ortasında benim değişken eklemek istiyorum.
Ahsan

filtre ekle sadece django docs göre bitiştirilmedi toplandı
Ahsan

Dokümanlar "tamsayılara zorlanabilecek dizeler toplanacak" diyor. Diğer dizeler birleştirilir. Ancak bu gerçekten önemli değil çünkü filtreyi kullanamazsınız :(
Daniel Hepper

2

Dokümanlardan:

Bu etiket iki şekilde kullanılabilir:

  • {% extends "base.html" %} (tırnak işaretleri ile) genişletilecek üst şablonun adı olarak "base.html" değişmez değerini kullanır.
  • {% extends variable %}değişkenin değerini kullanır. Değişken bir dize olarak değerlendirilirse, Django bu dizeyi üst şablonun adı olarak kullanır. Değişken Şablon nesnesini değerlendirirse, Django bu nesneyi üst şablon olarak kullanır.

Yani argümanı manipüle etmek için bir filtre kullanamazsınız. Arama görünümünde ya ata şablonunu başlatmanız ya da doğru yolla bir dize değişkeni oluşturmanız ve bunu bağlamla birlikte iletmeniz gerekir.


1

@ hatanın cevabı temel olarak doğrudur, bunun için bir şablon etiketi kullanmalısınız. Ancak, buna benzer her türlü işlemi gerçekleştirmek için kullanabileceğim biraz daha genel bir şablon etiketini tercih ederim:

from django import template
register = template.Library()


@register.tag(name='captureas')
def do_captureas(parser, token):
    """
    Capture content for re-use throughout a template.
    particularly handy for use within social meta fields 
    that are virtually identical. 
    """
    try:
        tag_name, args = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("'captureas' node requires a variable name.")
    nodelist = parser.parse(('endcaptureas',))
    parser.delete_first_token()
    return CaptureasNode(nodelist, args)


class CaptureasNode(template.Node):
    def __init__(self, nodelist, varname):
        self.nodelist = nodelist
        self.varname = varname

    def render(self, context):
        output = self.nodelist.render(context)
        context[self.varname] = output
        return ''

ve bunu şablonunuzda şu şekilde kullanabilirsiniz:

{% captureas template %}shop/{{ shop_name }}/base.html{% endcaptureas %}
{% include template %}

Yorumda belirtildiği gibi, bu şablon etiketi bir şablon boyunca tekrarlanabilir ancak şablonlarınızı tıklatacak mantık ve diğer şeyleri gerektiren veya şablonlar arasında bloklar arasında aktarılan verileri yeniden kullanmak istediğiniz durumlarda özellikle yararlıdır:

{% captureas meta_title %}{% spaceless %}{% block meta_title %}
    {% if self.title %}{{ self.title }}{% endif %}
    {% endblock %}{% endspaceless %} - DEFAULT WEBSITE NAME
{% endcaptureas %}

ve sonra:

<title>{{ meta_title }}</title>
<meta property="og:title" content="{{ meta_title }}" />
<meta itemprop="name" content="{{ meta_title }}">
<meta name="twitter:title" content="{{ meta_title }}">

Captureas etiketinin kredisi burada: https://www.djangosnippets.org/snippets/545/


1

{% with %}Etiketi ile çalışmayı oldukça güçlükle buldum . Bunun yerine, dizeler ve tamsayılar üzerinde çalışması gereken aşağıdaki şablon etiketini oluşturdum.

from django import template

register = template.Library()


@register.filter
def concat_string(value_1, value_2):
    return str(value_1) + str(value_2)

Ardından, aşağıdakileri kullanarak şablon etiketini en üstteki şablonunuza yükleyin:

{% load concat_string %}

Daha sonra aşağıdaki şekilde kullanabilirsiniz:

<a href="{{ SOME_DETAIL_URL|concat_string:object.pk }}" target="_blank">123</a>

Şahsen bununla çalışmak için çok daha temiz olduğunu gördüm.


0

Django şablonlarında değişken manipülasyon yapamazsınız. İki şablonunuz var, kendi şablon etiketinizi yazın veya bunu görünümde yapın,


benim gereksinim görünümler seçeneği yararlı değil bu yüzden sadece şablonlarda yapmaktır. Ayrıca özel şablon etiketi ile denedim ama {% load concat%} sonra {% uzatmak ....%} etiketi gerekir. şimdi nasıl yapabilirim?
Ahsan

Dize biçimini ve bağımsız değişkenleri kabul eden extended_extends etiketi yazın.
Paulo Scardine

u varsayılan etiketler için özel etiket yazma konusunda bana bir örnek verebilir misiniz?
Ahsan

0

extendsbunun için bir tesisi yok. Tüm şablon yolunu bir bağlam değişkenine yerleştirin ve bunu kullanın veya mevcut şablon etiketini kopyalayın ve uygun şekilde değiştirin.


cevap için teşekkürler! bağlam değişkeni için benim proje gereksinimi nedeniyle yapamam view.py ayarlamak zorunda. ve lütfen ikincisine örnek verin.
Ahsan

0

Ve çoklu birleştirme:

from django import template
register = template.Library()


@register.simple_tag
def concat_all(*args):
    """concatenate all args"""
    return ''.join(map(str, args))

Ve Şablonda:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.