The Django Book

Chapter 11: Generating Non-HTML Content

绗崄涓绔 杈撳嚭闈濰TML鍐呭

Usually when we talk about developing Web sites, were talking about producing HTML. Of course, theres a lot more to the Web than HTML; we use the Web to distribute data in all sorts of formats: RSS, PDFs, images, and so forth.

閫氬父褰撴垜浠皥鍒板紑鍙戠綉绔欐椂锛屼富瑕佽皥璁虹殑鏄疕TML銆傚綋鐒讹紝Web杩滀笉鍙湁HTML锛屾垜浠湪Web涓婄敤澶氱鏍煎紡鏉ュ彂甯冩暟鎹細RSS銆丳DF銆佸浘鐗囩瓑銆

So far weve focused on the common case of HTML production, but in this chapter well take a detour and look at using Django to produce other types of content.

鍒扮洰鍓嶄负姝紝鎴戜滑鐨勬敞鎰忓姏閮芥槸鏀惧湪甯歌 HTML 浠g爜鐢熸垚涓婏紝浣嗘槸鍦ㄨ繖涓绔犱腑锛屾垜浠皢浼氬浣跨敤 Django 鐢熸垚鍏跺畠鏍煎紡鐨勫唴瀹硅繘琛岀畝瑕佷粙缁嶃

Django has convenient built-in tools that you can use to produce some common non-HTML content:

Django鎷ユ湁涓浜涗究鍒╃殑鍐呭缓宸ュ叿甯姪浣犵敓鎴愬父瑙佺殑闈濰TML鍐呭锛

  • RSS/Atom syndication feeds

  • RSS/Atom 鑱氬悎鏂囦欢

  • Sitemaps (an XML format originally developed by Google that gives hints to search engines)

  • 绔欑偣鍦板浘 锛堜竴涓猉ML鏍煎紡鏂囦欢锛屾渶鍒濈敱Google寮鍙戯紝鐢ㄤ簬缁欐悳绱㈠紩鎿庢彁绀虹嚎绱級

Well examine each of those tools a little later on, but first well cover the basic principles.

鎴戜滑绋嶅悗浼氶愪竴鐮旂┒杩欎簺宸ュ叿锛屼笉杩囬鍏堣鎴戜滑鏉ヤ簡瑙d簺鍩虹鍘熺悊銆

The basics: views and MIME-types

鍩虹: 瑙嗗浘鍜孧IME绫诲瀷

Remember this from Chapter 3?

杩樿寰楃涓夌珷鐨勫唴瀹瑰悧锛

A view function, or view for short, is simply a Python function that takes a Web request and returns a Web response. This response can be the HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an imageor anything, really.

涓涓鍥惧嚱鏁帮紙view function锛夛紝鎴栬呯畝绉 view 锛屽彧涓嶈繃鏄竴涓彲浠ュ鐞嗕竴涓猈eb璇锋眰骞朵笖杩斿洖 涓涓猈eb鍝嶅簲鐨凱ython鍑芥暟銆傝繖涓搷搴斿彲浠ユ槸涓涓猈eb椤甸潰鐨凥TML鍐呭锛屾垨鑰呬竴涓烦杞紝鎴栬呬竴涓404 閿欒锛屾垨鑰呬竴涓猉ML鏂囨。锛屾垨鑰呬竴骞呭浘鐗囷紝鎴栬呮槧灏勫埌浠讳綍涓滆タ涓娿

More formally, a Django view function must

鏇存寮忕殑璇达紝涓涓狣jango瑙嗗浘鍑芥暟 蹇呴』

  • Accept an HttpRequest instance as its first argument

  • 鎺ュ彈涓涓 HttpRequest 瀹炰緥浣滀负瀹冪殑绗竴涓弬鏁

  • Return an HttpResponse instance

  • 杩斿洖涓涓 HttpResponse 瀹炰緥

The key to returning non-HTML content from a view lies in the HttpResponse class, specifically the mimetype constructor argument. By tweaking the MIME type, we can indicate to the browser that weve returned a response of a different format.

浠庝竴涓鍥捐繑鍥炰竴涓潪 HTML 鍐呭鐨勫叧閿槸鍦ㄦ瀯閫犱竴涓 HttpResponse 绫绘椂锛岄渶瑕佹寚瀹 mimetype 鍙傛暟銆傞氳繃鏀瑰彉 MIME 绫诲瀷锛屾垜浠彲浠ュ憡鐭ユ祻瑙堝櫒灏嗚杩斿洖鐨勬暟鎹槸鍙︿竴绉嶄笉鍚岀殑绫诲瀷銆

For example, lets look at a view that returns a PNG image. To keep things simple, well just read the file off the disk:

涓嬮潰鎴戜滑浠ヨ繑鍥炰竴寮燩NG鍥剧墖鐨勮鍥句负渚嬨備负浜嗕娇浜嬫儏鑳藉敖鍙兘鐨勭畝鍗曪紝鎴戜滑鍙槸璇诲叆涓寮犲瓨鍌ㄥ湪纾佺洏涓婄殑鍥剧墖锛

from django.http import HttpResponse

def my_image(request):
    image_data = open("/path/to/my/image.png", "rb").read()
    return HttpResponse(image_data, mimetype="image/png")

Thats it! If you replace the image path in the open() call with a path to a real image, you can use this very simple view to serve an image, and the browser will display it correctly.

灏辨槸杩欎箞绠鍗曘傚鏋滄敼鍙 open() 涓殑鍥剧墖璺緞涓轰竴寮犵湡瀹炲浘鐗囩殑璺緞锛岄偅涔堝氨鍙互浣跨敤杩欎釜鍗佸垎绠鍗曠殑瑙嗗浘鏉ユ彁渚涗竴寮犲浘鐗囷紝骞朵笖娴忚鍣ㄥ彲浠ユ纭殑鏄剧ず瀹冦

The other important thing to keep in mind is that HttpResponse objects implement Pythons standard file API. This means that you can use an HttpResponse instance in any place Python (or a third-party library) expects a file.

鍙﹀鎴戜滑蹇呴』浜嗚В鐨勬槸”HttpResponse”瀵硅薄搴旂敤浜哖ython鏍囧噯鐨勬枃浠跺簲鐢ㄧ▼搴忔帴鍙(API)銆傝繖灏辨槸璇翠綘鍙互鍦≒ython锛堟垨绗笁鏂瑰簱锛変换浣曠敤鍒版枃浠剁殑鍦版柟浣跨敤”HttpResponse”瀹炰緥銆

For an example of how that works, lets take a look at producing CSV with Django.

涓嬮潰灏嗙敤 Django 鐢熸垚 CSV 鏂囦欢涓轰緥锛岃鏄庡畠鐨勫伐浣滃師鐞嗐

Producing CSV

鐢熸垚 CSV 鏂囦欢

CSV is a simple data format usually used by spreadsheet software. Its basically a series of table rows, with each cell in the row separated by a comma (CSV stands for comma-separated values ). For example, heres some data on unruly airline passengers in CSV format:

CSV 鏄竴绉嶇畝鍗曠殑鏁版嵁鏍煎紡锛岄氬父涓虹數瀛愯〃鏍艰蒋浠舵墍浣跨敤銆傚畠涓昏鏄敱涓绯诲垪鐨勮〃鏍艰缁勬垚锛屾瘡琛屼腑鍗曞厓鏍间箣闂翠娇鐢ㄩ楀彿(CSV 鏄 閫楀彿鍒嗛殧鏁板(comma-separated values) 鐨勭缉鍐)闅斿紑銆備緥濡傦紝涓嬮潰鏄互 CSV 鏍煎紡璁板綍鐨勪竴浜涜繚瑙勮埅鐝箻瀹㈢殑鏁版嵁銆

Year,Unruly Airline Passengers
1995,146
1996,184
1997,235
1998,200
1999,226
2000,251
2001,299
2002,273
2003,281
2004,304
2005,203

Note

澶囨敞

The preceding listing contains real numbers; they come courtesy of the US Federal Aviation Administration. See http://www.faa.gov/data_statistics/passengers_cargo/unruly_passengers/.

鍓嶉潰鐨勫垪琛ㄦ槸鐪熷疄鐨勬暟鎹紝鏁版嵁鐢辩編鍥借仈閭﹁埅绌虹鐞嗗鎻愪緵銆傚叿浣撳唴瀹硅鍙傝 http://www.faa.gov/data_statistics/passengers_cargo/unruly_passengers/.

Though CSV looks simple, its not a format thats ever been formally defined. Different pieces of software produce and consume different variants of CSV, making it a bit tricky to use. Luckily, Python comes with a standard CSV library, csv , that is pretty much bulletproof.

铏界劧 CSV 鐪嬩笂鍘荤畝鍗曪紝浠ヨ嚦浜庣畝鍗曞埌杩欎釜鏍煎紡鐢氳嚦閮芥病鏈夋寮忕殑瀹氫箟銆備絾鏄笉鍚岀殑杞欢浼氱敓鎴愬拰浣跨敤涓嶅悓鐨 CSV 鐨勫彉绉嶏紝鍦ㄤ娇鐢ㄤ笂浼氭湁涓浜涗笉渚裤傚垢杩愮殑鏄紝 Python 浣跨敤鐨勬槸鏍囧噯 CSV 搴擄紝 csv 锛屾墍浠ュ畠鏇撮氱敤銆

Because the csv module operates on file-like objects, its a snap to use an HttpResponse instead:

鍥犱负 csv 妯″潡鎿嶄綔鐨勬槸绫讳技鏂囦欢鐨勫璞★紝鎵浠ュ彲浠ヤ娇鐢 HttpResponse 鏇挎崲锛

import csv
from django.http import HttpResponse

# Number of unruly passengers each year 1995 - 2005. In a real application
# this would likely come from a database or some other back-end data store.
UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]

def unruly_passengers_csv(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = 'attachment; filename=unruly.csv'

    # Create the CSV writer using the HttpResponse as the "file"
    writer = csv.writer(response)
    writer.writerow(['Year', 'Unruly Airline Passengers'])
    for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):
        writer.writerow([year, num])

    return response

The code and comments should be pretty clear, but a few things deserve special mention:

浠g爜鍜屾敞閲婂彲浠ヨ鏄緢娓呮锛屼絾杩樻湁涓浜涗簨鎯呴渶瑕佺壒鍒敞鎰忥細

  • The response is given the text/csv MIME type (instead of the default text/html ). This tells browsers that the document is a CSV file.

  • 鍝嶅簲杩斿洖鐨勬槸 text/csv MIME绫诲瀷锛堣岄潪榛樿鐨 text/html 锛夈傝繖浼氬憡璇夋祻瑙堝櫒锛岃繑鍥炵殑鏂囨。鏄疌SV鏂囦欢銆

  • The response gets an additional Content-Disposition header, which contains the name of the CSV file. This header (well, the attachment part) will instruct the browser to prompt for a location to save the file (instead of just displaying it). This file name is arbitrary; call it whatever you want. It will be used by browsers in the Save As dialog.

  • 鍝嶅簲浼氭湁涓涓檮鍔犵殑 Content-Disposition 澶撮儴锛屽畠鍖呭惈鏈塁SV鏂囦欢鐨勬枃浠跺悕銆傝繖涓ご閮紙鎴栬呰锛岄檮鍔犻儴鍒嗭級浼氭寚绀烘祻瑙堝櫒寮瑰嚭瀵硅瘽妗嗚闂枃浠跺瓨鏀剧殑浣嶇疆锛堣屼笉浠呬粎鏄樉绀猴級銆傝繖涓枃浠跺悕鏄换鎰忕殑锛屽畠浼氱敤鍦ㄦ祻瑙堝櫒鐨勫彟瀛樹负瀵硅瘽妗嗕腑銆

  • Hooking into the CSV-generation API is easy: just pass response as the first argument to csv.writer . The csv.writer function expects a filelike object, and HttpResponse objects fit the bill.

  • 涓庡垱寤篊SV鐨勫簲鐢ㄧ▼搴忕晫闈紙API锛夋寕鎺ユ槸寰堝鏄撶殑锛氬彧闇灏 response 浣滀负绗竴涓彉閲忎紶閫掔粰 csv.writercsv.writer 鍑芥暟甯屾湜鑾峰緱涓涓枃浠剁被鐨勫璞★紝 HttpResponse 姝eソ鑳借揪鎴愯繖涓洰鐨勩

  • For each row in your CSV file, call writer.writerow , passing it an iterable object such as a list or tuple.

  • 璋冪敤 writer.writerow 锛屽苟涓斾紶閫掔粰瀹冧竴涓被浼 list 鎴栬 tuple 鐨勫彲杩唬瀵硅薄锛屽氨鍙互鍦 CSV 鏂囦欢涓啓鍏ヤ竴琛屻

  • The CSV module takes care of quoting for you, so you dont have to worry about escaping strings with quotes or commas in them. Just pass information to writerow() , and it will do the right thing.

  • CSV 妯″潡鑰冭檻鍒颁簡寮曠敤鐨勯棶棰橈紝鎵浠ユ偍涓嶇敤鎷呭績閫稿嚭瀛楃涓蹭腑寮曞彿鍜岄楀彿銆傚彧瑕佹妸淇℃伅浼犻掔粰 writerow() 锛屽畠浼氬鐞嗗ソ鎵鏈夌殑浜嬫儏銆

This is the general pattern youll use any time you need to return non-HTML content: create an HttpResponse response object (with a special MIME type), pass it to something expecting a file, and then return the response.

鍦ㄤ换浣曢渶瑕佽繑鍥為潪 HTML 鍐呭鐨勬椂鍊欙紝閮介渶瑕佺粡杩囦互涓嬪嚑姝ワ細鍒涘缓涓涓 HttpResponse 鍝嶅簲瀵硅薄锛堥渶瑕佹寚瀹氱壒娈婄殑 MIME 绫诲瀷锛夈傚皢瀹冧綔涓哄弬鏁颁紶缁欎竴涓渶瑕佹枃浠剁殑鏂规硶锛岀劧鍚庤繑鍥炶繖涓搷搴斻

Lets look at a few more examples.

涓嬮潰鏄竴浜涘叾瀹冪殑渚嬪瓙

Generating PDFs

鐢熸垚 PDF 鏂囦欢

Portable Document Format (PDF) is a format developed by Adobe thats used to represent printable documents, complete with pixel-perfect formatting, embedded fonts, and 2D vector graphics. You can think of a PDF document as the digital equivalent of a printed document; indeed, PDFs are usually used when you need to give a document to someone else to print.

渚挎惡鏂囦欢鏍煎紡 (PDF) 鏄敱 Adobe 寮鍙戠殑鏍煎紡锛屼富瑕佺敤浜庡憟鐜板彲鎵撳嵃鐨勬枃妗o紝鍖呭惈鏈 pixel-perfect 鏍煎紡锛屽祵鍏ュ瓧浣撲互鍙2D鐭㈤噺鍥惧儚銆侾DF 鏂囦欢鍙互琚涓烘槸涓浠芥墦鍗版枃妗g殑鏁板瓧绛変环鐗╋紱瀹為檯涓婏紝PDF 鏂囦欢閫氬父鐢ㄤ簬闇瑕佸皢鏂囨。浜や粯缁欏叾浠栦汉鍘绘墦鍗扮殑鍦哄悎銆

You can easily generate PDFs with Python and Django thanks to the excellent open source ReportLab library (http://www.reportlab.org/rl_toolkit.html). The advantage of generating PDF files dynamically is that you can create customized PDFs for different purposes say, for different users or different pieces of content.

渚挎惡鏂囦欢鏍煎紡 (PDF) 鏄敱 Adobe 寮鍙戠殑鏍煎紡锛屼富瑕佺敤浜庡憟鐜板彲鎵撳嵃鐨勬枃妗o紝鍖呭惈鏈 pixel-perfect 鏍煎紡锛屽祵鍏ュ瓧浣撲互鍙2D鐭㈤噺鍥惧儚銆侾DF 鏂囦欢鍙互琚涓烘槸涓浠芥墦鍗版枃妗g殑鏁板瓧绛変环鐗╋紱瀹為檯涓婏紝PDF 鏂囦欢閫氬父鐢ㄤ簬闇瑕佸皢鏂囨。浜や粯缁欏叾浠栦汉鍘绘墦鍗扮殑鍦哄悎銆

For example, we used Django and ReportLab at KUSports.com to generate customized, printer-ready NCAA tournament brackets.

涓嬮潰鐨勪緥瀛愭槸浣跨敤 Django 鍜 ReportLab 鍦 KUSports.com 涓婄敓鎴愪釜鎬у寲鐨勫彲鎵撳嵃鐨 NCAA 璧涚▼琛 (tournament brackets) 銆

Installing ReportLab

瀹夎 ReportLab

Before you do any PDF generation, however, youll need to install ReportLab. Its usually pretty simple: just download and install the library from http://www.reportlab.org/downloads.html.

鍦ㄧ敓鎴 PDF 鏂囦欢涔嬪墠锛岄渶瑕佸畨瑁 ReportLab 搴撱傝繖閫氬父鏄釜寰堢畝鍗曠殑杩囩▼锛氫粠 http://www.reportlab.org/downloads.html 涓嬭浇骞朵笖瀹夎杩欎釜搴撳嵆鍙

The user guide (naturally available only as a PDF file) at http://www.reportlab.org/rsrc/userguide.pdf has additional installation instructions.

浣跨敤鎵嬪唽锛堝師濮嬬殑鍙湁 PDF 鏍煎紡锛夊彲浠ヤ粠 http://www.reportlab.org/rsrc/userguide.pdf 涓嬭浇锛屽叾涓寘鍚湁涓浜涘叾瀹冪殑瀹夎鎸囧崡銆

Note

娉ㄦ剰

If youre using a modern Linux distribution, you might want to check your package management utility before installing ReportLab. Most package repositories have added ReportLab.

濡傛灉浣跨敤鐨勬槸涓浜涙柊鐨 Linux 鍙戣鐗堬紝鍒欏湪瀹夎鍓嶅彲浠ュ厛妫鏌ュ寘绠$悊杞欢銆傚鏁拌蒋浠跺寘浠撳簱涓兘鍔犲叆浜 ReportLab 銆

For example, if youre using the (excellent) Ubuntu distribution, a simple apt-get install python-reportlab will do the trick nicely.

姣斿锛屽鏋滀娇鐢紙鏉板嚭鐨勶級 Ubuntu 鍙戣鐗堬紝鍙渶瑕佺畝鍗曠殑 apt-get install python-reportlab 涓琛屽懡浠ゅ嵆鍙畬鎴愬畨瑁呫

Test your installation by importing it in the Python interactive interpreter:

鍦 Python 浜や簰鐜涓鍏ヨ繖涓蒋浠跺寘浠ユ鏌ュ畨瑁呮槸鍚︽垚鍔熴

>>> import reportlab

If that command doesnt raise any errors, the installation worked.

濡傛灉鍒氭墠閭f潯鍛戒护娌℃湁鍑虹幇浠讳綍閿欒锛屽垯琛ㄦ槑瀹夎鎴愬姛銆

Writing Your View

缂栧啓瑙嗗浘

Like CSV, generating PDFs dynamically with Django is easy because the ReportLab API acts on filelike objects.

鍜 CSV 绫讳技锛岀敱 Django 鍔ㄦ佺敓鎴 PDF 鏂囦欢寰堢畝鍗曪紝鍥犱负 ReportLab API 鍚屾牱鍙互浣跨敤绫讳技鏂囦欢瀵硅薄銆

Heres a Hello World example:

涓嬮潰鏄竴涓 Hello World 鐨勭ず渚嬶細

from reportlab.pdfgen import canvas
from django.http import HttpResponse

def hello_pdf(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=hello.pdf'

    # Create the PDF object, using the response object as its "file."
    p = canvas.Canvas(response)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()
    return response

A few notes are in order:

闇瑕佹敞鎰忎互涓嬪嚑鐐癸細

  • Here we use the application/pdf MIME type. This tells browsers that the document is a PDF file, rather than an HTML file. If you leave off this information, browsers will probably interpret the response as HTML, which will result in scary gobbledygook in the browser window.

  • 杩欓噷鎴戜滑浣跨敤鐨 MIME 绫诲瀷鏄 application/pdf 銆傝繖浼氬憡璇夋祻瑙堝櫒杩欎釜鏂囨。鏄竴涓 PDF 鏂囨。锛岃屼笉鏄 HTML 鏂囨。銆傚鏋滃拷鐣ヤ簡杩欎釜鍙傛暟锛屾祻瑙堝櫒鍙兘浼氭妸杩欎釜鏂囦欢鐪嬫垚 HTML 鏂囨。锛岃繖浼氫娇娴忚鍣ㄧ殑绐楀彛涓嚭鐜板緢濂囨殑鏂囧瓧銆

  • Hooking into the ReportLab API is easy: just pass response as the first argument to canvas.Canvas . The Canvas class expects a filelike object, and HttpResponse objects fit the bill.

  • 浣跨敤 ReportLab 鐨 API 寰堢畝鍗曪細鍙渶瑕佸皢 response 瀵硅薄浣滀负 canvas.Canvas 鐨勭涓涓弬鏁颁紶鍏ャ Canvas 绫婚渶瑕佷竴涓被浼兼枃浠剁殑瀵硅薄锛 HttpResponse 瀵硅薄鍙互婊¤冻杩欎釜瑕佹眰銆

  • All subsequent PDF-generation methods are called on the PDF object (in this case, p ), not on response .

  • 鎵鏈夊悗缁殑 PDF 鐢熸垚鏂规硶闇瑕佺敱 PDF 瀵硅薄璋冪敤锛堝湪鏈緥涓槸 p 锛夛紝鑰屼笉鏄 response 瀵硅薄銆

  • Finally, its important to call showPage() and save() on the PDF file (or else youll end up with a corrupted PDF file).

  • 鏈鍚庨渶瑕佸 PDF 鏂囦欢璋冪敤 showPage()save() 鏂规硶锛堝惁鍒欎綘浼氬緱鍒颁竴涓崯鍧忕殑 PDF 鏂囦欢锛夈

Complex PDFs

澶嶆潅鐨 PDF 鏂囦欢

If youre creating a complex PDF document (or any large data blob), consider using the cStringIO library as a temporary holding place for your PDF file. The cStringIO library provides a file-like object interface that is written in C for maximum efficiency.

濡傛灉鎮ㄥ湪鍒涘缓涓涓鏉傜殑 PDF 鏂囨。锛堟垨鑰呬换浣曡緝澶х殑鏁版嵁鍧楋級锛岃浣跨敤 cStringIO 搴撳瓨鏀句复鏃剁敓鎴愮殑 PDF 鏂囦欢銆 cStringIO 鎻愪緵浜嗕竴涓敤 C 缂栧啓鐨勭被浼兼枃浠跺璞$殑鎺ュ彛锛屼粠鑰屽彲浠ヤ娇绯荤粺鐨勬晥鐜囨渶楂樸

Heres the previous Hello World example rewritten to use cStringIO :

涓嬮潰鏄娇鐢 cStringIO 閲嶅啓鐨 Hello World 渚嬪瓙锛

from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def hello_pdf(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=hello.pdf'

    temp = StringIO()

    # Create the PDF object, using the StringIO object as its "file."
    p = canvas.Canvas(temp)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly.
    p.showPage()
    p.save()

    # Get the value of the StringIO buffer and write it to the response.
    response.write(temp.getvalue())
    return response

Other Possibilities

鍏跺畠鐨勫彲鑳芥

Theres a whole host of other types of content you can generate in Python. Here are a few more ideas and some pointers to libraries you could use to implement them:

浣跨敤 Python 鍙互鐢熸垚璁稿鍏跺畠绫诲瀷鐨勫唴瀹癸紝涓嬮潰浠嬬粛鐨勬槸涓浜涘叾瀹冪殑鎯虫硶鍜屼竴浜涘彲浠ョ敤浠ュ疄鐜板畠浠殑搴撱

ZIP files : Pythons standard library ships with the zipfile module, which can both read and write compressed ZIP files. You could use it to provide on-demand archives of a bunch of files, or perhaps compress large documents when requested. You could similarly produce TAR files using the standard library tarfile module.

ZIP 鏂囦欢 锛歅ython 鏍囧噯搴撲腑鍖呭惈鏈 zipfile 妯″潡锛屽畠鍙互璇诲拰鍐欏帇缂╃殑 ZIP 鏂囦欢銆傚畠鍙互鐢ㄤ簬鎸夐渶鐢熸垚涓浜涙枃浠剁殑鍘嬬缉鍖咃紝鎴栬呭湪闇瑕佹椂鍘嬬缉澶х殑鏂囨。銆傚鏋滄槸 TAR 鏂囦欢鍒欏彲浠ヤ娇鐢ㄦ爣鍑嗗簱 tarfile 妯″潡銆

Dynamic images : The Python Imaging Library (PIL; http://www.pythonware.com/products/pil/) is a fantastic toolkit for producing images (PNG, JPEG, GIF, and a whole lot more). You could use it to automatically scale down images into thumbnails, composite multiple images into a single frame, or even do Web-based image processing.

鍔ㄦ佸浘鐗 锛 Python 鍥剧墖澶勭悊搴 (PIL; http://www.pythonware.com/products/pil/) 鏄瀬濂界殑鐢熸垚鍥剧墖(PNG, JPEG, GIF 浠ュ強鍏跺畠璁稿鏍煎紡)鐨勫伐鍏枫傚畠鍙互鐢ㄤ簬鑷姩涓哄浘鐗囩敓鎴愮缉鐣ュ浘锛屽皢澶氬紶鍥剧墖鍘嬬缉鍒板崟鐙殑妗嗘灦涓紝鎴栬呮槸鍋氬熀浜 Web 鐨勫浘鐗囧鐞嗐

Plots and charts : There are a number of incredibly powerful Python plotting and charting libraries you could use to produce on-demand maps, charts, plots, and graphs. We cant possibly list them all, so here are a couple of the highlights:

鍥捐〃 锛 Python 鏈夎澶氬嚭鑹插苟涓斿己澶х殑鍥捐〃搴撶敤浠ョ粯鍒跺浘琛紝鎸夐渶鍦板浘锛岃〃鏍肩瓑銆傛垜浠笉鍙兘灏嗗畠浠叏閮ㄥ垪鍑猴紝鎵浠ヤ笅闈㈠垪鍑虹殑鏄釜涓殑缈樻銆

In general, any Python library capable of writing to a file can be hooked into Django. The possibilities really are endless.

鎬讳箣锛屾墍鏈夊彲浠ュ啓鏂囦欢鐨勫簱閮藉彲浠ヤ笌 Django 鍚屾椂浣跨敤銆傝鐩镐俊涓鍒囩殕鏈夊彲鑳姐

Now that weve looked at the basics of generating non-HTML content, lets step up a level of abstraction. Django ships with some pretty nifty built-in tools for generating some common types of non-HTML content.

鎴戜滑宸茬粡浜嗚В浜嗙敓鎴愨滈潪HTML鈥濆唴瀹圭殑鍩烘湰鐭ヨ瘑锛岃鎴戜滑杩涗竴姝ユ荤粨涓涓嬨侱jango鎷ユ湁寰堝鐢ㄤ互鐢熸垚鍚勭被鈥滈潪HTML鈥濆唴瀹圭殑鍐呯疆宸ュ叿銆

The Syndication Feed Framework

鍐呭鑱氬悎鍣ㄥ簲鐢ㄦ鏋

Django comes with a high-level syndication-feed-generating framework that makes creating RSS and Atom feeds easy.

Django甯︽潵浜嗕竴涓珮绾х殑鑱氬悎鐢熸垚妗嗘灦锛屽畠浣垮緱鍒涘缓RSS鍜孉tom feeds鍙樺緱闈炲父瀹规槗銆

Whats RSS? Whats Atom?

浠涔堟槸RSS锛熶粈涔堟槸Atom锛

RSS and Atom are both XML-based formats you can use to provide automatically updating feeds of your sites content. Read more about RSS at http://www.whatisrss.com/, and get information on Atom at http://www.atomenabled.org/.

RSS鍜孉tom閮芥槸鍩轰簬XML鐨勬牸寮忥紝浣犲彲浠ョ敤瀹冩潵鎻愪緵鏈夊叧浣犵珯鐐瑰唴瀹圭殑鑷姩鏇存柊鐨刦eed銆備簡瑙f洿澶氬叧浜嶳SS鐨勫彲浠ヨ闂 http://www.whatisrss.com/, 鏇村Atom鐨勪俊鎭彲浠ヨ闂 http://www.atomenabled.org/.

To create any syndication feed, all you have to do is write a short Python class. You can create as many feeds as you want.

鎯冲垱寤轰竴涓仈鍚堜緵绋跨殑婧(syndication feed)锛屾墍闇瑕佸仛鐨勫彧鏄啓涓涓畝鐭殑python绫汇備綘鍙互鍒涘缓浠绘剰澶氱殑婧(feed)銆

The high-level feed-generating framework is a view thats hooked to /feeds/ by convention. Django uses the remainder of the URL (everything after /feeds/ ) to determine which feed to return.

楂樼骇feed鐢熸垚妗嗘灦鏄竴涓粯璁ょ粦瀹氬埌/feeds/鐨勮鍥撅紝Django浣跨敤URL鐨勫叾瀹冮儴鍒(鍦/feeds/涔嬪悗鐨勪换浣曚笢瑗)鏉ュ喅瀹氳緭鍑 鍝釜feed

To create a feed, youll write a Feed class and point to it in your URLconf (see Chapters 3 and 8 for more about URLconfs).

瑕佸垱寤轰竴涓猣eed, 鎮ㄥ皢鍒涘缓涓涓 Feed 绫, 骞跺湪鎮ㄧ殑 URLconf 涓寚鍚戝畠. ( 鏌ョ湅绗3绔犲拰绗8绔, 鍙互鑾峰彇鏇村鏈夊叧URLconfs鐨勬洿澶氫俊鎭 )

Initialization

鍒濆鍖

To activate syndication feeds on your Django site, add this URLconf:

涓轰簡鍦ㄦ偍鐨凞jango绔欑偣涓縺娲籹yndication feeds, 娣诲姞濡備笅鐨 URLconf:

(r'^feeds/(?P<url>.*)/$',
 'django.contrib.syndication.views.feed',
 {'feed_dict': feeds}
),

This line tells Django to use the RSS framework to handle all URLs starting with "feeds/" . (You can change that "feeds/" prefix to fit your own needs.)

杩欎竴琛屽憡璇塂jango浣跨敤RSS妗嗘灦澶勭悊鎵鏈夌殑浠 "feeds/" 寮澶寸殑URL. ( 浣犲彲浠ヤ慨鏀 "feeds/" 鍓嶇紑浠ユ弧瓒虫偍鑷繁鐨勮姹. )

This URLconf line has an extra argument: {'feed_dict': feeds} . Use this extra argument to pass the syndication framework the feeds that should be published under that URL.

URLConf閲屾湁涓琛屽弬鏁帮細``{‘feed_dict’: feeds}``锛岃繖涓弬鏁板彲浠ユ妸瀵瑰簲URL闇瑕佸彂甯冪殑feed鍐呭浼犻掔粰 syndication framework

Specifically, feed_dict should be a dictionary that maps a feeds slug (short URL label) to its Feed class. You can define the feed_dict in the URLconf itself. Heres a full example URLconf:

鐗瑰埆鐨勶紝feed_dict搴旇鏄竴涓槧灏刦eed鐨剆lug(绠鐭璘RL鏍囩)鍒板畠鐨凢eed绫荤殑瀛楀吀 浣犲彲浠ュ湪URL閰嶇疆鏈韩閲屽畾涔塮eed_dict锛岃繖閲屾槸涓涓畬鏁寸殑渚嬪瓙

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
    'latest': LatestEntries,
    'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)

The preceding example registers two feeds:

鍓嶉潰鐨勪緥瀛愭敞鍐屼簡涓や釜feed:

  • The feed represented by LatestEntries will live at feeds/latest/ .

  • LatestEntries``琛ㄧず鐨勫唴瀹瑰皢瀵瑰簲鍒癭`feeds/latest/ .

  • The feed represented by LatestEntriesByCategory will live at feeds/categories/ .

  • LatestEntriesByCategory``鐨勫唴瀹瑰皢瀵瑰簲鍒 ``feeds/categories/ .

Once thats set up, youll need to define the Feed classes themselves.

浠ヤ笂鐨勮瀹氬畬鎴愪箣鍚庯紝鎺ヤ笅鏉ラ渶瑕佽嚜宸卞畾涔 Feed

A Feed class is a simple Python class that represents a syndication feed. A feed can be simple (e.g., a site news feed, or a basic feed displaying the latest entries of a blog) or more complex (e.g., a feed displaying all the blog entries in a particular category, where the category is variable).

涓涓 Feed 绫绘槸涓涓畝鍗曠殑python绫伙紝鐢ㄦ潵琛ㄧず涓涓猻yndication feed. 涓涓猣eed鍙兘鏄畝鍗曠殑 (渚嬪涓涓珯鐐规柊闂籪eed锛屾垨鑰呮渶鍩烘湰鐨勶紝鏄剧ず涓涓猙log鐨勬渶鏂版潯鐩)锛屼篃鍙兘鏇村姞澶嶆潅(渚嬪涓涓樉绀篵log鏌愪竴绫诲埆涓嬫墍鏈夋潯鐩殑feed銆傝繖閲岀被鍒 category 鏄釜鍙橀噺).

Feed classes must subclass django.contrib.syndication.feeds.Feed . They can live anywhere in your code tree.

Feed绫诲繀椤荤户鎵縟jango.contrib.syndication.feeds.Feed锛屽畠浠彲浠ュ湪浣犵殑浠g爜鏍戠殑浠讳綍浣嶇疆

A Simple Feed

涓涓畝鍗曠殑Feed

This simple example, taken from chicagocrime.org, describes a feed of the latest five news items:

渚嬪瓙鏉ヨ嚜浜巆hicagocrime.org锛屾弿杩版渶杩5椤规柊闂绘潯鐩殑feed:

from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem

class LatestEntries(Feed):
    title = "Chicagocrime.org site news"
    link = "/sitenews/"
    description = "Updates on changes and additions to chicagocrime.org."

    def items(self):
        return NewsItem.objects.order_by('-pub_date')[:5]

The important things to notice here are as follows:

瑕佹敞鎰忕殑閲嶈鐨勪簨鎯呭涓嬫墍绀:

The class subclasses django.contrib.syndication.feeds.Feed .

瀛愮被 django.contrib.syndication.feeds.Feed .

title , link , and description correspond to the standard RSS <title> , <link> , and <description> elements, respectively.

title , link , 鍜 description 瀵瑰簲涓涓爣鍑 RSS 閲岀殑 <title> , <link> , 鍜 <description> 鏍囩.

items() is simply a method that returns a list of objects that should be included in the feed as <item> elements. Although this example returns NewsItem objects using Djangos database API, items() doesnt have to return model instances.

items() 鏄竴涓柟娉曪紝杩斿洖涓涓敤浠ュ寘鍚湪鍖呭惈鍦╢eed鐨 <item> 鍏冪礌閲岀殑 list 铏界劧渚嬪瓙閲岀敤Djangos database API杩斿洖鐨 NewsItem 瀵硅薄, items() 涓嶄竴瀹氬繀椤昏繑鍥 model鐨勫疄渚

You do get a few bits of functionality for free by using Django models, but items() can return any type of object you want.

浣犲彲浠ュ埄鐢 Django models鍏嶈垂瀹炵幇涓瀹氬姛鑳斤紝浣嗘槸 items() 鍙互杩斿洖浣犳兂瑕佺殑浠绘剰绫诲瀷鐨勫璞.

Theres just one more step. In an RSS feed, each <item> has a <title> , <link> , and <description> . We need to tell the framework what data to put into those elements.

杩樻湁涓涓楠わ紝鍦ㄤ竴涓猂SS feed閲岋紝姣忎釜(item)鏈変竴涓(title)锛(link)鍜(description)锛屾垜浠渶瑕佸憡璇夋鏋 鎶婃暟鎹斁鍒拌繖浜涘厓绱犱腑

To specify the contents of <title> and <description> , create Django templates (see Chapter 4) called feeds/latest_title.html and feeds/latest_description.html , where latest is the slug specified in the URLconf for the given feed. Note that the .html extension is required.

濡傛灉瑕佹寚瀹 <title><description> 锛屽彲浠ュ缓绔嬩竴涓狣jango妯℃澘锛堣Chapter 4锛夊悕瀛楀彨 feeds/latest_title.htmlfeeds/latest_description.html 锛屽悗鑰呮槸URLConf閲屼负瀵瑰簲feed鎸囧畾鐨 slug 銆傛敞鎰 .html 鍚庣紑鏄繀椤荤殑銆

The RSS system renders that template for each item, passing it two template context variables:

RSS绯荤粺妯℃澘娓叉煋姣忎竴涓潯鐩紝闇瑕佺粰浼犻2涓弬鏁扮粰妯℃澘涓婁笅鏂囧彉閲忥細

  • obj : The current object (one of whichever objects you returned in items() ).

  • obj : 褰撳墠瀵硅薄 ( 杩斿洖鍒 items() 浠绘剰瀵硅薄涔嬩竴 )銆

  • site : A django.models.core.sites.Site object representing the current site. This is useful for {{ site.domain }} or {{ site.name }} .

  • site : 涓涓〃绀哄綋鍓嶇珯鐐圭殑 django.models.core.sites.Site 瀵硅薄銆 杩欏浜 {{ site.domain }} 鎴栬 {{ site.name }} 寰堟湁鐢ㄣ

If you dont create a template for either the title or description, the framework will use the template "{{ obj }}" by default that is, the normal string representation of the object.

濡傛灉浣犲湪鍒涘缓妯℃澘鐨勬椂鍊欙紝娌℃湁鎸囨槑鏍囬鎴栬呮弿杩颁俊鎭紝妗嗘灦浼氶粯璁や娇鐢 "{{ obj }}" 锛屽璞$殑瀛楃涓茶〃绀恒

You can also change the names of these two templates by specifying title_template and description_template as attributes of your Feed class.

浣犱篃鍙互閫氳繃淇敼 Feed 绫讳腑鐨勪袱涓睘鎬 title_templatedescription_template 鏉ユ敼鍙樿繖涓や釜妯℃澘鐨勫悕瀛椼

To specify the contents of <link> , you have two options. For each item in items() , Django first tries executing a get_absolute_url() method on that object. If that method doesnt exist, it tries calling a method item_link() in the Feed class, passing it a single parameter, item , which is the object itself.

浣犳湁涓ょ鏂规硶鏉ユ寚瀹 <link> 鐨勫唴瀹广 Django 棣栧厛鎵ц items() 涓瘡涓椤圭殑 get_absolute_url() 鏂规硶銆 濡傛灉璇ユ柟娉曚笉瀛樺湪锛屽氨浼氬皾璇曟墽琛 Feed 绫讳腑鐨 item_link() 鏂规硶锛屽苟灏嗚嚜韬綔涓 item 鍙傛暟浼犻掕繘鍘汇

Both get_absolute_url() and item_link() should return the items URL as a normal Python string.

get_absolute_url()item_link() 閮藉簲璇ヤ互Python瀛楃涓插舰寮忚繑鍥濽RL銆

For the previous LatestEntries example, we could have very simple feed templates. latest_title.html contains:

瀵逛簬鍓嶉潰鎻愬埌鐨 LatestEntries 渚嬪瓙锛屾垜浠彲浠ュ疄鐜颁竴涓畝鍗曠殑feed妯℃澘銆 latest_title.html 鍖呮嫭锛

{{ obj.title }}

and latest_description.html contains:

骞朵笖 latest_description.html 鍖呭惈:

{{ obj.description }}

Its almost too easy

杩欑湡鏄 绠鍗曚簡锛

A More Complex Feed

涓涓洿澶嶆潅鐨凢eed

The framework also supports more complex feeds, via parameters.

妗嗘灦閫氳繃鍙傛暟鏀寔鏇村姞澶嶆潅鐨刦eeds銆

For example, chicagocrime.org offers an RSS feed of recent crimes for every police beat in Chicago. It would be silly to create a separate Feed class for each police beat; that would violate the Dont Repeat Yourself (DRY) principle and would couple data to programming logic.

涓句釜渚嬪瓙锛宑hicagocrime.org鎻愪緵浜嗕竴涓猂SS婧愪互璺熻釜姣忎竴鐗囧尯鍩熺殑鐘姜杩戝喌銆傚鏋滀负姣忎竴涓崟鐙殑鍖哄煙寤虹珛涓涓 Feed 绫诲氨鏄惧緱寰堜笉鏄庢櫤銆傝繖鏍峰仛灏辫繚鍙嶄簡DRY鍘熷垯浜嗭紝绋嬪簭閫昏緫涔熶細鍜屾暟鎹﹀悎鍦ㄤ竴璧枫

Instead, the syndication framework lets you make generic feeds that return items based on information in the feeds URL.

鍙栬屼唬涔嬬殑鏂规硶鏄紝浣跨敤鑱氬悎妗嗘灦鏉ヤ骇鐢熶竴涓氱敤鐨勬簮锛屼娇鍏跺彲浠ユ牴鎹甪eeds URL杩斿洖鐩稿簲鐨勪俊鎭

On chicagocrime.org, the police-beat feeds are accessible via URLs like this:

鍦╟hicagocrime杩欎釜渚嬪瓙涓紝鍖哄煙淇℃伅鍙互閫氳繃杩欐牱鐨刄RL鏂瑰紡鏉ヨ闂:

  • http://www.chicagocrime.org/rss/beats/0613/ : Returns recent crimes for beat 0613

  • http://www.chicagocrime.org/rss/beats/0613/ 锛氳繑鍥0613鍙峰湴鍖虹殑鐘姜鏁版嵁

  • http://www.chicagocrime.org/rss/beats/1424/ : Returns recent crimes for beat 1424

  • http://www.chicagocrime.org/rss/beats/1424/ 锛氳繑鍥1424鍙峰湴鍖虹殑鐘姜鏁版嵁

The slug here is "beats" . The syndication framework sees the extra URL bits after the slug 0613 and 1424 and gives you a hook to tell it what those URL bits mean and how they should influence which items get published in the feed.

鍥哄畾鐨勯偅涓閮ㄥ垎鏄 "beats" 锛堝尯鍩燂級銆傝仛鍚堟鏋剁湅鍒颁簡鍚庨潰鐨勪笉鍚屼箣澶 06131424 锛屽畠浼氭彁渚涚粰浣犱竴涓挬瀛愬嚱鏁版潵鎻忚堪杩欎簺URL鐨勬剰涔夛紝浠ュ強浼氬feed涓殑椤逛骇鐢熺殑褰卞搷銆

An example makes this clear. Heres the code for these beat-specific feeds:

涓句釜渚嬪瓙浼氭緞娓呬竴鍒囥備笅闈㈡槸姣忎釜鍦板尯鐗瑰畾鐨刦eeds锛

from django.core.exceptions import ObjectDoesNotExist

class BeatFeed(Feed):
    def get_object(self, bits):
        # In case of "/rss/beats/0613/foo/bar/baz/", or other such
        # clutter, check that bits has only one member.
        if len(bits) != 1:
            raise ObjectDoesNotExist
        return Beat.objects.get(beat__exact=bits[0])

    def title(self, obj):
        return "Chicagocrime.org: Crimes for beat %s" % obj.beat

    def link(self, obj):
        return obj.get_absolute_url()

    def description(self, obj):
        return "Crimes recently reported in police beat %s" % obj.beat

    def items(self, obj):
        crimes =  Crime.objects.filter(beat__id__exact=obj.id)
        return crimes.order_by('-crime_date')[:30]

Heres the basic algorithm the RSS framework, given this class and a request to the URL /rss/beats/0613/ :

浠ヤ笅鏄疪SS妗嗘灦鐨勫熀鏈畻娉曪紝鎴戜滑鍋囪閫氳繃URL /rss/beats/0613/ 鏉ヨ闂繖涓被锛

The framework gets the URL /rss/beats/0613/ and notices theres an extra bit of URL after the slug. It splits that remaining string by the slash character ("/" ) and calls the Feed classs get_object() method, passing it the bits.

妗嗘灦鑾峰緱浜哢RL /rss/beats/0613/ 骞朵笖娉ㄦ剰鍒癠RL涓殑slug閮ㄥ垎鍚庨潰鍚湁鏇村鐨勪俊鎭傚畠灏嗘枩鏉("/" )浣滀负鍒嗛殧绗︼紝鎶婂墿浣欑殑瀛楃涓插垎鍓插紑浣滀负鍙傛暟锛岃皟鐢 Feed 绫荤殑 get_object() 鏂规硶銆

In this case, bits is ['0613'] . For a request to /rss/beats/0613/foo/bar/ , bits would be ['0613', 'foo', 'bar'] .

鍦ㄨ繖涓緥瀛愪腑锛屾坊鍔犵殑淇℃伅鏄 ['0613'] 銆傚浜 /rss/beats/0613/foo/bar/ 鐨勪竴涓猆RL璇锋眰锛 杩欎簺淇℃伅灏辨槸 ['0613', 'foo', 'bar']

get_object() is responsible for retrieving the given beat, from the given bits .

get_object() 灏辨牴鎹粰瀹氱殑 bits 鍊兼潵杩斿洖鍖哄煙淇℃伅銆

In this case, it uses the Django database API to retrieve the beat. Note that get_object() should raise django.core.exceptions.ObjectDoesNotExist if given invalid parameters. Theres no try /except around the Beat.objects.get() call, because its not necessary. That function raises Beat.DoesNotExist on failure, and Beat.DoesNotExist is a subclass of ObjectDoesNotExist . Raising ObjectDoesNotExist in get_object() tells Django to produce a 404 error for that request.

鍦ㄨ繖涓緥瀛愪腑锛屽畠浣跨敤浜咲jango鐨勬暟鎹簱API鏉ヨ幏鍙栦俊鎭傛敞鎰忓埌濡傛灉缁欏畾鐨勫弬鏁颁笉鍚堟硶锛 get_object() 浼氭姏鍑 django.core.exceptions.ObjectDoesNotExist 寮傚父銆傚湪 Beat.objects.get() 璋冪敤涓篃娌℃湁鍑虹幇 try /except 浠g爜鍧椼傚嚱鏁板湪鍑洪敊鏃舵姏鍑 Beat.DoesNotExist 寮傚父锛岃 Beat.DoesNotExistObjectDoesNotExist 寮傚父鐨勪竴涓瓙绫诲瀷銆 鑰屽湪 get_object()

System Message: WARNING/2 (<string>, line 1583)

Block quote ends without a blank line; unexpected unindent.

涓姏鍑 ObjectDoesNotExist 寮傚父鍙堜細浣垮緱Django寮曞彂404閿欒銆

To generate the feeds <title> , <link> , and <description> , Django uses the title() , link() , and description() methods. In the previous example, they were simple string class attributes, but this example illustrates that they can be either strings or methods. For each of title , link , and description , Django follows this algorithm:

涓轰骇鐢 <title><link> 锛 鍜 <description> 鐨刦eeds锛 Django浣跨敤 title() , link() , 鍜 description() 鏂规硶銆 鍦ㄤ笂闈㈢殑渚嬪瓙涓紝瀹冧滑閮芥槸绠鍗曠殑瀛楃涓茬被鍨嬬殑绫诲睘鎬э紝鑰岃繖涓緥瀛愯〃鏄庯紝瀹冧滑鏃㈠彲浠ユ槸瀛楃涓诧紝 涔熷彲浠ユ槸 鏂规硶銆傚浜庢瘡涓涓 titlelinkdescription 鐨勭粍鍚堬紝Django浣跨敤浠ヤ笅鐨勭畻娉曪細

  1. It tries to call a method, passing the obj argument, where obj is the object returned by get_object() .

  1. 璇曞浘璋冪敤涓涓嚱鏁帮紝骞朵笖浠 get_object() 杩斿洖鐨勫璞′綔涓哄弬鏁颁紶閫掔粰 obj 鍙傛暟銆

  1. Failing that, it tries to call a method with no arguments.

  1. 濡傛灉娌℃湁鎴愬姛锛屽垯涓嶅甫鍙傛暟璋冪敤涓涓柟娉曘

  1. Failing that, it uses the class attribute.

  1. 杩樹笉鎴愬姛锛屽垯浣跨敤绫诲睘鎬с

Finally, note that items() in this example also takes the obj argument. The algorithm for items is the same as described in the previous step first, it tries items(obj) , then items() , and then finally an items class attribute (which should be a list).

鏈鍚庯紝鍊煎緱娉ㄦ剰鐨勬槸锛岃繖涓緥瀛愪腑鐨 items() 浣跨敤 obj 鍙傛暟銆傚浜 items 鐨勭畻娉曞氨濡傚悓涓婇潰绗竴姝ユ墍鎻忚堪鐨勯偅鏍凤紝棣栧厛灏濊瘯 items(obj) 锛 鐒跺悗鏄 items() 锛屾渶鍚庢槸 items 绫诲睘鎬э紙蹇呴』鏄竴涓垪琛級銆

Full documentation of all the methods and attributes of the Feed classes is always available from the official Django documentation (http://www.djangoproject.com/documentation/0.96/syndication_feeds/).

Feed 绫绘墍鏈夋柟娉曞拰灞炴х殑瀹屾暣鏂囨。锛岃鍙傝冨畼鏂圭殑Django鏂囨。 (http://www.djangoproject.com/documentation/0.96/syndication_feeds/) 銆

Specifying the Type of Feed

鎸囧畾Feed鐨勭被鍨

By default, the syndication framework produces RSS 2.0. To change that, add a feed_type attribute to your Feed class:

榛樿鎯呭喌涓, 鑱氬悎妗嗘灦鐢熸垚RSS 2.0. 瑕佹敼鍙樿繖鏍风殑鎯呭喌, 鍦 Feed 绫讳腑娣诲姞涓涓 feed_type 灞炴.

from django.utils.feedgenerator import Atom1Feed

class MyFeed(Feed):
    feed_type = Atom1Feed

Note that you set feed_type to a class object, not an instance. Currently available feed types are shown in Table 11-1.

娉ㄦ剰浣犳妸 feed_type 璧嬪兼垚涓涓被瀵硅薄锛岃屼笉鏄被瀹炰緥銆傜洰鍓嶅悎娉曠殑Feed绫诲瀷濡傝〃11-1鎵绀恒

Table 11-1. Feed Types
Feed Class Format
django.utils.feedgenerator.Rss201rev2Feed RSS 2.01 (default)
django.utils.feedgenerator.RssUserland091Feed RSS 0.91
django.utils.feedgenerator.Atom1Feed Atom 1.0
琛 11-1. Feed 绫诲瀷
Feed 绫 绫诲瀷
django.utils.feedgenerator.Rss201rev2Feed RSS 2.01 (default)
django.utils.feedgenerator.RssUserland091Feed RSS 0.91
django.utils.feedgenerator.Atom1Feed Atom 1.0

Enclosures

闂寘

To specify enclosures (i.e., media resources associated with a feed item such as MP3 podcast feeds), use the item_enclosure_url , item_enclosure_length , and item_enclosure_mime_type hooks, for example:

涓轰簡鎸囧畾闂寘锛堜緥濡傦紝涓巉eed椤规瘮鏂硅MP3 feeds鐩稿叧鑱旂殑濯掍綋璧勬簮淇℃伅锛夛紝浣跨敤 item_enclosure_urlitem_enclosure_length 锛 浠ュ強 item_enclosure_mime_type 锛屾瘮濡

from myproject.models import Song

class MyFeedWithEnclosures(Feed):
    title = "Example feed with enclosures"
    link = "/feeds/example-with-enclosures/"

    def items(self):
        return Song.objects.all()[:30]

    def item_enclosure_url(self, item):
        return item.song_url

    def item_enclosure_length(self, item):
        return item.song_length

    item_enclosure_mime_type = "audio/mpeg"

This assumes, of course, that youve created a Song object with song_url and song_length (i.e., the size in bytes) fields.

褰撶劧锛屼綘棣栧厛瑕佸垱寤轰竴涓寘鍚湁 song_urlsong_length 锛堟瘮濡傛寜鐓у瓧鑺傝绠楃殑闀垮害锛夊煙鐨 Song 瀵硅薄銆

Language

璇█

Feeds created by the syndication framework automatically include the appropriate <language> tag (RSS 2.0) or xml:lang attribute (Atom). This comes directly from your LANGUAGE_CODE setting.

鑱氬悎妗嗘灦鑷姩鍒涘缓鐨凢eed鍖呭惈閫傚綋鐨 <language> 鏍囩(RSS 2.0) 鎴 xml:lang 灞炴(Atom). 浠栫洿鎺ユ潵鑷簬鎮ㄧ殑 LANGUAGE_CODE 璁剧疆.

URLs

URLs

The link method/attribute can return either an absolute URL (e.g., "/blog/" ) or a URL with the fully qualified domain and protocol (e.g., "http://www.example.com/blog/" ). If link doesnt return the domain, the syndication framework will insert the domain of the current site, according to your SITE_ID setting.

link 鏂规硶/灞炴у彲浠ヤ互缁濆URL鐨勫舰寮忥紙渚嬪锛 "/blog/" 锛夋垨鑰呮寚瀹氬崗璁拰鍩熷悕鐨刄RL鐨勫舰寮忚繑鍥烇紙渚嬪 "http://www.example.com/blog/" 锛夈傚鏋 link 娌℃湁杩斿洖鍩熷悕锛岃仛鍚堟鏋朵細鏍规嵁 SITE_ID 璁剧疆锛岃嚜鍔ㄧ殑鎻掑叆褰撳墠绔欑偣鐨勫煙淇℃伅銆

Atom feeds require a <link rel="self"> that defines the feeds current location. The syndication framework populates this automatically, using the domain of the current site according to the SITE_ID setting.

Atom feeds闇瑕 <link rel="self"> 鎸囨槑feeds鐜板湪鐨勪綅缃傝仛鍚堟鏋舵牴鎹 SITE_ID 鐨勮缃紝浣跨敤绔欑偣鐨勫煙鍚嶈嚜鍔ㄥ畬鎴愯繖浜涘姛鑳姐

Publishing Atom and RSS Feeds in Tandem

鍚屾椂鍙戝竷Atom and RSS

Some developers like to make available both Atom and RSS versions of their feeds. Thats easy to do with Django: just create a subclass of your feed class and set the feed_type to something different. Then update your URLconf to add the extra versions. Heres a full example:

涓浜涘紑鍙戜汉鍛樻兂 鍚屾椂 鏀寔Atom鍜孯SS銆傝繖鍦―jango涓緢瀹规槗瀹炵幇锛氬彧闇鍒涘缓涓涓綘鐨 feed 绫荤殑瀛愮被锛岀劧鍚庝慨鏀 feed_type 锛屽苟涓旀洿鏂癠RLconf鍐呭銆備笅闈㈡槸涓涓畬鏁寸殑渚嬪瓙锛

from django.contrib.syndication.feeds import Feed
from chicagocrime.models import NewsItem
from django.utils.feedgenerator import Atom1Feed

class RssSiteNewsFeed(Feed):
    title = "Chicagocrime.org site news"
    link = "/sitenews/"
    description = "Updates on changes and additions to chicagocrime.org."

    def items(self):
        return NewsItem.objects.order_by('-pub_date')[:5]

class AtomSiteNewsFeed(RssSiteNewsFeed):
    feed_type = Atom1Feed

And heres the accompanying URLconf:

杩欐槸涓庝箣鐩稿搴旈偅涓殑URLconf锛

from django.conf.urls.defaults import *
from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed

feeds = {
    'rss': RssSiteNewsFeed,
    'atom': AtomSiteNewsFeed,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)

The Sitemap Framework

Sitemap 妗嗘灦

A sitemap is an XML file on your Web site that tells search engine indexers how frequently your pages change and how important certain pages are in relation to other pages on your site. This information helps search engines index your site.

sitemap 鏄綘鏈嶅姟鍣ㄤ笂鐨勪竴涓猉ML鏂囦欢锛屽畠鍛婅瘔鎼滅储寮曟搸浣犵殑椤甸潰鐨勬洿鏂伴鐜囧拰鏌愪簺椤甸潰鐩稿浜庡叾瀹冮〉闈㈢殑閲嶈鎬с傝繖涓俊鎭細甯姪鎼滅储寮曟搸绱㈠紩浣犵殑缃戠珯銆

For example, heres a piece of the sitemap for Djangos Web site (http://www.djangoproject.com/sitemap.xml):

渚嬪锛岃繖鏄 Django 缃戠珯(http://www.djangoproject.com/sitemap.xml)sitemap鐨勪竴閮ㄥ垎锛

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://www.djangoproject.com/documentation/</loc>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>http://www.djangoproject.com/documentation/0_90/</loc>
    <changefreq>never</changefreq>
    <priority>0.1</priority>
  </url>
  ...
</urlset>

For more on sitemaps, see http://www.sitemaps.org/.

闇瑕佷簡瑙f洿澶氭湁鍏 sitemaps 鐨勪俊鎭, 璇峰弬瑙 http://www.sitemaps.org/.

The Django sitemap framework automates the creation of this XML file by letting you express this information in Python code. To create a sitemap, you just need to write a Sitemap class and point to it in your URLconf.

Django sitemap 妗嗘灦鍏佽浣犵敤 Python 浠g爜鏉ヨ〃杩拌繖浜涗俊鎭紝浠庤岃嚜鍔ㄥ垱寤鸿繖涓猉ML鏂囦欢銆傝鍒涘缓涓涓 sitemap锛屼綘鍙渶瑕佸啓涓涓 Sitemap 绫荤劧鍚庨厤缃綘鐨刄RLconf鎸囧悜瀹冦

Installation

瀹夎

To install the sitemap application, follow these steps:

瑕佸畨瑁 sitemap 搴旂敤绋嬪簭, 鎸変笅闈㈢殑姝ラ杩涜:

  1. Add 'django.contrib.sitemaps' to your INSTALLED_APPS setting.

  1. 'django.contrib.sitemaps' 娣诲姞鍒版偍鐨 INSTALLED_APPS 璁剧疆涓.

  1. Make sure 'django.template.loaders.app_directories.load_template_source' is in your TEMPLATE_LOADERS setting. Its in there by default, so youll need to change this only if youve changed that setting.

  1. 纭繚 'django.template.loaders.app_directories.load_template_source' 鍦ㄦ偍鐨 TEMPLATE_LOADERS 璁剧疆涓傞粯璁ゆ儏鍐典笅瀹冨湪閭i噷, 鎵浠, 濡傛灉浣犲凡缁忔敼鍙樹簡閭d釜璁剧疆鐨勮瘽, 鍙渶瑕佹敼鍥炴潵鍗冲彲銆

  1. Make sure youve installed the sites framework (see Chapter 14).

  1. 纭畾鎮ㄥ凡缁忓畨瑁呬簡 sites 妗嗘灦 (鍙傝绗14绔).

Note

澶囨敞

The sitemap application doesnt install any database tables. The only reason it needs to go into INSTALLED_APPS is so the load_template_source template loader can find the default templates.

sitemap 搴旂敤绋嬪簭娌℃湁瀹夎浠讳綍鏁版嵁搴撹〃. 瀹冮渶瑕佸姞鍏ュ埌 INSTALLED_APPS 涓殑鍞竴鍘熷洜鏄: 杩欐牱 load_template_source 妯℃澘鍔犺浇鍣ㄥ彲浠ユ壘鍒伴粯璁ょ殑妯℃澘.

Initialization

鍒濆鍖

To activate sitemap generation on your Django site, add this line to your URLconf:

瑕佸湪鎮ㄧ殑Django绔欑偣涓縺娲籹itemap鐢熸垚, 璇峰湪鎮ㄧ殑 URLconf 涓坊鍔犺繖涓琛:

(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})

This line tells Django to build a sitemap when a client accesses /sitemap.xml .

杩欎竴琛屽憡璇 Django, 褰撳鎴疯闂 /sitemap.xml 鐨勬椂鍊, 鏋勫缓涓涓 sitemap.

The name of the sitemap file is not important, but the location is. Search engines will only index links in your sitemap for the current URL level and below. For instance, if sitemap.xml lives in your root directory, it may reference any URL in your site. However, if your sitemap lives at /content/sitemap.xml , it may only reference URLs that begin with /content/ .

sitemap鏂囦欢鐨勫悕瀛楁棤鍏崇揣瑕侊紝浣嗘槸瀹冨湪鏈嶅姟鍣ㄤ笂鐨勪綅缃嵈寰堥噸瑕併傛悳绱㈠紩鎿庡彧绱㈠紩浣犵殑sitemap涓綋鍓峌RL绾у埆鍙婂叾浠ヤ笅绾у埆鐨勯摼鎺ャ傜敤涓涓疄渚嬫潵璇达紝濡傛灉 sitemap.xml 浣嶄簬浣犵殑鏍圭洰褰曪紝閭d箞瀹冨皢寮曠敤浠讳綍鐨刄RL銆傜劧鑰岋紝濡傛灉浣犵殑sitemap浣嶄簬 /content/sitemap.xml 锛岄偅涔堝畠鍙紩鐢ㄤ互 /content/ 鎵撳ご鐨刄RL銆

The sitemap view takes an extra, required argument: {'sitemaps': sitemaps} . sitemaps should be a dictionary that maps a short section label (e.g., blog or news ) to its Sitemap class (e.g., BlogSitemap or NewsSitemap ). It may also map to an instance of a Sitemap class (e.g., BlogSitemap(some_var) ).

sitemap瑙嗗浘闇瑕佷竴涓澶栫殑蹇呴』鐨勫弬鏁帮細 {'sitemaps': sitemaps}sitemaps 搴旇鏄竴涓瓧鍏革紝瀹冩妸涓涓煭鐨勫潡鏍囩(渚嬪, blognews )鏄犲皠鍒板畠鐨 Sitemap 绫(渚嬪锛 BlogSitemapNewsSitemap )銆傚畠涔熷彲浠ユ槧灏勫埌涓涓 Sitemap 绫荤殑瀹炰緥(渚嬪锛 BlogSitemap(some_var) )銆

Sitemap Classes

Sitemap 绫

A Sitemap class is a simple Python class that represents a section of entries in your sitemap. For example, one Sitemap class could represent all the entries of your Weblog, while another could represent all of the events in your events calendar.

Sitemap 绫诲睍绀轰簡涓涓繘鍏ュ湴鍥剧珯鐐圭畝鍗曠殑Python绫荤墖鏂.渚嬪,涓涓 Sitemap 绫昏兘灞曠幇鎵鏈夋棩蹇楀叆鍙o紝鑰屽彟澶栦竴涓兘澶熻皟搴︽墍鏈夌殑鏃ュ巻浜嬩欢銆

In the simplest case, all these sections get lumped together into one sitemap.xml , but its also possible to use the framework to generate a sitemap index that references individual sitemap files, one per section (as described shortly).

鍦ㄦ渶绠鍗曠殑渚嬪瓙涓紝鎵鏈夐儴鍒嗗彲浠ュ叏閮ㄥ寘鍚湪涓涓 sitemap.xml 涓紝涔熷彲浠ヤ娇鐢ㄦ鏋舵潵浜х敓涓涓珯鐐瑰湴鍥撅紝涓烘瘡涓涓嫭绔嬬殑閮ㄥ垎浜х敓涓涓崟鐙殑绔欑偣鏂囦欢銆

Sitemap classes must subclass django.contrib.sitemaps.Sitemap . They can live anywhere in your code tree.

Sitemap 绫诲繀椤绘槸 django.contrib.sitemaps.Sitemap 鐨勫瓙绫. 浠栦滑鍙互瀛樺湪浜庢偍鐨勪唬鐮佹爲鐨勪换浣曞湴鏂广

For example, lets assume you have a blog system, with an Entry model, and you want your sitemap to include all the links to your individual blog entries. Heres how your Sitemap class might look:

渚嬪鍋囪浣犳湁涓涓猙log绯荤粺锛屾湁涓涓 Entry 鐨刴odel锛屽苟涓斾綘甯屾湜浣犵殑绔欑偣鍦板浘鍖呭惈鎵鏈夎繛鍒颁綘鐨刡log鍏ュ彛鐨勮秴閾炬帴銆備綘鐨 Sitemap 绫诲緢鍙兘鏄繖鏍风殑锛

from django.contrib.sitemaps import Sitemap
from mysite.blog.models import Entry

class BlogSitemap(Sitemap):
    changefreq = "never"
    priority = 0.5

    def items(self):
        return Entry.objects.filter(is_draft=False)

    def lastmod(self, obj):
        return obj.pub_date

Declaring a Sitemap should look very similar to declaring a Feed ; thats by design.

澹版槑涓涓 Sitemap 鍜屽0鏄庝竴涓 Feed 鐪嬭捣鏉ュ緢绫讳技锛涜繖閮芥槸棰勫厛璁捐濂界殑銆

Like Feed classes, Sitemap members can be either methods or attributes. See the steps in the earlier A Complex Example section for more about how this works.

濡傚悓 Feed 绫讳竴鏍凤紝 Sitemap 鎴愬憳涔熸棦鍙互鏄柟娉曪紝涔熷彲浠ユ槸灞炴с傛兂瑕佺煡閬撴洿璇︾粏鐨勫唴瀹癸紝璇峰弬瑙佷笂鏂 銆婁竴涓鏉傜殑渚嬪瓙銆嬬珷鑺傘

A Sitemap class can define the following methods/attributes:

涓涓 Sitemap 绫诲彲浠ュ畾涔夊涓 鏂规硶/灞炴:

items (required ): Provides list of objects. The framework doesnt care what type of objects they are; all that matters is that these objects get passed to the location() , lastmod() , changefreq() , and priority() methods.

items (蹇呴渶 )锛氭彁渚涘璞″垪琛ㄣ傛鏋跺苟涓嶅叧蹇冨璞$殑 绫诲瀷 锛涘敮涓鍏冲績鐨勬槸杩欎簺瀵硅薄浼氫紶閫掔粰 location()lastmod()changefreq() 锛屽拰 priority() 鏂规硶銆

location (optional): Gives the absolute URL for a given object. Here, absolute URL means a URL that doesnt include the protocol or domain. Here are some examples:

location 锛堝彲閫夛級锛氱粰瀹氬璞$殑缁濆URL銆傜粷瀵筓RL涓嶅寘鍚崗璁悕绉板拰鍩熷悕銆備笅闈㈡槸涓浜涗緥瀛愶細

  • Good: '/foo/bar/'

  • 濂界殑: '/foo/bar/'

  • Bad: 'example.com/foo/bar/'

  • 宸殑: 'example.com/foo/bar/'

  • Bad: 'http://example.com/foo/bar/'

  • 宸殑: 'http://example.com/foo/bar/'

If location isnt provided, the framework will call the get_absolute_url() method on each object as returned by items() .

濡傛灉娌℃湁鎻愪緵 location , 妗嗘灦灏嗕細鍦ㄦ瘡涓 items() 杩斿洖鐨勫璞′笂璋冪敤 get_absolute_url() 鏂规硶.

lastmod (optional): The objects last modification date, as a Python datetime object.

lastmod (鍙): 瀵硅薄鐨勬渶鍚庝慨鏀规棩鏈, 浣滀负涓涓狿ython datetime 瀵硅薄.

changefreq (optional): How often the object changes. Possible values (as given by the Sitemaps specification) are as follows:

changefreq 锛堝彲閫夛級锛氬璞″彉鏇寸殑棰戠巼銆傚彲閫夌殑鍊煎涓嬶紙璇﹁Sitemaps鏂囨。锛夛細

  • 'always'

  • 'always'

  • 'hourly'

  • 'hourly'

  • 'daily'

  • 'daily'

  • 'weekly'

  • 'weekly'

  • 'monthly'

  • 'monthly'

  • 'yearly'

  • 'yearly'

  • 'never'

  • 'never'

priority (optional): A suggested indexing priority between 0.0 and 1.0 . The default priority of a page is 0.5 ; see the http://sitemaps.org documentation for more about how priority works.

priority 锛堝彲閫夛級锛氬彇鍊艰寖鍥村湪 0.0 and 1.0 涔嬮棿锛岀敤鏉ヨ〃鏄庝紭鍏堢骇銆傞粯璁ゅ间负 0.5 锛涜璇﹁ http://sitemaps.org 鏂囨。銆

Shortcuts

蹇嵎鏂瑰紡

The sitemap framework provides a couple convenience classes for common cases. These are described in the sections that follow.

sitemap妗嗘灦鎻愪緵浜嗕竴浜涘父鐢ㄧ殑绫汇傚湪涓嬩竴閮ㄥ垎涓細鐪嬪埌銆

FlatPageSitemap
FlatPageSitemap

The django.contrib.sitemaps.FlatPageSitemap class looks at all flat pages defined for the current site and creates an entry in the sitemap. These entries include only the location attribute not lastmod , changefreq , or priority .

django.contrib.sitemaps.FlatPageSitemap 绫绘秹鍙婂埌绔欑偣涓墍鏈夌殑flat page锛屽苟鍦╯itemap涓缓绔嬩竴涓叆鍙c備絾浠呬粎鍙寘鍚 location 灞炴э紝涓嶆敮鎸 lastmodchangefreq 锛屾垨鑰 priority

See Chapter 14 for more about flat pages.

鍙傝绗16绔犺幏鍙栨湁鍏砯lat page鐨勬洿澶氱殑鍐呭.

GenericSitemap
GenericSitemap

The GenericSitemap class works with any generic views (see Chapter 9) you already have.

GenericSitemap 涓庢墍鏈夌殑閫氱敤瑙嗗浘涓鍚屽伐浣滐紙璇﹁绗9绔狅級銆

To use it, create an instance, passing in the same info_dict you pass to the generic views. The only requirement is that the dictionary have a queryset entry. It may also have a date_field entry that specifies a date field for objects retrieved from the queryset . This will be used for the lastmod attribute in the generated sitemap. You may also pass priority and changefreq keyword arguments to the GenericSitemap constructor to specify these attributes for all URLs.

浣犲彲浠ュ涓嬩娇鐢ㄥ畠锛屽垱寤轰竴涓疄渚嬶紝骞堕氳繃 info_dict 浼犻掔粰閫氱敤瑙嗗浘銆傚敮涓鐨勮姹傛槸瀛楀吀鍖呭惈 queryset 杩欎竴椤广備篃鍙互鐢 date_field 鏉ユ寚鏄庝粠 queryset 涓彇鍥炵殑瀵硅薄鐨勬棩鏈熷煙銆傝繖浼氳鐢ㄤ綔绔欑偣鍦板浘涓殑 lastmod 灞炴с備綘涔熷彲浠ュ悜 GenericSitemap 鐨勬瀯閫犲嚱鏁颁紶閫 prioritychangefreq 鏉ユ寚瀹氭墍鏈塙RL鐨勭浉搴斿睘鎬с

Heres an example of a URLconf using both FlatPageSitemap and GenericSiteMap (with the hypothetical Entry object from earlier):

涓嬮潰鏄竴涓娇鐢 FlatPageSitemap and GenericSiteMap 锛堝寘鎷墠闈㈡墍鍋囧畾鐨 Entry 瀵硅薄锛夌殑URLconf锛

from django.conf.urls.defaults import *
from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap
from mysite.blog.models import Entry

info_dict = {
    'queryset': Entry.objects.all(),
    'date_field': 'pub_date',
}

sitemaps = {
    'flatpages': FlatPageSitemap,
    'blog': GenericSitemap(info_dict, priority=0.6),
}

urlpatterns = patterns('',
    # some generic view using info_dict
    # ...

    # the sitemap
    (r'^sitemap.xml$',
     'django.contrib.sitemaps.views.sitemap',
     {'sitemaps': sitemaps})
)

Creating a Sitemap Index

鍒涘缓涓涓猄itemap绱㈠紩

The sitemap framework also has the ability to create a sitemap index that references individual sitemap files, one per each section defined in your sitemaps dictionary. The only differences in usage are as follows:

sitemap妗嗘灦鍚屾牱鍙互鏍规嵁 sitemaps 瀛楀吀涓畾涔夌殑鍗曠嫭鐨剆itemap鏂囦欢鏉ュ缓绔嬬储寮曘傜敤娉曞尯鍒涓嬶細

  • You use two views in your URLconf: django.contrib.sitemaps.views.index and django.contrib.sitemaps.views.sitemap .

  • 鎮ㄥ湪鎮ㄧ殑URLconf 涓娇鐢ㄤ簡涓や釜瑙嗗浘: django.contrib.sitemaps.views.indexdjango.contrib.sitemaps.views.sitemap .

  • The django.contrib.sitemaps.views.sitemap view should take a section keyword argument.

  • django.contrib.sitemaps.views.sitemap 瑙嗗浘闇瑕佸甫涓涓 section 鍏抽敭瀛楀弬鏁.

Here is what the relevant URLconf lines would look like for the previous example:

杩欓噷鏄墠闈㈢殑渚嬪瓙鐨勭浉鍏崇殑 URLconf 琛岀湅璧锋潵鐨勬牱瀛:

(r'^sitemap.xml$',
 'django.contrib.sitemaps.views.index',
 {'sitemaps': sitemaps}),

(r'^sitemap-(?P<section>.+).xml$',
 'django.contrib.sitemaps.views.sitemap',
 {'sitemaps': sitemaps})

This will automatically generate a sitemap.xml file that references both sitemap-flatpages.xml and sitemap-blog.xml . The Sitemap classes and the sitemaps dictionary dont change at all.

杩欏皢鑷姩鐢熸垚涓涓 sitemap.xml 鏂囦欢, 瀹冨悓鏃跺紩鐢 sitemap-flatpages.xmlsitemap-blog.xml . Sitemap 绫诲拰 sitemaps 鐩綍鏍规湰娌℃湁鏇存敼.

Pinging Google

閫氱煡Google

You may want to ping Google when your sitemap changes, to let it know to reindex your site. The framework provides a function to do just that: django.contrib.sitemaps.ping_google() .

褰撲綘鐨剆itemap鍙樺寲鐨勬椂鍊欙紝浣犱細鎯抽氱煡Google锛屼互渚胯瀹冪煡閬撳浣犵殑绔欑偣杩涜閲嶆柊绱㈠紩銆傛鏋跺氨鎻愪緵浜嗚繖鏍风殑涓涓嚱鏁帮細 django.contrib.sitemaps.ping_google()

Note

澶囨敞

At the time this book was written, only Google responded to sitemap pings. However, its quite likely that Yahoo and/or MSN will soon support these pings as well.

鍦ㄦ湰涔﹀啓鎴愮殑鏃跺, 鍙湁Google鍙互鍝嶅簲sitemap鏇存柊閫氱煡銆傜劧鑰岋紝Yahoo鍜孧SN鍙兘寰堝揩涔熶細鏀寔杩欎簺閫氱煡銆

At that time, well likely change the name of ping_google() to something like ping_search_engines() , so make sure to check the latest sitemap documentation at http://www.djangoproject.com/documentation/0.96/sitemaps/.

鍒伴偅涓椂鍊欙紝鎶娾減ing_google()鈥濊繖涓悕瀛楁敼鎴愨減ing_search_engines()鈥濅細姣旇緝濂姐傛墍浠ヨ繕鏄埌http://www.djangoproject.com/documentation/0.96/sitemaps/ 鍘绘鏌ヤ竴涓嬫渶鏂扮殑绔欑偣鍦板浘鏂囨。銆

ping_google() takes an optional argument, sitemap_url , which should be the absolute URL of your sites sitemap (e.g., '/sitemap.xml' ). If this argument isnt provided, ping_google() will attempt to figure out your sitemap by performing a reverse lookup on your URLconf.

ping_google() 鏈変竴涓彲閫夌殑鍙傛暟 sitemap_url 锛屽畠搴旇鏄綘鐨勭珯鐐瑰湴鍥剧殑URL缁濆鍦板潃锛堜緥濡傦細 /sitemap.xml 锛夈傚鏋滀笉鎻愪緵璇ュ弬鏁帮紝 ping_google() 灏嗗皾璇曢氳繃鍙嶆煡浣犵殑URLconf鏉ユ壘鍒颁綘鐨勭珯鐐瑰湴鍥俱

ping_google() raises the exception django.contrib.sitemaps.SitemapNotFound if it cannot determine your sitemap URL.

濡傛灉涓嶈兘澶熺‘瀹氫綘鐨剆itemap URL, ping_google() 浼氬紩鍙 django.contrib.sitemaps.SitemapNotFound 寮傚父銆

One useful way to call ping_google() is from a models save() method:

鎴戜滑鍙互閫氳繃妯″瀷涓殑 save() 鏂规硶鏉ヨ皟鐢 ping_google()

from django.contrib.sitemaps import ping_google

class Entry(models.Model):
    # ...
    def save(self):
        super(Entry, self).save()
        try:
            ping_google()
        except Exception:
            # Bare 'except' because we could get a variety
            # of HTTP-related exceptions.
            pass

A more efficient solution, however, would be to call ping_google() from a cron script or some other scheduled task. The function makes an HTTP request to Googles servers, so you may not want to introduce that network overhead each time you call save() .

涓涓洿鏈夋晥鐨勮В鍐虫柟妗堟槸鐢 cron 鑴氭湰鎴栦换鍔¤皟搴﹁〃鏉ヨ皟鐢 ping_google() 锛岃鏂规硶浣跨敤Http鐩存帴璇锋眰Google鏈嶅姟鍣紝浠庤屽噺灏戞瘡娆¤皟鐢 save() 鏃跺崰鐢ㄧ殑缃戠粶甯﹀銆

Whats Next?

鎺ヤ笅鏉ワ紵

Next, well continue to dig deeper into all the nifty built-in tools Django gives you. Chapter 12 looks at all the tools you need to provide user-customized sites: sessions, users, and authentication.

涓嬮潰, 鎴戜滑瑕佺户缁繁鍏ユ寲鎺樻墍鏈夌殑Django缁欎綘鐨勫緢濂界殑鍐呯疆宸ュ叿銆 鍦ㄧ12绔狅紝鎮ㄥ皢鐪嬪埌鎻愪緵鐢ㄦ埛鑷畾涔夌珯鐐规墍闇瑕佺殑鎵鏈夊伐鍏凤細 sessions, users 鍜宎uthentication.

Onward!

缁х画鍓嶈!

Copyright 2006 Adrian Holovaty and Jacob Kaplan-Moss.
This work is licensed under the GNU Free Document License.
Hosting graciously provided by media temple
Chinese translate hosting by py3k.cn.