主頁 > 後端開發 > 模板之自定義標簽、過濾器

模板之自定義標簽、過濾器

2020-09-19 06:13:06 後端開發

自動轉義HTML

當從模版中生成HTML檔案時,總會存在各種風險,比如xss代碼注入等惡意攻擊,比如下面的模版片段:

Hello, {{ name }}

首先,它看起來像是無害的,用來顯示用戶的名字,但是設想一下,如果用戶像下面這樣輸入他的名字,會發生什么:

<script>alert('hello')</script>

使用這個名字的值,模版將會被渲染成這樣:

Hello, <script>alert('hello')</script>

這意味著瀏覽器會彈出一個JavaScript警報框!

顯然,用戶提交的資料都被不應該被盲目的信任,并且被直接插入到網頁中,因為一個懷有惡意的用戶可能會使用這樣的漏洞來做一些壞事, 這種型別的安全問題被叫做跨站腳本攻擊(Cross Site Scripting)(XSS),

為避免這個問題,有兩個選擇:

  • 第一,對每個不被信任的值運行escape過濾器,這將把潛在的有害的HTML字符轉換成無害的字串,在Django最初的幾年里,這是默認的解決方案,但問題是它將責任放在開發人員/模板作者身上,以確保轉義了所有內容,而且很容易忘記轉義資料,
  • 第二,利用Django的自動HTML轉義功能,默認情況下,Django中的每個模板會自動轉義每個變數,也就是說,下面五個字符將被轉義:
    • <會轉換為<
    • >會轉換為>
    • '(單引號)轉換為'
    • "(雙引號)會轉換為"
    • &會轉換為&

建議:將第二種功能做為默認打開的設定,

但是,有時,模板變數含有一些你打算渲染成原始HTML的資料,你并不想轉義這些內容, 例如,你可能會在資料庫中儲存一些HTML代碼,并且直接在模板中嵌入它們,有以下解決方法:

對于單個變數

使用safe過濾器來關閉變數上的自動轉義:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

對于模板塊:

要控制模板上的自動轉義,將模板(或者模板中的特定區域)包裹在autoescape標簽中,像這樣:

{% autoescape off %}
    Hello {{ name }}
{% endautoescape %}

autoescape標簽接受on或者off作為它的引數,下面是一個模板的示例:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
    This will not be auto-escaped: {{ data }}.

    Nor this: {{ other_data }}
    {% autoescape on %}
        Auto-escaping applies again: {{ name }}
    {% endautoescape %}
{% endautoescape %}

自動轉義標簽autoescape還會作用于擴展(extend)了當前模板的模板,以及通過include標簽包含的模板,就像所有block標簽那樣, 看下面的例子:

# base.html檔案

{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}

# child.html檔案

{% extends "base.html" %}
{% block title %}This &amp; that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

由于自動轉義標簽在base模板中關閉,它也會在child模板中關閉,導致當greeting變數含有Hello!字串時,會渲染HTML,

過濾器的字串引數:

過濾器的引數可以是字串:

{{ data|default:"This is a string literal." }}

要注意,所有這種字串引數在插入模板時都不會進行任何自動轉義,模板的作者可以控制字串字面值的內容,可以確保在模板撰寫時文本經過正確轉義,即對自己傳遞的引數心里要有數,

{{ data|default:"3 &lt; 2" }}  # 正確的做法

{{ data|default:"3 < 2" }}     # 錯誤的做法

方法呼叫

大多數物件上的方法呼叫同樣可用于模板中,這意味著模板能夠訪問到的不僅僅是物件的屬性(比如欄位名稱)和視圖中傳入的變數,還可以執行物件的方法,例如:QuerySets提供了count()方法來計算含有物件的總數,因此,你可以像這樣獲取所有關于當前任務的評論總數:

{{ task.comment_set.all.count }}

還可以訪問已經顯式定義在模型上的方法:

# models.py
class Task(models.Model):
    def foo(self):
        return "bar"
template.html
{{ task.foo }}

由于Django有意限制了模板語言中的處理邏輯,不能夠在模板中傳遞引數來呼叫方法,資料應該在視圖中處理,然后傳遞給模板用于展示,

多對多呼叫

對于如下的模型:

from django.db import models

# Create your models here.

class Student(models.Model):
    name = models.CharField(max_length=128)

class Course(models.Model):
    name = models.CharField(max_length=128)
    students = models.ManyToManyField('Student')

模型Course有一個多對多欄位指向Student模型,

正向查詢

假設撰寫了一個如下的視圖:

def test(request):
    course = models.Course.objects.get(pk=1)        #pk:有主鍵的欄位
    return render(request, 'course.html', locals())

獲取了id為1的course物件,并將它傳遞給course.html模版,模版代碼如下:

{% for student in course.students.all %}

<p>{{ student.name }}</p>

{% endfor %}

首先通過course.students.all,查尋到course物件關聯的students物件集,然后用for標簽回圈它,獲取每個student物件,再用student模型的定義,訪問其各個欄位的屬性,

反向查詢

對于反向查詢,從student往course查,假設有如下的視圖:

def test2(request):
    student = models.Student.objects.get(pk=1)
    return render(request, 'student.html', locals())

獲取了id為1的student物件,并將它傳遞給student.html模版,模版代碼如下:

{% for course in  student.course_set.all %}
{{ course.name }}
{% endfor %}

通過student.course_set.all,反向獲取到student實體對應的所有course物件,然后再for標簽回圈每個course,呼叫course的各種欄位屬性,

對于外鍵ForeignKey,其用法基本類似,只不過正向是obj.fk,且只有1個對像,不是集合,反向則是obj.fk_set,類似多對多,

定義標簽和過濾器

Django為我們提供了自定義的機制,可以通過使用Python代碼,自定義標簽和過濾器來擴展模板引擎,然后使用{% load %}標簽,

前置步驟

Django對于自定義標簽和過濾器是有前置要求的,首先一條就是代碼布局和檔案組織:你可以為你的自定義標簽和過濾器新開一個app,也可以在原有的某個app中添加,

  1. 在app中新建一個templatetags名字固定,不能變),和views.py、models.py等檔案處于同一級別目錄下,不要忘記創建__init__.py檔案以使得該目錄可以作為Python的

  2. 在添加templatetags包后,需要重新啟動服務器,然后才能在模板中使用標簽或過濾器,

  • 將你自定義的標簽和過濾器將放在templatetags包下的一個模塊里,
  • 這個模塊的名字是后面載入標簽時使用的標簽名,所以要謹慎的選擇名字以防與Django內置的或其他應用下的(自定義)標簽和過濾器名字沖突,

假設你自定義的標簽/過濾器在一個名為poll_extras.py的檔案中:

polls/
    __init__.py
    models.py
    templatetags/
        __init__.py
        poll_extras.py
    views.py

為了讓{% load xxx %}標簽正常作業,包含自定義標簽的app必須在INSTALLED_APPS中注冊,然后就可以在模板中像如下這樣使用:

{% load poll_extras %}

在templatetags包中放多少個模塊沒有限制,{% load xxx %}將會載入給定模塊名中的標簽/過濾器,而不是app中所有的標簽和過濾器,

要在模塊內自定義標簽,首先,這個模塊必須包含一個名為register的變數,它是template.Library的一個實體,所有的標簽和過濾器都是在其中注冊的, 所以把如下的內容放在你的模塊的頂部:

from django import template

register = template.Library()

友情提示:可以閱讀Django的默認過濾器和標記的源代碼,它們分別位于django/template/defaultfilters.pydjango/template/defaulttags.py中,它們是最好的范例,

自定義過濾器

自定義過濾器就是一個帶有一個或兩個引數的Python函式,這個Python函式的第一個引數要過濾的物件,第二個引數才是自定義的引數,而且最多總共只能有兩個引數,所以你只能自定義一個引數,

  • 變數的值:不一定是字串形式,
  • 引數的值:可以有一個初始值,或者完全不要這個引數,

由于模板語言沒有提供例外處理,任何從過濾器中拋出的例外都將會顯示為服務器錯誤

下面是一個定義過濾器的例子:

def cut(value, arg):
    """將value中的所有arg部分切除掉"""
    return value.replace(arg, '')

下面是這個過濾器的使用方法:

{{ somevariable|cut:"0" }}

大多數過濾器沒有引數,但基本的value引數是必帶的,例如:

def lower(value): # Only one argument.
    """Converts a string into all lowercase"""
    return value.lower()
注冊過濾器

類原型:django.template.Library.filter()

好了過濾器函式,就需要注冊它,有兩種方法:

  1. 方法是呼叫register.filter,比如:
register.filter('cut', cut)
register.filter('lower', lower)

Library.filter()方法需要兩個引數:

  • 過濾器的名稱:一個字串物件
  • 編譯的函式 :撰寫的過濾器函式
  1. register.filter()用作裝飾器,以如下的方式注冊過濾器:
@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg, '')

@register.filter        #沒有宣告name引數,Django將使用函式名作為過濾器的名字,
def lower(value):
    return value.lower()

自定義標簽

Django提供了大量的快捷方式,使得撰寫標簽比較容易, 對于一般的自定義標簽來說,simple_tag是最重要的,它幫助你將一個Python函式注冊為一個簡單的模版標簽,

simple_tag

原型:django.template.Library.simple_tag()

為了簡單化模版標簽的創建,Django提供一個輔助函式simple_tag,這個函式是django.template.Library的一個方法,

具體的撰寫方法:

  1. 在settings中的INSTALLED_APPS配置當前app,不然django無法找到自定義的simple_tag,

  2. 在app中創建templatetags模塊(模塊名只能是templatetags),

  3. 創建任意 .py 檔案,如:my_tags.py

  4. 在使用自定義simple_tag和filter的html檔案中匯入之前創建的 my_tags.py,{% load my_tags %} 

from django import template

register = template.Library()   #register的名字是固定的,不可改變

@register.filter
def filter_multi(v1,v2):
    return  v1 * v2

@register.simple_tag       # 和自定義filter類似,只不過接收更靈活的引數,沒有個數限制,
def simple_tag_multi(v1,v2):
    return  v1 * v2


呼叫:
-------------------------------.html
{% load xxx %}  
# num=12
{{ num|filter_multi:2 }} # 24

{% simple_tag_multi num 5 %}  # 引數不限,但不能放在if、for陳述句中

注意:filter可以用在iffor等陳述句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

比如,我們想撰寫一個回傳當前時間的模版標簽,那么current_time函式從而可以這樣寫︰

import datetime
from django import template

register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)

關于simple_tag函式有幾件值得注意的事項︰

如果不需要額外的轉義,可以使用mark_safe()讓輸出不進行轉義,前提是你絕對確保代碼中不包含XSS漏洞, 如果要創建小型HTML片段,強烈建議使用format_html()而不是mark_safe()

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改變

@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

如果模板標簽需要訪問當前背景關系,可以在注冊標簽時使用takes_context引數︰

@register.simple_tag(takes_context=True)
def current_time(context, format_string):    # 一個引數必須稱作context
    timezone = context['timezone']        
    return your_get_current_time_method(timezone, format_string)

如果你需要重命名你的標簽,可以給它提供自定義的名稱︰

register.simple_tag(lambda x: x - 1, name='minusone')

或:
@register.simple_tag(name='minustwo')
def some_function(value):
    return value - 2

simple_tag函式可以接受任意數量的位置引數和關鍵字引數

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
    warning = kwargs['warning']
    profile = kwargs['profile']
    ...
    return ...

然后在模板中,可以將任意數量的由空格分隔的引數傳遞給模板標簽,關鍵字引數的值使用等號("=")賦予,并且必須在位置引數之后提供, 例子:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

可以將標簽結果存盤在模板變數中,而不是直接輸出,這是通過使用as引數后跟變數名來實作的:

{% current_time "%Y-%m-%d %I:%M %p" as the_time %}
<p>The time is {{ the_time }}.</p>

渲染組件

inclusion_tag

原型:django.template.Library.inclusion_tag()

另一種常見型別的模板標簽是通過渲染一個模板來顯示一些資料,例如,Django的Admin界面使用自定義模板標簽顯示"添加/更改"表單頁面底部的按鈕,這些按鈕看起來總是相同,但鏈接的目標卻是根據正在編輯的物件而變化的,這種型別的標簽被稱為"Inclusion 標簽",多用于回傳html代碼片段,

例:

#templatetags/inclusion_tag_test.py
from django import template

register = template.Library()

@register.inclusion_tag('result.html')  #將result.html里面的內容用下面函式的回傳值渲染,然后作為一個組件一樣,加載到使用這個函式的html檔案里面,
def show_results(n):             # 引數可以傳多個進來
    n = 1 if n < 1 else int(n)
    data = ["第{}項".format(i) for i in range(1, n+1)]
    return {"data": data}        # 這里可以傳多個值,

# templates/snippets/result.html
<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>

# templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>inclusion_tag test</title>
</head>
<body>
{% load inclusion_tag_test %}

{% show_results 10 %}  
</body>
</html>

注冊有兩種方法:

# 通過呼叫Library物件的inclusion_tag()裝飾器方法創建并注冊Inclusion標簽︰
@register.inclusion_tag('results.html')     # results.html要渲染的html檔案,
def show_results(poll):
    ...

# 也可以不用裝飾器方法:django.template.Template實體注冊Inclusion標簽︰
from django.template.loader import get_template
t = get_template('results.html')
register.inclusion_tag(t)(show_results)

inclusion_tag函式可以接受任意數量的位置引數和關鍵字引數,像這樣:

@register.inclusion_tag('my_template.html')
def my_tag(a, b, *args, **kwargs):
    warning = kwargs['warning']
    profile = kwargs['profile']
    ...
    return ...

然后在模板中,可以將任意數量的由空格分隔的引數傳遞給模板標簽,關鍵字引數的值的設定使用等號("=") ,并且必須在位置引數之后提供,例如:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

可以在標簽中傳遞背景關系中的引數,比如說,當你想要將背景關系context中的home_linkhome_title這兩個變數傳遞給模版, 如下所示:

@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
    return {
        'link': context['home_link'],
        'title': context['home_title'],
    }

注意函式的第一個引數必須叫做context,context必須是一個字典型別,

register.inclusion_tag()這一行,我們指定了takes_context=True和模板的名字,模板link.html很簡單,如下所示:

Jump directly to <a href=https://www.cnblogs.com/wby-110/p/"{{ link }}">{{ title }}</a>.

然后,當任何時候你想呼叫這個自定義的標簽時,只需要load它本身,不需要添加任何引數,{{ link }}{{ title }}會自動從標簽中獲取引數值,像這樣:

{% jump_link %}

使用takes_context=True,就表示不需要傳遞引數給這個模板標簽,它會自己去獲取背景關系,

或者使用django.template.Template實體注冊Inclusion標簽︰

from django.template.loader import get_template
t = get_template('results.html')
register.inclusion_tag(t)(show_results)

使用自定義標簽和過濾器

某些應用提供了自定義的標簽和過濾器,想要在模板中使用它們,首先要確保該應用已經在INSTALLED_APPS 中(比如在下面的例子中,添加了'django.contrib.humanize'),之后在模板中使用load標簽:

{% load humanize %}
{{ 45000|intcomma }}

上面的例子中, load標簽加載了humanizeapp的標簽庫,之后我們可以使用它的intcomma過濾器,

開啟django.contrib.admindocs查詢admin站點中的檔案,便可以查看安裝的自定義庫串列,

load標簽可以同時接受多個庫名稱,由空格分隔, 例如:

{% load humanize i18n %}

自定義庫和模板繼承:

當你加載一個自定義標簽或過濾器庫時,標簽或過濾器只在當前模板中有效--并不是帶有模板繼承關系的任何父模板或者子模版中都有效,即在父模板中加載了自定義標簽,子模版中還要再加載一次,

例如,如果一個模板foo.html帶有{% load humanize %},子模版(例如,帶有{% extends "foo.html" %})中不能訪問humanize模板標簽和過濾器, 子模版需要再添加自己的{% load humanize %}

這個特性是出于保持可維護性和邏輯性的目的,

配置模板引擎

模板引擎通過settings中的TEMPLATES設定來配置,串列中每個元素都是一個引擎配置字典,由startproject命令生成的settings.py會自定定義如下的值:

TEMPLATES = [
    {
        'BACKEND''django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS'True,
        'OPTIONS': {
            # ... some options here ...
        },
    },
]

# BACKEND:后端,內置的后端有django.template.backends.django.DjangoTemplates和django.template.backends.jinja2.Jinja2,

OPTIONS中包含了具體的后端設定,

由于絕大多數引擎都是從檔案加載模板的,所以每種模板引擎都包含兩項通用設定:

  • DIRS:定義了一個目錄串列,模板引擎按串列順序搜索這些目錄以查找模板源檔案,
  • APP_DIRS:告訴模板引擎是否應該進入每個已安裝的應用中查找模板,通常將該選項保持為True,

每種模板引擎后端都定義了一個慣用的名稱作為應用內部存放模板的子目錄名稱,(例如Django為它自己的模板引擎指定的是 ‘templates’,為jinja2指定的名字是‘jinja2’),尤其是,django允許你有多個模板引擎后端實體,且每個實體有不同的配置選項, 在這種情況下必須為每個配置指定一個唯一的NAME ,

DTL引擎的OPTIONS配置項中接受以下引數:

  • autoescape:一個布林值,用于控制是否啟用HTML自動轉義功能,默認為True,
  • context_processors: 以"."為分隔符的Python呼叫路徑的串列,默認是個空串列,
  • debug:打開/關閉模板除錯模式的布林值,默認和setting中的DEBUG有相同的值,
  • loaders:模板加載器類的虛擬Python路徑串列,默認值取決于DIRS和APP_DIRS的值,
  • string_if_invalid:非法變數時輸出的字串,默認為空字串,
  • file_charset:用于讀取磁盤上的模板檔案的字符集編碼,默認為FILE_CHARSET的值,
  • libraries:用于注冊模板引擎, 這可以用于添加新的庫或為現有庫添加備用標簽,
  • builtins:以圓點分隔的Python路徑的串列,

簡單的用法

django.template.loader中定義了兩個函式以加載模板,

get_template(template_name,using = None)[source]

該函式使用給定的名稱查找和加載模板,并回傳一個Template物件,

模板的查找和加載機制取決于每種后端引擎和配置,如果想使用指定的模板引擎進行查找,請將模板引擎的NAME賦給get_template的using引數,

select_template(template_name_list,using = None)[source]

和get_template()相似, 只不過它使用包含模板名稱的串列作為引數,

select_template()get_template()回傳的Template物件都必須提供一個render()方法,如下所示:

Template.render(context=None, request=None)

通過給定的context對該模板進行渲染,

如果提供了context,那么它必須是一個dict物件,如果要提供request引數 ,必須使用HttpRequest物件,

針對下面的TEMPLATES配置,對模版檔案的搜索順序和路徑如下:

TEMPLATES = [
    {
        'BACKEND''django.template.backends.django.DjangoTemplates',
        'DIRS': [
            '/home/html/example.com',
            '/home/html/default',
        ],
    },
    {
        'BACKEND''django.template.backends.jinja2.Jinja2',
        'DIRS': [
            '/home/html/jinja2',
        ],
    },
]

如果你呼叫函式get_template('story_detail.html'), Django將按以下順序查找story_detail.html

/home/html/example.com/story_detail.html('django'引擎)
/home/html/default/story_detail.html('django'引擎)
/home/html/jinja2/story_detail.html('jinja2'引擎)

如果你呼叫函式select_template(['story_253_detail.html','story_detail.html']),Django按以下順序查找:

/home/html/example.com/story_253_detail.html('django'引擎)
/home/html/default/story_253_detail.html('django'引擎)
/home/html/jinja2/story_253_detail.html('jinja2'引擎)
/home/html/example.com/story_detail.html('django'引擎)
/home/html/default/story_detail.html('django'引擎)
/home/html/jinja2/story_detail.html('jinja2'引擎)

注意:Django查找到任何一個匹配的模板后便停止搜尋,所以這是個類似url搜索的短路操作!

建議在每個APP的的模版子目錄下都建立一個子目錄來唯一對應這個APP,這樣做可以增強APP的可用性, 將所有的模版檔案放在根模版目錄下會引發混淆,

要在一個子目錄內加載模板,像下面這樣:

get_template('news/story_detail.html')

如果結合上面例子中的TEMPLATES配置,這將會嘗試按順序查找并加載下列模板︰

/home/html/example.com/news/story_detail.html('django'引擎)
/home/html/default/news/story_detail.html('django'引擎)
/home/html/jinja2/news/story_detail.html('jinja2'引擎)

另外,為了減少加載模板、渲染模板等重復作業,django提供了處理這些作業的快捷函式,

render_to_string(template_name, context=None, request=None, using=None)[source]

render_to_string()會像get_template()一樣加載模板并立即呼叫render()方法, 它需要以下引數,

  • TEMPLATE_NAME:要加載的模板的名稱或串列,
  • context:要用作模板的背景關系進行渲染的資料字典,也就是你要插入的動態資料字典,
  • request:可選的HttpRequest物件,
  • using:指定使用的模板引擎NAME, 搜索模板將僅限于該引擎,

用法示例:

from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo''bar'})

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/79396.html

標籤:Python

上一篇:Git入門

下一篇:04爬取拉勾網Python崗位分析報告

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more