Bagaimana cara menggabungkan string dalam template Django?

191

Saya ingin menyatukan string dalam tag template Django, seperti:

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

Ini shop_nameadalah variabel saya dan saya ingin menggabungkan ini dengan sisa jalur.

Misalkan saya punya shop_name=example.comdan saya ingin hasil diperpanjang shop/example.com/base.html.

Ahsan
sumber

Jawaban:

380

Gunakan dengan:

{% with "shop/"|add:shop_name|add:"/base.html" as template %}
{% include template %}
{% endwith %}
Steven
sumber
2
Saya benar-benar bingung dengan jawaban ini karena ia menggunakan tag include bukan dari tag extended, tetapi ternyata hanya berfungsi. Meskipun saya akan merekomendasikan jawaban Ahsan sendiri karena juga berfungsi dan (menurut saya) secara semantik lebih benar dan menimbulkan lebih sedikit kebingungan.
gitaarik
15
Ini mungkin berhasil tetapi tidak boleh dianggap sebagai jawaban umum untuk merangkai string dalam templat Django. Lihat stackoverflow.com/a/23783666/781695
pengguna
Seperti pepatah dalam dokumentasi Django, "String yang dapat dipaksakan ke bilangan bulat akan dijumlahkan, tidak digabungkan" Jadi, misalnya, jika Anda ingin menggabungkan kunci utama objek model (mungkin berguna untuk membuat kunci cache yang unik), itu tidak kerja.
zen11625
Saya pikir ini tidak luput shop_namesama sekali, jadi berbahaya.
Flimm
Sadarilah, sebagaimana telah disebutkan, ini hanya bekerja dengan string! Jika Anda menerjemahkan shop_namesebelum meneruskannya ke konteks dalam tampilan, get_context_datapastikan terjemahan itu diterjemahkan menggunakan ugettextalih-alih ugettext_lazy.
Kim
111

Jangan gunakan adduntuk string, Anda harus mendefinisikan tag khusus seperti ini:

Buat file: <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)

dan kemudian menggunakannya seperti yang dikatakan @Steven

{% load <appname>_extras %}

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

Alasan menghindari add:

Menurut dokumen

Filter ini pertama - tama akan mencoba untuk memaksa kedua nilai ke bilangan bulat ... String yang dapat dipaksa ke bilangan bulat akan dijumlahkan, bukan digabungkan ...

Jika kedua variabel tersebut adalah bilangan bulat, hasilnya tidak terduga.

pengguna
sumber
Bukankah itu @ register.filter (name = 'addstr')?
seddonym
6
Ini harus ditandai sebagai jawaban terbaik karena bekerja dengan benar dengan nilai-nilai yang dapat dipaksakan oleh Python sebagai bilangan bulat.
zen11625
2
Saya tidak tahu mengapa Anda bukan yang paling "naik" karena itu jawaban Anda yang benar, " add" saja tidak digunakan str()di tempat pertama dan tidak bekerja sama sekali untuk saya sedangkan solusi Anda bekerja dengan sempurna
Olivier Pons
1
Jawaban Anda telah menyelamatkan saya!
Ljubisa Livac
6
Ingatlah untuk memuat filter khusus Anda di bagian atas file template Anda:{% load <appname>_extras %}
Susanne Peng
13

Saya telah mengubah hierarki folder

/shop/shop_name/base.html Ke /shop_name/shop/base.html

dan kemudian di bawah ini akan bekerja.

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

Sekarang ini dapat memperluas halaman base.html.

Ahsan
sumber
7

Merujuk pada Concatenating String di Django Templates :

  1. Untuk versi Django sebelumnya:

    {{ "Mary had a little"|stringformat:"s lamb." }}

"Mary pernah punya domba kecil."

  1. Lain:

    {{ "Mary had a little"|add:" lamb." }}

"Mary pernah punya domba kecil."

bing
sumber
3

Lihatlah addfilternya .

Sunting: Anda dapat membuat rantai filter, sehingga Anda bisa melakukannya "shop/"|add:shop_name|add:"/base.html". Tapi itu tidak akan berfungsi karena terserah pada tag template untuk mengevaluasi filter dalam argumen, dan extends tidak.

Saya kira Anda tidak dapat melakukan ini dalam template.

Daniel Hepper
sumber
ini tidak akan berhasil. saya ingin menambahkan variabel saya di tengah jalan.
Ahsan
tambahkan saja filter yang dijumlahkan bukan digabungkan menurut django docs
Ahsan
Dokumen mengatakan "string yang dapat dipaksa ke bilangan bulat akan dijumlahkan". String lainnya digabungkan. Tapi itu tidak terlalu penting karena Anda tidak dapat menggunakan filter :(
Daniel Hepper
2

Dari dokumen:

Tag ini dapat digunakan dalam dua cara:

  • {% extends "base.html" %} (dengan tanda kutip) menggunakan nilai literal "base.html" sebagai nama templat induk untuk diperluas.
  • {% extends variable %}menggunakan nilai variabel. Jika variabel mengevaluasi ke string, Django akan menggunakan string itu sebagai nama templat induk. Jika variabel mengevaluasi ke objek Templat, Django akan menggunakan objek itu sebagai templat induk.

Jadi sepertinya Anda tidak dapat menggunakan filter untuk memanipulasi argumen. Di tampilan panggilan Anda harus instantiate template leluhur atau membuat variabel string dengan jalur yang benar dan meneruskannya dengan konteks.

Paulo Scardine
sumber
1

Jawaban @ error pada dasarnya benar, Anda harus menggunakan tag templat untuk ini. Namun, saya lebih suka tag templat yang sedikit lebih umum yang dapat saya gunakan untuk melakukan segala jenis operasi yang mirip dengan ini:

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 ''

dan kemudian Anda dapat menggunakannya seperti ini di templat Anda:

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

Seperti komentar yang disebutkan, tag templat ini sangat berguna untuk informasi yang dapat diulang di seluruh templat tetapi membutuhkan logika dan hal-hal lain yang akan merusak templat Anda, atau dalam kasus di mana Anda ingin menggunakan kembali data yang dikirimkan antara templat melalui blok:

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

lalu:

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

Kredit untuk tag captas jatuh tempo di sini: https://www.djangosnippets.org/snippets/545/

K3TH3R
sumber
1

Saya merasa bekerja dengan {% with %}tag itu cukup merepotkan. Alih-alih, saya membuat tag templat berikut, yang seharusnya berfungsi pada string dan integer.

from django import template

register = template.Library()


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

Kemudian muat tag templat di templat Anda di atas menggunakan yang berikut ini:

{% load concat_string %}

Anda kemudian dapat menggunakannya dengan cara berikut:

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

Saya pribadi menemukan ini menjadi jauh lebih bersih untuk dikerjakan.

Bono
sumber
0

Anda tidak dapat melakukan manipulasi variabel dalam template Django. Anda memiliki dua opsi, baik menulis tag templat Anda sendiri atau melakukannya dalam tampilan,

Damir
sumber
Persyaratan saya adalah melakukannya dalam templat saja sehingga opsi tampilan tidak membantu. saya juga mencoba melalui tag templat kustom tetapi {% load concat%} harus setelah tag {% extended ....%}. jadi bagaimana saya bisa melakukannya sekarang?
Ahsan
Tulis tag extended_extends yang menerima format string dan argumen.
Paulo Scardine
dapatkah Anda memberi saya contoh cara menulis tag khusus untuk tag standar?
Ahsan
0

extendstidak memiliki fasilitas untuk ini. Entah letakkan seluruh jalur templat dalam variabel konteks dan gunakan itu, atau salin tag templat yang ada dan modifikasi dengan tepat.

Ignacio Vazquez-Abrams
sumber
thanx untuk balasan! untuk variabel konteks saya harus menetapkan di view.py yang saya tidak bisa karena persyaratan proyek saya. dan tolong beri contoh yang kedua.
Ahsan
0

Dan beberapa rangkaian:

from django import template
register = template.Library()


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

Dan di Templat:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
Gassan
sumber