วิธีการเชื่อมสตริงในเทมเพลต django


191

ฉันต้องการเชื่อมสตริงในแท็กเทมเพลต Django เช่น:

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

นี่shop_nameคือตัวแปรของฉันและฉันต้องการเชื่อมต่อกับส่วนที่เหลือของเส้นทาง

สมมติว่าฉันมีและฉันต้องการที่จะขยายผลให้เกิดshop_name=example.comshop/example.com/base.html

คำตอบ:


380

ใช้กับ:

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

2
ฉันสับสนอย่างสิ้นเชิงกับคำตอบนี้เนื่องจากใช้แท็กรวมแทนแท็กขยาย แต่ดูเหมือนว่าจะใช้ได้ แม้ว่าฉันจะแนะนำคำตอบของ Ahsan ในขณะที่มันใช้งานได้และเป็น (ในความคิดของฉัน) ถูกต้องมากขึ้น semantically และทำให้เกิดความสับสนน้อยลง
gitaarik

15
สิ่งนี้อาจใช้งานได้ แต่ไม่ควรถือเป็นคำตอบทั่วไปในการต่อสตริงในแม่แบบ django ดูstackoverflow.com/a/23783666/781695
ผู้ใช้

ดังที่กล่าวไว้ในเอกสารประกอบของ Django "สตริงที่สามารถรวมกับจำนวนเต็มจะถูกรวมเข้าด้วยกันไม่รวมเข้าด้วยกัน" ตัวอย่างเช่นหากคุณต้องการเชื่อมโยงคีย์หลักของโมเดลวัตถุ (อาจเป็นประโยชน์สำหรับการสร้างแคชคีย์ที่ไม่ซ้ำกัน) งาน.
zen11625

ฉันคิดว่ามันไม่รอดshop_nameเลยดังนั้นมันอันตราย
Flimm

ระวังให้ดีดังที่กล่าวมาแล้วใช้งานได้กับสตริงเท่านั้น! ถ้าคุณแปลshop_nameก่อนที่จะผ่านมันให้เข้ากับบริบทในมุมมองของget_context_dataให้แน่ใจว่าจะได้รับการแปลโดยใช้แทนugettext ugettext_lazy
Kim

111

อย่าใช้addสำหรับสตริงคุณควรกำหนดแท็กที่กำหนดเองดังนี้:

สร้างไฟล์: <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)

จากนั้นใช้เป็น @Steven พูด

{% load <appname>_extras %}

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

เหตุผลในการหลีกเลี่ยงadd:

ตามเอกสาร

ตัวกรองนี้จะเป็นครั้งแรกพยายามที่จะบีบบังคับให้ทั้งสองค่าจำนวนเต็ม ... สายที่สามารถบังคับให้จำนวนเต็มจะสรุปไม่ได้ตัดแบ่ง ...

หากตัวแปรทั้งคู่เป็นจำนวนเต็มผลลัพธ์จะไม่คาดคิด


ไม่ควรเป็น @ register.filter (name = 'addstr') ใช่ไหม
seddonym

6
สิ่งนี้ควรถูกทำเครื่องหมายว่าเป็นคำตอบที่ดีที่สุดเพราะทำงานอย่างถูกต้องกับค่าที่สามารถใช้บังคับกับ Python เป็นจำนวนเต็ม
zen11625

2
ผมไม่รู้ว่าทำไมคุณไม่ได้หนึ่งที่มีมากที่สุด "ขึ้น" เพราะมันเป็นของคุณคำตอบที่ถูกต้องที่ " add" เพียงคนเดียวที่ไม่ได้ใช้str()ในสถานที่แรกและไม่ได้ทำงานที่ทุกคนสำหรับฉันในขณะที่วิธีการแก้ปัญหาของคุณทำงานไม่มีที่ติ
Olivier Pons

1
คำตอบของคุณช่วยฉันไว้!
Ljubisa Livac

6
อย่าลืมโหลดตัวกรองที่กำหนดเองของคุณที่ด้านบนของไฟล์เทมเพลตของคุณ:{% load <appname>_extras %}
Susanne Peng

13

ฉันเปลี่ยนลำดับชั้นของโฟลเดอร์แล้ว

/shop/shop_name/base.html ถึง /shop_name/shop/base.html

แล้วด้านล่างจะทำงาน

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

ตอนนี้มันสามารถที่จะขยายหน้า base.html



3

มีลักษณะที่เป็นตัวกรองadd

แก้ไข: "shop/"|add:shop_name|add:"/base.html"คุณสามารถกรองโซ่เพื่อให้คุณสามารถทำ แต่นั่นไม่ได้ผลเพราะมันขึ้นอยู่กับเทมเพลตแท็กเพื่อประเมินตัวกรองในการโต้แย้งและการขยายไม่ได้

ฉันเดาว่าคุณไม่สามารถทำได้ภายในเทมเพลต


สิ่งนี้จะไม่ทำงาน ฉันต้องการเพิ่มตัวแปรของฉันในเส้นทางกลาง
Ahsan

เพิ่มตัวกรองเท่านั้นที่สรุปไม่รวมกันตามเอกสาร django
Ahsan

เอกสารพูดว่า "สตริงที่สามารถรวมกับจำนวนเต็มจะถูกรวมไว้" สตริงอื่น ๆ ถูกต่อกัน แต่นั่นไม่สำคัญเลยเพราะคุณไม่สามารถใช้ตัวกรอง :(
Daniel Hepper

2

จากเอกสาร:

แท็กนี้สามารถใช้ได้สองวิธี:

  • {% extends "base.html" %} (พร้อมเครื่องหมายคำพูด) ใช้ค่าตัวอักษร "base.html" เป็นชื่อของแม่แบบแม่แบบเพื่อขยาย
  • {% extends variable %}ใช้ค่าของตัวแปร หากตัวแปรประเมินเป็นสตริง Django จะใช้สตริงนั้นเป็นชื่อของแม่แบบแม่แบบ หากตัวแปรประเมินเป็นวัตถุแม่แบบ Django จะใช้วัตถุนั้นเป็นแม่แบบหลัก

ดังนั้นดูเหมือนว่าคุณไม่สามารถใช้ตัวกรองเพื่อจัดการกับข้อโต้แย้ง ในมุมมองการโทรคุณต้องสร้างอินสแตนซ์ของเทมเพลตบรรพบุรุษหรือสร้างตัวแปรสตริงด้วยเส้นทางที่ถูกต้องและส่งผ่านกับบริบท


1

@ คำตอบของ error คือพื้นฐานที่ถูกต้องคุณควรใช้เทมเพลตแท็กสำหรับสิ่งนี้ อย่างไรก็ตามฉันชอบแท็กเทมเพลตทั่วไปที่ฉันสามารถใช้เพื่อดำเนินการใด ๆ ที่คล้ายกับสิ่งนี้:

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

และจากนั้นคุณสามารถใช้มันในเทมเพลตของคุณ:

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

ตามที่กล่าวถึงความคิดเห็นแท็กแม่แบบนี้มีประโยชน์อย่างยิ่งสำหรับข้อมูลที่สามารถทำซ้ำได้ตลอดทั้งแม่แบบ แต่ต้องใช้ตรรกะและสิ่งอื่น ๆ ที่จะทำให้แม่แบบของคุณพังหรือในกรณีที่คุณต้องการใช้ข้อมูลที่ส่งระหว่างแม่แบบผ่านบล็อกอีกครั้ง

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

แล้ว:

<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 มีกำหนดที่นี่: https://www.djangosnippets.org/snippets/545/


1

ฉันพบว่าการทำงานกับ{% with %}แท็กนั้นค่อนข้างยุ่งยาก ฉันสร้างเทมเพลตแท็กต่อไปนี้ซึ่งควรทำงานกับสตริงและจำนวนเต็มแทน

from django import template

register = template.Library()


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

จากนั้นโหลดแท็กแม่แบบในแม่แบบของคุณที่ด้านบนโดยใช้สิ่งต่อไปนี้:

{% load concat_string %}

จากนั้นคุณสามารถใช้วิธีดังต่อไปนี้:

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

โดยส่วนตัวแล้วฉันคิดว่านี่เป็นสิ่งที่ดีกว่าที่จะทำงานด้วย


0

คุณไม่สามารถปรับเปลี่ยนตัวแปรในแม่แบบ django ได้ คุณมีสองตัวเลือกไม่ว่าจะเป็นการเขียนแท็กแม่แบบของคุณเองหรือทำสิ่งนี้ในมุมมอง


ความต้องการของฉันคือการทำในแม่แบบเท่านั้นดังนั้นตัวเลือกมุมมองจะไม่เป็นประโยชน์ ฉันพยายามผ่านแท็กแม่แบบที่กำหนดเอง แต่ {% load concat%} ควรอยู่หลังแท็ก {% expand .... %} ดังนั้นฉันจะทำตอนนี้ได้อย่างไร
Ahsan

เขียนแท็ก Extended_extends ซึ่งยอมรับรูปแบบสตริงและอาร์กิวเมนต์
เปาโล Scardine

คุณช่วยยกตัวอย่างวิธีเขียนแท็กที่กำหนดเองสำหรับแท็กเริ่มต้นได้ไหม
Ahsan

0

extendsไม่มีสิ่งอำนวยความสะดวกสำหรับสิ่งนี้ วางพา ธ เทมเพลตทั้งหมดในตัวแปรบริบทและใช้หรือคัดลอกเทมเพลตแท็กที่มีอยู่และแก้ไขให้เหมาะสม


ขอบคุณสำหรับการตอบกลับ! สำหรับตัวแปรบริบทฉันต้องตั้งค่าใน view.py ซึ่งฉันไม่สามารถทำได้เนื่องจากความต้องการโครงการของฉัน และโปรดยกตัวอย่างของสอง
Ahsan

0

และการต่อข้อมูลหลายรายการ:

from django import template
register = template.Library()


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

และในแม่แบบ:

{% concat_all 'x' 'y' another_var as string_result %}
concatenated string: {{ string_result }}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.