diff --git a/LANGS.md b/LANGS.md index c524e745ed7..40edb26daeb 100644 --- a/LANGS.md +++ b/LANGS.md @@ -1,6 +1,14 @@ -* [English](en) -* [Polski](pl) -* [Українська](uk) -* [Español (beta)](es) -* [Français (beta)](fr) -* [Português-brasileiro (beta)](pt/) +* [🇺🇸 English](en/) +* [🇨🇿 Czech (beta)](cs/) +* [🇪🇸 Español (beta)](es/) +* [🇫🇷 Français](fr/) +* [🇮🇹 Italian (beta)](it/) +* [🇭🇺 Magyar (beta)](hu/) +* [🇵🇱 Polski](pl/) +* [🇵🇹 Português-brasileiro (beta)](pt/) +* [🇹🇷 Türkçe (beta)](tr/) +* [🇷🇺 Русский (beta)](ru/) +* [🇺🇦 Українська](uk/) +* [🇨🇳 简体中文](zh/) +* [🇰🇵/🇰🇷 한국어 (beta)](ko/) +* [🇸🇰 Slovak (beta)](sk) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..fcdd44ca093 --- /dev/null +++ b/LICENSE @@ -0,0 +1,2 @@ +This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. +To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ \ No newline at end of file diff --git a/README.md b/README.md index 6ddb2cd19ee..ebcd69bd8ea 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Django Girls Tutorial -This is the source code repository for the Django Girls Tutorial. Django Girls Tutorial is used on [tutorial.djangogirls.org](http://tutorial.djangogirls.org) so if you want to read it, please go there. If you want to contribute please do go further with this file. +This is the source code repository for the Django Girls Tutorial. Django Girls Tutorial is used on [tutorial.djangogirls.org](http://tutorial.djangogirls.org) so if you want to read it, please go there. If you want to contribute please do go further with this file. # How to contribute -The Django Girls Tutorial is licensed under a *Creative Commons Attribution-ShareAlike 4.0* license. Everyone is free to add, edit and correct the tutorial. +The Django Girls Tutorial is licensed under a [*Creative Commons Attribution-ShareAlike 4.0*](https://creativecommons.org/licenses/by-sa/4.0/) license. Everyone is free to add, edit and correct the tutorial. # Editing basics -The source code of the tutorial is [hosted on Github](http://github.com/DjangoGirls/tutorial). The Github [Fork & Pull workflow](https://help.github.com/articles/using-pull-requests) is used to accept and review changes. +The source code of the tutorial is [hosted on Github](https://github.com/DjangoGirls/tutorial). The Github [Fork & Pull workflow](https://help.github.com/articles/using-pull-requests) is used to accept and review changes. The tutorial uses the [GitBook](https://www.gitbook.io/) service for publishing its documentation. [See more information about how Gitbook works](http://help.gitbook.io/). @@ -17,6 +17,8 @@ The tutorial is written in [Markdown mark up language](https://help.github.com/a You can find any discussions about the contents of the tutorial on the [Github issue tracker](https://github.com/DjangoGirls/tutorial/issues). +[Crowdin](https://crowdin.com/project/django-girls-tutorial) platform is used to manage translations. If you want to join an existing translation team or launch a new translation, send an email to the [translation managers](mailto:translations@djangogirls.org) or contact [support team](mailto:hello@djangogirls.org). If you want to propose some small changes or fix typos in existing translations, please create a Pull Request. + # Getting started and prerequisites For contributing to the tutorial the following is needed to get started: @@ -58,7 +60,11 @@ Either use the Github app for your operating system (mentioned above) or `git` c git clone git@github.com:yourgithubusername/tutorial.git -Download the [Gitbook Editor](https://github.com/GitbookIO/editor/releases) app to your computer. +Then, create a branch for your new changes to sit in. It helps to call the branch something related to the changes you are going to make. + + git checkout -b contributing + +Download the [Gitbook Editor](https://www.gitbook.com/editor) app to your computer. Then you can open the tutorial in Gitbook Editor (*File* > *Open book*). @@ -90,8 +96,8 @@ Example: Total 5 (delta 1), reused 0 (delta 0) To git@github.com:miohtama/tutorial.git b37ca59..fe36152 contributing -> contributing - -If you don't want to download the Gitbook Editor app you can also go to the [Gitbook website](http://gitbook.com), sign up for free and work directly in your browser. + +If you don't want to download the Gitbook Editor app you can also go to the [Gitbook website](https://gitbook.com), sign up for free and work directly in your browser. # Making a pull request @@ -111,5 +117,4 @@ Github emails will notify you for the follow up process. GitHub has an excellent [documentation](https://help.github.com/). Check it out if you need help! -For further questions please [contact DjangoGirls](http://djangogirls.org/). - +For further questions please [contact DjangoGirls](https://djangogirls.org/). diff --git a/book.json b/book.json index 409e2e2b75f..c667d875bff 100644 --- a/book.json +++ b/book.json @@ -1,25 +1,41 @@ - { +{ + "gitbook": ">=3.2.0", "links": { "sidebar": { "Need help? Talk to us!": "https://gitter.im/DjangoGirls/tutorial" } }, - + "pdf": { + "fontSize": 14 + }, "plugins": [ - "anchors@0.4.0", "ga@0.2.1", "richquotes@0.0.5", "edit-link@1.4.1" + "heading-anchors@1.0.3", + "ga@1.0.1", + "richquotes@0.0.7", + "github@2.0.0", + "language-picker", + "sidebar-ad", + "codeblock-label", + "sectionx" ], "pluginsConfig": { "ga": { "token": "UA-51680040-3" }, - "richquotes" : { - "todos" : true + "richquotes": { + "default": false + }, + "github": { + "url": "https://github.com/DjangoGirls/tutorial" }, - "edit-link": { - "base": "https://github.com/djangogirls/tutorial/edit/master", - "label": "Edit This Page" + "language-picker": { + "grid-columns": 3 + }, + "sidebar-ad": { + "imageUrl": "https://cdn.shopify.com/s/files/1/0992/7712/products/codelikeagirl---mockup4_large.jpg", + "url": "https://store.djangogirls.org/", + "description": "💖 Support our work and buy a Django Girls t-shirt! ✨", + "btnText": "Get a t-shirt!" } - }, - - "gitbook": "2.1.0" + } } diff --git a/cs/GLOSSARY.md b/cs/GLOSSARY.md new file mode 100755 index 00000000000..3107893bace --- /dev/null +++ b/cs/GLOSSARY.md @@ -0,0 +1,3 @@ +# editor zdrojového kódu + +Editor kódu je aplikace, která umožňuje uložit váš kód, takže bude možné vrátit se k němu později. Kde ho můžeš získat se dozvíš v [Kapitole editor kódu](./code_editor/README.md). \ No newline at end of file diff --git a/cs/README.md b/cs/README.md new file mode 100755 index 00000000000..5ad33b27ddd --- /dev/null +++ b/cs/README.md @@ -0,0 +1,53 @@ +# Django Girls Tutoriál +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Tento návod je licencován pod Creative Commons Attribution-ShareAlike 4.0 mezinárodní licencí. Chcete-li zobrazit kopii této licence, navštivte https://creativecommons.org/licenses/by-sa/4.0/ + +## Úvod + +Už jsi někdy měla pocit, že svět stále více a více používá technologie a ty zůstáváš nějak pozadu? Přemýšlela jsi někdy, jak vytvořit webové stránky, ale nikdy jsi neměla dostatek motivace začít? Přemýšlela jsi někdy, že svět softwaru je pro tebe příliš složitý na to, abys zkusila něco naprogramovat sama? + +Máme pro tebe dobrou zprávu! Programování není tak těžké, jak se zdá, a zde ti chceme ukázat, jak zábavné to může být. + +Tento návod tě magicky nepromění v programátora. Jestli chceš být dobrá programátorka, budeš potřebovat měsíce nebo dokonce roky učení a praxe. Ale chceme ti ukázat, že programování nebo tvorba webových stránek není tak složitá, jak se zdá. Budeme se snažit ti vysvětlit různé kousky a střípky tak jednoduše, jak dokážeme, aby ses necítila technologiemi zastrašena. + +Doufáme, že se nám podaří přiblížit ti tuto technologii tak, abys ji měla stejně ráda jako my! + +## Co se naučíš během kurzu? + +Po dokončení kurzu budeš mít jednoduchou, fungující webovou aplikaci: vlastní blog. Ukážeme ti, jak ho zprovoznit online tak, aby se ostatní mohli na tvoji práci podívat! + +Tvá aplikace bude (více či méně) vypadat takto: + +![Figure 0.1][2] + + [2]: images/application.png + +> Pokud budeš procházet kurz sama bez učitele, který ti by ti pomáhal v případě, že narazíš na nějaký problém, máme pro tebe chat: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Požádali jsme kouče a předchozí účastníky kurzu, aby čas od času pomáhali ostatním s tímto kurzem. Neboj se zde zeptat na jakoukoliv otázku! + +OK, [začněme od začátku...][3] + + [3]: ./how_the_internet_works/README.md + +## O kurzu a přispěvatelích + +Tento kurz je provozován organizací [DjangoGirls][4]. Pokud najdeš nějaké chyby, nebo chceš aktualizovat návod, prosím, [postupuj podle pokynů pro přispívající][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Český překlad + +Původní DjangoGirls tutoriál přeložila do češtiny skupina dobrovolníků. Poděkování patří hlavně: +Davidovi (dakf), Kristýně Kumpánové, Veronice Gabrielové, Tomáši Ehrlichovi, +Aničce Jaegerové, Matějovi Stuchlíkovi, Filipovi Sivákovi a Juraji M. Bezručkovi. + +## Chtěla bys nám pomoci přeložit návod do jiných jazyků? + +V současné době jsou překlady provozovány na platformě crowdin.com na adrese: + +https://crowdin.com/project/django-girls-tutorial + +Pokud tvůj jazyk není uveden v seznamu na crowdin, prosím, [založ nový požadavek][6] pro přidání dalšího jazyka. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/cs/SUMMARY.md b/cs/SUMMARY.md new file mode 100755 index 00000000000..44793ad9d19 --- /dev/null +++ b/cs/SUMMARY.md @@ -0,0 +1,26 @@ +# Shrnutí + +* [Úvod](README.md) +* [Instalace](installation/README.md) +* [Jak funguje internet](how_the_internet_works/README.md) +* [Úvod do příkazové řádky](intro_to_command_line/README.md) +* [Instalace Pythonu](python_installation/README.md) +* [Editor zdrojového kódu](code_editor/README.md) +* [Úvod do Pythonu](python_introduction/README.md) +* [Co je Django?](django/README.md) +* [Instalace Django](django_installation/README.md) +* [Tvůj první Django projekt!](django_start_project/README.md) +* [Django modely](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Nasazení!](deploy/README.md) +* [Django URL](django_urls/README.md) +* [Django views -- je čas začít tvořit!](django_views/README.md) +* [Úvod do HTML](html/README.md) +* [Django ORM (tvorba dotazů)](django_orm/README.md) +* [Dynamická data v šablonách](dynamic_data_in_templates/README.md) +* [Django šablony](django_templates/README.md) +* [CSS - udělejte svou aplikaci hezčí](css/README.md) +* [Rozšíření šablon](template_extending/README.md) +* [Rozšíření vaší aplikace](extend_your_application/README.md) +* [Django formuláře](django_forms/README.md) +* [Co dál?](whats_next/README.md) diff --git a/cs/code_editor/README.md b/cs/code_editor/README.md new file mode 100755 index 00000000000..f91d7968087 --- /dev/null +++ b/cs/code_editor/README.md @@ -0,0 +1,7 @@ +# Editor zdrojového kódu + +Právě se chystáš napsat svůj první řádek kódu, takže je čas sáhnout po editoru kódu! + +> **Poznámka** Mohla jsi to udělat už dříve v kapitole o instalaci - jestli je to tak, prostě jen tuhle kapitolu přeskoč a vrhni se na další! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/cs/code_editor/instructions.md b/cs/code_editor/instructions.md new file mode 100755 index 00000000000..9666843aff6 --- /dev/null +++ b/cs/code_editor/instructions.md @@ -0,0 +1,31 @@ +Existuje mnoho různých editorů a z velké části se výběr scvrkává na osobní preference. Většina programátorům v Pythonu používá složité, ale mimořádně mocné IDE (integrovaná vývojová prostředí), například PyCharm. Pro začátečníka to může být pravděpodobně méně vhodné; naše doporučení jsou stejně mocná, ale mnohem jednodušší. + +Naše návrhy jsou napsané níže, ale neváhejte se zeptat svého kouče, jaké jsou jeho preference - poté bude i jednodušší získat od něj pomoc s prací v editoru. + +## Gedit + +Gedit je open-source editor. Je k dispozici zdarma pro všechny operační systémy. + +[Stáhnout si jej můžeš zde](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text je velmi oblíbený editor s bezplatnou zkušební dobou. Lze jej snadno nainstalovat a používat. Je k dispozici pro všechny operační systémy. + +[Stáhnout si jej můžeš zde](https://www.sublimetext.com/3) + +## Atom + +Atom je velmi nový editor kódu vytvořen [GitHub](https://github.com/)em. Je zdarma, je open-source a má snadnou instalaci a snadné použití. Je k dispozici pro Windows, OS X a Linux. + +[Stáhnout si jej můžeš zde](https://atom.io/) + +## Proč jsme instalovali editor kódu? + +Možná přemýšlíš, proč instalujeme speciální editor kódu a proč raději nezvolíme něco jako Notepad nebo Word. + +První důvod je, že kód musí být **prostý text** a programy jako Word a Textedit ve skutečnosti produkují bohatý text (s fonty a formátováním), používají vlastní formáty jako [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Druhým důvodem je, že editory kódu se specializují na editaci kódu, takže mohou poskytovat užitečné funkce, jako je barevné zvýraznění kódu podle jeho významu nebo automatické ukončování uvozovek apod. + +Vše to uvidíme v akci později. Brzy ti přijde tvůj oblíbený editor kódu jako jeden z tvých nejlepších nástrojů :) \ No newline at end of file diff --git a/cs/css/README.md b/cs/css/README.md new file mode 100755 index 00000000000..5c79c1a08a7 --- /dev/null +++ b/cs/css/README.md @@ -0,0 +1,296 @@ +# CSS - udělej svou aplikaci hezčí! + +Náš blog nevypadá stále dost pěkně, že? Je na čase ho udělat hezčí! Použijeme na to CSS. + +## Co je to CSS? + +CSS (neboli Cascading Style Sheets) je jazyk používaný pro popis vzhledu a formátování webové stránky. Je to značkovací jazyk (jako HTML). Ber ho jako make-up pro náš web ;). + +Nechceme ale zase začínat úplně od začátku, že? Opět použijeme něco, co již bylo vytvořeno jinými programátory a sdíleno na internetu pro použití zdarma. Vymýšlet znovu, co již před námi někdo vymyslel, to by nebyla žádná legrace. + +## Použijme Bootstrap! + +Bootstrap je jedním z nejpopulárnějších HTML a CSS frameworků pro vývoj pěkné webové stránky: https://getbootstrap.com/ + +Byl napsán programátory, kteří pracovali pro Twitter a je nyní vyvíjeno dobrovolníky z celého světa. + +## Instalace Bootstrapu + +Chceš-li nainstalovat Bootstrap, je třeba přidat do `< head >` v souboru `.html` (`blog/templates/blog/post_list.html`): + +```html + + +``` + +To nepřidá žádné soubory do projektu. Jen to odkazuje na soubory, které existují na internetu. Jen do toho, otevři tvůj web a aktualizuj stránku. Tady to je! + +![Obrázek 14.1][1] + + [1]: images/bootstrap1.png + +Hned to vypadá lépe! + +## Statické soubory v Djangu + +Konečně se podíváme zblízka na téma, které jsme již zmínili, **statické soubory**. Statické soubory jsou všechny naše CSS soubory a obrázky, které nejsou dynamické, takže jejich obsah není závislý na kontextu požadavku a budou stejné pro každého uživatele. + +### Kam umístit statické soubory pro Django + +Jak jsi viděla, když jsme spustili `collectstatic` na serveru, Django už ví, kde najít statické soubory pro vestavěnou aplikaci "admin". Teď jen musíme přidat nějaké statické soubory pro vlastní aplikaci, `blog`. + +Uděláš to tak, že vytvoříš složku s názvem `static` uvnitř aplikace blog: + +``` + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite +``` + +Django automaticky najde všechny složky s názvem "static" uvnitř vašich složek aplikací, a bude moci využívat jejich obsahu jako statické soubory. + +## Tvůj první soubor CSS! + +Vytvoř soubor CSS, chceš-li na stránku www přidat svůj vlastní styl. Vytvoř nový adresář s názvem `css` uvnitř adresáře `static`. Vytvoř nový soubor s názvem `blog.css` uvnitř tohoto adresáře `css`. Připraveno? + +``` + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css +``` + +Čas k napsání nějakého CSS! Otevři soubor `blog/static/css/blog.css` v editoru kódu. + +Nepůjdeme příliš hluboko do přizpůsobení webu a učení o CSS, protože je to docela snadné, a můžeš se o tom dozvědět sama po tomto workshopu. Opravdu můžeme doporučit [Codeacademy HTML & CSS kurz][2] kde se dozvíš vše, co potřebuješ vědět, aby tvoje stránky s CSS vypadaly dobře. + + [2]: https://www.codecademy.com/tracks/web + +Ale pojďme něco málo udělat. Možná bychom mohli změnit barvu našeho záhlaví? Pro interpretaci barev, počítače používají speciální kódy. Začínají `#` a následuje 6 písmen (A-F) a číslic (0-9). Kódy barev můžeš najít například zde: http://www.colorpicker.com/. Můžeš také použít [předdefinované barvy][3], `červená/red` a `zelená/green`. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +V souboru `blog/static/css/blog.css` přidej následující kód: + +```css + h1 a { + color: #FCA205; + } +``` + +`h1` je CSS selector. To znamená, že budeme aplikovat naše styly na jakýkoliv `a` element uvnitř `h1` (např. když máme v kódu něco jako: `< h1 >< href = "" > odkaz < /a >< / h1 >`). V takovém případě sdělujeme, že barvu elementu měníme na `#FCA205`, což je oranžová. Samozřejmě zde můžeš vložit vlastní barvu! + +V CSS souboru určujeme styly pro prvky v souboru HTML. Prvky jsou identifikovány pomocí názvu prvku (tj, `a`,`h1`, `body`), atributem `class` nebo atributem `id`. Třídy/Class a id jsou jména, které pojmenovávají samotný prvek. Třídy definují skupiny prvků a Id poukazují na konkrétní prvky. Například, následující tag může identifikovat pomocí CSS tag `a`, třídu `external_link` nebo id `link_to_wiki_page`: + +```html + +``` + +Přečti si o [CSS selektorech ve w3schools][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Pak je třeba také říct naší HTML šabloně, že jsme přidali nějaké CSS. Otevři soubor `blog/templates/blog/post_list.html` a přidej tento řádek na samý začátek: + +```html + {% load staticfiles %} +``` + +Právě nahráváme statické soubory :). Pak mezi `< head >` `a/< / head >`, za odkazy na soubory Bootstrap CSS (prohlížeč načte soubory v pořadí, ve kterém jsou zapsány, takže kód v našem souboru může přepsat kód v Bootstrap souborech), přidejte tento řádek: + + html + + + +Právě jsi řekla naší šabloně, kde je umístěn náš soubor CSS. + +Soubor by měl nyní vypadat takto: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + +
+

Django Girls Blog

+
+ + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, ulož soubor a aktualizuj stránky! + +![Obrázek 14.2][5] + + [5]: images/color2.png + +Dobrá práce! Možná bychom také chtěli provzdušnit náš web a zvětšit okraj na levé straně? Pojďme to zkusit! + +```css + body { + padding-left: 15px; + } +``` + +Přidej toto do svého CSS souboru, ulož soubor a koukni se, jak to funguje! + +![Obrázek 14.3][6] + + [6]: images/margin2.png + +Možná můžeme také chtít přizpůsobit písmo v našem záhlaví? Vlož mezi tag `< head >` v souboru `blog/templates/blog/post_list.html`: + +```html + +``` + +Tento řádek bude importovat písmo s názvem *Lobster* z Google písem (https://www.google.com/fonts). + +Nyní přidej řádek `font-family: "Lobster";` do CSS souboru `blog/static/css/blog.css` uvnitř deklarace `h1` bloku (kód mezi závorkami `{` a `}`) a aktualizuj stránky: + +```css + h1 a { + color: #FCA205; + font-family: 'Lobster'; + } +``` + +![Obrázek 14.3][7] + + [7]: images/font.png + +Skvěle! + +Jak bylo uvedeno výše, CSS má koncept tříd, který v podstatě umožňuje pojmenovat části kódu HTML a styly aplikovat pouze na tyto části bez ovlivnění ostatních částí. Je to super užitečné, pokud máš dva div tagy, ale každý dělá něco jiného (jako záhlaví a příspěvek), takže nechceš, aby vypadaly stejně. + +Pokračuj a pojmenuj některé části kódu HTML. Přidáš třídu s názvem `page-header` do tvého `div` tagu, který obsahuje záhlaví, jako je tento: + +```html + +``` + +A nyní přidej třídu, `post` do svého `div` obsahující blog post. + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Nyní přidáme deklaraci bloků pro jiné selektory. Selektory začínající `.` se týkají tříd. Existuje mnoho skvělých návodů a vysvětlení CSS na webu, které ti pomohou pochopit následující kód. Pro tuto chvíli stačí zkopírovat a vložit do souboru `blog/static/css/blog.css`: + +```css + .page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; + } + + .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; + } + + .content { + margin-left: 40px; + } + + h1, h2, h3, h4 { + font-family: 'Lobster', cursive; + } + + .date { + float: right; + color: #828282; + } + + .save { + float: right; + } + + .post-form textarea, .post-form input { + width: 100%; + } + + .top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; + } + + .post { + margin-bottom: 70px; + } + + .post h1 a, .post h1 a:visited { + color: #000000; + } +``` + +Pak obklopující HTML kód, který zobrazuje příspěvek s deklaracemi tříd. Nahraď tímto: + +```html + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +v `blog/templates/blog/post_list.html` tímto: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Tyto soubory ulož a aktualizuj své webové stránky. + +![Obrázek 14.4][8] + + [8]: images/final.png + +Woohoo! Vypadá to super, ne? Kód, který jsme vložili není opravdu tak těžký pochopit a měla bys být schopna pochopit jeho většinu, jen jeho čtením. + +Neobávej se trochu poupravit CSS a pokusit se změnit některé věci. Když něco rozbiješ, neboj se, můžeš jej vždy vrátit zpět! + +Mimochodem opravdu doporučujeme tento bezplatný online [Codeacademy HTML & CSS kurz][2] jako post-workshop úkol, naučíš se vše, co potřebuješ vědět, aby tvoje stránky byly hezčí s CSS. + +Připravena na další kapitolu?! :) diff --git a/fr/css/images/images/bootstrap1.png b/cs/css/images/bootstrap1.png similarity index 100% rename from fr/css/images/images/bootstrap1.png rename to cs/css/images/bootstrap1.png diff --git a/fr/css/images/images/color2.png b/cs/css/images/color2.png similarity index 100% rename from fr/css/images/images/color2.png rename to cs/css/images/color2.png diff --git a/fr/css/images/images/final.png b/cs/css/images/final.png similarity index 100% rename from fr/css/images/images/final.png rename to cs/css/images/final.png diff --git a/fr/css/images/images/font.png b/cs/css/images/font.png similarity index 100% rename from fr/css/images/images/font.png rename to cs/css/images/font.png diff --git a/fr/css/images/images/margin2.png b/cs/css/images/margin2.png similarity index 100% rename from fr/css/images/images/margin2.png rename to cs/css/images/margin2.png diff --git a/cs/deploy/README.md b/cs/deploy/README.md new file mode 100755 index 00000000000..bf4c84dd489 --- /dev/null +++ b/cs/deploy/README.md @@ -0,0 +1,317 @@ +# Nasazení! + +> **Poznámka:** Projití následující kapitoly, může být někdy trochu těžké. Vydrž a dokonči to; nasazení je důležitou součástí procesu vývoje webových stránek. Tato kapitola je umístěna uprostřed kurzu, aby ti tvůj kouč mohl pomoci s mírně složitějším procesem nasazení tvého webu online. To znamená, že stále můžeš dokončit kurz později sama, pokud ti dojde čas. + +Až dosud byly tvoje webové stránky k dispozici pouze ve tvém počítači, nyní se naučíš je nasadit! Nasazení je proces publikování aplikace na internetu, takže lidé konečně mohou najít a vidět tvou webovou aplikaci :). + +Jak jsi se dozvěděla, webové stránky musí být umístěny na serveru. Na internetu existuje mnoho poskytovatelů serverů. My budeme používat jednoho, který má relativně jednoduchý proces nasazení: [PythonAnywhere][1]. PythonAnywhere je zdarma pro malé aplikace, které nemají příliš mnoho návštěvníků, takže to pro tebe bude teď stačit. + + [1]: https://pythonanywhere.com/ + +Další externí službu, kterou budeme používa je [GitHub][2], což je hostingová služba pro zdrojové kódy. Na interntu existují i jiné služby, ale téměř všichni programátoři mají účet na GitHubu nyní ho budeš mít také! + + [2]: https://www.github.com + +Budeme používat GitHub jako odrazový můstek k přesunu našeho kódu do a z PythonAnywhere. + +# Git + +Git je "systém pro správu verzí" používaný spoustou programátorů. Tento software může sledovat změny v souborech v průběhu času tak, že konkrétní verze můžeš později znovu zobrazit. Trochu jako funkce "sledování změn" v aplikaci Microsoft Word, ale mnohem silnější. + +## Instalace Git + +> **Poznámka:** Pokud jsi již prošla instalační kroky, není třeba se k tomu vracet - můžeš přeskočit k další části a začít vytvářet Git repozitář. + +{% include "/deploy/install_git.md" %} + +## Spuštění Git repositáře + +Git sleduje změny v sadě souborů v takzvaném úložišti kódu/repository (nebo zkráceně "repo"). Založme si jeden pro náš projekt. Otevři konzoli a v `djangogirls` adresáři spusť tyto příkazy: + +> **Poznámka:** Zkontroluj si svůj aktuální pracovní adresář pomocí `pwd` (OS x/Linux) nebo příkazem `cd` (Windows) před inicializací úložiště. Měla bys být ve složce `djangogirls`. + +``` + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com +``` + +Inicializace úložiště git je něco, co musíme udělat jednou za projekt (a nebudeš muset znovu zadávat uživatelské jméno a e-mailovou adresu). + +Git bude sledovat změny souborů a složek v tomto adresáři, ale jsou tam některé soubory, které chceme ignorovat. Uděláme to tak, že vytvoříš soubor s názvem `.gitignore` v základním adresáři. Otevři editor a vytvoř nový soubor s následujícím obsahem: + +``` + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store +``` + +A ulož ho jako `.gitignore` ve složce nejvyšší úrovně "djangogirls". + +> **Poznámka:** Tečka na začátku názvu souboru je důležitá! Pokud budeš mít jakékoliv potíže se vytvořením (například Macu se nelíbí vytvářet soubory, které začínají tečkou přes Finder), pak použij funkci "Uložit jako" v editoru, což je neprůstřelné. + +Je vhodné použít příkaz `git status` před použitím příkazu `git add` nebo vždy, když si nejste jisti, co se změnilo. To pomůže předejít jakýmkoliv překvapením, například přidání nesprávných souborů. Příkaz `git status` vrátí informace o všech souborech nesledovaných (untracked), upravených (modified) a připravených ke commitu (staged), stav větve a mnoho dalšího. Výstup by měl být podobný tomuto: + +``` + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) +``` + +A nakonec uložíme naše změny. Přejdi do konzole a spusť tyto příkazy: + +``` + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py +``` + +## Přenesení našeho kódu na GitHub + +Přejdi na [GitHub.com][2] a zaregistruj si zdarma nový uživatelský účet. (Pokud jsi to již dříve ve workshopu udělala, tak to je skvělé!) + +Potom vytvoř nové úložiště, dej mu název "my-first-blog". Ponech zaškrtávací políčko "initialise with a README" nezašrkrtlé, ponechej prázdnou .gitignore možnost (to už jsme udělali ručně) a ponech licenci jako None. + +![][3] + + [3]: images/new_github_repo.png + +> **Poznámka:** Název `my-first-blog` je důležitý – mohla by si vybrat něco jiného, ale použijeme ho ještě mnohokrát později a musela bys ho pokaždé nahrazovat. Tak je zřejmě snazší se držet názvu `my-first-blog`. + +Na další obrazovce se zobrazí clon URL tvého repo. Zvol verzi "HTTPS", zkopíruj jí, a za chvilku ji použijeme v terminálu: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Teď potřebujeme připojit úložiště Git na tvém počítači s úložištěm na GitHub. + +Zadej následující příkaz do konzole (nahraď `< your-github-username >` uživatelským jménem, které jsi zadala, když jsi vytvořila svůj účet na GitHub, ale bez ostrých závorek): + +``` + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master +``` + +Zadej své uživatelské jméno pro GitHub a heslo a měla bys vidět něco takového: + +``` + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. +``` + + + +Tvůj kód je nyní na GitHubu. Můžeš jít a mrknout se na to! Zjistíš, že je v dobré společnosti - [Django][5], [Django girls tutorial][6] a mnoha dalších velkých open source software projektů, které také hostí svůj kód na GitHubu :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Vytvoření našeho blogu na PythonAnywhere + +> **Poznámka:** Možná, že jsi vytvořila účet PythonAnywhere již dříve, během instalačních kroků - pokud ano, nemusíš to nyní dělat znovu. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Natáhnutí našeho kódu na PythonAnywhere + +Když jsi se zaregistrovala na PythonAnywhere, budeš přesměrována na dashboard nebo na stránku "Konzole". Zvol možnost spustit konzoli "Bash" – je to PythonAnywhere verze konzole, stejná jako na tvém počítači. + +> **Poznámka:** PythonAnywhere je založen na Linuxu, takže pokud jsi na Windows, konzole bude vypadat trochu jinak, než ta, která je na tvém počítači. + +Pojďme natáhnout náš kód z GitHubu na PythonAnywhere vytvořením "klonu" našeho repo. Zadej následující příkaz do konzole na PythonAnywhere (nezapomeň používat GitHub uživatelské jméno namísto ``): + +``` + $ git clone https://github.com//my-first-blog.git +``` + +Tento příkaz nahraje kopii tvého kódu, na PythonAnywhere. Podívej se zadáním `tree my-first-blog`: + +``` + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py +``` + +### Vytvoření virtualenv na PythonAnywhere + +Stejně jako na tvém počítači, můžeš vytvořit virtualenv na PythonAnywhere. V Bash konzoli zadej postupně následující příkazy: + +``` + $ cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + (mvenv) $ pip install django whitenoise + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 +``` + +> **Poznámka:** Krok `pip install` může trvat několik minut. Trpělivost, trpělivost! Ale pokud to trvá déle než 5 minut, něco není v pořádku. Zeptej se svého kouče. + + + +### Shromažďování statických souborů. + +Byla jsi zvědavá, co bylo to "whitenoise" vlastně zač? Je to nástroj pro obsluhu takzvaných "statických souborů". Statické soubory jsou soubory, které se pravidelně nemění nebo nespouštějí programový kód, například soubory HTML nebo CSS. Na serverech fungují odlišně než na tvém osobním počítači a proto potřebujeme nástroj jako "whitenoise" k jejich obsloužení. + +O statických souborech zjistíme trochu více později v tomto kurzu, až budeme upravovat CSS pro naše stránky. + +Nyní jen musíme spustit další příkaz na serveru s názvem `collectstatic`. Ten řekne Djangu, aby posbíral všechny statické soubory, které potřebuje na serveru. V současnosti jsou to hlavně soubory, které upravují vzhled admin stránky. + +``` + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes +``` + +Zadej "Ano" a pokračujeme! Také zbožňuješ, když ti počítač začne vypisovat ty dlouhé stránky kódu? Já jsem to vždy doprovázela tichými zvuky. Brp, brp, brp... + +``` + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' [...] Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' 62 static files copied to '/home/edith/my-first-blog/static'. +``` + +### Vytvoření databáze na PythonAnywhere + +Zde je další věc, která se liší mezi tvým počítačem a serverem: server používá jinou databázi. Takže uživatelské účty a příspěvky mohou být jiné, na serveru a na tvém počítači. + +Můžeme inicializovat databázi na serveru, stejně jako jsi to udělala v počítači, `migrate` a `createsuperuser`: + +``` + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser +``` + +## Publikování našeho blogu jako webové aplikace + +Nyní je náš kód na PythonAnywhere a náš virtualenv je připraven, statické soubory jsou shromážděny a databáze inicializována. Jsme připraveni zveřejnit blog jako webovou aplikaci! + +Dostaň se zpět na dashboard PythonAnywhere kliknutím na logo a poté, klikni na kartu **Web**. Nakonec klikni na **Add a new web app**. + +Po potvrzení tvého názvu domény, zvol **manual configuration** (NB *není* "Django" volba) v dialogovém okně. Dále zvol **Python 3.4** a klepni na tlačítko Next pro dokončení průvodce. + +> **Poznámka:** Ujisti se, že volíš možnost "Manual configuration", nikoliv "Django". Jsme příliš cool pro výchozí nastavení PythonAnywhere Django ;-) + +### Nastavení virtualenv + +Budeš přesměrována na PythonAnywhere konfigurační obrazovku pro tvou webovou aplikaci, sem budeš muset jít pokaždé, když budeš chtít provést změny aplikace na serveru. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +V části "Virtualenv" klepni na červený text, který říká "Enter the path to a virtualenv" a zadej: `/home/ /my-first-blog/myvenv/`. Klikni na modré zaškrtávací políčko a tím uložit cestu před pokračováním. + +> **Poznámka:** Nahraď své vlastní uživatelské jméno podle potřeby. Pokud uděláš chybu, PythonAnywhere Ti zobrazí malé varování. + +### Konfigurace souboru WSGI + +Django používá "WSGI protokol", standard pro obsluhu webových stránek pomocí Pythonu, který PythonAnywhere podporuje. Aby PythonAnywhere poznal a mohl používat náš Django blog upravme WSGI konfigurační soubor. + +Klikni na odkaz "WSGI configuration file" (v sekci "Code" v horní části stránky – bude pojmenována nějak takto `/var/www/_pythonanywhere_com_wsgi.py`), a budeš přesměrována do editoru. + +Odstraň veškerý obsah a nahraď jej upraveným následujícím kódem: + +```python + import os + import sys + + path = '/home//my-first-blog' # use your own username here + if path not in sys.path: + sys.path.append(path) + + os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + + from django.core.wsgi import get_wsgi_application + from whitenoise.django import DjangoWhiteNoise + application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Poznámka:** Nezapomeň nahradit své vlastní uživatelské jméno, za `` + +Úkolem tohoto souboru je říct PythonAnywhere, kde je naše webová aplikace a jaký je název souboru nastavení Djanga. Také nastavuje nástroj pro statické soubory "whitenoise". + +Klikni na **Save** a přejdi zpět na kartu **Web**. + +Zvládli jsme to! Klikni na velké zelené tlačítko **Reload** a budeš mít možnost zobrazit svou aplikaci. Odkaz na to najdeš v horní části stránky. + +## Ladící tipy + +Pokud se ti zobrazí chyba při pokusu navštívit web, první místo kam se podívat na nějaké informace o ladění je v **error log**. Odkaz na něj najdeš na PythonAnywhere v [kartě Web][8]. Zkontroluj jestli tam nejsou nějaké chybové zprávy; nejnovější záznamy jsou na konci. Mezi běžné problémy patří: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* Často zapomínané kroky jsou ty, které jsme dělali v konzoly: vytvoření virtualenv, aktivace, instalace Django, spuštění collectstatic, přenesení databáze. + +* Chyba k cestě virtualenv na kartě Web – bude obvykle označená malou červenou zprávou na stejném místě. + +* Chyba v konfiguračním souboru WSGI – máš cestu do složky my-first-blog v pořádku? + +* Vybrala jsi stejnou verzi Pythonu pro svůj virtualenv stejně jako pro svoji webovou aplikaci? Obe verze by měly být 3.4. + +* Existují některé [obecné tipy ladění na PythonAnywhere wiki][9]. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +A pamatuj si, že tvůj coach je tady, aby ti pomohl! + +# Jsme online! + +Výchozí stránka tvé webové aplikace by měla ukázat "Welcome to Django", stejně jako to dělá na tvém počítači. Zkus přidat `/admin/` na konec adresy URL, a budeš přesměrována na admin stránku. Přihlas se pomocí uživatelského jména a hesla, a uvidíš, že můžeš přidávat nové příspěvky na server. + +Poplácej sama sebe *ohromně* po zádech! Nasazení serveru je jednou z nejsložitější částí vývoje webových aplikací a trvá lidem často i několik dní, než je funkční. Ale ty máš své stránky online na Internetu, právě teď! diff --git a/cs/deploy/images/github_get_repo_url_screenshot.png b/cs/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/cs/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/cs/deploy/images/new_github_repo.png b/cs/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/cs/deploy/images/new_github_repo.png differ diff --git a/cs/deploy/images/pythonanywhere_web_tab_virtualenv.png b/cs/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/cs/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/cs/deploy/install_git.md b/cs/deploy/install_git.md new file mode 100755 index 00000000000..081798d74f2 --- /dev/null +++ b/cs/deploy/install_git.md @@ -0,0 +1,19 @@ +### Windows + +Git si můžeš stáhnout z [git-scm.com](https://git-scm.com/). Klikej na "další" ve všech krocích s výjimkou 5. kroku s názvem "Nastavení prostředí PATH", zvol "Spustit Git a související Unixové nástroje z příkazového řádku systému Windows" (spodní možnost). Ostatní výchozí hodnoty jsou v pořádku. Odškrtni Windows-style konce řádků, pro commit je Unixový styl konce řádků správný. + +### MacOS + +Stáhni Git z [git-scm.com](https://git-scm.com/) a postupuj podle pokynů. + +### Linux + +Pokud ho již nemáš nainstalovaný, git měl by být k dispozici pomocí Správce balíčků, zkus: + +``` + sudo apt-get install git + # or + sudo yum install git + # or + sudo zypper install git +``` diff --git a/cs/deploy/signup_pythonanywhere.md b/cs/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..fe6e67a8fe7 --- /dev/null +++ b/cs/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Dále je čas přihlásit se zdarma k účtu "Beginner" na PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Poznámka:** Při výběru svého uživatelského jména měj na paměti, že adresa URL tvého blogu bude mít tvar `yourusername.pythonanywhere.com`, takže si pro svůj blog zvol vlastní přezdívku nebo jiné jméno. diff --git a/cs/django/README.md b/cs/django/README.md new file mode 100755 index 00000000000..3663ae96264 --- /dev/null +++ b/cs/django/README.md @@ -0,0 +1,27 @@ +# Co je Django? + +Django (*jang-goh/ˈdʒæŋɡoʊ /*) je svobodný a open source webový aplikační framework napsaný v Pythonu. Webový framework je sada komponent, která pomáhá vyvíjet webové stránky rychleji a snadněji. + +Když vytváříš webové stránky, vždy potřebuješ podobnou sadu komponent: způsob, jak zpracovat ověření uživatele (registraci, přihlášení, odhlášení), administrační panel pro tvé webové stránky, formuláře, způsob, jak nahrávat soubory, atd. + +Naštěstí si ostatní lidé již dávno všimli, že vývojáři čelí stejným problémům při vytváření nových stránek. Takže se spojili a vytvořili frameworky (Django je jedním z nich), které obsahují sadu hotových, snadno použitelných komponent. + +Frameworky existují, aby ti ušetřily čas a ty jsi nemusela znovu vynalézat, co už někdo zdlouhavě vymýšlel. Stejně tak by ti měly ušetřit čas při vytváření nových webových stránek. + +## Proč potřebuješ framework? + +Abychom pochopili, co ve skutečnosti Django je, musíme se blíže podívat na to, co dělá server. První věcí je, že server musí vědět, že chceš obsloužit tebou zvolenou webovou stránkou. + +Představ si poštovní schránku (port), která na zvoleném portu sleduje příchozí zprávy (požadavky). Podobně se chová webový server. Webový server čte požadavky od uživatele a odešle odpověď v podobě webové stránky. Ale když chceš něco poslat, musíš mít nějaký obsah. A Django je to, co ti pomůže vytvořit tento obsah. + +## Co se stane, když někdo požaduje webové stránky ze serveru? + +Pokud přijde žádost na webový server, je předána Django frameworku, který se snaží přijít na to, co vlastně uživatel požaduje. Nejprve vezme adresu webové stránky a snaží se přijít na to, co udělat. Tuto část provádí Django **urlresolver** (všimni si, že adresa webové stránky se nazývá URL - Uniform Resource Locator - proto jméno *urlresolver* dává smysl). Tato činnost není složitá - bere si seznam vzorů a v něm se pokouší vyhledat shodu s URL. Django kontroluje seznam vzorů od shora dolů a pokud některý odpovídá, pak Django předá žádost související funkci, která se nazývá *view*. + +Představ si pošťáka s dopisem. Kráčí po ulici a kontroluje každé číslo domu, jestli odpovídá adrese na dopisu. Pokud adresa odpovídá, dopis vloží do schránky. Stejným způsobem funguje urlresolver! + +Ve funkci *view* se provádí všechny zajímavé věci: můžeme se podívat do databáze a vyhledat nějaké informace. Co když chce uživatel změnit něco v datech? Dopis může říkat "prosím změňte popis mé práce." *View* může zkontrolovat, zda máš povolení tuto změnu provést, pak aktualizuje popis práce a odešle ti zprávu: "Hotovo!". V tuto chvíli *view* vygeneruje odpověď a Django ji může odeslat tvému webovému prohlížeci. + +Samozřejmě, že výše uvedený popis je trochu zjednodušený, ale prozatím není nutné znát všechny technické detaily. Pro obecnou představu to postačí. + +Takže místo studování přílišných podrobností jednoduše začneme něco vytvářet pomocí Djanga, čímž se naučíme všechny důležité části! diff --git a/cs/django_admin/README.md b/cs/django_admin/README.md new file mode 100755 index 00000000000..493e747936e --- /dev/null +++ b/cs/django_admin/README.md @@ -0,0 +1,49 @@ +# Django admin + +Chceš-li přidávat, upravovat a mazat příspěvky, které jsme právě vymodelovaly, použijeme Django admin. + +Otevřeme soubor `blog/admin.py` a nahradíme jeho obsah následujícím kódem: + +```python + from django.contrib import admin + from .models import Post + + admin.site.register(Post) +``` + +Jak vidíš, importujeme (vkládáme) Post model definovaný v předchozí kapitole. Pro zviditelnění našeho modelu na admin stránce musíme zaregistrovat model pomocí `admin.site.register(Post)`. + +OK, je čas se podívat na náš Post model. Nezapomeň spustit `Pythonu manage.py runserver` v konzoli www serveru. Přejdi do prohlížeče a zadej adresu http://127.0.0.1:8000/admin/. Uvidíš přihlašovací stránku jako je tato: + +![Login page][1] + + [1]: images/login_page2.png + +Chceš-li se přihlásit, musíš vytvořit *superusera* - uživatele, který má kontrolu nad celou webovou stránkou. Vrať se do příkazového řádku, zadej `python manage.py createsuperuser` a stiskni klávesu enter. Po zobrazení výzvy zadej své uživatelské jméno (malá písmena, bez mezer), e-mailovou adresu a heslo. Nedělej si starosti, že nevidíš heslo, které zadáváš - tak to má být. Jen ho napiš a stiskni `enter` pro pokračování. Výstup by měl vypadat takto (kde uživatelské jméno a e-mail by měly být tvé vlastní): + +``` + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. +``` + +Vrať se do svého prohlížeče. Přihlas se pomocí pověření superuživatele, kterého jsi právě vytvořila; měla bys vidět Django admin dashboard/nástěnku. + +![Django admin][2] + + [2]: images/django_admin3.png + +Klikni na příspěvky/Posts a trochu si s nimi pohraj. Přidej pět nebo šest příspěvků blogu. Nedělej si starosti s obsahem - pro ušetření času můžeš jednoduše kopírovat a vložit nějaký text z tohoto kurzu :). + +Ujisti se, že alespoň dva nebo tři příspěvky (ale ne všechny) mají nastavené datum publikování. Později to bude užitečné. + +![Django admin][3] + + [3]: images/edit_post3.png + +Pokud chceš vědět více o Django admin, koukni se do Django dokumentace: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +V tuto chvíli je asi dobrý čas dát si pro trochu vzpruhy kávu, čaj nebo něco k jídlu. Vytvořila jsi svůj první model Django - zasloužíš si malý oddech! diff --git a/fr/django_admin/images/images/django_admin3.png b/cs/django_admin/images/django_admin3.png similarity index 100% rename from fr/django_admin/images/images/django_admin3.png rename to cs/django_admin/images/django_admin3.png diff --git a/fr/django_admin/images/images/edit_post3.png b/cs/django_admin/images/edit_post3.png similarity index 100% rename from fr/django_admin/images/images/edit_post3.png rename to cs/django_admin/images/edit_post3.png diff --git a/fr/django_admin/images/images/login_page2.png b/cs/django_admin/images/login_page2.png similarity index 100% rename from fr/django_admin/images/images/login_page2.png rename to cs/django_admin/images/login_page2.png diff --git a/cs/django_forms/README.md b/cs/django_forms/README.md new file mode 100755 index 00000000000..b84bff0b8b3 --- /dev/null +++ b/cs/django_forms/README.md @@ -0,0 +1,395 @@ +# Django formuláře + +Poslední věc, kterou chceme udělat na našich webových stránkách, je vytvořit pohodlný způsob, jak přidávat a upravovat příspěvky na blogu. Django `admin` je super, ale je těžké ho přizpůsobit a upravit do hezčí podoby. S `formuláři` budeme mít absolutní moc nad naším rozhraním - můžeme dělat téměř cokoliv, co si dokážeme představit! + +Pěkná věc na Django formulářích je, že je můžeme definovat úplně od počátku nebo vytvořit `ModelForm`, který uloží výsledek z formuláře pomocí modelu. + +To je přesně to, co chceme udělat: vytvoříme formulář pro náš model `Post`. + +Stejně jako všechny důležité části Djanga mají formuláře své vlastní soubory: `forms.py`. + +V našem adresáři potřebujeme vytvořit soubor s názvem `blog`. + +``` + blog + └── forms.py +``` + +OK, otevři ho a zadej následující kód: + +```python + from django import forms + + from .models import Post + + class PostForm(forms.ModelForm): + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Musíme nejdříve importovat Django formuláře (`from django import forms`) a samozřejmě náš `Post` model (`from .models import Post`). + +`PostForm`, jak asi předpokládáš, je jméno našeho formuláře. Musíme říct Djangu, že tento formulář je `ModelForm` (tak pro nás bude moci Django udělat něco magického) - zodpovědný za to bude `forms.ModelForm`. + +Dále zde máme `třídu Meta`, kde řekneme Djangu, který model by měl být použit k vytvoření tohoto formuláře (`model = Post`). + +Nakonec můžeme Djangu říct, co se má stát s jednotlivými poli našeho formuláře. V tomto případě chceme pouze zobrazit pole `nadpis/title` a `text` - `autor` by měl být člověk, který je aktuálně přihlášen (ty!) a `created_date` by mělo být automaticky nastaveno, když vytvoříme příspěvek (tj. v kódu). + +A je to! Vše, co teď musíme udělat, je použít formulář ve *view* a zobrazit ho v šabloně. + +Takže ještě jednou: budeme vytvářet odkaz na stránky, URL, pohled a šablonu. + +## Odkaz na stránku s formulářem + +Je tedy čas otevřít soubor `blog/templates/blog/base.html`. Přidáme odkaz do `div` s názvem `page-header`: + +```html + +``` + +Všimni si, že chceme zavolat náš nový view `post_new`. + +Po přidání řádku by měl tvůj html soubor vypadat takto: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Po uložení a obnovení stránky http://127.0.0.1:8000 patrně uvidíš známou `NoReverseMatch` chybu. + +## URL + +Otevři `blog/urls.py` a přidej řádek: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + +Výsledný kód bude vypadat takto: + +```python + from django.conf.urls import url + from . import views + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), + ] +``` + +Po aktualizaci webu vidíme `AttributeError`, protože nemáme implementovaný `post_new` view. Přidáme ho právě teď. + +## post_new view + +Musíme otevřít soubor `blog/views.py` a přidat následující řádky: + +```python + from .forms import PostForm +``` + +a náš *view*: + +```python + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Chceš-li vytvořit nový formulář `Post`, musíš zavolat `PostForm()` a předat ho do šablony. Za chvilku se vrátíme k tomuto *view*, ale teď pojďme rychle vytvořit šablonu formuláře. + +## Šablona + +Musíme vytvořit soubor `post_edit.html` v adresáři `blog/templates/blog`. Pro vytvoření formuláře potřebujeme udělat několik věcí: + +* musíme zobrazit formulář. Můžeme to udělat například jednoduchým `{% raw %}{{ form.as_p }}{% endraw %}`. +* formulář musíme obalit HTML značkou (přidej řádek nad formulář): `< method="POST" >... < / form >` +* potřebujeme tlačítko `Uložit`. Vytvoříme HTML tlačítko: `< button type="submit"> Uložit < / button>` +* a nakonec těsně za otevírací značku `< form... >` musíme přidat `{% raw %}{% csrf_token %}{% endraw %}`. Toto je velmi důležité, protože tak vytvoříme bezpečnější formulář! Django si bude stěžovat v okamžiku, kdy se pokusíš uložit formulář, pokud zapomeneš na tuto část: + +![CSFR zakázaná stránka][1] + + [1]: images/csrf2.png + +Pojďme se nyní podívat, jak by mělo vypadat HTML v `post_edit.html`: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+ {% endblock %} +``` + +Čas aktualizovat naší stránku! Hurá! Zobrazil se formulář! + +![Nový formulář][2] + + [2]: images/new_form2.png + +Ale ještě chvilku počkej! Když něco zadáš do polí `titulek` a `text` a pokusíš se formulář uložit - co se stane? + +Nic! Jsme opět na stejné stránce, náš text je pryč... a nepřidal se žádný nový příspěvek. Tak co se stalo? + +Odpověď je: nic. Musíme ještě trochu zapracovat na našem *view*. + +## Ukládání formuláře + +Otevři znovu `blog/views.py`. Vše, co máme aktuálně v `post_new`, je toto: + +```python + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Když odešleme formulář, vrátíme se zpět na ten samý view, ale tentokrát obdržíme nějaká další data v `request`, přesněji v `request.POST` (pojmenování nemá nic společného s naším "post" v blogu, vychází to z toho, že "zasíláme" data). Pamatuješ si, že v našem HTML souboru ve `
` jsme definovali proměnnou `method="POST"`? Všechna pole z formuláře jsou nyní k dispozici v proměnné `request.POST`. Neměla bys přejmenovávat `POST` na něco jiného (jediná další platná hodnota proměnné `method` je `GET`, ale teď tady nebudeme vysvětlovat rozdíly). + +Takže v našem *view* máme dvě samostatné situace ke zpracování. První: když načteme stránku poprvé a chceme dostat prázdný formulář. Druhou: když se vrátíme zpět do našeho *view* s vyplněnými daty formuláře. Takže musíme přidat podmínku (použijeme na to `if`). + +```python + if request.method == "POST": + [...] + else: + form = PostForm() +``` + +Teď je čas k vyplnění mezer `[...]`. Je-li `method` `POST`, chceme vytvořit `PostForm` s údaji z formuláře, že? Udělejme to: + +```python + form = PostForm(request.POST) +``` + +Snadné! Další věcí je zjistit, zda-li je formulář v pořádku (všechna požadovaná pole jsou vyplněna a neobsahují špatné hodnoty). Uděláme to pomocí `form.is_valid()`. + +Zkontrolujeme, je-li formulář platný, a pokud ano, můžeme ho uložit! + +```python + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +V podstatě, tady máme dvě věci: ukládáme formulář pomocí `form.save` a přidáváme autora (vzhledem k tomu, že v `PostForm` nebylo žádné pole `Autor` a toto pole je požadováno!). `commit=False` znamená, že ještě nechceme `Post` uložit pomocí modelu - chceme nejdříve přidat autora. Většinu času budeš používat `form.save()`, bez `commit=False`, ale v tomto případě to potřebujeme takto udělat. `post.save()` zachová změny (přidá autora) a vytvoří nový příspěvek na blogu! + +A nakonec by bylo úžasné, pokud bychom okamžitě přešli na stránku `post_detail` s nově vytvořeným příspěvkem, že ano? K tomu potřebujeme jeden další import: + +```python + from django.shortcuts import redirect +``` + +Přidej to na samý začátek souboru. A nyní můžeš říci: Jdi na stránku `post_detail` s nově vytvořeným příspěvkem. + +```python + return redirect('blog.views.post_detail', pk=post.pk) +``` + +`blog.views.post_detail` je název pohledu, na který chceme jít. Pamatuj si, že tento *view* vyžaduje proměnnou `pk`. Pro předání do view použijeme `pk=post.pk`, kde `post` je nově vytvořený příspěvek! + +Už jsme si toho řekly hodně, ale pravděpodobně chceš vidět, jak nyní celý *view* vypadá nyní, nemám pravdu? + +```python + def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Pojďme se podívat, jestli to funguje. Přejdi na stránku http://127.0.0.1:8000/post/new/, přidej `title` a `text`, ulož jej... a hle! Byl přidán nový příspěvek na blog a my jsme přesměrovány na stránku `post_detail`! + +Možná jsi si všimla, že jsme nastavili proměnnou publish_date před uložením postu. Později si ukážeme *tlačítko Publikovat* v **Django girls tutorial: rozšíření**. + +## Ověření formuláře + +A teď ti ukážeme, jak cool jsou formuláře v Djangu. Blog příspěvek musí mít `title` a `text` pole. V našem modelu `Post` jsme neřekly (na rozdíl od `published_date`), že jsou tato pole nepovinná, takže Django ve výchozím nastavení očekává, že budou vyplněná. + +Pokus se uložit formulář bez `nadpisu` a `textu`. Hádej, co se stane! + +![Ověření formuláře][3] + + [3]: images/form_validation2.png + +Django se stará o ověřování, že všechna pole v našem formuláři jsou správně. Není to skvělé? + +> Jelikož jsme nedávno použily Django admin rozhraní, systém si v současné době myslí, že jsme přihlášeni. Existuje několik situací, které by mohly vést k našemu odhlášení (zavření prohlížeče, restartováním DB, atd.). Pokud při vytváření příspěvku dostaneš chybu, upozorňující na nepřihlášeného uživatele, zamiř na http://127.0.0.1:8000/admin a přihlas se znovu. Tím se dočasně vyřeší tento problém. Existuje trvalá oprava, která na tebe čeká v **domácím úkolu: zabezpeč svůj web!** v kapitole za hlavním tutorialem. + +![Chyba přihlášení][4] + + [4]: images/post_create_error.png + +## Upravit formulář + +Teď víme, jak přidat nový formulář. Ale co když chceme upravit stávající? Je to velmi podobné tomu, co jsme před chvílí dělaly. Vytvoříme teď rychle některé důležité věci (pokud něčemu neporozumíš, měla bys požádat svého kouče nebo se podívat do předchozích kapitol, protože jsme již všechny tyto kroky probíraly). + +Otevři `blog/templates/blog/post_detail.html` a přidej následující řádek: + +```html + +``` + +tak, aby šablona vypadala takto: + +```html + {% extends 'blog/base.html' %} + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + +V `blog/urls.py` přidej tento řádek: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Znovu použijeme šablonu `blog/templates/blog/post_edit.html`, takže jediné, co chybí, je *view*. + +Otevři `blog/views.py` a přidej na samý konec souboru: + +```python + def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_d etail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Vypadá to téměř úplně stejně jako náš view `post_new`. Ale ne zcela. Za prvé: máme navíc parametr `pk` z adresy URL. Za druhé: získáme model `Post`, který chceme upravit, pomocí `get_object_or_404 (Post, pk = pk)`. Když potom vytvoříme formulář, předáme tento post jako parametr `instance`, když ukládáme formulář: + +```python + form = PostForm(request.POST, instance=post) +``` + +a když jsme otevřely formulář s tímto příspěvkem pro úpravu: + +```python + form = PostForm(instance=post) +``` + +Ok, vyzkoušejme si, jestli to funguje! Pojďme na stránku `post_detail`. Tam by mělo být tlačítko Edit v pravém horním rohu: + +![Tlačítko Upravit][5] + + [5]: images/edit_button2.png + +Po klepnutí na něj se zobrazí formulář s naším příspěvkem: + +![Upravit formulář][6] + + [6]: images/edit_form2.png + +Neboj se změnit název nebo text a ulož změny! + +Blahopřejeme! Tvoje aplikace je skoro kompletní! + +Pokud potřebuješ více informací o Django formulářích, měla by sis přečíst dokumentaci: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## Zabezpečení + +Být schopná vytvářet nové příspěvky pouhým klepnutím na odkaz je super! Právě teď ale každý, kdo přijde na tvé stránky, je schopen odeslat nový příspěvek na blog a to asi nechceš. Udělejme to tak, že se tlačítko zobrazí tobě, ale nezobrazí se nikomu jinému. + +V `blog/templates/blog/base.html` najdeš naši `page-header`, `div` a tag `a`, který jsme tam dali dříve. Řádek by měl vypadat nějak takto: + +```html + +``` + +Chceme přidat další `{% if %}` příkaz, který zajistí, že se odkaz zobrazí pouze pro uživatele, kteří jsou přihlášeni jako admin. Ve skutečnosti jsi jím pouze ty! Změň tag `< a >`, aby vypadal takto: + +```html + {% if user.is_authenticated %} + + {% endif %} +``` + +Tento `{% if %}` způsobí, že odkaz bude odeslán do prohlížeče, pouze pokud je uživatel, který požaduje stránku, přihlášený. To zcela nezabrání možnosti vytvářet nové záznamy, ale je to dobrý první krok. Lepší zabezpečení vysvětlíme v rozšířené lekci. + +Vzhledem k tomu, že jsi pravděpodobně přihlášená, neuvidíš žádnou změnu, pokud aktualizuješ stránku. Při načtení stránky v novém prohlížeči nebo anonymním okně se odkaz již neukáže! + +## Ještě jedna věc: čas nasadit aplikaci! + +Uvidíme, jestli to funguje na PythonAnywhere. Čas na další nasazení! + +* Za prvé commitni nový kód a pošli ho na Github + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push +``` + +* Pak v [Bash konzoli PythonAnywhere][7]: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +* Nakonec skoč na [kartu Web][8] a klikni na **Reload**. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +A mělo by to být! Gratulujeme :) diff --git a/fr/django_forms/images/images/csrf2.png b/cs/django_forms/images/csrf2.png similarity index 100% rename from fr/django_forms/images/images/csrf2.png rename to cs/django_forms/images/csrf2.png diff --git a/fr/django_forms/images/images/drafts.png b/cs/django_forms/images/drafts.png similarity index 100% rename from fr/django_forms/images/images/drafts.png rename to cs/django_forms/images/drafts.png diff --git a/fr/django_forms/images/images/edit_button2.png b/cs/django_forms/images/edit_button2.png similarity index 100% rename from fr/django_forms/images/images/edit_button2.png rename to cs/django_forms/images/edit_button2.png diff --git a/fr/django_forms/images/images/edit_form2.png b/cs/django_forms/images/edit_form2.png similarity index 100% rename from fr/django_forms/images/images/edit_form2.png rename to cs/django_forms/images/edit_form2.png diff --git a/fr/django_forms/images/images/form_validation2.png b/cs/django_forms/images/form_validation2.png similarity index 100% rename from fr/django_forms/images/images/form_validation2.png rename to cs/django_forms/images/form_validation2.png diff --git a/fr/django_forms/images/images/new_form2.png b/cs/django_forms/images/new_form2.png similarity index 100% rename from fr/django_forms/images/images/new_form2.png rename to cs/django_forms/images/new_form2.png diff --git a/fr/django_forms/images/images/post_create_error.png b/cs/django_forms/images/post_create_error.png similarity index 100% rename from fr/django_forms/images/images/post_create_error.png rename to cs/django_forms/images/post_create_error.png diff --git a/cs/django_installation/README.md b/cs/django_installation/README.md new file mode 100755 index 00000000000..1c0841641c6 --- /dev/null +++ b/cs/django_installation/README.md @@ -0,0 +1,5 @@ +# Instalace Django + +> **Poznámka:** Pokud ses již propracovala přes kroky instalace - můžeš jít rovnou na další kapitolu! + +{% include "/django_installation/instructions.md" %} diff --git a/cs/django_installation/instructions.md b/cs/django_installation/instructions.md new file mode 100755 index 00000000000..d7e4e96d811 --- /dev/null +++ b/cs/django_installation/instructions.md @@ -0,0 +1,122 @@ +> Část této kapitoly je založena na tutorialu Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Další část této kapitoly je založena na [django-marcador tutorial](http://django-marcador.keimlink.de/) licencováno pod Creative Commons Attribution-ShareAlike 4.0, mezinárodní licenci. Ochranou známku pro Django-marcador drží Markus Zapke-Gründemann et al. + +## Virtuální prostředí + +Než začneme instalovat Django, nainstalujeme si velmi užitečný nástroj, který pomůže udržet pořádek ve vývojovém prostředí na tvém počítači. Je možné tento krok přeskočit, ale je doporučován. Začít s nejlepším možným nastavením ti ušetří spoustu starostí v budoucnosti! + +Takže pojďme vytvořit **virtuální prostředí** (tzv. *virtualenv*). Virtualenv bude izolovat nastavení Python/Django na základě projektu. To znamená, že změny provedené v jedné webové stránce neovlivní ostatní, které vyvíjíš. Elegantní, že? + +Vše, co musíš udělat je jít do adresáře, ve kterém chceš vytvořit `virtualenv`; Například tvůj domovský adresář. V systému Windows by to mohlo vypadat takto `C:\Users\Name` (kde `Name` je jméno tvého uživatelského účtu). + +Pro tento kurz budeme používat nový adresář `djangogirls` vytvořený v domovském adresáři: + +``` + mkdir djangogirls + cd djangogirls +``` + +Vytvoříme virtualenv, s názvem `myvenv`. Obecný příkaz bude vypadat takto: + +``` + Python3 -m venv myvenv +``` + +### Windows + +Chceš-li vytvořit nový `virtualenv`, je potřeba otevřít konzoli (mluvili jsme o tom v dřívější kapitole - vzpomínáš?) a spusť `C:\Python34\python -m venv myvenv`. Celý příkaz bude vypadat takto: + +``` + C:\Users\Name\djangogirls > C:\Python34\python -m venv myvenv +``` + +kde `C:\Python34\python` je adresář, kam jsme dříve nainstalovali Python a `myvenv` je název `virtualenv`. Můžeš použít i jiné jméno, ale používej malá písmena a nepoužívej mezery, diakritiku nebo speciální znaky. Je také dobrý nápad, abys zvolila krátké jméno - budeš ho používat častokrát! + +### Linux a OS X + +Vytvoření `virtualenv` na Linux a OS X je stejně jednoduché - spusť`python3 -m venv myvenv`. Celý příkaz bude vypadat takto: + +``` + ~/djangogirls$ python3 -m venv myvenv +``` + +`myvenv` je název `virtualenv`. Můžeš použít i jiné jméno, ale drž se těchto pravidel - používej v názvech malá písmena a bez mezer. Je dobrý nápad zvolit krátké jméno - budeš ho používat častokrát! + +> **POZNÁMKA:** Vytvoření virtuálního prostředí na Ubuntu 14.04, v současné době vyhazuje následující chybu: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Chceš-li se tomuto vyhnout, použij tento příkaz `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Práce s virtualenv + +Výše uvedený příkaz vytvoří adresář s názvem `myvenv` (či jiným jménem, které jsi zvolila), který obsahuje tvé virtuální prostředí (v podstatě svazek adresářů a souborů). + +#### Windows + +Spusť virtuální prostředí: + +``` + C:\Users\Name\djangogirls> myvenv\Scripts\activate +``` + +#### Linux a OS X + +Spusť virtuální prostředí: + +``` + ~/djangogirls$ source myvenv/bin/activate +``` + +Nezapomeň nahradit `myvenv` tvým zvoleným jménem `virtualenv`! + +> **Poznámka:** někdy příkaz `source` nemusí být k dispozici. V těchto případech, zkus raději: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Že je `virtualenv` spuštěné, poznáš pokud vidíš výzvu konzole vypadající takto: + +``` + (myvenv) C:\Users\Name\djangogirls> +``` + +nebo: + +``` + (myvenv) ~/djangogirls$ +``` + +Upozornění předpona `(myvenv)` se zobrazí! + +Pracuješ-li ve virtuálním prostředí, `python` bude automaticky odkazovat na správnou verzi, takže můžeš použít `python` místo `python3`. + +OK máme všechny důležité závislosti na místě a konečně můžeme nainstalovat Django! + +## Instalace Django + +Máš své `virtualenv` nastartované a můžeš nainstalovat Django pomocí příkazu `pip`. V konzoli, spusť `pip install django == 1.8` (<0>Poznámka: , používáme zde dvojité rovnítko: `==`). + +``` + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... +``` + +v systému Windows + +> Pokud se ti ukáže chyba při volání pip na platformě Windows, zkontroluj prosím, zda tvoje cesta k projektu neobsahuje mezery, diakritiku a speciální znaky (tj. `C:\Users\User Name\djangogirls`). Pokud ano zvaž přesunutí do jiného místa bez mezer, diakritiky a speciálních znaků (návrh je: `C:\djangogirls`). Po přesunutí opakuj výše uvedený příkaz. + +na Linuxu + +> Pokud se zobrazí chyba při volání pip na Ubuntu 12.04, prosím zkus spustit `python -m pip install -U --force-reinstall pip` k opravě instalace pip ve virtualenv. + +A je to! Teď jsi (konečně) připravena k vytvoření aplikace Django! diff --git a/cs/django_models/README.md b/cs/django_models/README.md new file mode 100755 index 00000000000..2e22a51e2b3 --- /dev/null +++ b/cs/django_models/README.md @@ -0,0 +1,183 @@ +# Django modely + +Nyní chceme vytvořit něco, co bude ukládat všechny příspěvky na náš blog. Ale abychom to mohly udělat, musíme si nejdříve říct něco o `objektech`. + +## Objekty + +V programování se používá koncept zvaný `objektově orientované programování`. Tato myšlenka předpokládá, že místo psaní všeho jako nudný sled programovacích instrukcí můžeme modelovat věci a definovat, jak komunikují mezi sebou navzájem. + +Co tedy je objekt? Je to kolekce vlastností a činností. Zní to divně, ale dáme ti příklad. + +Pokud chceme modelovat kočku, vytvoříme objekt `kočka`, který má nějaké vlastnosti, například `barva`, `věk`, `nálada` (ta je dobrá, špatná, ospalá ;)), `vlastník` (který je objektem `osoba` nebo je možný případ zatoulané kočky, kde bude tato vlastnost prázdná). + +`Kočka` má také některé akce: `předení`, `škrábání` nebo `žraní` (v němž dáváme kočce nějaké `kočičí granule`, které by mohlo být samostatný objekt s vlastnostmi, například `chuť`). + +``` + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste +``` + +Základní představa je popsat skutečné věci v kódu vlastnostmi (nazývané `vlastnosti objektu/object properties`) a akcemi (nazývané `metody/methods`). + +Jak tedy bude vypadat model blogu? + +Musíme odpovědět na otázku: Co je blog post/příspěvek? Jaké by měl mít vlastnosti? + +Určitě budeme v naše blogu potřebovat nějaký text s jeho obsahem a titulkem, že? Bylo by také dobré vědět, kdo příspěvek napsal, takže potřebujeme autora. Nakonec také chceme vědět, kdy byl příspěvek vytvořen a publikován. + +``` + Post + -------- + title + text + author + created_date + published_date +``` + +Jaký druh věcí můžeme s příspěvkem dělat? Bylo by hezké mít nějakou `metodu`, která publikuje příspěvek. + +Takže budeme potřebovat metodu `publish`. + +Vzhledem k tomu, že už víme, čeho chceme dosáhnout, můžeme začít modelování v Djangu! + +## Django model + +Nyní víme, jaký objekt chceme vytvořit, takže můžeme přistoupit k tvorbě Django modelu pro náš příspěvek v blogu. + +Model v Django je zvláštní druh objektu - který je uložen v `databázi`. Databáze je soubor dat. Je to místo, kam budeš ukládat informace o uživatelích a tvých příspěvcích v blogu, atd. Budeme používat SQLite databázi k ukládání dat. To je výchozí databázový adaptér v Djangu – to nám bude nyní stačit. + +Model v databázi si lze představit jako tabulku s řádky (data) a sloupci (údaje). + +### Vytvoření aplikace + +Abychom udržely pořádek, vytvoříme si samostatnou aplikaci uvnitř našeho projektu. Je velmi příjemné mít všechno zorganizované od samého začátku. Chceš-li vytvořit novou aplikaci, je třeba spustit následující příkaz v konzoli (z `djangogirls` adresáře, kde je `manage.py` soubor): + +``` + (myvenv) ~/djangogirls$ python manage.py startapp blog +``` + +Zjistíš, že nový adresář `blog` nyní obsahuje řadu souborů. Adresáře a soubory v našem projektu by měly vypadat následovně: + +``` + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py +``` + +Po vytvoření aplikace musíš také Djangu říct, že by ji měl použít. Uděláme to v souboru `mysite/settings.py`. Musíme najít `INSTALLED_APPS` a přidat řádek, který bude obsahovat `"blog",` `)`. Takže konečná konfigurace by měla vypadat takto: + +```python + INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', + ) +``` + +### Vytvoření modelu pro blog post + +V souboru `blog/models.py` budeme definovat všechny objekty nazývané `modely` - na tomto místě budeme definovat náš blog post. + +Otevři `blog/models.py`, odstraň vše, co v něm je, a vlož následující kód: + +```python + from django.db import models + from django.utils import timezone + + + class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Dvakrát si zkontroluj, že jsi použila dva znaky podtržítko(`_`) na každé straně `str`. Tato konvence se v Pythonu používá často. Někdy je také nazýváme "dunder" (zkratka pro "Double-UNDERscore"). + +Vypadá to děsivě, že? Ale žádný strach, vysvětlíme ti, co tyto řádky znamenají! + +Všechny řádky začínající `from` nebo `import` jsou řádky, které přidávají některé kousky z jiných souborů. Takže namísto kopírování a vkládání stejných věcí v každém souboru, můžeš zahrnout některé části s `from... import...`. + +`class Post(models.Model):` - Tento řádek definuje náš model (Jedná se o `objekt`). + +* `class` je speciální klíčové slovo, které říká, že definujeme objekt. +* `Post` je jméno našeho modelu, můžeme mu dát jiné jméno (ale musíme se vyvarovat speciálních znaků a bílých znaků). Název třídy vždy začínej velkým písmenem. +* `models. Model` znamená, že Post je Django Model, takže Django ví, že by to mělo být uloženo v databázi. + +Nyní definujeme vlastnosti, mluvily jsme o: `title`, `text`, `created_date`, `published_date` a `autor`. To uděláš tak, že definuješ typ každého pole (Je to text? Číslo? Datum? Vztah k jinému objektu, například uživateli?). + +* `models. CharField` - takto definuješ text s omezeným počtem znaků. +* `models. TextField` - toto použiješ na dlouhý text bez omezení. To zní ideálně pro obsah blog post, ne? +* `models. DateTimeField` - definuje datum a čas. +* `models. ForeignKey` - definuje odkaz do jiného modelu. + +Nebudeme vysvětlovat každý kousek kódu, vzhledem k tomu, že by trvalo příliš dlouho. Měla bys se podívat do Django dokumentace, pokud se chceš dozvědět víc o polích modelu a jak definovat jiné věci než výše uvedené (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +Co je `def publish(self):`? Je to `publish` metoda, o které jsme mluvili dříve. `def` znamená, že definuješ funkci/metodu, a `publish` je název metody. Název metody můžeš změnit, pokud chceš. Pravidlo pro pojmenovávání je, že používáme malá písmena a podtržítka místo mezer. Například metoda, která vypočítá průměrnou cenu, se bude jmenovat `calculate_average_price`. + +Metody často něco `vrací/return`. Zde je příklad metoda `__str__`. V tomto případě, když zavoláme metodu `__str__()`, dostaneme text (**řetězec/string**) s názvem Postu. + +Pokud ti něco stále ještě není jasné o modelech, neváhej se zeptat svého kouče! Víme, že je to složité, zvláště, když se dozvíte, co jsou objekty a funkce takto naráz. Doufejme, že to je nyní pro tebe trochu méně magické! + +### Vytvoření tabulek pro modely v databázi + +V posledním kroku přidáš náš nový model do databáze. Nejprve musíme dát Djangu vědět, že mám nějaké změny v modelu (které jsme právě vytvořily!). Napiš `Python manage.py makemigrations blog`. Celý příkaz bude vypadat takto: + +``` + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post +``` + +Django pro nás připravil soubor migrace, který budeme muset aplikovat na naši databázi. Napiš `Python manage.py migrate blog` a výstup by měl vypadat takto: + +``` + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK +``` + +Hurá! Náš Post model je nyní v naší databázi! Bylo by hezké vidět ho v akci, že ano? Přeskoč na další kapitolu a podívej se, jak vypadá tvůj příspěvek! diff --git a/cs/django_orm/README.md b/cs/django_orm/README.md new file mode 100755 index 00000000000..d39e78e7d0c --- /dev/null +++ b/cs/django_orm/README.md @@ -0,0 +1,176 @@ +# Django ORM a QuerySets + +V této kapitole se naučíš, jak se Django spojuje s databází a jak do ní ukládá data. Pojďme na to! + +## Co je QuerySet? + +QuerySet je v podstatě seznam objektů daného modelu. QuerySet ti umožňuje číst data z databáze, filtrovat je a řadit je. + +Je snazší naučit se to na příkladu. Pojďme to zkusit. + +## Django shell + +Otevři svou lokální konzoli (ne na Python Anywhere) a napiš tento příkaz: + +``` + (myvenv) ~/djangogirls$ python manage.py shell +``` + +Mělo by to mít takovýto efekt: + +``` + (InteractiveConsole) + >>> +``` + +Nyní jsi v Django interaktivní konzoli. Je to stejné jako Python konzole, ale s nějakými přídavnými Django kouzly :). Tady můžeš samozřejmě používat i všechny Python příkazy. + +### Všechny objekty + +Pojďme zkusit zobrazit všechny naše příspěvky. To můžeš udělat následujícím příkazem: + +``` + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined +``` + +Ale ne! Ukázala se chybová hláška. Říká nám, že tu není žádný Post objekt (příspěvek). To je správně – zapomněly jsme je importovat! + +``` + >>> from blog.models import Post +``` + +Tohle je jednoduché: importujeme model `Post` z `blog.models`. Pojďme znovu zkusit zobrazit všechny příspěvky: + +``` + >>> Post.objects.all() + [, ] +``` + +To je seznam příspěvků, které jsme dříve vytvořily pomocí Django administrátorského rozhraní. Teď nicméně chceme vytvořit příspěvky použitím Pythonu, tak jak na to? + +### Vytvoř objekt + +Takhle vytvoříš nový Post objekt v databázi: + +``` + >>> Post.objects.create(author=me, title='titulek', text='Test') +``` + +Ale chybí nám tu jedna ingredience: proměnná `me`. Jako autorku potřebujeme vložit instanci `User` (tj. "uživatelka") modelu. Jak to uděláme? + +Nejdříve pojďme importovat User model: + +``` + >>> from django.contrib.auth.models import User +``` + +Jaké uživatele máme v naší databázi? Zkus tohle: + +``` + >>> User.objects.all() + [] +``` + +Tohle je superuser, kterého jsme vytvořily dříve! Pojďme si teď vzít instanci tohoto uživatele: + +```python + me = User.objects.get(username='ola') +``` + +Jak vidíš, dostaly (tj. `get`) jsme uživatele (tj. `user`) s uživatelským jménem (tj. `username`) 'ola'. Pěkný! Samozřejmě ty si to musíš upravit na své jméno. + +Teď můžeme konečně vytvořit příspěvek: + +``` + >>> Post.objects.create(author=me, title='titulek', text='Test') +``` + +Hurá! Chceš se podívat, jestli to fungovalo? + +``` + >>> Post.objects.all() + [, , ] +``` + +A je to tu, další příspěvek v seznamu! + +### Přidej více příspěvků + +Teď si můžeš trochu pohrát a přidat více příspěvků, abys viděla, jak to funguje. Přidej 2 až 3 nové příspěvky a pusť se do další části. + +### Filtrování objektů + +Důležitá součást QuerySetů je možnost je filtrovat. Řekněme, že chceme najít všechny příspěvky, jejichž autorem je uživatel (user) ola. V `Post.objects.all()` použijeme `filter` místo `all`. V závorkách stanovíme podmínky, které musí příspěvek splňovat, aby skončil v našem querysetu. V našem případě je to tak, že `author` se rovná `ja`. Způsob, jakým se to v Django zapisuje, je: `author=ja`. Teď náš kus kódu vypadá takhle: + +``` + >>> Post.objects.filter(author=ja) + [, , , ] +``` + +Nebo možná chceme vidět všechny příspěvky, jež mají slovo 'titulek' v poli `title`? + +``` + >>> Post.objects.filter(title__contains='titulek') + [, ] +``` + +> **Poznámka** Mezi `title` a `contains` jsou dvě podtržítka (`_`). Django ORM používá tuto syntaxi k rozlišení názvů ("title") a operací nebo filterů ("contains"). Pokud použiješ pouze jedno podtržítko, dostaneš chybovou hlášku "FieldError: Cannot resolve keyword title_contains". + +Také můžeš získat seznam všech publikovaných příspěvků. Uděláme to vyfiltrováním všech příspěvků, které mají nastavené `published_date` na nějaké uplynulé datum: + +> > > from django.utils import timezone Post.objects.filter(published_date__lte=timezone.now()) [] + +Bohužel příspěvek, který jsme přidali pomocí Python konzole, ještě není publikován. To můžeme změnit! Nejdřív vezmeme instanci příspěvku, který chceme publikovat: + +``` + >>> post = Post.objects.get(title="Sample title") +``` + +A ten publikujeme pomocí naší metody `publish`! + +``` + >>> post.publish() +``` + +Teď se znovu pokus získat seznam publikovaných příspěvků (3krát zmáčkni šipku nahoru a zmáčkni `enter`): + +``` + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] +``` + +### Řazení objektů + +QuerySety ti také umožňují seřadit seznam objektů. Pojďme je zkusit seřadit podle data vytvoření (`created_date`): + +``` + >>> Post.objects.order_by('created_date') + [, , , ] +``` + +Můžeme je také seřadit obráceně přidáním `-` na začátek: + +``` + >>> Post.objects.order_by('-created_date') + [, , , ] +``` + +### Řetězení QuerySetů + +QuerySety můžeš také kombinovat dohromady pomocí **řetězení**: + +``` + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Je to mocný nástroj, který ti umožňuje psát docela komplexní query. + +Cool! Teď jsi připravená na další část! Pro zavření shell konzole zadej toto: + +``` + >>> exit() + $ +``` diff --git a/cs/django_start_project/README.md b/cs/django_start_project/README.md new file mode 100755 index 00000000000..75017f0e8f9 --- /dev/null +++ b/cs/django_start_project/README.md @@ -0,0 +1,143 @@ +# Tvůj první Django projekt! + +> Část této kapitoly je založena na kurzu Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Části této kapitoly jsou založeny na [django-marcador tutorial][1] licencováno pod Creative Commons Attribution-ShareAlike 4.0 mezinárodní licencí. Ochranou známku pro Django-marcador drží Markus Zapke-Gründemann et al. + + [1]: http://django-marcador.keimlink.de/ + +Chceme vytvořit jednoduchý blog! + +Prvním krokem je začít s novým projektem Django. V podstatě to znamená, že budeš spouštět některé skripty z Djanga, které vytvoří kostru Django projektu pro tebe. To je jen halda adresářů a souborů, které budeme později používat. + +Názvy některých souborů a adresářů jsou pro Django velmi důležité. Neměla bys přejmenovávat soubory, které vytvoříme. Přesouvat je na jiné místo také není dobrý nápad. V Django je třeba zachovat určitou strukturu, abychom mohli najít důležité věci. + +> Nezapomeň spouštět vše ve svém virtualenv. Pokud nevidíš předponu `(myvenv)` ve své konzoli, je potřeba aktivovat virtualenv. Jak se to dělá jsme si vysvětlily v kapitole **Django instalace** v části **práce s virtualenv**. Napiš `myvenv\Scripts\activate` na systému Windows nebo `source myvenv/bin/activate` na systému Mac OS / Linux. + +V MacOS a Linux konzoli bys měla spustit následující příkaz; **nezapomeň přidat tečku `.` na konci**: + +``` + (myvenv) ~/djangogirls$ django-admin startproject mysite . +``` + +V systému Windows; **nezapomeň přidat tečku `.` na konci**: + +``` + (myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . +``` + +> Tečka `.` je zásadní, protože říká, že skript pro instalaci Django se má provést v aktuálním adresáři (pro který je tečka `.` zkratkou - odkazem) +> +> **Poznámka:** Při zadávání těchto příkazů nezapomeň zadat pouze část, která začíná `django admin` nebo `django-admin.py`. `(myvenv) ~/djangogirls$` a `(myvenv) C:\Users\Name\djangogirls>` – tyto části jsou jen příklad cesty, kam budeš zadávat své příkazy. + +`django-admin.py` je skript, který za tebe vytvoří adresáře a soubory. Nyní bys měla mít adresářovou strukturu, která vypadá následovně: + +``` + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py +``` + +`manage.py` je skript, který slouží k řízení tvé webové stránky. S ním bude možné kromě jiného spustit webový server na tvém počítači bez instalovaní čehokoli jiného. + +Soubor `settings.py` obsahuje konfiguraci tvé webové stránky. + +Pamatuješ, jak jsme mluvili o pošťákovi, který zjišťuje kam doručit dopis? Soubor `urls.py` obsahuje seznam vzorů, které používá `urlresolver`. + +Prozatím budeme ignorovat ostatní soubory - nechceme v nich nic měnit. Jediná věc, na kterou nezapomeň, je, že žádný ze souborů se nemaže! + +## Změna nastavení + +Pojďme udělat nějaké změny v `mysite/settings.py`. Otevři soubor pomocí editoru kódu, který jsi si nainstalovala dříve. + +Bylo by hezké mít na svých stránkách správný čas. Přejdi na [wikipedia timezones list][2] a zkopíruj příslušné časové pásmo (TZ). (např. `Europe/Prague`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +V settings.py najdi řádek, který obsahuje `TIME_ZONE`, a uprav jej tak, aby obsahoval tvoje vlastní časové pásmo: + +```python + TIME_ZONE = 'Europe/Prague' +``` + +Uprav "Europe/Prague" podle potřeby. + +Budeme také muset přidat cestu pro statické soubory (o statických souborech a CSS se dozvíme dále v tutorialu). Přejdi na *konec* souboru a pod položkou `STATIC_URL`, přidej nový název `STATIC_ROOT`: + +```python + STATIC_URL = '/static/' + STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## Nastavení databáze + +Existuje mnoho různých databázových softwarů, které mohou ukládat data pro tvůj web. My budeme používat výchozí `sqlite3`. + +Ta je již nastavena v konfiguračním souboru `mysite/settings.py`: + +```python + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } +``` + +Chceš-li vytvořit databázi pro náš blog, spusť následující příkaz v konzoli: `python manage.py migrate` (pro spuštění musíš být v adresáři `djangogirls`, který obsahuje soubor `manage.py`). Pokud vše půjde dobře, měla bys uvidět něco takového: + +``` + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK +``` + +A máme hotovo! Čas spustit webový server a měla bys vidět naše fungující webové stránky! + +Pro spuštění musíš být v adresáři, který obsahuje soubor `manage.py` (adresář `djangogirls`). V konzoli spustíš webový server zadáním `pythonu manage.py runserver`: + +``` + (myvenv) ~/djangogirls$ python manage.py runserver +``` + +Pokud pracuješ v systému Windows a nezdaří se to s chybovou zprávou `UnicodeDecodeError`, použij tento příkaz: + +``` + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 +``` + +Nyní vše, co musíš udělat, je zkontrolovat, zda naše webové stránky běží - otevři svůj prohlížeč (Firefox, Chrome, Safari, Internet Explorer nebo co používáš) a zadej adresu: + +``` + http://127.0.0.1:8000/ +``` + +Webový server ti znemožní použít příkazovou řádkou, dokud jej nezastavíš. Chceš-li zadat další příkazy, spusť nové okno terminálu a aktivuj svůj virtualenv. Chceš-li zastavit server WWW, přepni se zpět do okna, ve kterém je spuštěn, a kombinací kláves CTRL + C - tlačítka CTRL a C, které stiskneš dohromady (na Windows, možná musíš stisknout kombinaci kláves Ctrl + Break) – ukončíš proces. + +Blahopřejeme! Právě jsi vytvořila svůj první web a spustila jej pomocí webového serveru! Není to super? + +![Fungovalo to!][3] + + [3]: images/it_worked2.png + +Připravena pro další krok? Je tu čas k vytvoření nějakého obsahu! diff --git a/fr/django_start_project/images/images/it_worked2.png b/cs/django_start_project/images/it_worked2.png similarity index 100% rename from fr/django_start_project/images/images/it_worked2.png rename to cs/django_start_project/images/it_worked2.png diff --git a/cs/django_templates/README.md b/cs/django_templates/README.md new file mode 100755 index 00000000000..26e3ff248fe --- /dev/null +++ b/cs/django_templates/README.md @@ -0,0 +1,108 @@ +# Django šablony + +Je čas zobrazit nějaká data! Django nám k tomuto účelu poskytuje užitečné vestavěné **šablonové tagy**. + +## Co jsou šablonové tagy? + +V HTML ve skutečnosti nemůžeš použít Python kód, protože prohlížeče mu nerozumí. Znají pouze HTML. Víme, že HTML je spíše statické, zatímco Python je mnohem dynamičtější. + +**Django šablonové tagy** nám umožňují přenést věci podobné Pythonu do HTML, abys mohla postavit dynamickou webovou stránku rychleji a snadněji. + +## Zobraz šablonu se seznamem příspěvků + +V předchozí kapitole jsme daly naší šabloně seznam příspěvků v proměnné `posts`. Teď to zobrazíme v HTML. + +V Django šabloně se proměnná vypíše pomocí dvojitých složených závorek s názvem proměnné uvnitř. Takhle: + +```html + {{ posts }} +``` + +Zkus to ve své šabloně `blog/templates/blog/post_list.html`. Nahraď vše od druhého `
` do třetího `
` řádkou `{{ posts }}`. Ulož soubor a obnov stránku, aby sis prohlédla výsledek: + +![Figure 13.1][1] + + [1]: images/step1.png + +Jak vidíš, dostali jsme toto: + +``` + [, ] +``` + +To znamená, že to Django chápe jako seznam objektů. Vzpomínáš si z kapitoly **Úvod do pythonu**, jak můžeme zobrazit seznam? Ano, pomocí for smyček! V Django šabloně je použiješ takto: + +```html + {% for post in posts %} + {{ post }} + {% endfor %} +``` + +Zkus udělat tohle ve své šabloně. + +![Figure 13.2][2] + + [2]: images/step2.png + +Funguje to! Ale chceme, aby se zobrazovaly jako ty statické příspěvky, které jsme vytvořili dříve v kapitole **Úvod do HTML**. Můžeš smíchat HTML tagy se šablonovými. Naše `body` bude vypadat takhle: + +```html + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +{% raw %}Všechno, co dáš mezi `{% for %}` a `{% endfor %}`, se zopakuje pro každý objekt v seznamu. Obnov svou stránku:{% endraw %} + +![Figure 13.3][3] + + [3]: images/step3.png + +Všimla sis, že jsme tentokrát použily lehce odlišnou notaci (`{{ post.title }}` nebo `{{ post.text }}`)? Přistupujeme k datům v každém poli definovaném v našem `Post` modelu. Dále `|linebreaksbr` posílá text příspěvku filtrem, aby převedl zalomení řádků na odstavce. + +## Ještě jedna věc + +Bylo by dobré vidět, jestli tvá webová stránka bude stále fungovat i na webu, že? Pojďme zkusit další nasazení/deploy na PythonAnywhere. Tady je rekapitulace postupu... + +* Nejdřív hoď svůj kód na Github + +``` + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push +``` + +* Pak se přihlaš do [PythonAnywhere][4] a jdi do **Bash konzole** (nebo vytvoř novou) a zadej: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ git pull + [...] +``` + +* Nakonec jdi na záložku [Web][5] a klikni na **Reload**. Tvá stránka by měla být aktuální! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Gratulujeme! Teď zkus přidat nové příspěvky ve tvém Django administračním rozhraní (nezapomeň přidat published_date!), potom obnov stránku a podívej se, jestli se nové příspěvky zobrazí. + +Funguje to dokonale? Jsme hrdí! Odpočiň si na chvíli od počítače, zasloužíš si přestávku :) + +![Figure 13.4][6] + + [6]: images/donut.png diff --git a/fr/django_templates/images/images/donut.png b/cs/django_templates/images/donut.png similarity index 100% rename from fr/django_templates/images/images/donut.png rename to cs/django_templates/images/donut.png diff --git a/fr/django_templates/images/images/step1.png b/cs/django_templates/images/step1.png similarity index 100% rename from fr/django_templates/images/images/step1.png rename to cs/django_templates/images/step1.png diff --git a/fr/django_templates/images/images/step2.png b/cs/django_templates/images/step2.png similarity index 100% rename from fr/django_templates/images/images/step2.png rename to cs/django_templates/images/step2.png diff --git a/fr/django_templates/images/images/step3.png b/cs/django_templates/images/step3.png similarity index 100% rename from fr/django_templates/images/images/step3.png rename to cs/django_templates/images/step3.png diff --git a/cs/django_urls/README.md b/cs/django_urls/README.md new file mode 100755 index 00000000000..e8f24e413f4 --- /dev/null +++ b/cs/django_urls/README.md @@ -0,0 +1,126 @@ +# Django URL + +Chystáme se napsat naši první webovou stránku: homepage pro tvůj blog! Ale nejdřív si něco málo řekneme o Django URL. + +## Co je adresa URL? + +Adresa URL je jednoduše webová adresa. Adresu URL můžeš vidět pokaždé, když navštívíš webové stránky - je vidět v adresním řádku tvého prohlížeče (Ano! `127.0.0.1:8000` je adresa URL! A `https://djangogirls.org` je také adresa URL): + +![Url][1] + + [1]: images/url.png + +Každá stránka na internetu potřebuje svou vlastní URL. Tímto způsobem aplikace ví, co by měla ukázat uživateli, který otevře URL. V Djangu používáme takzvaný `URLconf` (URL konfigurace). URLconf je sada vzorů, podle kterých Django zpracuje URL a pokusí se najít správné view. + +## Jak fungují URL v Djangu? + +Pojďme otevřít soubor `mysite/urls.py` v tvém zvoleném editoru kódu a uvidíme, jak vypadá: + +```python + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + ] +``` + +Jak vidíš, Django už má tady něco pro nás připravené. + +Řádky, které začínají na `#`, jsou komentáře - to znamená, že tyto řádky nebudou spuštěny v Pythonu. Docela užitečný nástroj, ne? + +Admin URL, které jsi navštívila v předchozí kapitole, už je tady: + +```python + url(r'^admin/', include(admin.site.urls)), +``` + +To znamená, že pro každou adresu URL, která začíná na `admin/`, bude Django hledat odpovídající *view*. V tomto případě je zde vložen odkaz na soubor s admin URL, takže není vše zabaleno v jednom souboru – je to mnohem čitelnější a jednodušší. + +## Regex + +Zajímá tě, jak Django porovnává URL pro views? No, tato část je složitější. Django používá `regex`, což je zkratka pro "regulární výrazy". Regex má hodně (hodně!) pravidel, ze kterých tvoří vzorek pro vyhledávání. Vzhledem k tomu, že regex jsou hodně pokročilou záležitostí, nepůjdeme do podrobností, jak fungují. + +Pokud chceš porozumět tomu, jak jsme vytvořili vzory, zde je příklad procesu - budeme potřebovat pouze omezenou sadu pravidel pro vyjádření vzoru, který hledáme, jmenovitě: + +``` + ^ pro začátek textu + $ pro konec textu + \d číslice + + označuje poslední položku, které by měla být zopakována + () k zachycení/ohraničení části vzoru +``` + +Cokoliv jiného v definici URL budeme brát doslovně. + +Nyní si představ, že máš webové stránky s adresou: `http://www.mysite.com/post/12345/`, kde `12345` je číslo tvého příspěvku. + +Psaní oddělených views pro všechna čísla příspěvků by bylo opravdu otravné. S regulárními výrazy můžeme vytvořit vzor, který bude odpovídat adrese URL a extrahovat z něj číslo, které potřebujeme: `^ post/(\d+) / $`. Pojďme si rozebrat kousek po kousku, co zde děláme: + +* **^ post/** říká Djangu: vezmi cokoliv, co má začátku adresy URL text `post/` (hned za `^`) +* **(\d+)** znamená, že bude následovat číslo (jedno nebo více číslic) a že chceme číslo zachytit a extrahovat +* **/** říká djangu, že by měl následovat další znak `/` +* **$** pak označuje konec adresy URL, což znamená, že pouze řetězce s `/` na konci budou odpovídat tomuto vzoru + +## Tvoje první Django URL! + +Čas na vytvoření našeho prvního URL! Chceme, aby ' http://127.0.0.1:8000 /' bylo domovskou stránkou našeho blogu a zobrazilo seznam postů. + +Chceme také, aby soubor `mysite/urls.py` zůstal čistý, takže budeme importovat adresy URL z našeho `blogu` do hlavního souboru `mysite/urls.py`. + +Odstraň zakomentované řádky (řádky začínající `#`) a přidej řádek, který bude importovat `blog.urls` do hlavní URL('').`''`). + +Tvůj `Mysite/urls.py` soubor by měl nyní vypadat takto: + +```python + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), + ] +``` + +Django nyní bude přesměrovávat vše, co přichází na ' http://127.0.0.1:8000/', do `blog.urls ` a hledat zde další instrukce. + +Při psaní regulárních výrazů v Pythonu se vždy přidává `r` před řetězec. To je užitečný tip pro Python, že řetězec může obsahovat zvláštní znaky, které nejsou určeny přímo pro Python samotný, ale pro regulární výraz namísto toho. + +## blog.urls + +Vytvoř nový prázdný soubor `blog/urls.py`. Přidej tyto dvě první řádky: + +```python + from django.conf.urls import url + from . import views +``` + +Zde jsme jen importovaly Django metody a všechny naše `views` z aplikace `blogu` (zatím žádné nemáme, ale dostaneme se k tomu za chvíli). + +Poté můžeme přidat náš první URL vzor: + +```python + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + ] +``` + +Jak vidíš, právě jsme přiřadili `view` nazvané `post_list`, k URL `^$`. Tento regulární výraz znamená `^` (začátek řetězce), následuje `$` (konec řetězce) - výrazu bude odpovídat pouze prázdný řetězec. Tak je to správně, protože v Django URL překladači/resolveru, část adresy ' http://127.0.0.1:8000 /' není součástí adresy URL. Tento vzor řekne Djangu, že `views.post_list` je správné místo, kam jít, když někdo vstoupí na tvé webové stránky na adrese ' http://127.0.0.1:8000 /'. + +Poslední část `name = 'post_list'` je název adresy URL, která bude použita k identifikaci view. Název URL může být stejný jako název view, ale také může být úplně jiný. Pojmenované URL budeme používat později v projektu, proto je důležité pojmenovat všechny adresy URL v aplikaci. Také by ses měla snažit udržet názvy adres URL jedinečné a snadno zapamatovatelné. + +Všechno v pořádku? Otevři http://127.0.0.1:8000 / v prohlížeči a uvidíš výsledek. + +![Error][2] + + [2]: images/error1.png + +Stránka přestala fungovat, co? Neboj se, je to chyba, které se nemusíš obávat! Tyto hlášky jsou vlastně docela užitečné: + +Můžeš si v ní přečíst, že neexistuje **žádný atribut/no attribute "post_list"**. Připomíná ti *post_list* něco? Tak jsme nazvali naše view! Znamená to, že vše je na svém místě, ale prostě jsme ještě nevytvořili naše *view*. Žádný strach, vytvoříme ho za chvilku. + +> Pokud chceš vědět více o Django URLconfs, podívej se na oficiální dokumentaci: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/fr/django_urls/images/images/error1.png b/cs/django_urls/images/error1.png similarity index 100% rename from fr/django_urls/images/images/error1.png rename to cs/django_urls/images/error1.png diff --git a/fr/django_urls/images/images/url.png b/cs/django_urls/images/url.png similarity index 100% rename from fr/django_urls/images/images/url.png rename to cs/django_urls/images/url.png diff --git a/cs/django_views/README.md b/cs/django_views/README.md new file mode 100755 index 00000000000..f2365ce5978 --- /dev/null +++ b/cs/django_views/README.md @@ -0,0 +1,38 @@ +# Django views – je čas začít tvořit! + +Nejdříve se musíme zbavit chyb, které jsme vytvořily v předchozí kapitole :) + +*View* je místo, kam píšeme "logiku" naší aplikace. Bude požadovat informace z `modelu`, který jsi vytvořila dříve, a předá je `šabloně`. Šablonu vytvoříme v příští kapitole. View jsou vlastně jen Python funkce, které jsou o trochu složitější než funkce z kapitoly **Úvod do Pythonu**. + +View se dávají do souboru `views.py`. My si teď přidáme naše vlastní *view* do souboru `blog/views.py`. + +## blog/views.py + +OK, pojďme otevřít tento soubor a podívat se, co tam je: + +```python + from django.shortcuts import render + + # Create your views here. +``` + +Zatím zde není příliš informací. Nejjednodušší *view* může vypadat následovně. + +```python + def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Jak vidíš vytvořily, jsme metodu (`def`) nazvanou `post_list`, která přebírá `request`(žádost) a `return` (vrací) metodu `render`, která bude vykreslovat naši šablonu `blog/post_list.html`. + +Ulož soubor, přejdi na http://127.0.0.1:8000/ a podívej se, co se nám nyní zobrazí. + +Další chyba! Přečti si, co je špatně nyní: + +![Error][1] + + [1]: images/error.png + +Je to jednoduché: *TemplateDoesNotExist*. Musíme opravit tuto chybu a v následující kapitole vytvořit šablonu! + +> Další informace ohledně Django views získáš v oficiální dokumentaci na: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/fr/django_views/images/images/error.png b/cs/django_views/images/error.png similarity index 100% rename from fr/django_views/images/images/error.png rename to cs/django_views/images/error.png diff --git a/cs/domain/README.md b/cs/domain/README.md new file mode 100755 index 00000000000..45882b8235f --- /dev/null +++ b/cs/domain/README.md @@ -0,0 +1,71 @@ +# Doména + +Heroku ti přidělil doménu, ale je dlouhá, těžce zapamatovatelná a ošklivá. Bylo by super mít krátký a snadno zapamatovatelný název domény, ne? + +V této kapitole tě naučíme, jak si koupit doménu a nasměrovat ji na Heroku! + +## Kde si zaregistrovat doménu? + +Typická doména stojí kolem 15 dolarů ročně. Existují levnější a dražší varianty, podle poskytovatele. Existuje mnoho společností, které nabízejí koupi domény: jednoduše pomocí [vyhledávání google][1] nalezneš stovky možností. + + [1]: https://www.google.com/search?q=register%20domain + +Naše oblíbená je [I want my name][2]. Inzerují se jako "bezbolestný doménový management" a je to opravdu bezbolestné. + + [2]: https://iwantmyname.com/ + +## Jak si zaregistrovat doménu na IWantMyName? + +Přejdi na [iwantmyname][3] a zadej doménu, kterou chceš zaregistrovat, do pole Search/Hledat. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +Nyní bys měla vidět seznam všech dostupných domén s termínem, který jsi vložila do pole Hledat. Jak vidíš, veselý obličej znamená, že doména je k dispozici pro tvůj nákup, a smutná tvář znamená, že je již obsazená. + +![][5] + + [5]: images/2.png + +Rozhodli jsme se koupit `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Přejdi k pokladně/checkout. Nyní by ses měla přihlásit do iwantmyname, pokud ještě nemáš účet. Poté poskytneš informace o kreditní kartě a koupíš doménu! + +Pak klepni na tlačítko `domény` v menu a vyber nově zakoupenou doménu. Vyber ji a klepni na odkaz `Spravovat záznamy DNS/manage DNS record`: + +![][7] + + [7]: images/4.png + +Nyní je třeba najít tento formulář: + +![][8] + + [8]: images/5.png + +A vyplnit jej s následujícími podrobnosti: - Hostname: www - typ: CNAME - hodnota: vaši doménu z Heroku (například djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Klepni na tlačítko Přidat a změny se uloží - uvidíš je v dolní části. + +Změny se mohou projevit až za několik hodin, než začne fungovat tvá doména, tak buď trpělivá! + +## Konfigurace domény v Heroku + +Musíš také říci Heroku, kterou doménu chceš použít jako vlastní. + +Přejdi na [Heroku Dashboard][10], přihláš se k účtu Heroku a vyber si aplikaci. Poté přejdi do aplikace nastavení a přidej doménu v sekci `domény` a ulož provedené změny. + + [10]: https://dashboard.heroku.com/apps + +A je to! diff --git a/cs/dynamic_data_in_templates/README.md b/cs/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..e72dacd7929 --- /dev/null +++ b/cs/dynamic_data_in_templates/README.md @@ -0,0 +1,75 @@ +# Dynamická data v šablonách + +Máme různé části na svém místě: `Post` model je definován v `models.py`, `post_list` máme v `views.py` a máme přidanou šablonu. Ale jak skutečně přinutíme naše příspěvky objevit se v naší HTML šabloně? Protože to je to, co chceme: Vzít nějaký obsah (modely uložené v databázi) a zobrazit je hezky v naší šabloně, správně? + +To je přesně to, co *views* mají dělat: spojovat modely a šablony. Do našeho `post_list` *view* budeme potřebovat vzít modely, které chceme zobrazit a předat je šabloně. Takže v podstatě se ve *view* rozhodneme, co (model) bude zobrazeno v šabloně. + +OK, tak jak toho dosáhneme? + +Potřebujeme otevřít `blog/views.py`. Prozatím `post_list` *view* vypadá takhle: + +```python + from django.shortcuts import render + + def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Vzpomínáš si, jak jsme mluvily o zahrnování kódu napsaného v různých souborech? Teď je ten moment, kdy musíme zahrnout model, který jsme napsaly do `models.py`. Přidáme tuto řádku `from .models import Post`: + +```python + from django.shortcuts import render + from .models import Post +``` + +Tečka po `from` znamená *aktuální adresář* nebo *aktuální aplikace*. Protože se `views.py` a `models.py` nachází ve stejném adresáři, můžeme jednoduše použít `.` a jméno souboru (bez `.py`). Potom importujeme název modelu (`Post`). + +Ale co dál? Abychom mohly vzít skutečné příspěvky z `Post`, potřebujeme něco, čemu říkáme `QuerySet`. + +## QuerySet + +Už bys měla mít povědomí o tom, jak QuerySety fungují. To jsme probraly v kapitole [Django ORM (QuerySets)][1]. + + [1]: ../django_orm/README.md + +Takže teď nás zajímá seznam příspěvků, které jsou publikovány a setříděny podle `published_date`, že? To jsme už udělaly v kapitole na QuerySety! + +```python + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Teď tento kousek kódu vložíme do souboru `blog/views.py` do funkce `def post_list(request)`: + +```python + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + +Vezmi, prosím, na vědomí, že jsme vytvořily *proměnnou* pro QuerySet: `posts`. Považuj to za název našeho QuerySetu. Od teď k němu budeme referovat tímto názvem. + +Kód také používá funkci `timezone.now()`, takže potřebujeme přidat import pro `timezone`. + +Poslední chybějící část je předat `posts` QuerySet do šablony (jak ho zobrazit si ukážeme v další kapitole). + +Ve funkci `render` už máme parametr `request` (všechno, co přijmeme od uživatele přes internet) a šablonu `'blog/post_list.html'`. Poslední parametr, který vypadá takhle: `{}`, je místo, kam můžeme přidat nějaké věci, u kterých chceme, aby je šablona mohla používat. Potřebujeme je pojmenovat (teď zůstaneme u `'posts'` :)). Mělo by to vypadat takhle: `{'posts': posts}`. Všimni si, prosím, že část před `:` je string: musíš ho obalit uvozovkami `''`. + +A nakonec by náš `blog/views.py` soubor měl vypadat takhle: + +```python + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +A je to! Čas jít zpět do šablony a zobrazit tento QuerySet! + +Pokud si chceš přečíst něco víc o QuerySetech v Django, měla by ses podívat sem: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ diff --git a/cs/extend_your_application/README.md b/cs/extend_your_application/README.md new file mode 100755 index 00000000000..37addb964dc --- /dev/null +++ b/cs/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Rozšíření tvé aplikace + +Dokončily jsme již všechny kroky potřebné k vytvoření našeho webu: víme, jak napsat model, url, view a šablonu. Víme také, jak udělat naše webové stránky pěkné. + +Čas na procvičení! + +První věc, kterou potřebujeme v našem blogu, je pochopitelně stránka, která zobrazí jeden příspěvek, že ano? + +Již máme `Post` model, takže nebudeme muset přidávat nic k `models.py`. + +## Vytvoření šablony odkazu na post detail + +Začneme s přidáním odkazu do `blog/templates/blog/post_list.html` souboru. Zatím by měl vypadat takto: + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + + +{% raw %}Chceme mít odkaz ze seznamu příspěvků na stránku detail příspěvku. Změňme `< h1 >< href ="">{{ post.title }}< /a>` tak, aby odkazoval na stránku detailu příspěvku:{% endraw %} + +```html +

{{ post.title }}

+``` + +{% raw %}Čas k vysvětlení tajemného `{% url 'post_detail' pk=post.pk %}`. Jak asi tušíš, `{% %}` tato notace znamená, že používáme Django šablonovací značky. Tentokrát použijeme jednu, která pro nás vytvoří adresu URL.{% endraw %} + +`blog.views.post_detail` je cesta k `post_detail` *view*, který chceme vytvořit. Poznámka: `blog` je název naší aplikace (adresář `blog`), `views` je jméno ze souboru, `views.py` a poslední kousek - `post_detail` - je název *view*. + +Teď, když půjdeme na: http://127.0.0.1:8000/, dostaneme chybu (což očekáváme, protože nemáme adresu URL nebo *view* pro `post_detail`). View bude vypadat takto: + +![NoReverseMatch error][1] + + [1]: images/no_reverse_match2.png + +## Vytváříme adresu URL na detail příspěvku + +Pojďme vytvořit adresu URL v `urls.py` pro náš `post_detail` *view*! + +Chceme, aby se detail našeho prvního příspěvku zobrazil na této **URL**: http://127.0.0.1:8000/post/1/ + +Pojďme vytvořit adresu URL v souboru `blog/urls.py` odkazující Django na *view* s názvem `post_detail`, který bude zobrazovat celý příspěvek blogu. Přidej řádek `url (r'^post/(?)P< pk>[0-9]+)/$', views.post_detail, name='post_detail'),` do souboru `blog/urls.py`. Tento soubor by měl vypadat takto: + +```python + from django.conf.urls import url + from . import views + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + ] +``` + +Tato část `^post/(?)P[0-9] +)/$` vypadá děsivě, ale bez obav - my ti to vysvětlíme: - začíná to `^` – "to znamená začátek řetězce" - `post/` znamená pouze to, že po začátku by adresa URL měla obsahovat slovo **post** a **/**. Zatím dobré. - `(?P[0-9]+)` - Tato část je složitější. Znamená to, že Django vezme vše, co zde bude umístěné, a přesune to do view do proměnné s názvem `pk`. `[0-9]` nám také říká, že to může být pouze číslo, ne písmeno (takže cokoliv mezi 0 a 9). `+` znamená, že je zde má být jedna nebo více číslic. Takže něco jako `http://127.0.0.1:8000/post //` není platné URL, ale `http://127.0.0.1:8000/post/1234567890/` je naprosto v pořádku! -`/` - pak potřebujeme **/** znovu znak / - `$` - znamená "konec" řetězce! + +Znamená to, že pokud zadáte `http://127.0.0.1:8000/post/5/` do prohlížeče, Django pochopí, že hledáte *view* s názvem `post_detail` a přenese informaci, že `pk` se rovná `5` do *view*. + +`pk` je zkratka pro `primární klíč`. Tento název se často používá v Django projektech. Ale můžeš si své proměnné pojmenovat jak chceš (nezapomeň: malá písmena a `_` namísto mezer!). Například namísto `(?. P [0-9]+)` máme proměnnou `post_id`, takže tento kousek pak vypadá takto: `(?P< post_id> [0-9]+)`. + +OK, přidaly jsme nový vzor adresy URL do `blog/urls.py`! Musíme obnovit stránku: http://127.0.0.1:8000/. Ještě další chyba, jak jsme čekaly! + +![AttributeError][2] + + [2]: images/attribute_error2.png + +Pamatuješ si, jaký je další krok? Jistě: Přidat view! + +## Přidání view pro detail příspěvku + +Tentokrát má náš *view* uveden dodatečný parametr `pk`. Náš *view* potřebuje tento parametr zachytit, že? Takže definujeme naši funkci jako `def post_detail (request, pk):`. Všimni si, že musíme použít přesně stejný název jako ten, který jsme určili v URL (`pk`). Vynechání této proměnné je nesprávné a bude mít za následek chybu! + +A teď chceme dostat jeden a pouze jeden příspěvek z blogu. K tomu můžeme použít querysets jako je tento: + +```python + Post.objects.get(pk=pk) +``` + +Ale tento kód má problém. Pokud neexistuje žádný `Post` s `primárním klíčem` (`pk`), dostaneme velice nepěknou chybu! + +![DoesNotExist error][3] + + [3]: images/does_not_exist2.png + +A to my nechceme! Ale samozřejmě Django přichází s něčím, co nám to pomůže ošetřit za nás: `get_object_or_404`. V případě, že neexistuje žádný `Post` s daným `pk`, zobrazí se mnohem hezčí stránka (nazývaná `Page Not Found 404`). + +![Page not found][4] + + [4]: images/404_2.png + +Dobrou zprávou je, že můžeš skutečně vytvořit vlastní stránku `Page Not Found 404` a udělat ji tak pěkně, jak jen chceš. Ale to teď není tak důležité, takže to přeskočíme. + +Ok, čas k přidání *view* do našeho souboru `views.py`! + +Měla bys otevřít `blog/views.py` a přidat následující kód: + +```python + from django.shortcuts import render, get_object_or_404 +``` + +Poblíž jiné řádky `from`. A na konec souboru přidáme náš *view*: + +```python + def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Ano. Je na čase aktualizovat stránku: http://127.0.0.1:8000 / + +![Post list view][5] + + [5]: images/post_list2.png + +Fungovalo to! Ale co se stane, když klepneš na odkaz v názvu příspěvku? + +![TemplateDoesNotExist error][6] + + [6]: images/template_does_not_exist2.png + +Ach ne! Další chyba! Ale my už víme, jak s tím naložit správně. Musíme přidat šablonu. + +## Vytvoření šablony pro detail příspěvku + +Vytvoříme soubor `blog/templates/blog` s názvem `post_detail.html`. + +Celý příkaz bude vypadat takto: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + +Opět rozšiřujeme `base.html`. V bloku `content` chceme zobrazit published_date příspěvku (pokud existuje), název a text. Ale měli bychom probrat některé důležité věci. + +{% raw %} `{% if ... %} ... {% endif %}` je značka šablony, kterou můžeme použít, když chceme něco zkontrolovat (nezapomeň `, if... else...` v kapitole **Úvod do Pythonu**?). V tomto případě chceme zjistit, jestli `published_date` příspěvku není prázdný.{% endraw %} + +OK, teď můžeme aktualizovat naše stránky a uvidíš, jestli `Page Not Found` je pryč. + +![Post detail page][7] + + [7]: images/post_detail2.png + +Hurá! Funguje to! + +## Ještě jedna věc: čas nasadit aplikaci! + +Bylo by dobré zjistit, jestli naše webové stránky budou stále fungovat na PythonAnywhere. Zkusme je znovu nasadit. + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push +``` + +* Pak v [Bash konzoli PythonAnywhere][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +* Nakonec jdi na [kartu Web][9] a klikni na **Reload**. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +A mělo by to být! Gratulujeme :) diff --git a/fr/extend_your_application/images/images/404_2.png b/cs/extend_your_application/images/404_2.png similarity index 100% rename from fr/extend_your_application/images/images/404_2.png rename to cs/extend_your_application/images/404_2.png diff --git a/fr/extend_your_application/images/images/attribute_error2.png b/cs/extend_your_application/images/attribute_error2.png similarity index 100% rename from fr/extend_your_application/images/images/attribute_error2.png rename to cs/extend_your_application/images/attribute_error2.png diff --git a/fr/extend_your_application/images/images/does_not_exist2.png b/cs/extend_your_application/images/does_not_exist2.png similarity index 100% rename from fr/extend_your_application/images/images/does_not_exist2.png rename to cs/extend_your_application/images/does_not_exist2.png diff --git a/cs/extend_your_application/images/no_reverse_match2.png b/cs/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/cs/extend_your_application/images/no_reverse_match2.png differ diff --git a/fr/extend_your_application/images/images/post_detail2.png b/cs/extend_your_application/images/post_detail2.png similarity index 100% rename from fr/extend_your_application/images/images/post_detail2.png rename to cs/extend_your_application/images/post_detail2.png diff --git a/fr/extend_your_application/images/images/post_list2.png b/cs/extend_your_application/images/post_list2.png similarity index 100% rename from fr/extend_your_application/images/images/post_list2.png rename to cs/extend_your_application/images/post_list2.png diff --git a/fr/extend_your_application/images/images/template_does_not_exist2.png b/cs/extend_your_application/images/template_does_not_exist2.png similarity index 100% rename from fr/extend_your_application/images/images/template_does_not_exist2.png rename to cs/extend_your_application/images/template_does_not_exist2.png diff --git a/cs/how_the_internet_works/README.md b/cs/how_the_internet_works/README.md new file mode 100755 index 00000000000..3543d4bd56a --- /dev/null +++ b/cs/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# Jak funguje internet + +> Tato kapitola je inspirována přednáškou "How the Internet works", kterou přednesla Jessica McKellar (http://web.mit.edu/jesstess/www/). + +Internet jistě používáš každý den. Ale víš ve skutečnosti co se stane, když do prohlížeče napíšeš adresu jako https://djangogirls.org a zmáčkneš `enter`? + +První věc, které musíš rozumět, je, že webová stránka je jen pár souborů uložených na hard disku. Přesně jako tvé filmy, hudba nebo obrázky. Je tu ale něco, co dělá webové stránky unikátními: obsahují počítačový kód nazývaný HTML. + +Pokud je ti programování zcela cizí, z počátku pro tebe může být těžké HTML pochopit, ale tvé webové prohlížeče (jako Chrome, Safari, Firefox atd.) jej milují. Webové prohlížeče jsou navrženy tak, aby tomuto kódu rozuměly, plnily instrukce a zobrazovaly soubory, ze kterých je tvá stránka vytvořena, přesně tak, jak chceš. + +Jako každý soubor potřebujeme HTML soubory ukládat někam na hard disk. Pro internet používáme speciální, mocné počítače nazývané *servery*. Nemají obrazovku, myš ani klávesnici, protože jejich hlavním účelem je skladovat data a servírovat je. Proto je nazýváme *servery* -- protože ti *servírují* data. + +OK, ale chceš vědět jak internet vypadá, že ano? + +Nakreslili jsme pro tebe obrázek! Vypadá takhle: + +![Figure 1.1][1] + + [1]: images/internet_1.png + +Vypadá to jako pěkný bordel, že? Ve skutečnosti je to síť propojených strojů (výše zmíněných *serverů*). Stovek tisíc strojů! Mnoho, mnoho kilometrů kabelů kolem celého světa! Můžeš navštívit stránku mapování podmořských kabelů (http://submarinecablemap.com/), abys viděla, jak komplikovaná tato síť je. Tady je screenshot z té stránky: + +![Figure 1.2][2] + + [2]: images/internet_3.png + +Není to fascinující? Samozřejmě není možné mít dráty mezi každými dvěma stroji připojenými k internetu. Proto abychom získaly přístup ke konkrétnímu počítači (třeba k tomu, na kterém je uložena stránka https://djangogirls.org), musí být požadavek postupně předáván mezi mnoha různými stroji. + +Vypadá to takhle: + +![Figure 1.3][3] + + [3]: images/internet_2.png + +Představ si, že když napíšeš https://djangogirls.org, pošleš dopis, ve kterém stojí "Drahé Django Girls, chci si prohlédnout stránku djangogirls.org. Pošlete mi ji, prosím!" + +Tvůj dopis se pošle na tvou nejbližší poštu. Potom se pošle na jinou poštu, která je trochu blíže tvému adresátovi, potom na další a další, až se doručí do cílové destinace. Jediná unikátní věc je, že když pošleš hodně dopisů (*data paketů*) na stejné místo, můžou se tam dostat přes naprosto jiné pošty (*routery*). To závisí na tom, jak jsou na každé poště distribuovány. + +![Figure 1.4][4] + + [4]: images/internet_4.png + +Ano, je to takhle jednoduché. Odešleš zprávu a očekáváš nějakou odpověď. Samozřejmě, místo papíru a pera používáš byty dat, ale princip je stejný! + +Místo adres s názvem ulice, města a poštovním kódem používáme IP adresy. Tvůj počítač nejprve požádá DNS server (Domain Name System) o překlad djangogirls.org do IP adresy. Funguje to trochu jako staromódní telefonní seznam, kde sis mohla vyhledat jméno člověka, na kterého potřebuješ kontakt, a najít jeho telefonní číslo a adresu. + +Když posíláš dopis, musí mít určité náležitosti, aby mohl být správně doručen: adresu, známku atp. Také používáš jazyk, kterému adresát rozumí, že? Stejné platí o *data paketech*, které posíláš, abys viděla webovou stránku. My používáme protokol zvaný HTTP (Hypertext Transfer Protocol). + +Takže když máš webovou stránku, potřebuješ *server* (stroj), na kterém může žít. Když *server* přijme přicházející *požadavek/request* (v dopise), pošle zpátky tvoji webovou stránku (v dalším dopise). + +Jelikož je toto Django tutoriál, budeš se ptát, co Django dělá. Když odesíláš odpověď, ne vždy chceš, aby se všem odeslala stejná věc. Je mnohem lepší, když jsou tvé dopisy personalizované, obzvláště pro osobu, která ti právě napsala, že? Django ti pomáhá s vytvářením těchto personalizovaných, zajímavých dopisů :). + +Dost řečí, je čas tvořit! diff --git a/fr/how_internet_works/images/internet_1.png b/cs/how_the_internet_works/images/internet_1.png similarity index 100% rename from fr/how_internet_works/images/internet_1.png rename to cs/how_the_internet_works/images/internet_1.png diff --git a/fr/how_internet_works/images/internet_2.png b/cs/how_the_internet_works/images/internet_2.png similarity index 100% rename from fr/how_internet_works/images/internet_2.png rename to cs/how_the_internet_works/images/internet_2.png diff --git a/fr/how_internet_works/images/internet_3.png b/cs/how_the_internet_works/images/internet_3.png similarity index 100% rename from fr/how_internet_works/images/internet_3.png rename to cs/how_the_internet_works/images/internet_3.png diff --git a/cs/how_the_internet_works/images/internet_4.png b/cs/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/cs/how_the_internet_works/images/internet_4.png differ diff --git a/cs/html/README.md b/cs/html/README.md new file mode 100755 index 00000000000..80045ca8647 --- /dev/null +++ b/cs/html/README.md @@ -0,0 +1,216 @@ +# Úvod do HTML + +Co je to šablona? + +Šablona je soubor, který můžeme opakovaně použít pro prezentaci různých informací v konzistentním formátu - například bys mohla šablonu použít pro psaní dopisu, protože ačkoli každý dopis může obsahovat jinou zprávu a být adresován jiné osobě, všechny dopisy budou sdílet stejný formát. + +Formát Django šablony je popsán v jazyku nazývaném HTML (Je to to stejné HTML, které jsme zmínili v první kapitole **Jak funguje internet**). + +## Co je HTML? + +HTML je jednoduchý kód, který je interpretován tvým webovým prohlížečem - jako je Chrome, Firefox nebo Safari - aby se uživateli zobrazila webová stránka. + +HTML je zkratka od "HyperText Markup Language". **HyperText** znamená, že je to typ textu, který podporuje hypertextové odkazy mezi stránkami. **Markup** znamená, že jsme vzali dokument a označili ho kódem, abychom něčemu (v tomto případě prohlížeči) řekli, jak interpretovat stránku. HTML kód se vytváží pomocí **tagů**. Každý začíná znakem `<` a končí znakem `>`. Tyto tagy představují **elementy** značkovacího jazyka (Markup). + +## Tvá první šablona! + +Vytvoření šablony znamená vytvoření souboru šablony. Všechno je soubor, že? Toho sis už asi všimla. + +Šablony jsou uloženy v adresáři `blog/templates/blog`. Takže nejdříve vytvoř adresář `templates` uvnitř tvé blog složky. Potom vytvoř další složku nazvanou `blog` uvnitř templates složky: + +``` + blog + └───templates + └───blog +``` + +(Mohlo by tě zajímat proč potřebujeme dva adresáře s názvem `blog` - jak později zjistíš, je to pouze užitečná konvence, která dělá život jednodušším, když věci začnou být komplikovanější.) + +A teď vytvoř soubor `post_list.html` uvnitř adresáře `blog/templates/blog`. Prozatím ho nech prázdný. + +Podívej se, jak tvá stránka vypadá teď: http://127.0.0.1:8000/ + +> Pokud máš stále chybu `TemplateDoesNotExists`, zkus restartovat server. Běž do příkazové řádky, zastav server zmáčknutím Ctrl+C (Control a C zároveň) a znovu ho rozběhni pomocí příkazu `python manage.py runserver`. + +![Figure 11.1][1] + + [1]: images/step1.png + +Žádná chybová hláška! Gratulujeme :) Nicméně na tvé stránce se ještě nezveřejnilo nic kromě prázdné stránky, protože tvá šablona je také prázdná. To musíme napravit. + +Do souboru šablony (template) přidej následující: + +```html + +

Ahoj!

+

Funguje to!

+ +``` + +Tak jak tvá stránka vypadá teď? Klikni a zjisti to: http://127.0.0.1:8000/ + +![Figure 11.2][2] + + [2]: images/step3.png + +Fungovalo to! Pěkná práce :) + +* Nejzákladnější tag, ``, je vždy na začátku jakékoli stránky a `` na jejím konci. Jak vidíš, celý obsah stránky je mezi otevíracím tagem `` a zavíracím tagem `` +* `

` je tag pro element paragraf; `

` každý paragraf ukončuje + +## Head & body + +Každá HTML stránka je také rozdělena na dva elementy: **head** (hlavu) a **body** (tělo). + +* **head** je element, který obsahuje informace o dokumentu, které se nezobrazují na webu. + +* **body** je element, který obsahuje vše ostatní, co se zobrazuje jakou součást webové stránky. + +`` používáme, abychom prohlížeči sdělili konfiguraci stránky, ``, abychom řekli, co na té stránce skutečně je. + +Například dovnitř `` můžeš dát element title (titulek), třeba takhle: + +```html + + + Ola's blog + + +

Ahoj!

+

Funguje to!

+ + +``` + +Ulož soubor a načti znovu svou stránku. + +![Figure 11.3][3] + + [3]: images/step4.png + +Všimla sis, že prohlížeč už ví, že "Ola's blog" je titulek stránky? Interpretoval `Ola's blog` a umístil text jako název záložky. + +Pravděpodobně sis také všimla, že každý otevírací tag je doplněn *zavíracím tagem* se znakem `/`, a že elementy jsou *vnořené* (tzn. že nemůžeš zavřít daný tag, dokud nejsou zavřeny všechny tagy uvnitř). + +Je to jako dávat věci do krabic. Máš jednu velkou krabici, ``; uvnitř je ``. A ta obsahuje další, menší krabice: `

`. + +Musíš dodržovat pravidlo *zavíracích* tagů a *vnořených* elementů - pokud ne, prohlížeč je nemusí správně interpretovat a tvá webová stránka se bude zobrazovat nesprávně. + +## Přizpůsob si šablonu + +Teď si můžeš užít trochu zábavy a pokusit se přizpůsobit si svou šablonu! Tady je pár užitečných tagů: + +* `

Hlavní nadpis

` - Pro tvůj nejdůležitější nadpis +* `

Pod-nadpis

` pro nadpis na nižší úrovni +* `

Pod-pod-nadpis

` ... a tak dále, až k `
` +* `text` zvýrazňuje tvůj text +* `text` zvýrazňuje tvůj text silnějji +* `
` vkládá novou řádku (dovnitř br nemůžeš nic dát) +* `link` vytváří odkaz +* `
  • První položka seznamu
  • druhá položka seznamu
` vytváří seznam, zrovna jako tento! +* `
` definuje sekce stránky + +Zde je příklad celé šablony: + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

Můj první příspěvek

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

Můj druhý příspěvek

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.

+
+ + +``` + +Tady vytvoříme tři `div` sekce. + +* První `div` element obsahuje titulek našeho blogu - jeho nadpis a odkaz +* Další dva `div` elementy obsahují naše příspěvky s datem zveřejnění, na `h2` s titulkem příspěvku se dá kliknout a dva `p` (paragrafy) obsahují text, jeden datum a druhý samotný příspěvek. + +To nám dá následující výsledek: + +![Figure 11.4][4] + + [4]: images/step6.png + +Jupííí! Ale teď naše šablona zobrazuje jen **neměnné informace** - dříve jsme ovšem mluvily o tom, že šablony nám umožňují zobrazovat **různé** informace ve **stejném formátu**. + +Co ve skutečnosti chceme, je zobrazit opravdové příspěvky přidané v našem Django administrátorském rozhraní - a to se chystáme udělat za chvilku. + +## Ještě jedna věc: nasaďme to! + +Bylo by fajn vidět všecho tohle venku a živě na internetu, že ano? Pojďme udělat další PythonAnywhere nasazení (deploy): + +### Commitni a hoď svůj kód na Github + +Nejdříve se podívejme, které soubory se změnily od posledního nasazení (deploy). Zadej tyto příkazy lokálně (ne na PythonAnywhere): + +``` + $ git status +``` + +Ujisti se, že jsi v `djangogirls` adresáři a řekni `gitu`, ať zahrne všechny nové změny v adresáři: + +``` + $ git add --all . +``` + +> **Poznámka** `-A` (zkratka pro "all", tj. "vše") znamená, že `git` také rozpozná, jestli jsi smazala nějaké soubory (defaultně rozpoznává pouze nové a modifikované soubory). Taky si vzpomeň (ze 3. kapitoly), že `.` znamená aktuální adresář. + +Než nahrajeme všechny soubory, zkontrolujme, co bude `git` nahrávat (všechny soubory, které bude `git` nahrávat, se zobrazí zeleně): + +``` + $ git status +``` + +Jsme skoro u konce, teď je čas uložit změny do historie. Vytvoříme "commit zprávu", kde popíšeme, co jsme změnily. Můžeš napsat, cokoli tě napadne, ale je užitečné napsat něco popisného, aby sis v budoucnosti mohla vzpomenout, cos udělala. + +``` + $ git commit -m "Změněn HTML kód stránek." +``` + +> **Poznámka** Ujisti se, že používáš dvojité uvozovky kolem zprávy. + +Jakmile jsme s tímto hotovy, nahrajeme (push) naše změny na Github: + +``` + git push +``` + +### Stáhni svůj nový kód na PythonAnywhere a načti webovou aplikaci + +* Otevři [stránku s konzolí na PythonAnywhere][5] a jdi do své **Bash konzole** (nebo začni novou). Potom zadej: + + [5]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +A sleduj svůj kód, jak se stahuje. Pokud si chceš zkontrolovat, že se kód opravdu nahrál, můžeš skočit do záložky **Files** a podívat se na svůj kód na PythonAnywhere. + +* A konečně, skoč na záložku [Web][6] a klikni na **Reload** (Znovu načíst). + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +Tvůj update by měl běžet živě! Obnov svou stránku v prohlížeči. Měla bys vidět změny :) diff --git a/cs/html/images/step1.png b/cs/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/cs/html/images/step1.png differ diff --git a/cs/html/images/step3.png b/cs/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/cs/html/images/step3.png differ diff --git a/cs/html/images/step4.png b/cs/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/cs/html/images/step4.png differ diff --git a/cs/html/images/step6.png b/cs/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/cs/html/images/step6.png differ diff --git a/es/images/images/application.png b/cs/images/application.png similarity index 100% rename from es/images/images/application.png rename to cs/images/application.png diff --git a/cs/installation/README.md b/cs/installation/README.md new file mode 100755 index 00000000000..bb9faf25871 --- /dev/null +++ b/cs/installation/README.md @@ -0,0 +1,49 @@ +# Pokud děláš tutoriál doma + +Pokud děláš tento tutorial doma, ne na jedné z [Django girls akcí](https://djangogirls.org/events/), můžeš zcela vynechat tuto kapitolu a jít rovnou na kapitolu [jak funguje Internet?](../how_the_internet_works/README.md). + +To proto, že zde uvedené věci stejně vysvětlíme v průběhu celého kurzu a tato stránka pouze shromažďuje všechny pokyny pro instalaci na jednom místě. Jedna z Django Girls událostí "Instalační večer" se zaobírá instalováním všeho, co budeme potřebovat, což nás už nebude zdržovat během samotného worshopu. To je pro nás užitečná úspora času. + +Pokud myslíš, že je pro tebe tato kapitola užitečná, můžeš si ji projít. Ale pokud se chceš začít učit ještě před instalací hromady věcí do tvého počítače, přeskoč tuto kapitolu a my ti vysvětlíme proces instalace později. + +Hodně štěstí! + +# Instalace + +Při workshopu budeme vytvářet blog, přičemž zde existuje několik nastavení, která se budou během kurzu hodit před tím, než začneš programovat. + +# Instalace Pythonu + +{% include "/python_installation/instructions.md" %} + +# Nastavení virtualenv a instalace Django + +{% include "/django_installation/instructions.md" %} + +# Instalace editoru kódu + +{% include "/code_editor/instructions.md" %} + +# Instalace Git + +{% include "/deploy/install_git.md" %} + +# Vytvoření účtu na GitHub + +Přejděte na [GitHub.com](https://www.github.com) a vytvořte si zdarma uživatelský účet. + +# Vytvoření účtu PythonAnywhere + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Začni číst + +Gratulujeme, právě sis zřídila všechny účty a nastavila vše, co potřebuješ! Pokud máš ještě nějaký čas před workshopem, bylo by užitečné začít číst některou z prvních kapitol: + + * [Jak funguje internet](../how_the_internet_works/README.md) + + * [Úvod do příkazového řádku](../intro_to_command_line/README.md) + + * [Úvod do Pythonu](../intro_to_command_line/README.md) + + * [Co je Django?](../django/README.md) diff --git a/cs/intro_to_command_line/README.md b/cs/intro_to_command_line/README.md new file mode 100755 index 00000000000..f98f15504ee --- /dev/null +++ b/cs/intro_to_command_line/README.md @@ -0,0 +1,305 @@ +# Úvod k příkazové řádce + +Hm, to je vzrušující, že? Napíšeš svůj první řádek kódu za pouhých pár minut :) + +**Dovol nám, abychom ti představili tvého prvního nového přítele: příkazovou řádku! ** + +Následující kroky ti ukážou, jak používat černé okno, které všichni počítačoví odborníci používají. Může to na první pohled vypadat trochu děsivě, ale opravdu je to jen okno, které čeká na tvé příkazy. + +> **Poznáma** Ber, prosím, na vědomí, že v tomto tutoriálu používáme termíny 'adresář' a 'složka', ale je to jedna a ta samá věc. + +## Co je příkazová řádka? + +Okno, které se obvykle nazývá **příkazová řádka** nebo **rozhraní příkazové řádky**, je textová aplikace pro zobrazování, zpracovávání a manipulaci se soubory na tvém počítači. Docela jako Windows Explorer nebo Finder na Mac, ale bez grafického rozhraní. Další jména pro příkazovou řádku jsou: *cmd*, *prompt*, *command line*, *konzole* nebo *terminál*. + +## Otevři rozhraní příkazové řádky + +Chceš-li začít experimentovat, je třeba nejprve otevřít naše rozhraní příkazové řádky. + +### Windows + +Jdi na menu Start → Všechny programy → Příslušenství → Příkazová řádka. + +### Mac OS X + +Aplikace → Nástroje → Terminál. + +### Linux + +Pravděpodobně ji nalezneš pod Aplikace → Příslušenství → Terminál, ale závisí to na tvém systému. Pokud to tam není, prostě to vygoogli :) + +## Příkazová řádka + +Nyní bys měla vidět bílé nebo černé okno, které čeká na tvé příkazy. + +Pokud jsi na Mac nebo na Linuxu, pravděpodobně uvidíš výzvu začínající tímto znakem `$`, právě takhle: + +``` + $ +``` + +V systému Windows je to tento znak `>`: + +``` + > +``` + +Každý příkaz budeš psát za tento znak a jednu mezeru, ale není nutné to zadávat. Tvůj počítač to udělá za tebe :) + +> Jen malá Poznámka: někteří mohou vidět něco jako `C:\Users\ola >` nebo `Olas-MacBook-Air: ~ ola$` před znakem $. To je naprosto v pořádku. V tomto kurzu se jen snažíme vše zjednodušit na minimum. + +## Tvůj první příkaz (hurá!) + +Pojďme začít s něčím jednoduchým. Zadej tento příkaz: + +``` + $ whoami +``` + +nebo + +``` + > whoami +``` + +A zmáčkni `enter`. Tohle je výsledek: + +``` + $ whoami + olasitarska +``` + +Jak vidíš, počítač právě vypsal tvé uživatelské jméno. Pěkný, co?:) + +> Zkus každý příkaz zadat, nekopíruj ho prostým vyjmout/vložit. Zapamatuješ si tak více! + +## Základy + +Každý operační systém má mírně odlišnou sadu příkazů na příkazové řádce, takže se ujisti, že sleduješ pokyny pro tvůj operační systém. Zkusme to, ano? + +### Aktuální složka + +Bylo by hezké vědět, kde právě jsme, ne? Podívejme se. Zadej následující příkaz a stiskni `enter`: + +``` + $ pwd + /Users/olasitarska +``` + +Pokud jsi v systému Windows: + +``` + > cd + C:\Users\olasitarska +``` + +Pravděpodobně se ti zobrazí něco podobného. Jakmile otevřeš příkazovou řádku, obvykle začínáš ve svém domovském adresáři. + +> Poznámka: 'pwd' je zkratka pro "print working directory / zobrazení cesty pro pracovní adresář". + +* * * + +### Seznam souborů a adresářů + +Tak co je v něm? Bylo by fajn zjistit, co je v našem adresáři. Podívejme se: + +``` + $ ls + Aplikace + Desktop + Stažené soubory + Hudba... +``` + +Windows: + +``` + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... +``` + +* * * + +### Změna aktuálního adresáře + +Teď pojďme do adresáře plochy: + +``` + $ cd Desktop +``` + +Windows: + +``` + > cd Desktop +``` + +Zkontroluj, zda-li se adresář skutečně změnil: + +``` + $ pwd + /Users/olasitarska/Desktop +``` + +Windows: + +``` + > cd + C:\Users\olasitarska\Desktop +``` + +A je to! + +> PRO tip: Pokud zadáš `cd D` a poté stiskneš klávesu `tab` na klávesnici, příkazová řádka automaticky předvyplní zbytek názvu, tak můžeš adresáře procházet rychleji. Pokud existuje více než jedna složka od "D", musíš tlačítko `tab` zmáčknout dvakrát a zobrazí se ti seznam dostupných možností. + +* * * + +### Jak vytvořit složku + +Co si vytvořit pokusnou složku na ploše? Můžeš to udělat tímto způsobem: + +``` + $ mkdir pokus +``` + +Windows: + +``` + > mkdir pokus +``` + +Tento malý příkaz vytvoří složku s názvem `pokus` na ploše. Zda se na ploše složka vytvořila můžeš zkontrolovat pouhým pohledem na pracovní plochu nebo spuštěním příkazu `ls` nebo `dir`! Zkus to :) + +> PRO tip: Pokud nechceš znovu a znovu zadávat stejné příkazy, zkus stisknutím `šipka nahoru` a `šipka dolů` na klávesnici přepínat mezi nedávno použitými příkazy. + +* * * + +### Cvičení! + +Malá výzva: v nově vytvořeném adresáři `pokus` vytvoř adresář s názvem `test`. Použij příkazy `cd` a `mkdir`. + +#### Řešení: + +``` + $ cd pokus + $ mkdir test + $ ls + test +``` + +Windows: + +``` + > cd pokus + > mkdir test + > dir + 05/08/2014 07:28 PM test +``` + +Gratulujeme! :) + +* * * + +### Jak odstranit složku + +Nechceme si nechat nepořádek v počítači, takže musíme odstranit vše, co jsme až do tohoto okamžiku dělaly. + +Za prvé se potřebujeme dostat zpátky na plochu: + +``` + $ cd .. +``` + +Windows: + +``` + > cd .. +``` + +Použití `..` s příkazem `cd` změní tvůj aktuální adresář na rodičovský adresář (adresář, který obsahuje tvůj aktuální adresář). + +Zkontroluj, kde se nacházíš: + +``` + $ pwd + /Users/olasitarska/Desktop +``` + +Windows: + +``` + > cd + C:\Users\olasitarska\Desktop +``` + +Teď je čas vymazat adresář `pokus`: + +> **Pozor**: odstraňování souborů pomocí `del`, `rmdir` nebo `rm` je nevratné, což znamená, *že odstraněné soubory budou navždy pryč*! Takže buď s tímto příkazem velmi opatrná. + +``` + $ rm -r pokus +``` + +Windows: + +``` + > rmdir /S pokus + Are you sure ? Y +``` + +Hotovo! Vše je skutečně odstraněno. Pojďme to zkontrolovat: + +``` + $ ls +``` + +Windows: + +``` + > dir +``` + +### Zavření příkazové řádky + +To je pro tuto chvíli vše! Bezpečně můžeš nyní zavřít příkazovou řádku. Uděláme to hackerským stylem, ano? :) + +``` + $ exit +``` + +Windows: + +``` + > exit +``` + +Suprový, co? :) + +## Shrnutí + +Zde je přehled některých užitečných příkazů: + +| Příkaz (Windows) | Příkaz (Mac OS / Linux) | Popis | Příklad | +| ---------------- | ----------------------- | ------------------------ | ------------------------------------------------- | +| exit | exit | Zavřít okno | **exit** | +| cd | cd | změnit adresář | **cd test** | +| dir | ls | seznam adresářů/souborů | **dir** | +| copy | cp | kopírovat soubor | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | přesunout soubor | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | vytvořit nový adresář | **mkdir testdirectory** | +| del | rm | odstranit adresář/soubor | **del c:\test\test.txt** | + +Toto je jen velmi malá část příkazů, které lze spustit v příkazovém řádku, ale pro dnešek to bude stačit. + +Pokud jsi zvědavá, na [ss64.com][1] je úplný přehled příkazů pro všechny operační systémy. + + [1]: http://ss64.com + +## Připravena? + +Pojďme se ponořit do Pythonu! diff --git a/cs/python_installation/README.md b/cs/python_installation/README.md new file mode 100755 index 00000000000..42f150debad --- /dev/null +++ b/cs/python_installation/README.md @@ -0,0 +1,13 @@ +# Začněme s Pythonem + +Konečně jsme u něj! + +Nejdříve si pojďme říci, co Python je. Python je velmi populární programovací jazyk, který lze použít k vytváření webových stránek, her, vědeckého software, grafického software a mnoho, mnoho dalšího. + +Python vznikl na konci 80. let a jeho hlavním cílem je být pro lidské bytosti čitelný (nejen pro stroje!). Právě proto vypadá mnohem jednodušeji než jiné programovací jazyky. Díky tomu je snadné se ho naučit, ale neboj, Python je opravdu mocný! + +# Instalace Pythonu + +> **Poznámka:** Pokud jsi již prošla přes kroky instalace, není třeba se k tomu znovu vracet - můžeš přeskočit přímo vpřed na další kapitolu! + +{% include "/python_installation/instructions.md" %} diff --git a/cs/python_installation/images/add_python_to_windows_path.png b/cs/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/cs/python_installation/images/add_python_to_windows_path.png differ diff --git a/cs/python_installation/instructions.md b/cs/python_installation/instructions.md new file mode 100755 index 00000000000..525935c414b --- /dev/null +++ b/cs/python_installation/instructions.md @@ -0,0 +1,72 @@ +> Tato podkapitola čerpá z Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django je napsán v Pythonu. Na to, abys mohla cokoliv dělat v Djangu, potřebuješ Python. Začněme s instalací! Chceme, aby sis nainstalovala verzi Python 3.4, takže pokud máš starší verzi, musíš ji upgradovat. + +### Windows + +Python pro Windows můžeš stáhnout z webové stránky https://www.python.org/downloads/release/python-343/. Po stažení **msi** souboru, bys jej měla spustit (poklepáním na něj) a postupovat podle uvedených pokynů. Je důležité si zapamatovat cestu (k adresáři), kam jsi Python nainstalovala. Později jej budeš potřebovat! + +Pozor na jednu věc: na druhé obrazovce průvodce instalací, označené "Přizpůsobit", se ujisti, že máš zvolenou možnost "Add python.exe to the Path": + +![Nezapomeň přidat Python do cesty](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Je velmi pravděpodobné, že již máš Python nainstalován v základní instalaci. Chceš-li zkontrolovat, zda jej máš nainstalován (a o jakou verzi se jedná), otevři konzoli a zadej následující příkaz: + +``` + $ python3 --version + Python 3.4.2 +``` + +Pokud Python nemáš nainstalovaný nebo pokud chceš nainstalovat jinou verzi, můžeš postupovat takto: + +#### Debian nebo Ubuntu + +Použij tento příkaz v konzoli: + +``` + sudo apt-get install python3.4 +``` + +#### Fedora (do verze 21) + +Použij tento příkaz v konzoli: + +``` + sudo yum install python3.4 +``` + +#### Fedora (22 +) + +Použij tento příkaz v konzoli: + +``` + $ sudo dnf nainstalovat python3.4 +``` + +#### openSUSE + +Použij tento příkaz v konzoli: + +``` + $ sudo zypper install python3 +``` + +### OS X + +Musíš jít na web https://www.python.org/downloads/release/python-342/ a stáhnout si instalátor Python: + + * Stáhni *Mac OS X 64-bit/32-bit installer* soubor, + * Poklepej na *python-3.4.3-macosx10.6.pkg*, chceš-li spustit instalační program. + +Ověř, zda instalace proběhla úspěšně, otevři aplikaci *Terminal* a spusť příkaz `python3`: + +``` + $ python3 – version + Python 3.4.2 +``` + +* * * + +Pokud máš nějaké pochybnosti nebo se něco při instalaci nepovedlo a ty nemáš ponětí, co dělat dál - zeptej se svého kouče! Někdy se věci nevyvíjejí hladce a je lepší požádat o pomoc někoho s více zkušenostmi. diff --git a/cs/python_introduction/README.md b/cs/python_introduction/README.md new file mode 100755 index 00000000000..d619f1ce20c --- /dev/null +++ b/cs/python_introduction/README.md @@ -0,0 +1,847 @@ +# Úvod do Pythonu + +> Část této kapitoly je založena na kurzu Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Pojďme napsat nějaký kód! + +## Interaktivní režim Pythonu + +Chceš-li si začít hrát s Pythonem, musíme otevřít *příkazový řádek* v počítači. Již bys měla vědět jak na to – naučily jsme se to v kapitole [Úvod do příkazového řádku][1]. + + [1]: ../intro_to_command_line/README.md + +Jakmile budeš připravena, postupuj podle níže uvedených pokynů. + +Chceme otevřít Python konzoli, takže napiš `python` na Windows nebo `python3` na Mac a OS/Linuxu a zmáčkni `enter`. + +``` + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> +``` + +## Tvůj první příkaz v Pythonu! + +Po spuštění interaktivního režimu Python se výzva na řádku změní na `>>>`. Pro nás to znamená, že pro tuto chvíli můžeme používat pouze příkazy v jazyce Python. Není nutné zadávat `>>>` - Python to udělá za tebe. + +Pokud chceš ukončit Python konzoli, kdykoliv stačí zadat `exit()` nebo použít zkratku `Ctrl + Z` na Windows a `Ctrl + D` pro Mac/Linux. Pak již neuvidíš `>>>`. + +Pro tuto chvíli nechceme Python konzoli opustit. Chceme se o ní naučit více. Začněme s něčím opravdu jednoduchým. Například zkusme napsat nějakou matematiku. Napiš třeba `2 + 3` a zmáčkni `enter`. + +``` + >>> 2 + 3 + 5 +``` + +Hezké! Vidíš, jak se zobrazila odpověď? Python umí matematiku! Můžeš zkusit jiné příkazy typu: `4 * 5` ; `5-1` ; `40 / 2` + +Chvíli si s tím hraj a pak se sem vrať zpátky :). + +Jak vidíš, Python je skvělá kalkulačka. Pokud tě zajímá, co jiného můžeš dělat... + +## Řetězce + +A co tvé jméno? Zadej své jméno do uvozovek, jak vidíš níže: + +``` + >>> "Ola" + "Ola" +``` + +Nyní jsi vytvořila svůj první řetězec! Je to posloupnost znaků, které mohou být zpracovány počítačem. Řetězec musí vždy začínat a končit stejným znakem. To může být jednoduchá (`'`) nebo dvojitá (`"`) uvozovka (neexistuje žádný rozdíl!) Uvozovkami Pythonu říkáš, že co je uvnitř, je řetězec. + +Řetězce mohou být spojovány. Zkus toto: + +``` + >>> "Ahoj " + "Ola" + 'Ahoj Ola' +``` + +Také můžeš násobit řetězce s číslem: + +``` + >>> "Ola" * 3 + 'OlaOlaOla' +``` + +Pokud budeš chtít dát apostrof dovnitř svého řetězce, máš dvě možnosti, jak to udělat. + +Pomocí dvojité uvozovky: + +``` + >>> "Runnin' down the hill" + "Runnin' down the hill" +``` + +nebo použít escape sekvenci - před apostrof napsat zpětné lomítko (\`): + +``` + >>> 'Runnin\' down the hill' + "Runnin' down the hill" +``` + +Pěkné, co? Chceš-li vidět své jméno velkými písmeny, jednoduše zadej: + +``` + >>> "Ola".upper() + 'OLA' +``` + +Právě jsi použila `upper` **funkci** na svém řetězci! Funkce (jako `upper()`) je sled instrukcí, které Python provádí na daném objektu (`"Ola"`) poté, co ji zavoláš. + +Pokud chceš znát počet písmen ve svém jméně, tak pro to má Python také funkci! + +``` + >>> len("Ola") + 3 +``` + +Zajímá tě, proč někdy voláš funkce s `.` na konci řetězce (jako `"Ola".upper()`) a někdy nejprve zavoláš funkci a vložíš řetězec do závorek? V některých případech funkce patří do objektů, jako `upper()`, což lze provést pouze u řetězců. V tomto případě nazýváme funkci **metodou**. Jindy, funkce nepatří k ničemu konkrétnímu a lze ji použít na různé typy objektů, stejně jako `len()`. To je důvod, proč předáváme `"Ola"` jako parametr pro funkci `len`. + +### Shrnutí + +OK, dost bylo řetězců. Co ses zatím naučila: + +* **interaktivní režim Pythonu** - zadávání příkazů (kódu) do Pythonového interaktivního režimu a zobrazení výsledku/odpovědi v Pythonu +* **čísla a řetězce** - v Pythonu se čísla používají pro matematiku a řetězce pro textové objekty +* **operátor** - jako + a * kombinuje hodnoty a vytvoří nové +* **funkce** - jako upper() a len() provádí akce u objektů. + +To jsou základy každého programovacího jazyka. Připravena na něco dalšího? Vsadíme se, že ano! + +## Chyby + +Pojďme zkusit něco nového. Můžeme zkusit zjistit délku čísla stejným způsobem, jakým jsme zjišťovali délku našeho jména? Zadej `len(304023)` a stiskni klávesu `Enter`: + +``` + >>> len(304023) + Traceback (most recent call last): + File "", + line 1, in + TypeError: object of type 'int' has no len() +``` + +Zobrazila se ti naše první chyba! Ta říká, že objekty typu "int" (integers, celá čísla) nemají délku. Tak co můžeme udělat teď? Možná můžeme zkusit napsat naše číslo jako řetězec? Řetězce mají délky, že? + +``` + >>> len(str(304023)) + 6 +``` + +Funguje to! Použili jsme funkci `str` uvnitř funkce `len`. `str()` vše převádí na řetězec. + +* Funkce `str`převede věci do **řetězců** +* Funkce `int` převede věci na **celá čísla** + +> Důležité upozornění: můžeme převést čísla na text, ale nemůžeme jen tak převést text na čísla - co by se stalo, kdybychom se pokusily o toto: `int('hello')`? + +## Proměnné + +Důležitým konceptem v programování jsou proměnné. Proměnná není nic jiného než pojmenování něčeho, co budeme chtít použít později. Programátoři proměnné používají k ukládání dat, aby byl jejich kód čitelnější a nemuseli si pamatovat, co dané věci jsou. + +Řekněme, že chceme vytvořit novou proměnnou s názvem `name`: + +``` + >>> name = "Ola" +``` + +Vidíš? Je to snadné! Jednoduše napíšeš: name se rovná Ola. + +Jak sis jistě všimla, tvůj program nevrátil nic jako předtím. Jak tedy víme, že proměnná skutečně existuje? Jednoduše zadejte `name` a stiskni klávesu `Enter`: + +``` + >>> name + 'Ola' +``` + +Hurá! První proměnná :)! Kdykoli můžeš změnit to, na co daná proměnná ukazuje: + +``` + >>> name = "Sonja" + >>> name + 'Sonja' +``` + +Můžeš ji také použít ve funkcích: + +``` + >>> len(name) + 5 +``` + +Super, ne? Samozřejmě proměnná může obsahovat cokoliv, například také čísla! Zkus tohle: + +``` + >>> a = 4 + >>> b = 6 + >>> a * b + 24 +``` + +Ale co když použijeme nesprávné jméno? Dokážeš odhadnout, co se stane? Pojďme to zkusit! + +``` + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): File "", line 1, in + NameError: name 'ctiy' is not defined +``` + +Chyba! Jak vidíš, Python má různé typy chyb a tato se nazývá **NameError**. Python ti vrátí tuto chybu, pokud se pokusíš použít proměnnou, která nebyla dosud definována. Pokud někdy dojde k této chybě, zkontroluj svůj kód, abys zjistila, jestli jsi nezadala nějaké jméno nesprávně. + +Chvilku si s tím, ať vidíš, co se s tím dá dělat! + +## Funkce print + +Zkus toto: + +``` + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria +``` + +Zadáš-li jen `name`, interpretr Pythonu reaguje na řetězcovou *reprezentaci* proměnné "name", což jsou písmena M-a-r-i-a, obklopená jednoduchými uvozovkami ''. Když napíšeš `print(name)`, Python vypíše obsah proměnné na obrazovku bez uvozovek, což vypadá lépe. + +Jak uvidíme později, funkce `print()` je také užitečná, když chceme vypsat věci uvnitř funkce nebo na více řádcích. + +## Seznamy + +Vedle řetězců a celých čísel má Python další druhy různých typů objektů. Teď se podíváme na jeden, který se nazývá **list**. Seznamy jsou přesně to, co si myslíš, že jsou: jsou to objekty, které obsahují seznam ostatních objektů :) + +Nestyď se a vytvoř seznam: + +``` + >>> [] + [] +``` + +Ano, tento seznam je prázdný. Není moc užitečný, že? Pojďme vytvořit seznam čísel z loterie. Nechceme se stále opakovat, takže seznam uložíme také do proměnné: + +``` + >>> lottery = [3, 42, 12, 19, 30, 59] +``` + +Dobrá máme seznam! Co s ním můžeme dělat? Uvidíme, kolik čísel loterie je v seznamu. Máš nějakou představu, jakou funkci bys měla použít? Už to přeci víš! + +``` + >>> len(lottery) + 6 +``` + +Ano! Funkce `len()` ti zjistí počet objektů v seznamu. Šikovné, že? Možná bychom je teď měli zkusit seřadit: + +``` + >>> lottery.sort() +``` + +Tato funkce nic nevrátí, jen změní pořadí čísel v seznamu. Pojďme ho znovu vypsat a uvidíme co se stalo: + +``` + >>> print(lottery) + [3, 12, 19, 30, 42, 59] +``` + +Jak můžeš vidět, čísla v seznamu jsou nyní seřazena od nejnižší k nejvyšší hodnotě. Gratulujeme! + +Můžeme také zkusit obrátit pořadí? Udělejme to! + +``` + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] +``` + +Snadné, že? Pokud chceš něco přidat do svého seznamu, můžeš to provést zadáním tohoto příkazu: + +``` + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] +``` + +Pokud chceš zobrazit pouze první číslo, můžeš to udělat pomocí **indexů**. Index je číslo, které říká, kde se v seznamu položka najde. Programátoři preferují počítání od 0, takže první objekt v seznamu je v indexu 0, druhý je v indexu 1 a tak dále. Zkus toto: + +``` + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 +``` + +Jak vidíš, pro přístup k různým objektům ve tvém seznamu použiješ jméno seznamu a index objektu uvnitř hranatých závorek. + +Chceš-li odstranit něco ze svého seznamu, budeš muset použít **indexy**, jak jsme se dozvěděli výše, a příkaz `pop()`. Zkusme to, co jsme se naučily dříve; budeme odstraňovat první číslo našeho seznamu. + +``` + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] +``` + +Funguje to všechno skvěle! + +Pro další zábavu zkus nějaké jiné indexy: 6, 7, 1000, -1, -6 nebo -1000. Pokus se předpovědět výsledek před zadáním příkazu. Jsou výsledky správné? + +Seznam všech dostupných metod pro seznam nalezneš v této kapitole Python dokumentace: https://docs.python.org/3/tutorial/datastructures.html + +## Slovníky + +Slovník je podobný seznamu, ale pro přístup k hodnotám se používá klíč místo indexu. Klíč může být jakýkoli řetězec nebo číslo. Syntaxe pro definování prázdného slovníku je: + +``` + >>> {} + {} +``` + +Vidíš, že jsi právě vytvořila prázdný slovník. Hurá! + +A teď zkus napsat následující příkaz (zkus nahradit vlastními informacemi): + +``` + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` + +Tímto příkazem jsi právě vytvořila proměnnou s názvem `participant` s třemi dvojicemi klíčů hodnot: + +* Klíč `name` odkazuje na hodnotu `"Ola"` (`string/řetězcový` objekt), +* klíč`country`, ukazuje na `"Polsko"` (další `řetězec`)), +* a `favorite_numbers` ukazuje `[7, 42, 92]` (`list/seznam` obsahující 3 čísla). + +Můžeš zkontrolovat obsah jednotlivých klíčů následující syntaxí: + +``` + >>> print(participant['name']) + Ola +``` + +Je to podobné seznamu. Ale není nutné si pamatovat index - jen jméno. + +Co se stane, když se zeptáme Pythonu na hodnotu klíče, který neexistuje? Zkus hádat! Pojďme to vyzkoušet a uvidíš! + +``` + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' +``` + +Podívej, další chyba! Toto je **KeyError**. Python ti napomáhá a řekne ti, že klíč `"věk"` v tomto slovníku neexistuje. + +Kdy použít slovník a kdy seznam? To je dobrý postřeh k zamyšlení. Kdy použít jakou variantu pochopíš, až si přečteš následující řádky. + +* Potřebuješ jen seřazenou sekvenci položek? Použij seznam. +* Pokud potřebuješ přiřadit hodnotám klíče, abys je mohla později efektivně vyhledávat (klíčem)? Používej slovník. + +Slovníky stejně jako seznamy jsou *mutable/proměnlivé*, což znamená, že je lze změnit po jejich vytvoření. Do slovníku můžeš přidat nové páry klíč/hodnota po jeho vytvoření: + +``` + >>> participant['favorite_language'] = 'Python' +``` + +Stejně jako u seznamů můžeš použít metodu `len()` na slovníky, vrací počet párů klíč/hodnota ve slovníku. Nestyď se a zadej příkaz: + +``` + >>> len(participant) + 4 +``` + +Doufám, že ti to nyní dává větší smysl. :) Připravena na více zábavy se slovníky? Pojďme na další řádek a další úžasné věci. + +Příkazem `pop()` odstraníš položky ve slovníku. Například pokud chceš odstranit záznam, kterému odpovídá klíč `"favorite_numbers"`, zadej následující příkaz: + +``` + >>> participant.pop('favorite_numbers') + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Jak vidíš, z výstupu byla odstraněna odpovídající dvojice klíč hodnota 'favorite_numbers'. + +Kromě toho můžeš také změnit hodnotu přidruženou k již vytvořenému klíči ve slovníku. Napiš: + +``` + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` + +Jak můžeš vidět, hodnota klíče `'country'` se změnila z `"Poland"` na `"Germany"`. :) Úžasné? Hurá! Právě jsi se naučila další úžasnou věc. + +### Shrnutí + +Skvělé! Nyní víš o programování hodně. V této poslední části jsi se naučila o: + +* **errors/chyby** - nyní víš jak číst a pochopit chyby, které ti Python zobrazí, pokud nerozumí příkazu, který jsi zadala +* **proměnné/variables** - názvy pro objekty, které umožňují psát kód snadněji tak, aby byl čitelnější +* **seznamy/lists** - seznamy objektů uložených v určitém pořadí +* **slovníky/dictionaries** - objekty, které jsou uloženy jako dvojice klíč–hodnota + +Jsi připravena na další část? + +## Porovnávání věcí + +Velká část programování zahrnuje porovnání věci. Co je nejjednodušší věc k porovnání? Čísla, samozřejmě. Podívejme se, jak to funguje: + +``` + >>> 5 > 2 + True + >>> 3 < 1 + False >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True +``` + +Dali jsme Pythonu nějaká čísla na porovnání. Jak vidíš, Python může porovnávat nejen čísla, ale může také porovnat výsledky metod. Pěkný, co? + +Zajímá tě, proč jsme daly dva symboly rovná se `==` vedle sebe pro porovnání, zda jsou čísla stejná? Jedno rovnítko `=` používáme pro přiřazení hodnoty do proměnné. Vždy, **vždy** musíte dát dvě rovnítka `==`, pokud chcete zkontrolovat, jestli se věci navzájem rovnají. Můžeme také zjišťovat, že se věci navzájem nerovnají. Pro takové porovnání můžeme použít symbol `!=`, jak je uvedeno v příkladu výše. + +Dejme Pythonu dva další úkoly: + +``` + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False +``` + +`>` a `<` jsou pro použití snadné, ale co `> =` a `< =` - víš, co se tím myslí? Podívejme se na to: + +* x `>` y znamená: x je větší než y +* x `<` y znamená: x je menší než y +* x `<=` y znamená: x je menší nebo rovno y +* x `>=` y znamená: x je větší nebo rovno y + +Úžasné! Chceš zkusit ještě něco? Zkuste tohle: + +``` + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True +``` + +Pythonu můžeš dát porovnat tolik čísel kolik chceš a na vše ti dá odpověď! Je docela chytrý, že? + +* **and** - Pokud použiješ operátor `and`, obě strany musí být pravdivé, aby celý příkaz byl pravdivý +* **or** - Pokud použiješ operátor `or`, stačí, aby jen jedna strana z porovnání byla pravdivá, aby celý příkaz byl pravdivý + +Už jsi někdy slyšela výraz "srovnávat jablka a hrušky"? Zkusme v Pythonu ekvivalent: + +``` + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() +``` + +Zde vidíš, že stejně jako nelze srovnávat "jablka a hrušky", Python není schopen porovnávat řetězce (`str`) a čísla (`int`). Místo toho zobrazí **TypeError** a říká nám, že tyto dva typy nelze srovnávat společně. + +## Logic hodnoty/Booleany + +Mimochodem právě jste se dozvěděly o novém typu objektu v Pythonu. Říká se mu **boolean** a je to asi nejjednodušší typ. + +Existují pouze dva logické objekty: - True - False + +Aby Python pochopil, že se jedná o tento typ, je potřeba vždy psát jako True (první písmeno velké, zbytek malý). **true, TRUE, tRUE nebude fungovat – jedině True je správně.** (Totéž samozřejmě platí pro False.) + +Pravdivostní hodnoty mohou být také v proměnné! Viz zde: + +``` + >>> a = True + >>> a + True +``` + +Rovněž to můžete provést takto: + +``` + >>> a = 2 > 5 + >>> a + False +``` + +Zkoušej a bav se s logickými hodnotami. Zkus spustit následující příkazy: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Gratulujeme! Logické hodnoty jsou jedny z nejbezvadnějších vlastností v programování a vy jste se je právě naučily používat! + +# Ulož to! + +Zatím jsme psaly všechny naše programy v konzoli v interaktivním režimu Pythonu, který nás omezuje na jeden řádek kódu v jednu chvíli. Normální programy jsou uloženy v souborech a spouští je **konzole** nebo **překladač** programovacího jazyku. Zatím jsme spouštěly naše programy po jednom řádku v **konzoli, v interaktivním režimu** Python. Pro příštích několik úkolů budeme potřebovat více než jeden řádek kódu, takže rychle musíme: + +* Ukončit interaktivní režim Pythonu +* Otevřít náš zvolený editor kódu +* Uložit nějaký kód do nového pythonovského souboru +* Spustit ho! + +Chceš-li opustit interaktivní režim Pythonu, který jsme dosud používaly, jednoduše zadejte ~ ~ ~ exit() ~ ~ ~ funkci: + +``` + >>> exit() + $ +``` + +Tak se dostaneš zpět do příkazové řádky. + +Dříve sis vybrala editor kódu v části [editor kódu][2]. Nyní potřebujeme editor otevřít a napsat vlastní kód do nového souboru: + + [2]: ../code_editor/README.md + +```python + print('Hello, Django girls!') +``` + +> **Poznámka:** Měla bys objevit jednu z nejúžasnější věcí na editorech kódu: barvy! V interaktivním režimu Pythonu mělo vše stejnou barvu, ale nyní bys měla vidět, že funkce `print` je jinou barvou než řetězec uvnitř. To se nazývá "zvýrazňování syntaxe" a je to opravdu užitečná funkce při kódování. Barvy ti napoví, že máš neuzavřený řetězce nebo překlep v názvu slova (jako `def` ve funkci, kterou uvidíš níže). To je jeden z důvodů, proč používáme editory kódu :) + +Samozřejmě teď jsi již pěkně ostřílená python programátorka, tak neváhej napsat nějaký kód, který ses dnes naučila. + +Teď potřebujeme uložit vytvořený soubor a dát mu popisný název. Pojďme ho nazvat **python_intro.py** a uložit jej na plochu. Soubor můžeš pojmenovat jakkoliv chceš, ale důležitá věc je, aby ses ujistila, že soubor končí na **.py**. Přípona **.py** říká našemu operačnímu systému, že jde o **spustitelný soubor Pythonu** a Python ho může spustit. + +Pokud máš soubor uložen, je čas jej spustit! Pomocí dovedností, které jsi se naučila v sekci příkazová řádka, **změň adresář** pomocí terminálu na plochu. + +Na Macu bude příkaz vypadat přibližně takto: + +``` + $ cd /Users//Desktop +``` + +Na Linuxu to bude vypadat takto (slovo "Desktop" (Plocha) může být přeloženo do tvého jazyka): + +``` + $ cd /home//Desktop +``` + +A na Windows to bude vypadat takto: + +``` + > cd C:\Users\\Desktop +``` + +Pokud nevíš jak dál, stačí požádat o pomoc kouče. + +Nyní pomocí Pythonu spustíš kód v souboru takto: + +``` + $ python3 python_intro.py + Hello, Django girls! +``` + +V pořádku! Právě jsi spustila svůj první program v Pythonu, který byl uložen do souboru. Cítíš se úžasně? + +Nyní můžeme přejít k základním nástrojům pro programování: + +## If...elif...else + +Spousty věcí v kódu chceme provádět, jen pokud jsou splněny určité podmínky. To je důvod, proč Python má něco, čemu se říká **if statements**. + +Nahraďte kód v souboru **python_intro.py** tímto: + +```python + if 3 > 2: +``` + +Pokud jsi soubor uložila a spustila, pravděpodobně uvidíš následující chybu: + +``` + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing +``` + +Python očekává, že mu dáš další pokyny, které mají být provedeny, pokud bude podmínka `3 > 2` splněna (`True`). Řekněme tedy Pythonu, ať vypíše "Funguje to!". Změň svůj kód v souboru **python_intro.py** na tento: + +```python + if 3 > 2: + print('It works!') +``` + +Všimla sis, jak jsme odsadily poslední řádek kódu o 4 mezery? Musíme to udělat, podle toho Python pozná, jakou část kódu má spustit, pokud vyhodnotí předchozí výraz jako pravdivý. Můžete udělat jen jednu mezeru, ale téměř všichni programátoři v Pythonu dělají 4, aby kód vypadal upraveně a čitelně. Jeden `Tab` bude také počítán jako 4 mezery. + +Ulož a spusť: + +``` + $ python3 python_intro.py + It works! +``` + +### Co když podmínka není pravdivá? + +V předchozích příkladech byl kód proveden pouze v případě, že podmínky byly splněny. Python má také příkazy `elif` a `else`: + +```python + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') +``` + +Pokud je výraz pravdivý, po spuštění se vytiskne: + +``` + $ python3 python_intro.py + 5 is not greater than 2 +``` + +Kdyby 2 bylo větší než 5, spustil by se první příkaz. Jak snadné! Podívejme se, jak funguje `elif`: + +```python + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') +``` + +a spusť: + +``` + $ python3 python_intro.py + Hey Sonja! +``` + +Viděla jsi co se tam stalo? `elif` umožňuje přidat další podmínky, které se spustí, pokud se předchozí podmínky nezdaří. + +Můžeš po počátečním `if` přidat tolik `elif` příkazů, kolik se ti zlíbí. Například: + +```python + volume = 57 + if volume < 20: + print("Je to dost potichu.") + elif 20 <= volume < 40: + print("Jako hudba v pozadí dobré.") + elif 40 <= volume < 60: + print("Skvělé, slyším všechny detaily.") + elif 60 <= volume < 80: + print("Dobré na party.") + elif 80 <= volume < 100: + print("Trochu moc nahlas!") + else: + print("Krvácí mi uši!") +``` + +Python prochází a testuje každou položku v posloupnosti a vypíše: + +``` + $ python3 python_intro.py + Skvělé, slyším všechny detaily. +``` + +### Shrnutí + +V posledních třech cvičeních ses dozvěděla o: + +* **Porovnání věcí** - v Pythonu můžeš porovnat věci pomocí operátorů `>`, `> =`, `==` `< =`, `<` a `and`, `or` +* **Logické hodnoty / Booleany** - typy, které mohou mít pouze jednu ze dvou hodnot: `True` nebo `False` +* **Ukládání do souborů** - pokud uložíme kód do souboru, můžeme spouštět velké programy +* **if...elif...else** - příkazy, které umožňují spouštět kód pouze v případě, kdy jsou splněny určité podmínky. + +Čas na poslední část této kapitoly! + +## Vlastní funkce! + +Pamatuješ na funkci `len()`, kterou jsi spouštěla v Pythonu? Máme pro tebe dobrou zprávu. Nyní se dozvíš, jak napsat své vlastní funkce! + +Funkce je sled instrukcí, které by měl Python provést. Každá funkce v Pythonu začíná klíčovým slovem `def`, dále je uveden název a funkce může mít také nějaké parametry. Začněme u té nejlehčí. Nahraď kód v **python_intro.py** následujícím: + +```python + def hi(): + print('Hi there!') + print('How are you?') + + hi() +``` + +Naše první funkce je připravena! + +Asi se divíš, proč jsme napsaly název funkce v dolní části souboru. To je proto, že Python přečte soubor a spustí ho od shora dolů. Pokud chceš využívat svou funkci, musíš její název znovu napsat dole (tím ji zavoláš/spustíš). + +Tak to teď zkus a uvidíš, co se stane: + +``` + $ python3 python_intro.py + Hi there! + How are you? +``` + +To bylo snadné! Napišme naši první funkci s parametry. Použijeme předchozí příklad - napíšeme funkci, která nás pozdraví podle toho, jaké zadáme jméno při jejím spuštění: + +```python + def hi(name): +``` + +Jak vidíš, nyní jsme přidaly naší funkci parametr, `name`: + +```python + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() +``` + +Pamatuj si: Funkce `print` je odsazená čtyři mezery v příkazu `if`. To je proto, aby se funkce spustila, pokud je splněna podmínka. Podívej se, jak to funguje nyní: + +``` + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' +``` + +Jejda, chyba. Naštěstí nám Python vypsal docela užitečnou chybovou zprávu. Jak vidíš, funkce `hi()` (kterou jsme definovaly) má jeden povinný parametr `(s názvem name)`, který jsme zapomněly při volání funkce předat. Pojďme to opravit v následující části: + +```python + hi("Ola") +``` + +A znovu jej spusť: + +``` + $ python3 python_intro.py + Hi Ola! +``` + +A co když změníme jméno? + +```python + hi("Sonja") +``` + +Spustíme: + +``` + $ python3 python_intro.py + Hi Sonja! +``` + +C myslíš, že se stane, když tam napíšeš jiné jméno než Ola nebo Sonja? Zkus to a uvidíme, jestli máš pravdu. Mělo by to vypsat toto: + +``` + Hi anonymous! +``` + +To je paráda, co? Nemusíš se opakovat a měnit takto jméno pokaždé, když chceš, aby funkce pozdravila jinou osobu. To je přesně důvod, proč potřebujeme funkce: abychom nikdy neopakovaly náš kód! + +Udělejme to ještě chytřeji – existuje více jmen než dvě a psaní podmínky pro každé jméno by bylo těžké, že? + +```python + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") +``` + +Pojďme zavolat náš nový kód: + +``` + $ python3 python_intro.py + Hi Rachel! +``` + +Blahopřejeme! Právě ses naučila, jak psát funkce :) + +## Smyčky/Loops + +Nyní pojďme na poslední část. To bylo rychlé, co? :) + +Programátoři se neradi opakují. Programování je o automatizaci věci, takže nechceme zdravit každého člověka podle jeho jména manuálně, že? Zde se budou smyčky hodit. + +Ještě si vzpomínáš na seznamy? Udělejme seznam dívek: + +```python + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +Chceme pozdravit všechny s použitím jejich jména. Máme funkci `hi`, která to umí udělat. Tak ji použijeme ve smyčce: + +```python + for name in girls: +``` + +Příkaz ~ ~ ~ for ~ ~ ~ se chová podobně jako příkaz ~ ~ ~ if ~ ~ ~, v následujícím kódu musíme oba řádky odsadit o čtyři mezery. + +Zde je celý kód, který umístíme do souboru: + +```python + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('Next girl') +``` + +A když ho spustíme: + +``` + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl +``` + +Jak vidíš, vše, co jsi vložila dovnitř příkazu `for` s odsazením, se zopakuje pro každý prvek seznamu `girls`. + +Ve funkci `for` můžeš také použít čísla pomocí funkce `range`: + +```python + for i in range(1, 6): + print(i) +``` + +Což ti vypíše: + +``` + 1 + 2 + 3 + 4 + 5 +``` + +`range` je funkce, která vytvoří seznam s posloupností čísel (tato čísla zadáváš jako parametry funkce). + +Všimni si, že druhé z těchto dvou čísel není zahrnuto v seznamu, který je výstupem Pythonu (`range (1, 6)` počítá od 1 do 5, ale nezahrnuje číslo 6). To je proto, že "range" je z poloviny otevřený, čímž myslíme, že obsahuje první hodnotu, ale ne poslední. + +## Shrnutí + +A je to. **Jsi naprosto skvělá!** To byla složitá kapitola, takže bys na sebe měla být hrdá. My jsme na tebe velmi hrdí za to, že ses dostala tak daleko! + +Můžeš si jít krátce odpočinout - protáhnout se, projít se, zavřít oči - než se pustíme do další kapitoly. :) + +![Hrnek][3] + + [3]: images/cupcake.png diff --git a/cs/python_introduction/images/cupcake.png b/cs/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/cs/python_introduction/images/cupcake.png differ diff --git a/cs/template_extending/README.md b/cs/template_extending/README.md new file mode 100755 index 00000000000..cada48de7da --- /dev/null +++ b/cs/template_extending/README.md @@ -0,0 +1,123 @@ +# Rozšiřování šablon + +Další pěknou věcí, kterou pro nás Django má, je **rozšiřování šablon**. Co to znamená? To znamená, že můžeš použít stejné HTML pro různé stránky na svém blogu. + +Tímto způsobem nemusíš opakovat v každém souboru stejný kód, když chceš použít stejné informace/rozvržení. A pokud chceš něco změnit, není nutné to dělat v každé šabloně, stačí jen v jedné! + +## Vytvoření základní šablony + +Základní šablona je šablona, kterou použijeme na každé stránce našich webových stránek. + +Vytvoříme soubor `base.html` v `blog/templates/blog/`: + +``` + blog + └───templates + └───blog + base.html + post_list.html +``` + +Pak jej otevři a zkopíruj vše z `post_list.html` do `base.html` souboru, jako je to níže: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Pak v `base.html` nahraď celé `` (vše mezi `` a ``) tímto: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +Nahradili jsme v podstatě všechno, co bylo mezi `{% for post in posts %}{% endfor %}`, za: + +```html + {% block content %} + {% endblock %} +``` + +Co to znamená? Právě jsi vytvořila `block`, což je šablonovací značka, která umožňuje vkládat HTML kód do tohoto bloku v jiných šablonách, které rozšiřují `base.html`. Hned ti ukážeme, jak to udělat. + +Nyní ulož a znovu otevři svůj `blog/templates/blog/post_list.html`. Odstraň vše, co není uvnitř body, a pak také odstraň `< div class="page-header" >< / div >`, takže soubor bude vypadat takto: + +```html + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +A teď přidej na začátek souboru tento řádek: + +```html + {% extends 'blog/base.html' %} +``` + +{% raw %} to znamená, že nyní rozšiřujeme šablonu `base.html` v `post_list.html`. Jen jedna věc zbývá: vše dát (kromě řádku, který jsme právě přidaly) mezi `{% block content %}` a `{% endblock content %}`. Takto: {% endraw %} + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + +To je ono! Zkontroluj, zda tvoje stránky stále správně fungují :) + +> Jestliže dostaneš chybu `TemplateDoesNotExists`, která říká, že neexistuje žádný soubor `blog/base.html` a máš `runserver` v konzoli, zkus ho zastavit (stisknutím kombinace kláves Ctrl + C - ctrl a tlačítka C společně) a restartovat spuštěním příkazu `pythonu manage.py runserver`. diff --git a/cs/whats_next/README.md b/cs/whats_next/README.md new file mode 100755 index 00000000000..f00eee800f1 --- /dev/null +++ b/cs/whats_next/README.md @@ -0,0 +1,40 @@ +# Co dál? + +Můžeš si pogratulovat! **Jsi naprosto úžasná**. Jsme na tebe hrdí! < 3 + +### Co mám dělat teď? + +Odpočiň si a relaxuj. Právě jsi udělala něco opravdu obrovského. + +Poté nezapomeň: + +* Sleduj Django Girls na [Facebooku][1] nebo [Twitteru][2] a zůstaň v obraze + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Můžete mi doporučit nějaké další zdroje? + +Ano! Zaprvé, jdi a zkus naši další knihu, jmenuje se [Django Girls Tutorial: Extensions][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Později můžeš zkusit, některý ze zdrojů uvedených níže. Všechny můžeme velmi doporučit! + +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/en/README.md b/en/README.md index e268dbe5030..c6e56b20676 100644 --- a/en/README.md +++ b/en/README.md @@ -1,10 +1,8 @@ # Django Girls Tutorial -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -> This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 -International License. To view a copy of this license, visit -http://creativecommons.org/licenses/by-sa/4.0/ +[![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial) +> This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. +> To view a copy of this license, visit https://creativecommons.org/licenses/by-sa/4.0/ ## Introduction @@ -12,7 +10,7 @@ Have you ever felt that the world is more and more about technology and you are Well, we have good news for you! Programming is not as hard as it seems and we want to show you how fun it can be. -The tutorial will not magically turn you into a programmer. If you want to be good at it, you need months or even years of learning and practice. But we want to show you that programming or creating websites is not as complicated as it seems. We will try to explain different bits and pieces as well as we can, so you will not feel intimidated by technology. +This tutorial will not magically turn you into a programmer. If you want to be good at it, you need months or even years of learning and practice. But we want to show you that programming or creating websites is not as complicated as it seems. We will try to explain different bits and pieces as well as we can, so you will not feel intimidated by technology. We hope that we'll be able to make you love technology as much as we do! @@ -24,18 +22,25 @@ It will (more or less) look like this: ![Figure 0.1](images/application.png) -> If you work with the tutorial on your own and don't have a coach that will help you in case of any problem, we have a chat for you: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). We asked our coaches and previous attendees to be there from time to time and help others with the tutorial! Don't be afraid to ask your question there! +> If you work with the tutorial on your own and don't have a coach who will help you in case of any problem, we have a chat system for you: [![Gitter](https://badges.gitter.im/DjangoGirls/tutorial.svg)](https://gitter.im/DjangoGirls/tutorial). We asked our coaches and previous attendees to be there from time to time and help others with the tutorial! Don't be afraid to ask your question there! + +OK, [let's start at the beginning…](./how_the_internet_works/README.md) + +## Following the tutorial at home + +It is amazing to take part in a Django Girls workshop, but we are aware that it is not always possible to attend one. This is why we encourage you to try following this tutorial at home. For readers at home we are currently preparing videos that will make it easier to follow the tutorial on your own. It is still a work in progress, but more and more things will be covered soon at the [Coding is for girls](https://www.youtube.com/channel/UC0hNd2uW8jTR5K3KBzRuG2A/feed) YouTube channel. + +In every chapter already covered, there is a link that points to the correct video. -OK, [let's start at the beginning...](./how_the_internet_works/README.md) ## About and contributing -This tutorial is maintained by [DjangoGirls](http://djangogirls.org/). If you find any mistakes or want to update the tutorial please [follow the contributing guidelines](https://github.com/DjangoGirls/tutorial/blob/master/README.md). +This tutorial is maintained by [DjangoGirls](https://djangogirls.org/). If you find any mistakes or want to update the tutorial please [follow the contributing guidelines](https://github.com/DjangoGirls/tutorial/blob/master/README.md). ## Would you like to help us translate the tutorial to other languages? -Currently, translations are being kept on crowdin.com platform in: +Currently, translations are being kept on crowdin.com platform at: https://crowdin.com/project/django-girls-tutorial -If your language is not listed on crowdin, please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing the language so we can add it. +If your language is not listed on crowdin, please [open a new issue](https://github.com/DjangoGirls/tutorial/issues/new) informing us of the language so we can add it. diff --git a/en/SUMMARY.md b/en/SUMMARY.md index d844137a295..679a8744f74 100644 --- a/en/SUMMARY.md +++ b/en/SUMMARY.md @@ -1,26 +1,26 @@ # Summary * [Introduction](README.md) -* [How the Internet works?](how_the_internet_works/README.md) +* [Installation](installation/README.md) +* [How the Internet works](how_the_internet_works/README.md) * [Introduction to command line](intro_to_command_line/README.md) * [Python installation](python_installation/README.md) * [Code editor](code_editor/README.md) * [Introduction to Python](python_introduction/README.md) * [What is Django?](django/README.md) * [Django installation](django_installation/README.md) -* [Starting Django project](django_start_project/README.md) +* [Your first Django project!](django_start_project/README.md) * [Django models](django_models/README.md) * [Django admin](django_admin/README.md) * [Deploy!](deploy/README.md) * [Django urls](django_urls/README.md) -* [Django views - time to create!](django_views/README.md) +* [Django views – time to create!](django_views/README.md) * [Introduction to HTML](html/README.md) * [Django ORM (Querysets)](django_orm/README.md) * [Dynamic data in templates](dynamic_data_in_templates/README.md) * [Django templates](django_templates/README.md) -* [CSS - make it pretty](css/README.md) +* [CSS – make it pretty](css/README.md) * [Template extending](template_extending/README.md) * [Extend your application](extend_your_application/README.md) * [Django Forms](django_forms/README.md) -* [Domain](domain/README.md) * [What's next?](whats_next/README.md) diff --git a/en/chromebook_setup/README.md b/en/chromebook_setup/README.md new file mode 100644 index 00000000000..a4843977603 --- /dev/null +++ b/en/chromebook_setup/README.md @@ -0,0 +1,5 @@ +# Chromebook setup + +> **Note** If you already worked through the Installation steps, no need to do this again – you can skip straight ahead to [Introduction to Python](../python_introduction/README.md). + +{% include "/chromebook_setup/instructions.md" %} \ No newline at end of file diff --git a/en/chromebook_setup/instructions.md b/en/chromebook_setup/instructions.md new file mode 100644 index 00000000000..f42484514df --- /dev/null +++ b/en/chromebook_setup/instructions.md @@ -0,0 +1,81 @@ +You can [skip right over this section](http://tutorial.djangogirls.org/en/installation/#install-python) if you're not using a Chromebook. If you +are, your installation experience will be a little different. You can ignore the +rest of the installation instructions. + +### Cloud 9 + +Cloud 9 is a tool that gives you a code editor and access to a computer running +on the Internet where you can install, write, and run software. For the duration +of the tutorial, Cloud 9 will act as your _local machine_. You'll still be +running commands in a terminal interface just like your classmates on OS X, +Ubuntu, or Windows, but your terminal will be connected to a computer running +somewhere else that Cloud 9 sets up for you. + +1. Install Cloud 9 from the [Chrome web store](https://chrome.google.com/webstore/detail/cloud9/nbdmccoknlfggadpfkmcpnamfnbkmkcp) +2. Go to [c9.io](https://c9.io) +3. Sign up for an account +4. Click _Create a New Workspace_ +5. Name it _django-girls_ +6. Select the _Blank_ (second from the right on the bottom row with orange logo) + +Now you should see an interface with a sidebar, a big main window with some +text, and a small window at the bottom that looks something like this: + +{% filename %}Cloud 9{% endfilename %} +``` +yourusername:~/workspace $ +``` + +This bottom area is your _terminal_, where you will give the computer Cloud 9 +has prepared for you instructions. You can resize that window to make it a bit +bigger. + +### Virtual Environment + +A virtual environment (also called a virtualenv) is like a private box we can +stuff useful computer code into for a project we're working on. We use them to +keep the various bits of code we want for our various projects separate so +things don't get mixed up between projects. + +In your terminal at the bottom of the Cloud 9 interface, run the following: + +{% filename %}Cloud 9{% endfilename %} +``` +sudo apt install python3.5-venv +``` + +If this still doesn't work, ask your coach for some help. + +Next, run: + +{% filename %}Cloud 9{% endfilename %} +``` +mkdir djangogirls +cd djangogirls +python3.5 -mvenv myvenv +source myvenv/bin/activate +pip install django~=1.9.0 +``` + +(note that on the last line we use a tilde followed by an equal sign: ~=). + +### Github + +Make a [Github](https://github.com) account. + +### PythonAnywhere + +The Django Girls tutorial includes a section on what is called Deployment, +which is the process of taking the code that powers your new web application +and moving it to a publicly accessible computer (called a server) so other +people can see your work. + +This part is a little odd when doing the tutorial on a Chromebook since we're +already using a computer that is on the Internet (as opposed to, say, a laptop). +However, it's still useful, as we can think of our Cloud 9 workspace as a place +or our "in progress" work and Python Anywhere as a place to show off our stuff +as it becomes more complete. + +Thus, sign up for a new Python Anywhere account at +[www.pythonanywhere.com](https://www.pythonanywhere.com). + diff --git a/en/code_editor/README.md b/en/code_editor/README.md index 699681faf58..e9f908b2936 100644 --- a/en/code_editor/README.md +++ b/en/code_editor/README.md @@ -1,38 +1,11 @@ # Code editor -You're about to write your first line of code, so it's time to download a code editor! - -There are a lot of different editors and it largely boils down to personal preference. Most Python programmers use complex but extremely powerful IDEs (Integrated Development Environments), such as PyCharm. As a beginner, however, that's probably less suitable; our recommendations are equally powerful, but a lot simpler. - -Our suggestions are below, but feel free to ask your coach what their preferences are - it'll be easier to get help from them. - -## Gedit - -Gedit is an open-source, free editor, available for all operating systems. - -[Download it here](https://wiki.gnome.org/Apps/Gedit#Download) - -## Sublime Text 2 - -Sublime Text is a very popular editor with a free evaluation period. It's easy to install and use, and it's available for all operating systems. - -[Download it here](http://www.sublimetext.com/2) +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA&t=4m43s) video. -## Atom - -Atom is an extremely new code editor created by [GitHub](http://github.com/). It's free, open-source, easy to install and easy to use. It's available for Windows, OSX and Linux. - -[Download it here](https://atom.io/) - - - -# Why are we installing a code editor? - -You might be wondering why we are installing this special code editor software, rather than using something like Word or Notepad. - -The first is that code needs to be **plain text**, and the problem with programs like Word and Textedit is that they don't actually produce plain text, they produce rich text (with fonts and formatting), using custom formats like rtf. +You're about to write your first line of code, so it's time to download a code editor! -The second reason is that code editors are specialised in editing code, so they can provide helpful features, like highlighting code with colour according to its meaning, or automatically closing quotes for you. +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. -We'll see all this in action later. Soon, you'll come to think of your trusty old code editor as one of your favourite tools :) +> **Note** You might have done this earlier in the Installation chapter – if so, you can skip right ahead to the next chapter! +{% include "/code_editor/instructions.md" %} diff --git a/en/code_editor/instructions.md b/en/code_editor/instructions.md new file mode 100644 index 00000000000..f00c716f82f --- /dev/null +++ b/en/code_editor/instructions.md @@ -0,0 +1,34 @@ +There are a lot of different editors and it largely boils down to personal preference. Most Python programmers use complex but extremely powerful IDEs (Integrated Development Environments), such as PyCharm. As a beginner, however, that's probably less suitable; our recommendations are equally powerful, but a lot simpler. + +Our suggestions are below, but feel free to ask your coach what their preferences are – it'll be easier to get help from them. + +## Gedit + +Gedit is an open-source, free editor, available for all operating systems. + +[Download it here](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text is a very popular editor with a free evaluation period. It's easy to install and use, and it's available for all operating systems. + +[Download it here](https://www.sublimetext.com/3) + + +## Atom + +Atom is an extremely new code editor created by [GitHub](https://github.com/). It's free, open-source, easy to install and easy to use. It's available for Windows, OS X and Linux. + +[Download it here](https://atom.io/) + + +## Why are we installing a code editor? + +You might be wondering why we are installing this special code editor software, rather than using something like Word or Notepad. + +The first reason is that code needs to be **plain text**, and the problem with programs like Word and Textedit is that they don't actually produce plain text, they produce rich text (with fonts and formatting), using custom formats like [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +The second reason is that code editors are specialized for editing code, so they can provide helpful features like highlighting code with color according to its meaning, or automatically closing quotes for you. + +We'll see all this in action later. Soon, you'll come to think of your trusty old code editor as one of your favorite tools. :) + diff --git a/en/css/README.md b/en/css/README.md index 43086a7fd83..9a0051f2ca6 100644 --- a/en/css/README.md +++ b/en/css/README.md @@ -1,30 +1,30 @@ -# CSS - make it pretty! +# CSS – make it pretty! Our blog still looks pretty ugly, right? Time to make it nice! We will use CSS for that. ## What is CSS? -Cascading Style Sheets (CSS) is a language used for describing the look and formatting of a website written in markup language (like HTML). Treat it as make-up for our webpage ;). +Cascading Style Sheets (CSS) is a language used for describing the look and formatting of a website written in a markup language (like HTML). Treat it as make-up for our web page. ;) -But we don't want to start from scratch again, right? We will, once more, use something that has already been done by programmers and released on the Internet for free. You know, reinventing the wheel is no fun. +But we don't want to start from scratch again, right? Once more, we'll use something that programmers released on the Internet for free. Reinventing the wheel is no fun, you know. ## Let's use Bootstrap! -Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: http://getbootstrap.com/ +Bootstrap is one of the most popular HTML and CSS frameworks for developing beautiful websites: https://getbootstrap.com/ -It was written by programmers who worked for Twitter and is now developed by volunteers from all over the world. +It was written by programmers who worked for Twitter. Now it's developed by volunteers from all over the world! ## Install Bootstrap -To install Bootstrap, you need to add this to your `` in your `.html` file (`blog/templates/blog/post_list.html`): +To install Bootstrap, you need to add this to your `` in your `.html` file: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html ``` -This doesn't add any files to your project. It just points to files that exist on the internet. -Just go ahead, open your website and refresh the page. Here it is! +This doesn't add any files to your project. It just points to files that exist on the Internet. Just go ahead, open your website and refresh the page. Here it is! ![Figure 14.1](images/bootstrap1.png) @@ -33,75 +33,85 @@ Looking nicer already! ## Static files in Django -Finally we will take a closer look at these things we've been calling __static files__. Static files are all your CSS and images -- files that are not dynamic, so their content doesn't depend on the request context and will be the same for every user. +Finally we will take a closer look at these things we've been calling __static files__. Static files are all your CSS and images. Their content doesn't depend on the request context and will be the same for every user. ### Where to put static files for Django -As you saw when we ran `collectstatic` on the server, Django already knows where to find the static files for the built-in "admin" app. Now we just need to add some static files for our own app, `blog`. +Django already knows where to find the static files for the built-in "admin" app. Now we just need to add some static files for our own app, `blog`. We do that by creating a folder called `static` inside the blog app: - djangogirls - ├── blog - │ ├── migrations - │ └── static - └── mysite - -Django will automatically find any folders called "static" inside any of your apps' folders, and it will be able to use their contents as static files. +``` +djangogirls +├── blog +│ ├── migrations +│ └── static +└── mysite +``` +Django will automatically find any folders called "static" inside any of your apps' folders. Then it will be able to use their contents as static files. ## Your first CSS file! -Let's create a CSS file now, to add your own style to your web-page. Create a new directory called `css` inside your `static` directory. Then create a new file called `blog.css` inside this `css` directory. Ready? +Let's create a CSS file now, to add your own style to your web page. Create a new directory called `css` inside your `static` directory. Then create a new file called `blog.css` inside this `css` directory. Ready? - djangogirls - └─── blog - └─── static - └─── css - └─── blog.css +``` +djangogirls +└─── blog + └─── static + └─── css + └─── blog.css +``` Time to write some CSS! Open up the `blog/static/css/blog.css` file in your code editor. -We won't be going too deep into customizing and learning about CSS here, because it's pretty easy and you can learn it on your own after this workshop. We really recommend doing this [Codeacademy HTML & CSS course](http://www.codecademy.com/tracks/web) to learn everything you need to know about making your websites more pretty with CSS. +We won't be going too deep into customizing and learning about CSS here. It's pretty easy and you can learn it on your own after this workshop. There is a recommendation for a free course to learn more at the end of this page. -But let's do at least a little. Maybe we could change the color of our header? To understand colors, computers use special codes. They start with `#` and are followed by 6 letters (A-F) and numbers (0-9). You can find color codes for example here: http://www.colorpicker.com/. You may also use [predefined colors](http://www.w3schools.com/cssref/css_colornames.asp), such as `red` and `green`. +But let's do at least a little. Maybe we could change the color of our header? +To understand colors, computers use special codes. These codes start with `#` followed by 6 letters (A–F) and numbers (0–9). For example, the code for blue is `#0000FF`. You can find the color codes for many colors here: http://www.colorpicker.com/. You may also use [predefined colors](http://www.w3schools.com/colors/colors_names.asp), such as `red` and `green`. In your `blog/static/css/blog.css` file you should add the following code: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css h1 a { color: #FCA205; } ``` -`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element (e.g. when we have in code something like: `

link

`). In this case, we're telling it to change its color to `#FCA205`, which is orange. Of course, you can put your own color here! +`h1 a` is a CSS Selector. This means we're applying our styles to any `a` element inside of an `h1` element. So when we have something like `

link

`, the `h1 a` style will apply. In this case, we're telling it to change its color to `#FCA205`, which is orange. Of course, you can put your own color here! -In a CSS file we determine styles for elements in the HTML file. The elements are identified by the element name (i.e. `a`, `h1`, `body`), the attribute `class` or the attribute `id`. Class and id are names you give the element by yourself. Classes define groups of elements, and ids point to specific elements. For example, the following tag may be identified by CSS using the tag name `a`, the class `external_link`, or the id `link_to_wiki_page`: +In a CSS file we determine styles for elements in the HTML file. The first way we identify elements is with the element name. You might remember these as tags from the HTML section. Things like `a`, `h1`, and `body` are all examples of element names. +We also identify elements by the attribute `class` or the attribute `id`. Class and id are names you give the element by yourself. Classes define groups of elements, and ids point to specific elements. For example, you could identify the following tag by using the tag name `a`, the class `external_link`, or the id `link_to_wiki_page`: ```html - + ``` -Read about [CSS Selectors in w3schools](http://www.w3schools.com/cssref/css_selectors.asp). +You can read more about [CSS Selectors at w3schools](http://www.w3schools.com/cssref/css_selectors.asp). -Then, we need to also tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file and add this line at the very beginning of it: +We also need to tell our HTML template that we added some CSS. Open the `blog/templates/blog/post_list.html` file and add this line at the very beginning of it: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% load staticfiles %} ``` -We're just loading static files here :). Then, between the `` and ``, after the links to the Bootstrap CSS files (the browser reads the files in the order they're given, so code in our file may override code in Bootstrap files), add this line: +We're just loading static files here. :) +Between the `` and `` tags, after the links to the Bootstrap CSS files, add this line: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html ``` - +The browser reads the files in the order they're given, so we need to make sure this is in the right place. Otherwise the code in our file may override code in Bootstrap files. We just told our template where our CSS file is located. Your file should now look like this: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% load staticfiles %} @@ -120,7 +130,7 @@ Your file should now look like this:

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -133,26 +143,29 @@ OK, save the file and refresh the site! Nice work! Maybe we would also like to give our website a little air and increase the margin on the left side? Let's try this! +{% filename %}blog/static/css/blog.css{% endfilename %} ```css body { padding-left: 15px; } ``` -Add this to your CSS, save the file and see how it works! +Add that to your CSS, save the file and see how it works! ![Figure 14.3](images/margin2.png) Maybe we can customize the font in our header? Paste this into your `` in `blog/templates/blog/post_list.html` file: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html - + ``` -This line will import a font called *Lobster* from Google Fonts (https://www.google.com/fonts). +As before, check the order and place before the link to `blog/static/css/blog.css`. This line will import a font called *Lobster* from Google Fonts (https://www.google.com/fonts). -Now add the line `font-family: 'Lobster';` in the CSS file `blog/static/css/blog.css` inside the `h1 a` declaration block (the code between the braces `{` and `}`) and refresh the page: +Find the `h1 a` declaration block (the code between braces `{` and `}`) in the CSS file `blog/static/css/blog.css`. Now add the line `font-family: 'Lobster';` between the braces, and refresh the page: +{% filename %}blog/static/css/blog.css{% endfilename %} ```css h1 a { color: #FCA205; @@ -165,10 +178,11 @@ h1 a { Great! -As mentioned above, CSS has a concept of classes, which basically allows you to name a part of the HTML code and apply styles only to this part, not affecting others. It's super helpful if you have two divs, but they're doing something very different (like your header and your post), so you don't want them to look the same. +As mentioned above, CSS has a concept of classes. These allow you to name a part of the HTML code and apply styles only to this part, without affecting other parts. This can be super helpful! Maybe you have two divs that are doing something different (like your header and your post). A class can help you make them look different. Go ahead and name some parts of the HTML code. Add a class called `page-header` to your `div` that contains your header, like this: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% endif %}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endblock %} ``` Once again we are extending `base.html`. In the `content` block we want to display a post's published_date (if it exists), title and text. But we should discuss some important things, right? -{% raw %}`{% if ... %} ... {% endif %}` is a template tag we can use when we want to check something (remember `if ... else ..` from __Introduction to Python__ chapter?). In this scenario we want to check if a post's `published_date` is not empty.{% endraw %} +{% raw %}`{% if ... %} ... {% endif %}` is a template tag we can use when we want to check something. (Remember `if ... else ..` from __Introduction to Python__ chapter?) In this scenario we want to check if a post's `published_date` is not empty.{% endraw %} -Ok, we can refresh our page and see if `Page not found` is gone now. +OK, we can refresh our page and see if `TemplateDoesNotExist` is gone now. ![Post detail page](images/post_detail2.png) Yay! It works! - ## One more thing: deploy time! It'd be good to see if your website will still be working on PythonAnywhere, right? Let's try deploying again. +{% filename %}command-line{% endfilename %} ``` $ git status -$ git add -A . +$ git add --all . $ git status -$ git commit -m "Added views to create/edit blog post inside the site." +$ git commit -m "Added view and template for detailed blog post as well as CSS for the site." $ git push ``` -* Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): +Then, in a [PythonAnywhere Bash console](https://www.pythonanywhere.com/consoles/): +{% filename %}command-line{% endfilename %} ``` $ cd my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic +$ git pull [...] ``` -* Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. +Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload**. And that should be it! Congrats :) diff --git a/en/extend_your_application/images/attribute_error2.png b/en/extend_your_application/images/attribute_error2.png index 6edcd9933c3..05296adf4a5 100644 Binary files a/en/extend_your_application/images/attribute_error2.png and b/en/extend_your_application/images/attribute_error2.png differ diff --git a/en/extend_your_application/images/no_reverse_match2.png b/en/extend_your_application/images/no_reverse_match2.png index db65a5dc70a..306926206f8 100644 Binary files a/en/extend_your_application/images/no_reverse_match2.png and b/en/extend_your_application/images/no_reverse_match2.png differ diff --git a/en/how_the_internet_works/README.md b/en/how_the_internet_works/README.md index c2be9a5e68c..cfcc8482452 100644 --- a/en/how_the_internet_works/README.md +++ b/en/how_the_internet_works/README.md @@ -1,8 +1,10 @@ # How the Internet works -> This chapter is inspired by a talk "How the Internet works" by Jessica McKellar (http://web.mit.edu/jesstess/www/). +> For readers at home: this chapter is covered in the [How the Internet Works](https://www.youtube.com/watch?v=oM9yAA09wdc) video. -We bet you use the Internet every day. But do you actually know what happens when you type an address like http://djangogirls.org into your browser and press `enter`? +> This chapter is inspired by the talk "How the Internet works" by Jessica McKellar (http://web.mit.edu/jesstess/www/). + +We bet you use the Internet every day. But do you actually know what happens when you type an address like https://djangogirls.org into your browser and press `enter`? The first thing you need to understand is that a website is just a bunch of files saved on a hard disk. Just like your movies, music, or pictures. However, there is one part that is unique for websites: they include computer code called HTML. @@ -11,25 +13,25 @@ If you're not familiar with programming it can be hard to grasp HTML at first, b follow its instructions, and present these files that your website is made of, exactly the way you want. As with every file, we need to store HTML files somewhere on a hard disk. For the Internet, we use special, powerful computers called *servers*. They don't have -a screen, mouse or a keyboard, because their main purpose is to store data and serve it. That's why they're called *servers* -- because they *serve* you data. +a screen, mouse or a keyboard, because their main purpose is to store data and serve it. That's why they're called *servers* – because they *serve* you data. -OK, but you want to know how the Internet looks like, right? +OK, but you want to know how the Internet looks, right? We drew you a picture! It looks like this: ![Figure 1.1](images/internet_1.png) -Looks like a mess, right? In fact it is a network of connected machines (the above mentioned *servers*). Hundreds of thousands of machines! Many, many kilometers of cables around the world! You can visit a Submarine Cable Map website (http://submarinecablemap.com/) to see how complicated the net is. Here is a screenshot from the website: +Looks like a mess, right? In fact it is a network of connected machines (the above-mentioned *servers*). Hundreds of thousands of machines! Many, many kilometers of cables around the world! You can visit a Submarine Cable Map website (http://submarinecablemap.com) to see how complicated the net is. Here is a screenshot from the website: ![Figure 1.2](images/internet_3.png) -It is fascinating, isn't it? But obviously, it is not possible to have a wire between every machine connected to the Internet. So, to reach a machine (for example the one where http://djangogirls.org is saved) we need to pass a request through many, many different machines. +It is fascinating, isn't it? But obviously, it is not possible to have a wire between every machine connected to the Internet. So, to reach a machine (for example, the one where https://djangogirls.org is saved) we need to pass a request through many, many different machines. It looks like this: ![Figure 1.3](images/internet_2.png) -Imagine that when you type http://djangogirls.org, you send a letter that says: "Dear Django Girls, I want to see the djangogirls.org website. Send it to me, please!" +Imagine that when you type https://djangogirls.org, you send a letter that says: "Dear Django Girls, I want to see the djangogirls.org website. Send it to me, please!" Your letter goes to the post office closest to you. Then it goes to another that is a bit nearer to your addressee, then to another, and another until it is delivered at its destination. The only unique thing is that if you send many letters (*data packets*) to the same place, they could go through totally different post offices (*routers*). This depends on how they are distributed at each office. @@ -37,12 +39,12 @@ Your letter goes to the post office closest to you. Then it goes to another that Yes, it is as simple as that. You send messages and you expect some response. Of course, instead of paper and pen you use bytes of data, but the idea is the same! -Instead of addresses with a street name, city, zip code and country name, we use IP addresses. Your computer first asks the DNS (Domain Name System) to translate djangogirls.org into an IP address. It works a little bit like old-fashioned phonebooks where you could look up the name of the person you want to contact and find their phone number and address. +Instead of addresses with a street name, city, zip code and country name, we use IP addresses. Your computer first asks the DNS (Domain Name System) to translate djangogirls.org into an IP address. It works a little bit like old-fashioned phonebooks where you can look up the name of the person you want to contact and find their phone number and address. -When you send a letter, it needs to have certain features to be delivered correctly: an address, stamp etc. You also use a language that the receiver understands, right? The same applies to the *data packets* you send to see a website. We use a protocol called HTTP (Hypertext Transfer Protocol). +When you send a letter, it needs to have certain features to be delivered correctly: an address, a stamp, etc. You also use a language that the receiver understands, right? The same applies to the *data packets* you send to see a website. We use a protocol called HTTP (Hypertext Transfer Protocol). So, basically, when you have a website, you need to have a *server* (machine) where it lives. When the *server* receives an incoming *request* (in a letter), it sends back your website (in another letter). -Since this is a Django tutorial, you will ask what Django does. When you send a response, you don't always want to send the same thing to everybody. It is so much better if your letters are personalized, especially for the person that has just written to you, right? Django helps you with creating these personalized, interesting letters :). +Since this is a Django tutorial, you might ask what Django does. When you send a response, you don't always want to send the same thing to everybody. It is so much better if your letters are personalized, especially for the person that has just written to you, right? Django helps you with creating these personalized, interesting letters. :) -Enough talk, time to create! +Enough talk – time to create! diff --git a/en/how_the_internet_works/images/internet_4.png b/en/how_the_internet_works/images/internet_4.png index 05f1aed562f..2661cec1b61 100644 Binary files a/en/how_the_internet_works/images/internet_4.png and b/en/how_the_internet_works/images/internet_4.png differ diff --git a/en/html/README.md b/en/html/README.md index 6be809b8e95..ac5181be379 100644 --- a/en/html/README.md +++ b/en/html/README.md @@ -2,13 +2,13 @@ What's a template, you may ask? -A template is a file that we can re-use to present different information in a consistent format - for example, you could use a template to help you write a letter, because although each letter might contain a different message and be addressed to a different person, they will share the same format. +A template is a file that we can re-use to present different information in a consistent format – for example, you could use a template to help you write a letter, because although each letter might contain a different message and be addressed to a different person, they will share the same format. -A Django template's format is described in a language called HTML (that's the HTML we mentioned in the first chapter __How the Internet works__). +A Django template's format is described in a language called HTML (that's the HTML we mentioned in the first chapter, __How the Internet works__). ## What is HTML? -HTML is a simple code that is interpreted by your web browser - such as Chrome, Firefox or Safari - to display a webpage for the user. +HTML is a simple code that is interpreted by your web browser – such as Chrome, Firefox or Safari – to display a web page for the user. HTML stands for "HyperText Markup Language". __HyperText__ means it's a type of text that supports hyperlinks between pages. __Markup__ means we have taken a document and marked it up with code to tell something (in this case, a browser) how to interpret the page. HTML code is built with __tags__, each one starting with `<` and ending with `>`. These tags represent markup __elements__. @@ -18,17 +18,19 @@ Creating a template means creating a template file. Everything is a file, right? Templates are saved in `blog/templates/blog` directory. So first create a directory called `templates` inside your blog directory. Then create another directory called `blog` inside your templates directory: - blog - └───templates - └───blog +``` +blog +└───templates + └───blog +``` -(You might wonder why we need two directories both called `blog` - as you will discover later, this is simply a useful naming convention that makes life easier when things start to get more complicated.) +(You might wonder why we need two directories both called `blog` – as you will discover later, this is simply a useful naming convention that makes life easier when things start to get more complicated.) And now create a `post_list.html` file (just leave it blank for now) inside the `blog/templates/blog` directory. See how your website looks now: http://127.0.0.1:8000/ -> If you still have an error `TemplateDoesNotExists`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C buttons together) and start it again by running a `python manage.py runserver` command. +> If you still have an error `TemplateDoesNotExist`, try to restart your server. Go into command line, stop the server by pressing Ctrl+C (Control and C buttons together) and start it again by running a `python manage.py runserver` command. ![Figure 11.1](images/step1.png) @@ -36,6 +38,7 @@ No error anymore! Congratulations :) However, your website isn't actually publis Add the following to your template file: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html

Hi there!

@@ -43,16 +46,16 @@ Add the following to your template file: ``` -So how does your website look now? Click to find out: http://127.0.0.1:8000/ +So how does your website look now? Visit it to find out: http://127.0.0.1:8000/ ![Figure 11.2](images/step3.png) It worked! Nice work there :) -- The most basic tag, ``, is always the beginning of any webpage and `` is always the end. As you can see, the whole content of the website goes between the beginning tag `` and closing tag `` +- The most basic tag, ``, is always the beginning of any web page and `` is always the end. As you can see, the whole content of the website goes between the beginning tag `` and closing tag `` - `

` is a tag for paragraph elements; `

` closes each paragraph -## Head & body +## Head and body Each HTML page is also divided into two elements: __head__ and __body__. @@ -62,8 +65,9 @@ Each HTML page is also divided into two elements: __head__ and __body__. We use `` to tell the browser about the configuration of the page, and `` to tell it what's actually on the page. -For example, you can put a webpage title element inside the ``, like this: +For example, you can put a web page title element inside the ``, like this: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -86,24 +90,26 @@ Probably you have also noticed that each opening tag is matched by a _closing ta It's like putting things into boxes. You have one big box, ``; inside it there is ``, and that contains still smaller boxes: `

`. -You need to follow these rules of _closing_ tags, and of _nesting_ elements - if you don't, the browser may not be able to interpret them properly and your page will display incorrectly. +You need to follow these rules of _closing_ tags, and of _nesting_ elements – if you don't, the browser may not be able to interpret them properly and your page will display incorrectly. ## Customize your template You can now have a little fun and try to customize your template! Here are a few useful tags for that: -- `

A heading

` - for your most important heading +- `

A heading

` for your most important heading - `

A sub-heading

` for a heading at the next level -- `

A sub-sub-heading

` ... and so on, up to `
` +- `

A sub-sub-heading

` …and so on, up to `
` +- `

A paragraph of text

` - `text` emphasizes your text - `text` strongly emphasizes your text - `
` goes to another line (you can't put anything inside br) -- `link` creates a link +- `link` creates a link - `
  • first item
  • second item
` makes a list, just like this one! - `
` defines a section of the page Here's an example of a full template: +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html @@ -131,16 +137,16 @@ Here's an example of a full template: We've created three `div` sections here. -- The first `div` element contains the title of our blog - it's a heading and a link +- The first `div` element contains the title of our blog – it's a heading and a link - Another two `div` elements contain our blogposts with a published date, `h2` with a post title that is clickable and two `p`s (paragraph) of text, one for the date and one for our blogpost. It gives us this effect: ![Figure 11.4](images/step6.png) -Yaaay! But so far, our template only ever displays exactly __the same information__ - whereas earlier we were talking about templates as allowing us to display __different__ information in the __same format__. +Yaaay! But so far, our template only ever displays exactly __the same information__ – whereas earlier we were talking about templates as allowing us to display __different__ information in the __same format__. -What we really want to do is display real posts added in our Django admin - and that's where we're going next. +What we really want to do is display real posts added in our Django admin – and that's where we're going next. ## One more thing: deploy! @@ -150,39 +156,51 @@ It'd be good to see all this out and live on the Internet, right? Let's do anot First off, let's see what files have changed since we last deployed (run these commands locally, not on PythonAnywhere): - $ git status +{% filename %}command-line{% endfilename %} +``` +$ git status +``` Make sure you're in the `djangogirls` directory and let's tell `git` to include all the changes within this directory: - $ git add -A . +{% filename %}command-line{% endfilename %} +``` +$ git add --all . +``` -> __Note__ `-A` (short for "all") means that `git` will also recognize if you've deleted files (by default, it only recognizes new/modified files). Also remember (from chapter 3) that `.` means the current directory. +> __Note__ `--all` means that `git` will also recognize if you've deleted files (by default, it only recognizes new/modified files). Also remember (from chapter 3) that `.` means the current directory. Before we upload all the files, let's check what `git` will be uploading (all the files that `git` will upload should now appear in green): - $ git status +{% filename %}command-line{% endfilename %} +``` +$ git status +``` We're almost there, now it's time to tell it to save this change in its history. We're going to give it a "commit message" where we describe what we've changed. You can type anything you'd like at this stage, but it's helpful to type something descriptive so that you can remember what you've done in the future. - $ git commit -m "Changed the HTML for the site." +{% filename %}command-line{% endfilename %} +``` +$ git commit -m "Changed the HTML for the site." +``` > __Note__ Make sure you use double quotes around the commit message. -Once we've done that, we upload (push) our changes up to Github: - - git push +Once we've done that, we upload (push) our changes up to GitHub: +{% filename %}command-line{% endfilename %} +``` +$ git push +``` ### Pull your new code down to PythonAnywhere, and reload your web app * Open up the [PythonAnywhere consoles page](https://www.pythonanywhere.com/consoles/) and go to your **Bash console** (or start a new one). Then, run: +{% filename %}command-line{% endfilename %} ``` $ cd ~/my-first-blog -$ source myvenv/bin/activate -(myvenv)$ git pull -[...] -(myvenv)$ python manage.py collectstatic +$ git pull [...] ``` @@ -191,4 +209,4 @@ And watch your code get downloaded. If you want to check that it's arrived, you * Finally, hop on over to the [Web tab](https://www.pythonanywhere.com/web_app_setup/) and hit **Reload** on your web app. -Your update should be live! Go ahead and refresh your website in the browser. Changes should be visible :) +Your update should be live! Go ahead and refresh your website in the browser. Changes should be visible. :) diff --git a/en/installation/README.md b/en/installation/README.md new file mode 100644 index 00000000000..9f929e157bc --- /dev/null +++ b/en/installation/README.md @@ -0,0 +1,53 @@ +# If you're doing the tutorial at home + +If you're doing the tutorial at home, not at one of the [Django Girls events](https://djangogirls.org/events/), you can completely skip this chapter now and go straight to the [How the Internet works?](../how_the_internet_works/README.md) chapter. + +This is because we cover these things in the whole tutorial anyway, and this is just an additional page that gathers all of the installation instructions in one place. The Django Girls event includes one "Installation evening" where we install everything so we don't need to bother with it during the workshop, so this is useful for us. + +If you find it useful, you can follow through this chapter too. But if you want to start learning things before installing a bunch of stuff on your computer, skip this chapter and we will explain the installation part to you later on. + +Good luck! + +# Installation +In the workshop you will be building a blog, and there are a few setup tasks in the tutorial which would be good to work through beforehand so that you are ready to start coding on the day. + + +{% include "/chromebook_setup/instructions.md" %} + + +# Install Python +{% include "/python_installation/instructions.md" %} + +# Set up virtualenv and install Django +{% include "/django_installation/instructions.md" %} + +# Install a code editor +{% include "/code_editor/instructions.md" %} + +# Install Git +{% include "/deploy/install_git.md" %} + +# Create a GitHub account +Go to [GitHub.com](https://www.github.com) and sign up for a new, free user account. + +# Create a PythonAnywhere account +{% include "/deploy/signup_pythonanywhere.md" %} + + +# Start reading + +Congratulations, you are all set up and ready to go! If you still have some time before the workshop, it would be useful to start reading a few of the beginning chapters: + +* [How the internet works](../how_the_internet_works/README.md) + +* [Introduction to the command line](../intro_to_command_line/README.md) + +* [Introduction to Python](../python_introduction/README.md) + +* [What is Django?](../django/README.md) + + +# Enjoy the workshop! + +When you begin the workshop, you'll be able to go straight to [Your first Django project!](../django_start_project/README.md) because you already covered the material in the earlier chapters. diff --git a/en/intro_to_command_line/README.md b/en/intro_to_command_line/README.md index 0552f573aeb..5496e5903a9 100644 --- a/en/intro_to_command_line/README.md +++ b/en/intro_to_command_line/README.md @@ -1,67 +1,111 @@ # Introduction to the command-line interface -Huh, it's exciting, right?! You'll write your first line of code in just a few minutes :) +> For readers at home: this chapter is covered in the [Your new friend: Command Line](https://www.youtube.com/watch?v=jvZLWhkzX-8) video. + +It's exciting, right?! You'll write your first line of code in just a few minutes! :) __Let us introduce you to your first new friend: the command line!__ The following steps will show you how to use the black window all hackers use. It might look a bit scary at first but really it's just a prompt waiting for commands from you. -> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangably but they are one and the same thing. +> **Note** Please note that throughout this book we use the terms 'directory' and 'folder' interchangeably but they are one and the same thing. ## What is the command line? -The window, which is usually called the __command line__ or __command-line interface__, is a text-based application for viewing, handling, and manipulating files on your computer. Much like Windows Explorer or Finder on Mac, but without the graphical interface. Other names for the command line are: *cmd*, *CLI*, *prompt*, *console* or *terminal*. +The window, which is usually called the __command line__ or __command-line interface__, is a text-based application for viewing, handling, and manipulating files on your computer. It's much like Windows Explorer or Finder on the Mac, but without the graphical interface. Other names for the command line are: *cmd*, *CLI*, *prompt*, *console* or *terminal*. ## Open the command-line interface To start some experiments we need to open our command-line interface first. -### Windows + + Go to Start menu → All Programs → Accessories → Command Prompt. -### Mac OS X + + + + + +Go to Applications → Utilities → Terminal. -Applications → Utilities → Terminal. + -### Linux + -It's probably under Applications → Accessories → Terminal, but that may depend on your system. If it's not there, just Google it :) +It's probably under Applications → Accessories → Terminal, but that may depend on your system. If it's not there, just Google it. :) + + ## Prompt You now should see a white or black window that is waiting for your commands. + + + If you're on Mac or Linux, you probably see `$`, just like this: - $ +{% filename %}command-line{% endfilename %} +``` +$ +``` + + + + On Windows, it's a `>` sign, like this: - > +{% filename %}command-line{% endfilename %} +``` +> +``` + -Each command will be prepended by this sign and one space, but you don't have to type it. Your computer will do it for you :) +Each command will be prepended by this sign and one space, but you don't have to type it. Your computer will do it for you. :) -> Just a small note: in your case there may be something like `C:\Users\ola>` or `Olas-MacBook-Air:~ ola$` before the prompt sign and that's 100% correct. In this tutorial we will just simplify it to the bare minimum. +> Just a small note: in your case there may be something like `C:\Users\ola>` or `Olas-MacBook-Air:~ ola$` before the prompt sign, and this is 100% OK. + +The part up to and including the `$` or the `>` is called the *command line prompt*, or *prompt* for short. It prompts you to input something there. + +In the tutorial, when we want you to type in a command, we will include the `$` or `>`, and occasionally more to the left. You can ignore the left part and just type in the command which starts after the prompt. ## Your first command (YAY!) Let's start with something simple. Type this command: - $ whoami + + +{% filename %}command-line{% endfilename %} +``` +$ whoami +``` + + + -or + - > whoami +{% filename %}command-line{% endfilename %} +``` +> whoami +``` + + And then hit `enter`. This is our result: - $ whoami - olasitarska +{% filename %}command-line{% endfilename %} +``` +$ whoami +olasitarska +``` -As you can see, the computer has just printed your username. Neat, huh?:) +As you can see, the computer has just printed your username. Neat, huh? :) -> Try to type each command, do not copy-paste. You'll remember more this way! +> Try to type each command; do not copy-paste. You'll remember more this way! ## Basics @@ -71,13 +115,26 @@ Each operating system has a slightly different set of commands for the command l It'd be nice to know where are we now, right? Let's see. Type this command and hit `enter`: - $ pwd - /Users/olasitarska + + + +{% filename %}command-line{% endfilename %} +``` +$ pwd +/Users/olasitarska +``` + + + -If you're on Windows: + - > cd - C:\Users\olasitarska +{% filename %}command-line{% endfilename %} +``` +> cd +C:\Users\olasitarska +``` + You'll probably see something similar on your machine. Once you open the command line you usually start at your user's home directory. @@ -89,22 +146,33 @@ You'll probably see something similar on your machine. Once you open the command So what's in it? It'd be cool to find out. Let's see: - $ ls - Applications - Desktop - Downloads - Music - ... - - Windows: - - > dir - Directory of C:\Users\olasitarska - 05/08/2014 07:28 PM Applications - 05/08/2014 07:28 PM Desktop - 05/08/2014 07:28 PM Downloads - 05/08/2014 07:28 PM Music - ... + + +{% filename %}command-line{% endfilename %} +``` +$ ls +Applications +Desktop +Downloads +Music +... +``` + + + + + +{% filename %}command-line{% endfilename %} +``` +> dir + Directory of C:\Users\olasitarska +05/08/2014 07:28 PM Applications +05/08/2014 07:28 PM Desktop +05/08/2014 07:28 PM Downloads +05/08/2014 07:28 PM Music +... +``` + --- @@ -112,39 +180,71 @@ So what's in it? It'd be cool to find out. Let's see: Now, let's go to our Desktop directory: - $ cd Desktop + + +{% filename %}command-line{% endfilename %} +``` +$ cd Desktop +``` + -Windows: + - > cd Desktop + +{% filename %}command-line{% endfilename %} +``` +> cd Desktop +``` + Check if it's really changed: - $ pwd - /Users/olasitarska/Desktop + + +{% filename %}command-line{% endfilename %} +``` +$ pwd +/Users/olasitarska/Desktop +``` + -Windows: + - > cd - C:\Users\olasitarska\Desktop +{% filename %}command-line{% endfilename %} +``` +> cd +C:\Users\olasitarska\Desktop +``` + Here it is! -> PRO tip: if you type `cd D` and then hit `tab` on your keyboard, the command line will automatically autofill the rest of the name so you can navigate faster. If there is more than one folder starting with "D", hit the `tab` button twice to get a list of options. +> PRO tip: if you type `cd D` and then hit `tab` on your keyboard, the command line will automatically fill in the rest of the name so you can navigate faster. If there is more than one folder starting with "D", hit the `tab` button twice to get a list of options. --- ### Create directory -How about creating a Django Girls directory on your desktop? You can do it this way: +How about creating a practice directory on your desktop? You can do it this way: - $ mkdir djangogirls + -Windows: +{% filename %}command-line{% endfilename %} +``` +$ mkdir practice +``` + - > mkdir djangogirls + -This little command will create a folder with the name `djangogirls` on your desktop. You can check if it's there just by looking on your Desktop or by running a `ls`/`dir` command! Try it :) + +{% filename %}command-line{% endfilename %} +``` +> mkdir practice +``` + + +This little command will create a folder with the name `practice` on your desktop. You can check if it's there just by looking on your Desktop or by running a `ls` or `dir` command! Try it. :) > PRO tip: If you don't want to type the same commands over and over, try pressing the `up arrow` and `down arrow` on your keyboard to cycle through recently used commands. @@ -152,21 +252,32 @@ This little command will create a folder with the name `djangogirls` on your des ### Exercise! -Small challenge for you: in your newly created `djangogirls` directory create a directory called `test`. Use `cd` and `mkdir` commands. +A small challenge for you: in your newly created `practice` directory, create a directory called `test`. (Use the `cd` and `mkdir` commands.) #### Solution: - $ cd djangogirls - $ mkdir test - $ ls - test + + +{% filename %}command-line{% endfilename %} +``` +$ cd practice +$ mkdir test +$ ls +test +``` + -Windows: + - > cd djangogirls - > mkdir test - > dir - 05/08/2014 07:28 PM test + +{% filename %}command-line{% endfilename %} +``` +> cd practice +> mkdir test +> dir +05/08/2014 07:28 PM test +``` + Congrats! :) @@ -178,68 +289,124 @@ We don't want to leave a mess, so let's remove everything we did until that poin First, we need to get back to Desktop: - $ cd .. + + +{% filename %}command-line{% endfilename %} +``` +$ cd .. +``` + -Windows: + - > cd .. -Using `..` with the `cd` command will change your current directory to the parent directory (this is the directory that contains your current directory). +{% filename %}command-line{% endfilename %} +``` +> cd .. +``` + + +Using `..` with the `cd` command will change your current directory to the parent directory (that is, the directory that contains your current directory). Check where you are: - $ pwd - /Users/olasitarska/Desktop + + +{% filename %}command-line{% endfilename %} +``` +$ pwd +/Users/olasitarska/Desktop +``` + + + + + +{% filename %}command-line{% endfilename %} +``` +> cd +C:\Users\olasitarska\Desktop +``` + -Windows: +Now time to delete the `practice` directory: - > cd - C:\Users\olasitarska\Desktop +> __Attention__: Deleting files using `del`, `rmdir` or `rm` is irrecoverable, meaning _the deleted files will be gone forever_! So be very careful with this command. -Now time to delete the `djangogirls` directory: + -> __Attention__: Deleting files using `del`, `rmdir` or `rm` is irrecoverable, meaning _deleted files will be gone forever_! So, be very careful with this command. +{% filename %}command-line{% endfilename %} +``` +$ rm -r practice +``` + - $ rm -r djangogirls + -Windows: - > rmdir /S djangogirls - djangogirls, Are you sure ? Y +{% filename %}command-line{% endfilename %} +``` +> rmdir /S practice +practice, Are you sure ? Y +``` + Done! To be sure it's actually deleted, let's check it: - $ ls + -Windows: +{% filename %}command-line{% endfilename %} +``` +$ ls +``` + - > dir + + + +{% filename %}command-line{% endfilename %} +``` +> dir +``` + ### Exit -That's it for now! You can safely close the command line now. Let's do it the hacker way, alright?:) +That's it for now! You can safely close the command line now. Let's do it the hacker way, alright? :) + + + +{% filename %}command-line{% endfilename %} +``` +$ exit +``` + - $ exit + -Windows: - > exit +{% filename %}command-line{% endfilename %} +``` +> exit +``` + -Cool, huh?:) +Cool, huh? :) ## Summary Here is a summary of some useful commands: -| Command (Windows) | Command (Mac OS / Linux) | Description | Example | -| ----------------- | ------------------------ | ----------------------- | --------------------------------------------- | -| exit | exit | close the window | **exit** | -| cd | cd | change directory | **cd test** | -| dir | ls | list directories/files | **dir** | -| copy | cp | copy file | **copy c:\test\test.txt c:\windows\test.txt** | -| move | mv | move file | **move c:\test\test.txt c:\windows\test.txt** | -| mkdir | mkdir | create a new directory | **mkdir testdirectory** | -|del | rm | delete a directory/file | **del c:\test\test.txt** | +Command (Windows) | Command (Mac OS / Linux) | Description | Example +------------- | ----- | ---------------------- | --------------------------------------------- +exit | exit | close the window | **exit** +cd | cd | change directory | **cd test** +dir | ls | list directories/files | **dir** +copy | cp | copy file | **copy c:\test\test.txt c:\windows\test.txt** +move | mv | move file | **move c:\test\test.txt c:\windows\test.txt** +mkdir | mkdir | create a new directory | **mkdir testdirectory** +rmdir (or del)| rm | delete a file | **del c:\test\test.txt** +rmdir /S | rm -r | delete a directory | **rm -r testdirectory** These are just a very few of the commands you can run in your command line, but you're not going to use anything more than that today. diff --git a/en/python_installation/README.md b/en/python_installation/README.md index bb77037c15c..2b674d8d2c9 100644 --- a/en/python_installation/README.md +++ b/en/python_installation/README.md @@ -4,69 +4,13 @@ We're finally here! But first, let us tell you what Python is. Python is a very popular programming language that can be used for creating websites, games, scientific software, graphics, and much, much more. -Python originated in the late 1980s and its main goal is to be readable by human beings (not only machines!). This is why it looks much simpler than other programming languages. This makes it easy to learn, but don't worry, Python is also really powerful! - +Python originated in the late 1980s and its main goal is to be readable by human beings (not only machines!). This is why it looks much simpler than other programming languages. This makes it easy to learn, but don't worry – Python is also really powerful! # Python installation -> This subchapter is based on a tutorial by Geek Girls Carrots (http://django.carrots.pl/) - -Django is written in Python. We need Python to do anything in Django. Let's start with installing it! We want you to install Python 3.4, so if you have any earlier version, you will need to upgrade it. - - -### Windows - -You can download Python for Windows from the website https://www.python.org/downloads/release/python-343/. After downloading the ***.msi** file, you should run it (double-click on it) and follow the instructions there. It is important to remember the path (the directory) where you installed Python. It will be needed later! - -One thing to watch out for: on the second screen of the installation wizard, marked "Customize", make sure you scroll down and choose the "Add python.exe to the Path" option, as shown here: - -![Don't forget to add Python to the Path](images/add_python_to_windows_path.png) - - -### Linux - -It is very likely that you already have Python installed out of the box. To check if you have it installed (and which version it is), open a console and type the following command: - - $ python3 --version - Python 3.4.2 - -If you don't have Python installed, or if you want a different version, you can install it as follows: - - -#### Debian or Ubuntu - -Type this command into your console: - - $ sudo apt-get install python3.4 - - -#### Fedora (up to 21) - -Use this command in your console: - - $ sudo yum install python3.4 - - -#### Fedora (22+) - -Use this command in your console: - - $ sudo dnf install python3.4 - - -### OS X - -You need to go to the website https://www.python.org/downloads/release/python-342/ and download the Python installer: - -* Download the *Mac OS X 64-bit/32-bit installer* *DMG* file, -* Double click to open it, -* Double click *Python.mpkg* to run the installer. - -Verify the installation was successful by opening the *Terminal* application and running the `python3` command: +> **Note** If you're using a Chromebook, skip this chapter and make sure you follow the [Chromebook Setup](../chromebook_setup/README.md) instructions. - $ python3 --version - Python 3.4.2 +> **Note** If you already worked through the Installation steps, there's no need to do this again – you can skip straight ahead to the next chapter! ----- +{% include "/python_installation/instructions.md" %} -If you have any doubts, or if something went wrong and you have no idea what to do next - please ask your coach! Sometimes things don't go smoothly and it's better to ask for help from someone with more experience. diff --git a/en/python_installation/images/add_python_to_windows_path.png b/en/python_installation/images/add_python_to_windows_path.png index 7946019bc29..9510d6f2176 100644 Binary files a/en/python_installation/images/add_python_to_windows_path.png and b/en/python_installation/images/add_python_to_windows_path.png differ diff --git a/en/python_installation/images/python-installation-options.png b/en/python_installation/images/python-installation-options.png new file mode 100644 index 00000000000..4cb886349a1 Binary files /dev/null and b/en/python_installation/images/python-installation-options.png differ diff --git a/en/python_installation/images/windows-plus-r.png b/en/python_installation/images/windows-plus-r.png new file mode 100644 index 00000000000..d99a4d1ac20 Binary files /dev/null and b/en/python_installation/images/windows-plus-r.png differ diff --git a/en/python_installation/instructions.md b/en/python_installation/instructions.md new file mode 100644 index 00000000000..aef1e8bd90d --- /dev/null +++ b/en/python_installation/instructions.md @@ -0,0 +1,117 @@ +> For readers at home: this chapter is covered in the [Installing Python & Code Editor](https://www.youtube.com/watch?v=pVTaqzKZCdA) video. + +> This section is based on a tutorial by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django is written in Python. We need Python to do anything in Django. Let's start by installing it! We want you to install Python 3.5, so if you have any earlier version, you will need to upgrade it. + + + + +First check whether your computer is running a 32-bit version or a 64-bit version of Windows at https://support.microsoft.com/en-au/kb/827218. You can download Python for Windows from the website https://www.python.org/downloads/windows/. Click on the "Latest Python 3 Release - Python x.x.x" link. If your computer is running a **64-bit** version of Windows, download the **Windows x86-64 executable installer**. Otherwise, download the **Windows x86 executable installer**. After downloading the installer, you should run it (double-click on it) and follow the instructions there. + +One thing to watch out for: During the installation you will notice a window marked "Setup". Make sure you tick the "Add Python 3.5 to PATH" checkbox and click on "Install Now", as shown here: + +![Don't forget to add Python to the Path](../python_installation/images/python-installation-options.png) + +In upcoming steps, you'll be using the Windows Command Line (which we'll also tell you about). For now, if you need to type in some commands, go to Start menu → All Programs → Accessories → Command Prompt. You can also hold in the Windows key and press the "R"-key until the "Run" window pops up. To open the Command Line, type "cmd" and press enter in the "Run" window. (On newer versions of Windows, you might have to search for "Command Prompt" since it's sometimes hidden.) + +![Type "cmd" in the "Run" window](../python_installation/images/windows-plus-r.png) + +Note: if you are using an older version of Windows (7, Vista, or any older version) and the Python 3.5.x installer fails with an error, you can try either: +1. install all Windows Updates and try to install Python 3.5 again; or +2. install an [older version of Python](https://www.python.org/downloads/windows/), e.g., [3.4.4](https://www.python.org/downloads/release/python-344/). + +If you install an older version of Python, the installation screen may look a bit different than shown above. Make sure you scroll down to see "Add python.exe to Path", then click the button on the left and pick "Will be installed on local hard drive": + +![Add Python to the Path, older versions](../python_installation/images/add_python_to_windows_path.png) + + + + + +> **Note** Before you install Python on OS X, you should ensure your Mac settings allow installing packages that aren't from the App Store. Go to System Preferences (it's in the Applications folder), click "Security & Privacy," and then the "General" tab. If your "Allow apps downloaded from:" is set to "Mac App Store," change it to "Mac App Store and identified developers." + +You need to go to the website https://www.python.org/downloads/release/python-351/ and download the Python installer: + +* Download the *Mac OS X 64-bit/32-bit installer* file, +* Double click *python-3.5.1-macosx10.6.pkg* to run the installer. + + + + + +It is very likely that you already have Python installed out of the box. To check if you have it installed (and which version it is), open a console and type the following command: + +{% filename %}command-line{% endfilename %} +``` +$ python3 --version +Python 3.5.1 +``` + +If you have a different 'micro version' of Python installed, e.g. 3.5.0, then you don't have to upgrade. If you don't have Python installed, or if you want a different version, you can install it as follows: + + + + + + +Type this command into your console: + +{% filename %}command-line{% endfilename %} +``` +$ sudo apt-get install python3.5 +``` + + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} +``` +$ sudo yum install python3 +``` + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} +``` +$ sudo dnf install python3 +``` + + + + + +Use this command in your console: + +{% filename %}command-line{% endfilename %} +``` +$ sudo zypper install python3 +``` + + + +Verify the installation was successful by opening the *Terminal* application and running the `python3` command: + +{% filename %}command-line{% endfilename %} +``` +$ python3 --version +Python 3.5.1 +``` + +---- + +If you have any doubts, or if something went wrong and you have no idea what to do next, please ask your coach! Sometimes things don't go smoothly and it's better to ask for help from someone with more experience. diff --git a/en/python_introduction/README.md b/en/python_introduction/README.md index e89377d2cef..4bc4d5b0d06 100644 --- a/en/python_introduction/README.md +++ b/en/python_introduction/README.md @@ -1,84 +1,120 @@ # Introduction to Python -> Part of this chapter is based on tutorials by Geek Girls Carrots (http://django.carrots.pl/). +> Part of this chapter is based on tutorials by Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Let's write some code! ## Python prompt -To start playing with Python, we need to open up a *command line* on your computer. You should already know how to do that -- you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. +> For readers at home: this part is covered in the [Python Basics: Integers, Strings, Lists, Variables and Errors](https://www.youtube.com/watch?v=MO63L4s-20U) video. + +To start playing with Python, we need to open up a *command line* on your computer. You should already know how to do that – you learned it in the [Intro to Command Line](../intro_to_command_line/README.md) chapter. Once you're ready, follow the instructions below. We want to open up a Python console, so type in `python` on Windows or `python3` on Mac OS/Linux and hit `enter`. - $ python3 - Python 3.4.2 (...) - Type "copyright", "credits" or "license" for more information. - >>> +{% filename %}command-line{% endfilename %} +``` +$ python3 +Python 3.5.1 (...) +Type "help", "copyright", "credits" or "license" for more information. +>>> +``` ## Your first Python command! -After running the Python command, the prompt changed to `>>>`. For us this means that for now we may only use commands in the Python language. You don't have to type in `>>>` - Python will do that for you. +After running the Python command, the prompt changed to `>>>`. For us this means that for now we may only use commands in the Python language. You don't have to type in `>>>` – Python will do that for you. If you want to exit the Python console at any point, just type `exit()` or use the shortcut `Ctrl + Z` for Windows and `Ctrl + D` for Mac/Linux. Then you won't see `>>>` any longer. -But now, we don't want to exit the Python console. We want to learn more about it. Let's start with something really simple. For example, try typing some math, like `2 + 3` and hit `enter`. +For now, we don't want to exit the Python console. We want to learn more about it. Let's start with something really simple. For example, try typing some math, like `2 + 3` and hit `enter`. - >>> 2 + 3 - 5 +{% filename %}command-line{% endfilename %} +```python +>>> 2 + 3 +5 +``` Nice! See how the answer popped out? Python knows math! You could try other commands like: + - `4 * 5` - `5 - 1` - `40 / 2` -Have fun with this for a little while and then get back here :). +To perform exponential calculation, say 2 to the power 3, we type: +```python +>>> 2 ** 3 +8 +``` -As you can see, Python is a great calculator. If you're wondering what else you can do... +Have fun with this for a little while and then get back here. :) + +As you can see, Python is a great calculator. If you're wondering what else you can do… ## Strings How about your name? Type your first name in quotes like this: - >>> "Ola" - 'Ola' +{% filename %}command-line{% endfilename %} +```python +>>> "Ola" +'Ola' +``` -You've now created your first string! It's a sequence of characters that can be processed by a computer. The string must always begin and end with the same character. This may be single (`'`) or double (`"`) quotes - they tell Python that what's inside of them is a string. +You've now created your first string! It's a sequence of characters that can be processed by a computer. The string must always begin and end with the same character. This may be single (`'`) or double (`"`) quotes (there is no difference!) The quotes tell Python that what's inside of them is a string. Strings can be strung together. Try this: - >>> "Hi there " + "Ola" - 'Hi there Ola' +{% filename %}command-line{% endfilename %} +```python +>>> "Hi there " + "Ola" +'Hi there Ola' +``` You can also multiply strings with a number: - >>> "Ola" * 3 - 'OlaOlaOla' +{% filename %}command-line{% endfilename %} +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` If you need to put an apostrophe inside your string, you have two ways to do it. Using double quotes: - >>> "Runnin' down the hill" - "Runnin' down the hill" +{% filename %}command-line{% endfilename %} +```python +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` or escaping the apostrophe with a backslash (`\`): - >>> 'Runnin\' down the hill' - "Runnin' down the hill" +{% filename %}command-line{% endfilename %} +```python +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` Nice, huh? To see your name in uppercase letters, simply type: - >>> "Ola".upper() - 'OLA' +{% filename %}command-line{% endfilename %} +```python +>>> "Ola".upper() +'OLA' +``` -You just used the `upper` __function__ on your string! A function (like `upper()`) is a sequence of instructions that Python has to perform on a given object (`"Ola"`) once you call it. +You just used the `upper` __method__ on your string! A method (like `upper()`) is a sequence of instructions that Python has to perform on a given object (`"Ola"`) once you call it. -If you want to know the number of letters contained in your name, there is a function for that too! +If you want to know the number of letters contained in your name, there is a __function__ for that too! - >>> len("Ola") - 3 +{% filename %}command-line{% endfilename %} +```python +>>> len("Ola") +3 +``` Wonder why sometimes you call functions with a `.` at the end of a string (like `"Ola".upper()`) and sometimes you first call a function and place the string in parentheses? Well, in some cases, functions belong to objects, like `upper()`, which can only be performed on strings. In this case, we call the function a __method__. Other times, functions don't belong to anything specific and can be used on different types of objects, just like `len()`. That's why we're giving `"Ola"` as a parameter to the `len` function. @@ -86,10 +122,10 @@ Wonder why sometimes you call functions with a `.` at the end of a string (like OK, enough of strings. So far you've learned about: -- __the prompt__ - typing commands (code) into the Python prompt results in answers in Python -- __numbers and strings__ - in Python numbers are used for math and strings for text objects -- __operators__ - like + and \*, combine values to produce a new one -- __functions__ - like upper() and len(), perform actions on objects. +- __the prompt__ – typing commands (code) into the Python prompt results in answers in Python +- __numbers and strings__ – in Python numbers are used for math and strings for text objects +- __operators__ – like `+` and `\*`, combine values to produce a new one +- __functions__ – like `upper()` and `len()`, perform actions on objects. These are the basics of every programming language you learn. Ready for something harder? We bet you are! @@ -97,22 +133,28 @@ These are the basics of every programming language you learn. Ready for somethin Let's try something new. Can we get the length of a number the same way we could find out the length of our name? Type in `len(304023)` and hit `enter`: - >>> len(304023) - Traceback (most recent call last): - File "", line 1, in - TypeError: object of type 'int' has no len() +{% filename %}command-line{% endfilename %} +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` We got our first error! It says that objects of type "int" (integers, whole numbers) have no length. So what can we do now? Maybe we can write our number as a string? Strings have a length, right? - >>> len(str(304023)) - 6 +{% filename %}command-line{% endfilename %} +```python +>>> len(str(304023)) +6 +``` It worked! We used the `str` function inside of the `len` function. `str()` converts everything to strings. - The `str` function converts things into __strings__ - The `int` function converts things into __integers__ -> Important: we can convert numbers into text, but we can't necessarily convert text into numbers - what would `int('hello')` be anyway? +> Important: we can convert numbers into text, but we can't necessarily convert text into numbers – what would `int('hello')` be anyway? ## Variables @@ -120,40 +162,58 @@ An important concept in programming is variables. A variable is nothing more tha Let's say we want to create a new variable called `name`: - >>> name = "Ola" +{% filename %}command-line{% endfilename %} +```python +>>> name = "Ola" +``` You see? It's easy! It's simply: name equals Ola. As you've noticed, your program didn't return anything like it did before. So how do we know that the variable actually exists? Simply enter `name` and hit `enter`: - >>> name - 'Ola' +{% filename %}command-line{% endfilename %} +```python +>>> name +'Ola' +``` -Yippee! Your first variable :)! You can always change what it refers to: +Yippee! Your first variable! :) You can always change what it refers to: - >>> name = "Sonja" - >>> name - 'Sonja' +{% filename %}command-line{% endfilename %} +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` You can use it in functions too: - >>> len(name) - 5 +{% filename %}command-line{% endfilename %} +```python +>>> len(name) +5 +``` -Awesome, right? Of course, variables can be anything, so numbers too! Try this: +Awesome, right? Of course, variables can be anything – numbers too! Try this: - >>> a = 4 - >>> b = 6 - >>> a * b - 24 +{% filename %}command-line{% endfilename %} +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` But what if we used the wrong name? Can you guess what would happen? Let's try! - >>> city = "Tokyo" - >>> ctiy - Traceback (most recent call last): - File "", line 1, in - NameError: name 'ctiy' is not defined +{% filename %}command-line{% endfilename %} +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` An error! As you can see, Python has different types of errors and this one is called a **NameError**. Python will give you this error if you try to use a variable that hasn't been defined yet. If you encounter this error later, check your code to see if you've mistyped any names. @@ -164,11 +224,14 @@ Play with this for a while and see what you can do! Try this: - >>> name = 'Maria' - >>> name - 'Maria' - >>> print(name) - Maria +{% filename %}command-line{% endfilename %} +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` When you just type `name`, the Python interpreter responds with the string *representation* of the variable 'name', which is the letters M-a-r-i-a, surrounded by single quotes, ''. When you say `print(name)`, Python will "print" the contents of the variable to the screen, without the quotes, which is neater. @@ -177,63 +240,90 @@ As we'll see later, `print()` is also useful when we want to print things from i ## Lists -Beside strings and integers, Python has all sorts of different types of objects. Now we're going to introduce one called __list__. Lists are exactly what you think they are: objects which are lists of other objects :) +Beside strings and integers, Python has all sorts of different types of objects. Now we're going to introduce one called __list__. Lists are exactly what you think they are: objects which are lists of other objects. :) Go ahead and create a list: - >>> [] - [] +{% filename %}command-line{% endfilename %} +```python +>>> [] +[] +``` Yes, this list is empty. Not very useful, right? Let's create a list of lottery numbers. We don't want to repeat ourselves all the time, so we will put it in a variable, too: - >>> lottery = [3, 42, 12, 19, 30, 59] +{% filename %}command-line{% endfilename %} +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` All right, we have a list! What can we do with it? Let's see how many lottery numbers there are in a list. Do you have any idea which function you should use for that? You know this already! - >>> len(lottery) - 6 +{% filename %}command-line{% endfilename %} +```python +>>> len(lottery) +6 +``` Yes! `len()` can give you a number of objects in a list. Handy, right? Maybe we will sort it now: - >>> lottery.sort() +{% filename %}command-line{% endfilename %} +```python +>>> lottery.sort() +``` This doesn't return anything, it just changed the order in which the numbers appear in the list. Let's print it out again and see what happened: - >>> print(lottery) - [3, 12, 19, 30, 42, 59] +{% filename %}command-line{% endfilename %} +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` As you can see, the numbers in your list are now sorted from the lowest to highest value. Congrats! Maybe we want to reverse that order? Let's do that! - >>> lottery.reverse() - >>> print(lottery) - [59, 42, 30, 19, 12, 3] +{% filename %}command-line{% endfilename %} +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` Easy, right? If you want to add something to your list, you can do this by typing this command: - >>> lottery.append(199) - >>> print(lottery) - [59, 42, 30, 19, 12, 3, 199] +{% filename %}command-line{% endfilename %} +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` If you want to show only the first number, you can do this by using __indexes__. An index is the number that says where in a list an item occurs. Programmers prefer to start counting at 0, so the first object in your list is at index 0, the next one is at 1, and so on. Try this: - >>> print(lottery[0]) - 59 - >>> print(lottery[1]) - 42 +{% filename %}command-line{% endfilename %} +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` As you can see, you can access different objects in your list by using the list's name and the object's index inside of square brackets. -To delete something from your list you will need to use __indexes__ as we learnt above and the __del__ statement (del is an abbreviation for delete). Let's try an example and reinforce what we learnt previously; we will be deleting the first number of our list. +To delete something from your list you will need to use __indexes__ as we learned above and the `pop()` method. Let's try an example and reinforce what we learned previously; we will be deleting the first number of our list. - >>> print(lottery) - [59, 42, 30, 19, 12, 3, 199] - >>> print(lottery[0]) - 59 - >>> del lottery[0] - >>> print(lottery) - [42, 30, 19, 12, 3, 199] +{% filename %}command-line{% endfilename %} +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` That worked like a charm! @@ -243,18 +333,26 @@ You can find a list of all available list methods in this chapter of the Python ## Dictionaries -A dictionary is similar to a list, but you access values by looking up a key instead of an index. A key can be any string or number. The syntax to define an empty dictionary is: +> For readers at home: this part is covered in the [Python Basics: Dictionaries](https://www.youtube.com/watch?v=ZX1CVvZLE6c) video. + +A dictionary is similar to a list, but you access values by looking up a key instead of a numeric index. A key can be any string or number. The syntax to define an empty dictionary is: - >>> {} - {} +{% filename %}command-line{% endfilename %} +```python +>>> {} +{} +``` This shows that you just created an empty dictionary. Hurray! -Now, try writing the following command (try replacing your own information too): +Now, try writing the following command (try substituting your own information, too): - >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +{% filename %}command-line{% endfilename %} +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` -With this command, you just created a variable named `participant` with three key-value pairs: +With this command, you just created a variable named `participant` with three key–value pairs: - The key `name` points to the value `'Ola'` (a `string` object), - `country` points to `'Poland'` (another `string`), @@ -262,88 +360,114 @@ With this command, you just created a variable named `participant` with three ke You can check the content of individual keys with this syntax: - >>> print(participant['name']) - Ola +{% filename %}command-line{% endfilename %} +```python +>>> print(participant['name']) +Ola +``` -See, it's similar to a list. But you don't need to remember the index - just the name. +See, it's similar to a list. But you don't need to remember the index – just the name. What happens if we ask Python the value of a key that doesn't exist? Can you guess? Let's try it and see! - >>> participant['age'] - Traceback (most recent call last): - File "", line 1, in - KeyError: 'age' +{% filename %}command-line{% endfilename %} +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` Look, another error! This one is a **KeyError**. Python is helpful and tells you that the key `'age'` doesn't exist in this dictionary. -When to use a dictionary or a list? Well, that's a good point to ponder on. Just have a solution in mind before looking at the answer in the next line. +When should you use a dictionary or a list? Well, that's a good point to ponder. Just have a solution in mind before looking at the answer in the next line. - Do you just need an ordered sequence of items? Go for a list. - Do you need to associate values with keys, so you can look them up efficiently (by key) later on? Use a dictionary. -Dictionaries, like lists, are *mutable*, meaning that they can be changed after they are created. You can add new key/value pairs to the dictionary after it is created, like: +Dictionaries, like lists, are *mutable*, meaning that they can be changed after they are created. You can add new key–value pairs to a dictionary after it is created, like this: - >>> participant['favorite_language'] = 'Python' +{% filename %}command-line{% endfilename %} +```python +>>> participant['favorite_language'] = 'Python' +``` -Like lists, using `len()` method on the dictionaries, returns the number of key-value pairs in the dictionary. Go ahead and type in the command: +Like lists, using the `len()` method on the dictionaries returns the number of key–value pairs in the dictionary. Go ahead and type in this command: - >>> len(participant) - 4 +{% filename %}command-line{% endfilename %} +```python +>>> len(participant) +4 +``` -I hope it makes sense up to now. :) Ready for some more fun with dictionaries? Hop onto the next line for some amazing things. +I hope it makes sense up to now. :) Ready for some more fun with dictionaries? Read on for some amazing things. -You can use the `del` command to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, just type in the following command: +You can use the `pop()` method to delete an item in the dictionary. Say, if you want to delete the entry corresponding to the key `'favorite_numbers'`, just type in the following command: - >>> del participant['favorite_numbers'] - >>> participant - {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +{% filename %}command-line{% endfilename %} +```python +>>> participant.pop('favorite_numbers') +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` -As you can see from the output, the key-value pair corresponding to the 'favorite_numbers' key has been deleted. +As you can see from the output, the key–value pair corresponding to the 'favorite_numbers' key has been deleted. -As well as this, you can also change a value associated with an already created key in the dictionary. Type: +As well as this, you can also change a value associated with an already-created key in the dictionary. Type this: - >>> participant['country'] = 'Germany' - >>> participant - {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +{% filename %}command-line{% endfilename %} +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` -As you can see, the value of the key `'country'` has been altered from `'Poland'` to `'Germany'`. :) Exciting? Hurrah! You just learnt another amazing thing. +As you can see, the value of the key `'country'` has been altered from `'Poland'` to `'Germany'`. :) Exciting? Hurrah! You just learned another amazing thing. ### Summary Awesome! You know a lot about programming now. In this last part you learned about: -- __errors__ - you now know how to read and understand errors that show up if Python doesn't understand a command you've given it -- __variables__ - names for objects that allow you to code more easily and to make your code more readable -- __lists__ - lists of objects stored in a particular order -- __dictionaries__ - objects stored as key-value pairs +- __errors__ – you now know how to read and understand errors that show up if Python doesn't understand a command you've given it +- __variables__ – names for objects that allow you to code more easily and to make your code more readable +- __lists__ – lists of objects stored in a particular order +- __dictionaries__ – objects stored as key–value pairs Excited for the next part? :) ## Compare things -A big part of programming includes comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: +> For readers at home: this part is covered in the [Python Basics: Comparisons](https://www.youtube.com/watch?v=7bzxqIKYgf4) video. - >>> 5 > 2 - True - >>> 3 < 1 - False - >>> 5 > 2 * 2 - True - >>> 1 == 1 - True - >>> 5 != 2 - True +A big part of programming involves comparing things. What's the easiest thing to compare? Numbers, of course. Let's see how that works: -We gave Python some numbers to compare. As you can see, Python can compare not only numbers, but it can also compare method results. Nice, huh? +{% filename %}command-line{% endfilename %} +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` + +We gave Python some numbers to compare. As you can see, not only can Python compare numbers, but it can also compare method results. Nice, huh? -Do you wonder why we put two equal signs `==` next to each other to compare if numbers are equal? We use a single `=` for assigning values to variables. You always, __always__ need to put two `==` if you want to check if things are equal to each other. We can also state that things are unequal to each other. For that, we use the symbol `!=`, as shown in the example above. +Do you wonder why we put two equal signs `==` next to each other to compare if numbers are equal? We use a single `=` for assigning values to variables. You always, __always__ need to put two of them – `==` – if you want to check if things are equal to each other. We can also state that things are unequal to each other. For that, we use the symbol `!=`, as shown in the example above. Give Python two more tasks: - >>> 6 >= 12 / 2 - True - >>> 3 <= 2 - False +{% filename %}command-line{% endfilename %} +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` `>` and `<` are easy, but what do `>=` and `<=` mean? Read them like this: @@ -354,49 +478,61 @@ Give Python two more tasks: Awesome! Wanna do one more? Try this: - >>> 6 > 2 and 2 < 3 - True - >>> 3 > 2 and 2 < 1 - False - >>> 3 > 2 or 2 < 1 - True +{% filename %}command-line{% endfilename %} +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` You can give Python as many numbers to compare as you want, and it will give you an answer! Pretty smart, right? -- __and__ - if you use the `and` operator, both comparisons have to be True in order for the whole command to be True -- __or__ - if you use the `or` operator, only one of the comparisons has to be True in order for the whole command to be True +- __and__ – if you use the `and` operator, both comparisons have to be True in order for the whole command to be True +- __or__ – if you use the `or` operator, only one of the comparisons has to be True in order for the whole command to be True Have you heard of the expression "comparing apples to oranges"? Let's try the Python equivalent: - >>> 1 > 'django' - Traceback (most recent call last): - File "", line 1, in - TypeError: unorderable types: int() > str() +{% filename %}command-line{% endfilename %} +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: unorderable types: int() > str() +``` Here you see that just like in the expression, Python is not able to compare a number (`int`) and a string (`str`). Instead, it shows a **TypeError** and tells us the two types can't be compared together. ## Boolean -Incidentally, you just learned about a new type of object in Python. It's called a __Boolean__ -- and it probably is the easiest type there is. +Incidentally, you just learned about a new type of object in Python. It's called __Boolean__, and it is probably the easiest type there is. There are only two Boolean objects: - True - False -But for Python to understand this, you need to always write it as 'True' (first letter uppercased, with the rest of the letter lowercased). __true, TRUE, tRUE won't work -- only True is correct.__ (The same applies to 'False' as well, of course.) +But for Python to understand this, you need to always write it as 'True' (first letter uppercased, with the rest of the letter lowercased). __true, TRUE, and tRUE won't work – only True is correct.__ (The same applies to 'False' as well, of course.) Booleans can be variables, too! See here: - >>> a = True - >>> a - True +{% filename %}command-line{% endfilename %} +```python +>>> a = True +>>> a +True +``` You can also do it this way: - >>> a = 2 > 5 - >>> a - False +{% filename %}command-line{% endfilename %} +```python +>>> a = 2 > 5 +>>> a +False +``` Practice and have fun with Booleans by trying to run the following commands: @@ -409,77 +545,108 @@ Congrats! Booleans are one of the coolest features in programming, and you just # Save it! -So far we've been writing all our python code in the interpreter, which limits us to one line of code at a time. Normal programs are saved in files and executed by our programming language __interpreter__ or __compiler__. So far we've been running our programs one line at a time in the Python __interpreter__. We're going to need more than one line of code for the next few tasks, so we'll quickly need to: +> For readers at home: this part is covered in the [Python Basics: Saving files and "If" statement](https://www.youtube.com/watch?v=dOAg6QVAxyk) video. + + +So far we've been writing all our python code in the interpreter, which limits us to entering one line of code at a time. Normal programs are saved in files and executed by our programming language __interpreter__ or __compiler__. So far we've been running our programs one line at a time in the Python __interpreter__. We're going to need more than one line of code for the next few tasks, so we'll quickly need to: - Exit the Python interpreter - Open up our code editor of choice - Save some code into a new python file - Run it! -To exit from the Python interpreter that we've been using, simply type the ```exit()``` function: +To exit from the Python interpreter that we've been using, simply type the `exit()` function - >>> exit() - $ +{% filename %}command-line{% endfilename %} +```python +>>> exit() +$ +``` This will put you back into the command prompt. Earlier, we picked out a code editor from the [code editor](../code_editor/README.md) section. We'll need to open the editor now and write some code into a new file: +{% filename %}editor{% endfilename %} ```python print('Hello, Django girls!') ``` -> **Note** You should notice one of the coolest thing about code editors: colours! In the Python console, everything was the same colour, now you should see that the `print` function is a different colour from the string. This is called "syntax highlighting", and it's a really useful feature when coding. The colour of things will give you hints, such as unclosed strings, or a typo in a keyword name (like the `def` in a function, which we'll see below). This is one of the reasons we use a code editor :) +Obviously, you're a pretty seasoned Python developer now, so feel free to write some code that you've learned today. +Now we need to save the file and give it a descriptive name. Let's call the file **python_intro.py** and save it to your desktop. We can name the file anything we want, but the important part here is to make sure the file ends in __.py__. The __.py__ extension tells our operating system that this is a **Python executable file** and Python can run it. -Obviously, you're a pretty seasoned python developer now, so feel free to write some code that you've learned today. +> **Note** You should notice one of the coolest thing about code editors: colors! In the Python console, everything was the same color; now you should see that the `print` function is a different color from the string. This is called "syntax highlighting", and it's a really useful feature when coding. The color of things will give you hints, such as unclosed strings or a typo in a keyword name (like the `def` in a function, which we'll see below). This is one of the reasons we use a code editor. :) -Now we need to save the file and give it a descriptive name. Let's call the file **python_intro.py** and save it to your desktop. We can name the file anything we want, the important part here is to make sure the file ends in __.py__, this tells our computer that this is a **python executable file** and Python can run it. -With the file saved, it's time to run it! Using the skills you've learned in the command line section, use the terminal to **change directories** to the desktop. +With the file saved, it's time to run it! Using the skills you've learned in the command line section, use the terminal to **change directories** to the desktop. (**Note**: Replace `` including the `<` and `>` with your user name.) On a Mac, the command will look something like this: - cd /Users//Desktop +{% filename %}command-line{% endfilename %} +``` +$ cd /Users//Desktop +``` -On Linux, it will be like this (the word "Desktop" might be translated to your language): +On Linux, it will be like this (the word "Desktop" might be translated to your local language): - cd /home//Desktop +{% filename %}command-line{% endfilename %} +``` +$ cd /home//Desktop +``` -And on windows, it will be like this: +And on Windows, it will be like this: - cd C:\Users\\Desktop +{% filename %}command-line{% endfilename %} +``` +> cd C:\Users\\Desktop +``` If you get stuck, just ask for help. -and then use Python to execute the code in the file like this: +Now use Python to execute the code in the file like this: + +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hello, Django girls! +``` + +Note: on Windows 'python3' is not recognized as a command. Instead, use 'python' to execute the file: - $ python3 python_intro.py - Hello, Django girls! +{% filename %}command-line{% endfilename %} +```python +> python python_intro.py +``` -Alright! You just ran your first python program that was saved to a file. Feel awesome? +Alright! You just ran your first Python program that was saved to a file. Feel awesome? You can now move on to an essential tool in programming: -## If...elif...else +## If … elif … else -Lots of things in code should only be executed when given conditions are met. That's why Python has something called __if statements__. +Lots of things in code should be executed only when given conditions are met. That's why Python has something called __if statements__. Replace the code in your **python_intro.py** file with this: +{% filename %}python_intro.py{% endfilename %} ```python if 3 > 2: ``` -If we saved this and ran it, we'd see an error like this: +If we were to save and run this, we'd see an error like this: - $ python3 python_intro.py - File "python_intro.py", line 2 - ^ - SyntaxError: unexpected EOF while parsing +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +File "python_intro.py", line 2 + ^ +SyntaxError: unexpected EOF while parsing +``` Python expects us to give further instructions to it which are executed if the condition `3 > 2` turns out to be true (or `True` for that matter). Let’s try to make Python print “It works!”. Change your code in your **python_intro.py** file to this: +{% filename %}python_intro.py{% endfilename %} ```python if 3 > 2: print('It works!') @@ -489,13 +656,19 @@ Notice how we've indented the next line of code by 4 spaces? We need to do this Save it and give it another run: - $ python3 python_intro.py - It works! +{% filename %}command-line{% endfilename %} +```python +$ python3 python_intro.py +It works! +``` + +Note: Remember that on Windows, 'python3' is not recognized as a command. From now on, replace 'python3' with 'python' to execute the file. -### What if not? +### What if a condition isn't True? In previous examples, code was executed only when the conditions were True. But Python also has `elif` and `else` statements: +{% filename %}python_intro.py{% endfilename %} ```python if 5 > 2: print('5 is indeed greater than 2') @@ -503,13 +676,17 @@ else: print('5 is not greater than 2') ``` -When this is ran it will print out: +When this is run it will print out: - $ python3 python_intro.py - 5 is indeed greater than 2 +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +5 is indeed greater than 2 +``` If 2 were a greater number than 5, then the second command would be executed. Easy, right? Let's see how `elif` works: +{% filename %}python_intro.py{% endfilename %} ```python name = 'Sonja' if name == 'Ola': @@ -522,28 +699,79 @@ else: and executed: - $ python3 python_intro.py - Hey Sonja! +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hey Sonja! +``` + +See what happened there? `elif` lets you add extra conditions that run if the previous conditions fail. + +You can add as many `elif` statements as you like after your initial `if` statement. For example: + +{% filename %}python_intro.py{% endfilename %} +```python +volume = 57 +if volume < 20: + print("It's kinda quiet.") +elif 20 <= volume < 40: + print("It's nice for background music") +elif 40 <= volume < 60: + print("Perfect, I can hear all the details") +elif 60 <= volume < 80: + print("Nice for parties") +elif 80 <= volume < 100: + print("A bit loud!") +else: + print("My ears are hurting! :(") +``` + +Python runs through each test in sequence and prints: + +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Perfect, I can hear all the details +``` + +## Comments + +Comments are lines beginning with `#`. You can write whatever you want after the `#` and Python will ignore it. Comments can make your code easier for other people to understand. + +Let's see how that looks: + +{% filename %}python_intro.py{% endfilename %} +```python +# Change the volume if it's too loud or too quiet +if volume < 20 or volume > 80: + volume = 50 + print("That's better!") +``` + +You don't need to write a comment for every line of code, but they are useful for explaining why your code is doing something, or providing a summary when it's doing something complex. -See what happened there? ### Summary -In the last three exercises you learned about: +In the last few exercises you learned about: -- __comparing things__ - in Python you can compare things by using `>`, `>=`, `==`, `<=`, `<` and the `and`, `or` operators -- __Boolean__ - a type of object that can only have one of two values: `True` or `False` -- __Saving files__ - storing code in files so you can execute larger programs. -- __if...elif...else__ - statements that allow you to execute code only when certain conditions are met. +- __comparing things__ – in Python you can compare things by using `>`, `>=`, `==`, `<=`, `<` and the `and`, `or` operators +- __Boolean__ – a type of object that can only have one of two values: `True` or `False` +- __Saving files__ – storing code in files so you can execute larger programs. +- __if … elif … else__ – statements that allow you to execute code only when certain conditions are met. +- __comments__ - lines that Python won't run which let you document your code Time for the last part of this chapter! ## Your own functions! -Remember functions like `len()` that you can execute in Python? Well, good news, you will learn how to write your own functions now! +> For readers at home: this part is covered in the [Python Basics: Functions](https://www.youtube.com/watch?v=5owr-6suOl0) video. -A function is a sequence of instructions that Python should execute. Each function in Python starts with the keyword `def`, is given a name, and it can have some parameters. Let's start with an easy one. Replace the code in **python_intro.py** with the following: +Remember functions like `len()` that you can execute in Python? Well, good news – you will learn how to write your own functions now! +A function is a sequence of instructions that Python should execute. Each function in Python starts with the keyword `def`, is given a name, and can have some parameters. Let's start with an easy one. Replace the code in **python_intro.py** with the following: + +{% filename %}python_intro.py{% endfilename %} ```python def hi(): print('Hi there!') @@ -558,18 +786,23 @@ You may wonder why we've written the name of the function at the bottom of the f Let's run this now and see what happens: - $ python3 python_intro.py - Hi there! - How are you? +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hi there! +How are you? +``` -That was easy! Let's build our first function with parameters. We will use the previous example - a function that says 'hi' to the person running it - with a name: +That was easy! Let's build our first function with parameters. We will use the previous example – a function that says 'hi' to the person running it – with a name: +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): ``` As you can see, we now gave our function a parameter that we called `name`: +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): if name == 'Ola': @@ -584,44 +817,59 @@ hi() Remember: The `print` function is indented four spaces within the `if` statement. This is because the function runs when the condition is met. Let's see how it works now: - $ python3 python_intro.py - Traceback (most recent call last): - File "python_intro.py", line 10, in - hi() - TypeError: hi() missing 1 required positional argument: 'name' +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Traceback (most recent call last): +File "python_intro.py", line 10, in + hi() +TypeError: hi() missing 1 required positional argument: 'name' +``` Oops, an error. Luckily, Python gives us a pretty useful error message. It tells us that the function `hi()` (the one we defined) has one required argument (called `name`) and that we forgot to pass it when calling the function. Let's fix it at the bottom of the file: +{% filename %}python_intro.py{% endfilename %} ```python hi("Ola") ``` And run it again: - $ python3 python_intro.py - Hi Ola! +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hi Ola! +``` And if we change the name? +{% filename %}python_intro.py{% endfilename %} ```python hi("Sonja") ``` And run it: - $ python3 python_intro.py - Hi Sonja! +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hi Sonja! +``` -Now, what do you think will happen if you write another name in there? (Not Ola or Sonja) Give it a try and see if you're right. It should print out this: +Now, what do you think will happen if you write another name in there? (Not Ola or Sonja.) Give it a try and see if you're right. It should print out this: - Hi anonymous! +{% filename %}command-line{% endfilename %} +``` +Hi anonymous! +``` -This is awesome, right? This way you don't have to repeat yourself every time you want to change the name of the person the function is supposed to greet. And that's exactly why we need functions - you never want to repeat your code! +This is awesome, right? This way you don't have to repeat yourself every time you want to change the name of the person the function is supposed to greet. And that's exactly why we need functions – you never want to repeat your code! -Let's do something smarter -- there are more names than two, and writing a condition for each would be hard, right? +Let's do something smarter – there are more names than two, and writing a condition for each would be hard, right? +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): print('Hi ' + name + '!') @@ -631,25 +879,32 @@ hi("Rachel") Let's call the code now: - $ python3 python_intro.py - Hi Rachel! +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hi Rachel! +``` Congratulations! You just learned how to write functions! :) ## Loops +> For readers at home: this part is covered in the [Python Basics: For Loop](https://www.youtube.com/watch?v=aEA6Rc86HF0) video. + This is the last part already. That was quick, right? :) Programmers don't like to repeat themselves. Programming is all about automating things, so we don't want to greet every person by their name manually, right? That's where loops come in handy. Still remember lists? Let's do a list of girls: +{% filename %}python_intro.py{% endfilename %} ```python girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] ``` We want to greet all of them by their name. We have the `hi` function to do that, so let's use it in a loop: +{% filename %}python_intro.py{% endfilename %} ```python for name in girls: ``` @@ -658,6 +913,7 @@ The ```for``` statement behaves similarly to the ```if``` statement; code below Here is the full code that will be in the file: +{% filename %}python_intro.py{% endfilename %} ```python def hi(name): print('Hi ' + name + '!') @@ -670,41 +926,50 @@ for name in girls: And when we run it: - $ python3 python_intro.py - Hi Rachel! - Next girl - Hi Monica! - Next girl - Hi Phoebe! - Next girl - Hi Ola! - Next girl - Hi You! - Next girl +{% filename %}command-line{% endfilename %} +``` +$ python3 python_intro.py +Hi Rachel! +Next girl +Hi Monica! +Next girl +Hi Phoebe! +Next girl +Hi Ola! +Next girl +Hi You! +Next girl +``` As you can see, everything you put inside a `for` statement with an indent will be repeated for every element of the list `girls`. You can also use `for` on numbers using the `range` function: - for i in range(1, 6): - print(i) +{% filename %}python_intro.py{% endfilename %} +```python +for i in range(1, 6): + print(i) +``` Which would print: - 1 - 2 - 3 - 4 - 5 +{% filename %}command-line{% endfilename %} +``` +1 +2 +3 +4 +5 +``` `range` is a function that creates a list of numbers following one after the other (these numbers are provided by you as parameters). -Note that the second of these two numbers is not included in the list that is output by Python (meaning `range(1, 6)` counts from 1 to 5, but does not include the number 6). That is because "range" is half-open, and with that we mean it includes the first value, but not the last. +Note that the second of these two numbers is not included in the list that is output by Python (meaning `range(1, 6)` counts from 1 to 5, but does not include the number 6). That is because "range" is half-open, and by that we mean it includes the first value, but not the last. ## Summary That's it. __You totally rock!__ This was a tricky chapter, so you should feel proud of yourself. We're definitely proud of you for making it this far! -You might want to briefly do something else - stretch, walk around for a bit, rest your eyes - before going on to the next chapter. :) +You might want to briefly do something else – stretch, walk around for a bit, rest your eyes – before going on to the next chapter. :) ![Cupcake](images/cupcake.png) diff --git a/en/template_extending/README.md b/en/template_extending/README.md index 3f8d6ae5830..17a13a46ce6 100644 --- a/en/template_extending/README.md +++ b/en/template_extending/README.md @@ -2,22 +2,25 @@ Another nice thing Django has for you is __template extending__. What does this mean? It means that you can use the same parts of your HTML for different pages of your website. -This way you don't have to repeat yourself in every file, when you want to use the same information/layout. And if you want to change something, you don't have to do it in every template, just once! +Templates help when you want to use the same information or layout in more than one place. You don't have to repeat yourself in every file. And if you want to change something, you don't have to do it in every template, just one! -## Create base template +## Create a base template A base template is the most basic template that you extend on every page of your website. Let's create a `base.html` file in `blog/templates/blog/`: - blog - └───templates - └───blog - base.html - post_list.html +``` +blog +└───templates + └───blog + base.html + post_list.html +``` Then open it up and copy everything from `post_list.html` to `base.html` file, like this: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% load staticfiles %} @@ -42,7 +45,7 @@ Then open it up and copy everything from `post_list.html` to `base.html` file, l {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -54,6 +57,7 @@ Then open it up and copy everything from `post_list.html` to `base.html` file, l Then in `base.html`, replace your whole `` (everything between `` and ``) with this: +{% filename %}blog/templates/blog/base.html{% endfilename %} ```html {% endfor %} ``` -And now add this line to the beginning of the file: +We want to use this as part of our template for all the content blocks. +Time to add block tags to this file! - {% extends 'blog/base.html' %} +{% raw %}You want your block tag to match the tag in your `base.html` file. You also want it to include all the code that belongs in your content blocks. To do that, put everything between `{% block content %}` and `{% endblock content %}`. Like this:{% endraw %} -{% raw %}It means that we're now extending the `base.html` template in `post_list.html`. Only one thing left: put everything (except the line we just added) between `{% block content %}` and `{% endblock content %}`. Like this:{% endraw %} +{% filename %}blog/templates/blog/post_list.html{% endfilename %} +```html +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` +Only one thing left. We need to connect these two templates together. This is what extending templates is all about! We'll do this by adding an extends tag to the beginning of the file. Like this: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} ```html {% extends 'blog/base.html' %} @@ -109,12 +132,12 @@ And now add this line to the beginning of the file: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} -{% endblock content %} +{% endblock %} ``` -That's it! Check if your website is still working properly :) +That's it! Check if your website is still working properly. :) -> If you have an error `TemplateDoesNotExists` that says that there is no `blog/base.html` file and you have `runserver` running in the console, try to stop it (by pressing Ctrl+C - Control and C buttons together) and restart it by running a `python manage.py runserver` command. +> If you get the error `TemplateDoesNotExist`, that means that there is no `blog/base.html` file and you have `runserver` running in the console. Try to stop it (by pressing Ctrl+C – the Control and C keys together) and restart it by running a `python manage.py runserver` command. diff --git a/en/whats_next/README.md b/en/whats_next/README.md index 7e64be31c91..2b826bbc31e 100644 --- a/en/whats_next/README.md +++ b/en/whats_next/README.md @@ -6,20 +6,19 @@ Congratulate yourself! __You're totally awesome__. We're proud! <3 Take a break and relax. You have just done something really huge. -After that make sure to: - -- Follow Django Girls on [Facebook](http://facebook.com/djangogirls) or [Twitter](http://twitter.com/djangogirls) to stay up to date +After that, make sure to follow Django Girls on [Facebook](http://facebook.com/djangogirls) or [Twitter](https://twitter.com/djangogirls) to stay up to date. ### Can you recommend any further resources? -Yes! First, go ahead and try our other book, called [Django Girls Tutorial: Extensions](http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/). +Yes! First, go ahead and try our other book, called [Django Girls Tutorial: Extensions](https://djangogirls.gitbooks.io/django-girls-tutorial-extensions/content/). -Later on, you can try recources listed below. They're all very recommended! -- [Django's official tutorial](https://docs.djangoproject.com/en/1.8/intro/tutorial01/) +Later on, you can try the resources listed below. They're all very recommended! +- [Django's official tutorial](https://docs.djangoproject.com/en/1.9/intro/tutorial01/) - [New Coder tutorials](http://newcoder.io/tutorials/) -- [Code Academy Python course](http://www.codecademy.com/en/tracks/python) -- [Code Academy HTML & CSS course](http://www.codecademy.com/tracks/web) -- [Django Carrots tutorial](http://django.carrots.pl/en/) +- [Code Academy Python course](https://www.codecademy.com/en/tracks/python) +- [Code Academy HTML & CSS course](https://www.codecademy.com/tracks/web) +- [Django Carrots tutorial](https://github.com/ggcarrots/django-carrots) - [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) - [Getting Started With Django video lessons](http://gettingstartedwithdjango.com/) -- [Two Scoops of Django: Best Practices for Django](http://twoscoopspress.org/products/two-scoops-of-django-1-6) book +- [Two Scoops of Django: Best Practices for Django 1.8 book](https://twoscoopspress.com/products/two-scoops-of-django-1-8) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) diff --git a/es/CONTRIBUTING.md b/es/CONTRIBUTING.md deleted file mode 100755 index 2bb0b745e82..00000000000 --- a/es/CONTRIBUTING.md +++ /dev/null @@ -1,109 +0,0 @@ -# ¿Cómo contribuir? - -The Django Girls Tutorial está licenciado bajo la licencia internacional*Creative Commons Attribution-ShareAlike 4.0*. Cualquiera puede añadir, editar y corregir el tutorial. - -# Editar lo basico - -El código fuente del tutorial se encuentra [en Github](http://github.com/DjangoGirls/tutorial). Para aceptar y revisar cambios se usa el la guía [Fork & Pull workflow](https://help.github.com/articles/using-pull-requests) de Github. - -El tutorial utiliza el servicio de [GitBook](https://www.gitbook.io/) para la publicación de su documentación. Visita el siguiente enlace para [ver más información acerca de cómo funciona Gitbook](http://help.gitbook.io/). - -El tutorial esta escrito en [el lenguaje de marcado Markdown](https://help.github.com/articles/markdown-basics). - -Puedes encontrar todas las discusiones sobre el contenido del tutorial en el [issue tracker](https://github.com/DjangoGirls/tutorial/issues) de Github. - -# Primeros pasos y requisitos previos - -Para contribuir en el tutorial es necesario que cuente con lo siguiente: - - * Una [cuenta de Github](https://github.com) - * En el caso de hacer una edición compleja, estar familiarizado con [los conceptos básicos de línea de comandos de Git](https://help.github.com/articles/set-up-git) o familiarizado con una aplicación ([Windows](https://windows.github.com/), [Mac](https://mac.github.com/)) que te permita enviar los cambios realizados en tu computadora a Github. - -## Hazle Fork al repositorio - -Primero hazle Fork al repositorio de [DjangoGirls/tutorial](https://github.com/DjangoGirls/tutorial) hacia tu cuenta personal de Github: - -![Fork button](contributing/images/fork.png) - -# Editando el contenido de un capitulo - -## Pequeños cambios - -Para pequeños cambios como correcciones puedes usar el editor online de Github: - - * Abre el fork que hiciste a tu cuenta de Github - * ve al archivo *README.md* en cualquiera de los capitulos, - * Presiona el icono de *editar* (lápiz) - -así puede editar el capitulo directamente desde github.com. - -![Edit button](contributing/images/edit.png) - -La sintaxis de Markdown es usada para editar las paginas individuales del tutorial. - -![Github editor](contributing/images/github_editor.png) - -Guarda tus cambios y crea una pull request como se explicara más adelante. - -## Contenidos nuevos y cambios complejos - -Para añadir nuevos capitulos, escribir pequeños fragmentos de texto o añadir imagenes, necesitaras hacer una copia del tutorial en tu computadora local. - -O bien utilizar la aplicación Github para su sistema operativo (antes mencionado) o la linea de comando de `git` para obtener el repositorio de manera local. Obtendrá la dirección del repositorio de la pagina principal de su propio Fork del repositorio en Github: - - git clone git@github.com:tu_usuario_de_github/tutorial.git - - -descarga la aplicación del [editor de Gitbook](http://help.gitbook.io/editor/README.html) para tu computadora. - -A continuación, puedes abrir el tutorial en el Editor de Gitbook (*File* > *Open book*). - -![Gitbook](contributing/images/gitbook.png) - -Haz todos los cambios que quieras en el tutorial usando el editor y luego guardalos(*Book*>*Save All*). - -Luego haz un commit para los cambios usando `git` y envía los cambios hacia tu repositorio remoto de Github. - -Ejemplo: - - $ git status - On branch contributing - Untracked files: - (use "git add ..." to include in what will be committed) - - contributing_and_editing_this_book/images/gitbook.png - - $ git add contributing_and_editing_this_book/images/gitbook.png - - $ git commit -m "Added gitbook editor screenshot" - [contributing fe36152] Added gitbook screenshot - 1 file changed, 0 insertions(+), 0 deletions(-) - create mode 100644 contributing_and_editing_this_book/images/gitbook.png - - $ git push - Counting objects: 11, done. - Delta compression using up to 8 threads. - Compressing objects: 100% (5/5), done. - Writing objects: 100% (5/5), 266.37 KiB | 0 bytes/s, done. - Total 5 (delta 1), reused 0 (delta 0) - To git@github.com:miohtama/tutorial.git - b37ca59..fe36152 contributing -> contributing - - -# Hacer un pull request - -Después de finalizar los cambios necesitaras crear [una pull request](https://help.github.com/articles/using-pull-requests) en Github. DjangoGirls será informado acerca de la pull request, revisara tus cambios, sugerirá cualquier corrección sí la necesita y luego hara un *pull* a tus cambios hacia la versión original. - -En tu propio repositorio de Github presiona el botón *Compare & pull request* - -![Gitbook](contributing/images/pull_request.png) - -Rellena la información de *por que* fueron hechos estos cambios. el inspector analizará los detalles de los cambios actuales, de esta forma no necesitas repetir el contenido de los cambios. - -Luego presiona *Create pull request*. - -Github le notificara a través de e-mails el seguimiento del proceso. - -# Más información y ayuda - -Para cualquier duda póngase en [contacto con DjangoGirls](http://djangogirls.org/). \ No newline at end of file diff --git a/es/README.md b/es/README.md index 6d2d47792e0..0e0b494c221 100755 --- a/es/README.md +++ b/es/README.md @@ -2,52 +2,50 @@ [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -> Este trabajo esta licenciado bajo la licencia internacional Creative Commons Attribution-ShareAlike 4.0. Para ver una copia de esta licencia, visita el siguiente enlace http://creativecommons.org/licenses/by-sa/4.0/ +> Este trabajo está bajo la licencia internacional Creative Commons Attribution-ShareAlike 4.0. Para ver una copia de esta licencia, visita el siguiente enlace https://creativecommons.org/licenses/by-sa/4.0/ ## Translation - -This tutorial has been translated from English to Spanish by a group of awesome volunteers. Special thanks for help go to Joshua Aranda, Kevin Morales, Silvia Frias, Andrea Gonzales, Adrian Manjarres, Rodrigo Caicedo, Maria Chavez, Marcelo Manso, Rosa Durante, Moisés, Israel Martinez Vargas, Juan Carlos, N0890Dy, Khaterine Castellano, ZeroSoul13 and Erik Aguayo. <3 <3 +This tutorial has been translated from English into Spanish by a wonderful group of volunteers. Special thanks goes to Victoria Martinez de la Cruz, Kevin Morales, Joshua Aranda, Silvia Frias, Leticia, Andrea Gonzalez, Adrian Manjarres, Rodrigo Caicedo, Maria Chavez, Marcelo Nicolas Manso, Rosa Durante, Moises, Israel Martinez Vargas, JuanCarlos_, N0890Dy, Ivan Yivoff, Khaterine Castellano, Erick Navarro, cyncyncyn, ZeroSoul13, Erick Aguayo, Ernesto Rico-Schmidt, Miguel Lozano, osueboy, dynarro and Geraldina Garcia Alvarez. ## Introducción -¿Te has sentido que el mundo está cada vez más cercano a la tecnología y de cierto modo te has quedado atrás? ¿Te has preguntado cómo crear un sitio web pero nunca has tenido la suficiente motivación para empezar? ¿Has pensado que el mundo del software is demasiado complicado para intentar hacer algo por tu cuenta? +¿Alguna vez has sentido que el mundo está cada vez más cercano a la tecnología y de cierto modo te has quedado atrás? ¿Alguna vez te has preguntado cómo crear un sitio web pero nunca has tenido la suficiente motivación para empezar? ¿Has pensado alguna vez que el mundo del software es demasiado complicado para ti como para intentar hacer algo por tu cuenta? -Bueno, Tenemos buenas noticias para ti! programar no es tan difícil como aparenta y queremos mostrarte cuán divertido que puede llegar a ser. +Bueno, ¡tenemos buenas noticias para ti! Programar no es tan difícil como aparenta y queremos mostrarte cuán divertido puede llegar a ser. -Este tutorial no convertirá mágicamente en un programador. Sí quieres ser buena en eso, necesitaras meses o inclusos años de aprendizaje y práctica. sin embargo queremos mostrarte que programar o crear sitios web no es tan complicado como parece. Intentaremos explicarte en pequeñas partes tan bien como podamos, para que no te sientas intimidada por la tecnología. +Este tutorial no te convertirá en programador mágicamente. Si quieres ser buena en esto, necesitarás meses o inclusos años de aprendizaje y práctica. Pero queremos mostrarte que programar o crear sitios web no es tan complicado como parece. Intentaremos explicar pequeñas partes lo mejor que podamos, de forma que no te sientas intimidada por la tecnología. ¡Esperamos poder hacerte amar la tecnología tanto como nosotras lo hacemos! ## ¿Qué aprenderás con este tutorial? -Una vez terminado el tutorial, tendrás una simple y funcional aplicación web: tu propio blog. Te mostraremos como ponerla online, así otros podrán ver tu trabajo! +Cuando termines el tutorial, tendrás una aplicación web simple y funcional: tu propio blog. Te mostraremos como publicarla online, ¡así otros podrán ver tu trabajo! -se verá (más o menos) como ésta: +Tendrá (más o menos) ésta apariencia: ![Figura 0.1][2] [2]: images/application.png -> Sí estás siguiendo este tutorial por tu cuenta y no tienes nadie que te ayude a resolver algún problema, tenemos un chat para ti: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -. ¡Hemos pedido a nuestros coaches y asistentes anteriores estar ahi de vez en cuando para ayudar a otros con el tutorial! ¡No dudes dejar tus preguntas allí! +> Si estás siguiendo este tutorial por tu cuenta y no tienes a nadie que te ayude en caso de surgir algún problema, tenemos un chat para ti: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). ¡Hemos pedido a nuestros tutores y participantes anteriores que estén ahí de vez en cuando para ayudar a otros con el tutorial! ¡No temas dejar tus preguntas allí! -Esta bien, [empecemos desde el inicio...][3] +Bien, [empecemos por el principio...][3] [3]: ./how_the_internet_works/README.md ## Sobre nosotros y cómo contribuir -Este turorial es mantenido por [DjangoGirls][4]. Sí encuentras algún error o quieres actualizar el tutorial por favor [sigue la guía de cómo contribuir][5]. +Este tutorial lo mantiene [DjangoGirls][4]. Si encuentras algún error o quieres actualizar el tutorial, por favor [sigue la guía de cómo contribuir][5]. - [4]: http://djangogirls.org/ + [4]: https://djangogirls.org/ [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md -## ¿Te gustaría ayudarnos a traducir el tutorial hacia otros idiomas? +## ¿Te gustaría ayudarnos a traducir el tutorial a otros idiomas? -Actualmente, las traducciones son llevadas a cabo en la formaleta crowdin.com, en el siguiente enlace: +Actualmente, las traducciones se llevan a cabo sobre la plataforma crowdin.com en: https://crowdin.com/project/django-girls-tutorial -Sí tu idioma no aparece en la lista de crowdin, por favor [abre una nueva issue][6] informando el idioma así nosotros podemos añadirlo +Si tu idioma no esta listado en crowdin, por favor [abre un nuevo problema][6] informando el idioma así podemos agregarlo. [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/es/SUMMARY.md b/es/SUMMARY.md index 65a1fe883c9..fa7f9e5f3a0 100755 --- a/es/SUMMARY.md +++ b/es/SUMMARY.md @@ -1,26 +1,26 @@ # Índice -* [Introducción](README.md) -* [Cómo funciona el internet](how_the_internet_works/README.md) -* [Introducción a la línea de comandos](intro_to_command_line/README.md) -* [Instalación de Python](python_installation/README.md) -* [Editor de código](code_editor/README.md) -* [Introducción a Python](python_introduction/README.md) -* [¿Qué es Django?](django/README.md) -* [Instalación de Django](django_installation/README.md) -* [Comenzando un proyecto en Django](django_start_project/README.md) -* [Modelos en Django](django_models/README.md) -* [ORM de Django (Querysets)](django_orm/README.md) -* [Administrador de Django](django_admin/README.md) -* [Deploy!](deploy/README.md) -* [Django urls](django_urls/README.md) -* [Vistas de Django - es hora de crear!](django_views/README.md) -* [Introducción a HTML](html/README.md) -* [Datos dinámicos en plantillas](dynamic_data_in_templates/README.md) -* [Plantillas de Django](django_templates/README.md) -* [CSS - Hazlo bonito](css/README.md) -* [Extendiendo plantillas](template_extending/README.md) -* [Extiende tu aplicación](extend_your_application/README.md) -* [Formularios en Django](django_forms/README.md) -* [Dominio](domain/README.md) -* [¿Qué sigue?](whats_next/README.md) +* [Introducción](README.md) +* [¿Cómo funciona Internet?](how_the_internet_works/README.md) +* [Introducción a la línea de comandos](intro_to_command_line/README.md) +* [Instalación de Python](python_installation/README.md) +* [Editor de código](code_editor/README.md) +* [Introducción a Python](python_introduction/README.md) +* [¿Qué es Django?](django/README.md) +* [Instalación de Django](django_installation/README.md) +* [Comenzar un proyecto en Django](django_start_project/README.md) +* [Modelos en Django](django_models/README.md) +* [Administrador de Django](django_admin/README.md) +* [¡Desplegar!](deploy/README.md) +* [Django urls](django_urls/README.md) +* [Vistas de Django - ¡Es hora de crear!](django_views/README.md) +* [Introducción a HTML](html/README.md) +* [ORM de Django (Querysets)](django_orm/README.md) +* [Datos dinámicos en plantillas](dynamic_data_in_templates/README.md) +* [Plantillas de Django](django_templates/README.md) +* [CSS - Hazlo bonito](css/README.md) +* [Extender plantillas](template_extending/README.md) +* [Amplía tu aplicación](extend_your_application/README.md) +* [Formularios en Django](django_forms/README.md) +* [Dominio](domain/README.md) +* [¿Qué sigue?](whats_next/README.md) diff --git a/es/code_editor/README.md b/es/code_editor/README.md index 72bcb5d920a..3f6c86b1f73 100755 --- a/es/code_editor/README.md +++ b/es/code_editor/README.md @@ -1,10 +1,10 @@ # Editor de código -Estás a punto de escribir tu primera línea de código, así que es hora de descargar un editor de código! +Estás a punto de escribir tu primera línea de código, así que ¡es hora de descargar un editor de código! -Hay muchos editores diferentes, cual usar depende mucho de la preferencia personal. La mayoría de programadores de python usan entornos de desarrollo integrado (IDEs) complejos, pero muy poderosos, como PyCharm. Sin embargo, como principiante, eso es probablemente menos conveniente; nuestras recomendaciones son igual de poderosas pero mucho mas simples. +Hay muchos editores diferentes, cuál usar depende mucho de la preferencia personal. La mayoría de programadores de Python usan IDEs (Entornos de Desarrollo Integrados) complejos pero muy poderosos, como PyCharm. Sin embargo, como principiante, eso es probablemente menos conveniente; nuestras recomendaciones son igual de poderosas pero mucho mas simples. -Nuestras recomendaciones están listadas abajo, pero siéntete libre de preguntarle a tu instructor cuales son sus preferencias - de esa forma será mas fácil obtener ayuda de ellos. +Nuestras sugerencias están listadas abajo, pero siéntete libre de preguntarle a tu tutor cuáles son sus preferencias - así será más fácil obtener su ayuda. ## Gedit @@ -14,20 +14,30 @@ Gedit es un editor de código abierto, gratis, disponible para todos los sistema [1]: https://wiki.gnome.org/Apps/Gedit#Download -## Sublime Text 2 +## Sublime Text 3 Sublime Text es un editor muy popular con un periodo de prueba gratis. Es fácil de instalar y está disponible para todos los sistemas operativos. [Descárgalo aquí][2] - [2]: http://www.sublimetext.com/2 + [2]: https://www.sublimetext.com/3 ## Atom -Atom es un editor de código muy nuevo creado por [GitHub][3]. Es gratis, de código abierto, fácil de instalar y fácil de usar. Esta disponible para Windows, OSX y Linux. +Atom es un editor de código muy nuevo creado por [GitHub][3]. Es gratis, de código abierto, fácil de instalar y fácil de usar. Está disponible para Windows, OSX y Linux. - [3]: http://github.com/ + [3]: https://github.com/ [Descárgalo aquí][4] - [4]: https://atom.io/ \ No newline at end of file + [4]: https://atom.io/ + +# ¿Por qué estamos instalando un editor de código? + +Puedes estar preguntándote por qué estamos instalando un editor especial, en lugar de usar un editor convencional como Word o Notepad. + +En primer lugar, el código tiene que ser **texto plano** y el problema de las aplicaciones como Word o Textedit es que en realidad no producen texto plano. Lo que generan es texto enriquecido (con tipografías y formato), usando formatos propios como rtf. + +La segunda razón es que los editores de código son herramientas especializadas y, como tales, tienen características muy útiles, como resaltar la sintáxis del código con diferentes colores de acuerdo a su significado o cerrar comillas por ti automáticamente. + +Veremos todo esto en acción más adelante. En breve empezarás a pensar en tu fiel editor de código como una de tus herramientas favoritas :) \ No newline at end of file diff --git a/es/css/README.md b/es/css/README.md index 5c79c16ad81..f252d90e6a3 100755 --- a/es/css/README.md +++ b/es/css/README.md @@ -1,29 +1,29 @@ # CSS - ¡Hazlo bonito! -Nuestro blog todavia se ve bastante feo, verdad? Es hora de hacerlo bonito! Vamos a usar CSS para eso. +Nuestro blog todavía se ve bastante feo, ¿verdad? ¡Es hora de hacerlo bonito! Vamos a usar CSS para eso. ## ¿Qué es CSS? -CSS ('Cascading Style Sheets', que significa 'hojas de estilo en cascada') es un lenguaje utilizado para describir el aspecto y el formato de un sitio web escrito en lenguaje de marcado (como HTML). Trátalo como maquillaje para nuestra página web ;). +CSS (Cascading Style Sheets, que significa 'hojas de estilo en cascada') es un lenguaje utilizado para describir el aspecto y el formato de un sitio web escrito en lenguaje de marcado (como HTML). Trátalo como maquillaje para nuestra página web ;). -Pero no queremos empezar de cero otra vez, ¿verdad? Una vez más, usaremos algo que ya ha sido realizado por programadores y publicado en Internet de forma gratuita. Reinventar la rueda no es divertido, ¿Sabes? +Pero no queremos empezar de cero otra vez, ¿verdad? Una vez más, usaremos algo que ya ha sido realizado por programadores y publicado en Internet de forma gratuita. Ya sabes, reinventar la rueda no es divertido. ## ¡Vamos a usar Bootstrap! -Bootstrap es una de las herramientas (framework) HTML y CSS más populares para desarrollar webs bonitas: http://getbootstrap.com/ +Bootstrap es uno de los frameworks HTML y CSS más populares para desarrollar webs bonitas: https://getbootstrap.com/ -Fue escrito por programadores que trabajaban para Twitter y ahora colaboran en él desarrolladores voluntarios de todo el mundo. +Lo escribieron programadores que trabajaban para Twitter y ahora lo desarrollan voluntarios de todo el mundo. ## Instalar Bootstrap -Para instalar Bootstrap, tienes que añadir esto al `` en el archivo `.html` (`blog/templates/blog/post_list.html`): +Para instalar Bootstrap tienes que añadir esto al `` de tu fichero `.html` (`blog/templates/blog/post_list.html`): +```html - - +``` -Esa línea no incluye ningún fichero a tu proyecto, simplemente utiliza uno existente en internet. Adelante, abre tu página web y actualízala. ¡Ahí lo tienes! +Esto no añade ningún fichero a tu proyecto. Simplemente apunta a ficheros que existen en Internet. Adelante, abre tu sitio web y actualiza la página. ¡Aquí está! ![Figure 14.1][1] @@ -31,274 +31,264 @@ Esa línea no incluye ningún fichero a tu proyecto, simplemente utiliza uno exi ¡Se ve mucho mejor! -## Archivos estáticos en Django +## Ficheros estáticos en Django -Otra cosa que aprenderás hoy se llama **archivos estáticos**. Las paginas estáticas son todo tu CSS e imágenes -- archivos que no son dinámicos, es decir, su contenido no depende del contexto de la petición y será el mismo para todos los usuarios. +Finalmente nos vamos a fijar en estas cosas que hemos estado llamando **ficheros estáticos**. Los ficheros estáticos son todos tus CSS e imágenes; ficheros que no son dinámicos, por lo que su contenido no depende del contexto de la petición y serán iguales para todos los usuarios. -CSS es un fichero estatico, así que para reflejar las modificaciones que se realicen en CSS necesitamos primero configurar archivos estáticos en Django. Solo tendrás que hacerlo una vez. Empecemos: +### Dónde poner los ficheros estáticos para Django -### Configurar archivos estáticos en Django +Como has visto cuando hemos ejecutado `collectstatic` en el servidor, Django ya sabe dónde encontrar los ficheros estáticos para la aplicación "admin". Ahora necesitamos añadir algunos ficheros estáticos para nuestra propia aplicación, `blog`. -En primer lugar, necesitamos crear un directorio para almacenar nuestros archivos estáticos. Adelante, crea un directorio llamado `static` dentro de tu directorio `djangogirls`. +Esto lo conseguimos creando una carpeta llamada `static` dentro de la aplicación blog: djangogirls - ├─── static - └─── manage.py - - -Abre el fichero `mysite/settings.py`, desplázate hasta el fondo del fichero y agregue las siguientes líneas: - - STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "static"), - ) - - -De esta manera Django sabrá dónde encontrar los archivos estáticos. + ├── blog + │ ├── migrations + │ └── static + └── mysite + -## ¡Tu primer archivo CSS! +Django encontrará automáticamente cualquier carpeta que se llame "static" dentro de las carpetas de tus aplicaciones y podrá utilizar su contenido como ficheros estáticos. -Vamos ahora a crear un fichero CSS para añadir tu propio estilo a tu página web. Crear un nuevo directorio llamado `css` dentro de tu directorio `static`. Crea un nuevo fichero llamado `blog.css` dentro de este directorio `css`. Listo? +## ¡Tu primer fichero CSS! - static - └─── css - blog.css +Crea un nuevo directorio llamado `css` dentro de tu directorio `static`. Para añadir tu propio estilo a tu página web, crea un nuevo fichero llamado `blog.css` dentro de este directorio `css`. ¿Lista? + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + -Hora de escribir CSS! Abra el archivo `static/css/blog.css` en el editor de código. +¡Es hora de escribir algo de CSS! Abre el fichero `blog/static/css/blog.css` en tu editor de código. -No nos adentraremos mucho en la personalización y aprendizaje sobre CSS aquí porque es muy fácil y lo puedes aprender por tu cuenta después de este taller. Recomendamos enormemente hacer este [curso de HTML y CSS en Codecademy][2] para aprender todo lo que necesitas saber sobre cómo hacer tus sitios web más bonitos con CSS. +No vamos a entrar mucho en la personalización y el aprendizaje de CSS aquí porque es bastante fácil y lo puedes aprender por tu cuenta después de este taller. Recomendamos enormemente hacer este [curso de HTML y CSS en Codecademy][2] para aprender todo lo que necesitas saber sobre cómo hacer tus sitios web más bonitos con CSS. - [2]: http://www.codecademy.com/tracks/web + [2]: https://www.codecademy.com/tracks/web -Pero vamos a hacer un poco al menos. ¿Tal vez podríamos cambiar el color de nuestro titulo? Para entender los colores, las computadoras utilizan códigos especiales. Empiezan con `#` y siguen con 6 letras (A-F) y números (0-9). Puedes encontrar los códigos de color, por ejemplo, aquí: http://www.colorpicker.com/. También puedes utilizar [colores predefinidos][3], tales como `rojo` y `verde`. +Pero vamos a hacer un poco al menos. ¿Tal vez podríamos cambiar el color de nuestro título? Los ordenadores utilizan códigos especiales para entender los colores. Empiezan con `#` y les siguen 6 letras (A-F) y números (0-9). Puedes encontrar códigos de color, por ejemplo, aquí: http://www.colorpicker.com/. También puedes utilizar [colores predefinidos][3] utilizando su nombre en inglés, como `red` y `green`. [3]: http://www.w3schools.com/cssref/css_colornames.asp -En el fichero `static/css/blog.css` debes añadir el siguiente código: +En tu fichero `blog/static/css/blog.css` deberías añadir el siguiente código: +```css h1 a { color: #FCA205; } +``` +`h1 a` es un selector CSS. Quiere decir que estamos aplicando nuestros estilos a cualquier elemento `a` que se encuentre dentro de un elemento `h1` (por ejemplo cuando tenemos en código algo como: `

enlace

`). En este caso le estamos diciendo que cambie el color a `#FCA205`, que es naranja. Por supuesto, ¡puedes poner tu propio color aquí! -`h1 un` es un Selector de CSS. Esto significa que estamos aplicando nuestros estilos a `cualquier elemento dentro de un elemento h1` (por ejemplo cuando tenemos en código algo como: `

enlace

`). En este caso, estamos diciendo que cambie su color a `#FCA205`, que es de color naranja. Por supuesto, puedes poner tu propio color aquí! - -En el fichero CSS se definen los estilos de los elementos que se encuentran en el fichero HTML. Los elementos se identifican por el nombre del elemento (es decir, `a` `h1`, `body`), el atributo `class` o el atributo `id`. Class y id son nombres que le das al elemento tu mismo. Classes definen grupos de elementos y ids apuntan a elementos específicos. Por ejemplo, la siguiente etiqueta puede identificarse mediante CSS usando el nombre `a`, la clase `external_link` o el id `link_to_wiki_page`: - - +En un fichero CSS definimos los estilos para los elementos del fichero HTML. Los elementos se identifican por el nombre del elemento (es decir, `a`, `h1`, `body`), el atributo `class` (clase) o el atributo `id` (identificador). Class e id son nombres que le asignas tú misma al elemento. Las clases definen grupos de elementos y los ids apuntan a elementos específicos. Por ejemplo, la siguiente etiqueta se puede identificar con CSS usando el nombre `a`, la clase `external_link` o el id `link_to_wiki_page`: +```html + +``` -Leer sobre [Selectores de CSS en w3schools][4]. +Puedes leer más sobre [selectores de CSS en w3schools][4]. [4]: http://www.w3schools.com/cssref/css_selectors.asp -Entonces, necesitamos decirle a nuestra plantilla HTML que hemos añadido CSS. Abra el fichero `blog/templates/blog/post_list.html` y añade esta línea al principio: +También necesitamos decirle a nuestra plantilla HTML que hemos añadido CSS. Abre el fichero `blog/templates/blog/post_list.html` y añade esta línea justo al principio: ```html -{% load staticfiles %} -``` + {% load staticfiles %} +``` -Estamos cargando archivos estáticos aquí:). Luego, entre el `` y ``, después de los enlaces a los archivos CSS Bootstrap (el navegador lee los archivos en el orden que los das, así que nuestro archivo de código puede sobreescribir partes del código en de Bootstrap), añade la siguiente línea: +Aquí sólo estamos cargando ficheros estáticos :). Luego, entre el `` y ``, después de los enlaces a los ficheros CSS de Bootstrap (el navegador lee los ficheros en el orden en que están, así que nuestro fichero podría sobrescribir partes del código de Bootstrap), añade la siguiente línea: ```html - -``` + +``` -Le acabamos de decir a nuestra plantilla donde se encuentra nuestro archivo CSS. +Le acabamos de decir a nuestra plantilla dónde se encuentra nuestro fichero CSS. -Tu archivo ahora debe verse así: +Ahora tu fichero debería tener este aspecto: ```html -{% load staticfiles %} - - - Django Girls blog - - - - - - - - - {% for post in posts %} + {% load staticfiles %} + + + Django Girls blog + + + + +
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

+

Django Girls Blog

- {% endfor %} - - -``` - + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` -OK, guarde el archivo y actualiza el sitio! +De acuerdo, ¡guarda el fichero y actualiza el sitio! ![Figure 14.2][5] [5]: images/color2.png -¡Buen trabajo! Tal vez también nos gustaría dar un poco de aire a nuestro sitio web y aumentar el margen en el lado izquierdo. Vamos a intentarlo! +¡Buen trabajo! ¿Quizá nos gustaría darle un poco de aire a nuestro sitio web y aumentar también el margen en el lado izquierdo? ¡Vamos a intentarlo! ```css -body { - padding-left: 15px; -} -``` - + body { + padding-left: 15px; + } +``` -Añade esto a tu CSS, guarda el archivo y mira cómo funciona! +Añade esto a tu CSS, guarda el fichero y ¡mira cómo funciona! ![Figure 14.3][6] [6]: images/margin2.png -¿Tal vez podemos personalizar la tipografía en nuestra cabecera? Pegue esto en `` del archivo `blog/templates/blog/post_list.html`: +¿Quizá podríamos personalizar la tipografía del título? Pega esto en la sección `` del fichero `blog/templates/blog/post_list.html`: ```html - -``` + +``` Esta línea va a importar una tipografía llamada *Lobster* de Google Fonts (https://www.google.com/fonts). -Ahora agrega la linea `font-family: 'Lobster';` en el archivo CSS `static/css/blog.css` dentro del bloque `h1 a` (el codigo entre las llaves `{` and `}`) y actualiza la página: +Ahora añade la línea `font-family: 'Lobster';` en el fichero CSS `blog/static/css/blog.css` dentro del bloque de declaración `h1 a` (el código entre llaves `{` y `}`) y actualiza la página: ```css -h1 a { - color: #FCA205; - font-family: 'Lobster'; -} -``` - + h1 a { + color: #FCA205; + font-family: 'Lobster'; + } +``` ![Figure 14.3][7] [7]: images/font.png -Genial! +¡Genial! -Como se mencionó anteriormente, CSS tiene un concepto de clases, que básicamente permite nombrar una parte del código HTML y aplicarle estilos solo a esa parte, no afectara a los otros. Es super útil si tienes dos divs, pero están haciendo algo muy diferente (como tu header y tu post), así que no quieres que se vean de la misma forma. +Como se mencionó anteriormente, CSS tiene un concepto de clases que básicamente permite nombrar una parte del código HTML y aplicar estilos sólo a esta parte, sin afectar a otras. Es muy útil si tienes dos divs que hacen algo muy diferente (como el encabezado y la entrada) y no quieres que tengan el mismo aspecto. -Adelante! Nombra algunas partes del código HTML. Añade una clase llamada `page-header` a tu `div` que contiene el encabezado, así: +¡Adelante! Nombra algunas partes del código HTML. Añade una clase llamada `page-header` al `div` que contiene el encabezado, así: ```html - -``` - - -Y ahora añade la clase `post` a tu `div` que contiene una entrada del blog. - -```html -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
-``` - + +``` -Ahora añadiremos bloques de declaración a diferentes selectores. Selectores a partir de `.` se refieren a las clases. Hay muchos tutoriales y explicaciones sobre CSS en la web para ayudarte entender el siguiente codigo. Por ahora, sólo copia y pega en tu archivo `mysite/static/css/blog.css`: - -```css -.page-header { - background-color: #ff9400; - margin-top: 0; - padding: 20px 20px 20px 40px; -} - -.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { - color: #ffffff; - font-size: 36pt; - text-decoration: none; -} - -.content { - margin-left: 40px; -} - -h1, h2, h3, h4 { - font-family: 'Lobster', cursive; -} - -.date { - float: right; - color: #828282; -} - -.save { - float: right; -} - -.post-form textarea, .post-form input { - width: 100%; -} - -.top-menu, .top-menu:hover, .top-menu:visited { - color: #ffffff; - float: right; - font-size: 26pt; - margin-right: 20px; -} - -.post { - margin-bottom: 70px; -} - -.post h1 a, .post h1 a:visited { - color: #000000; -} -``` - - -Luego envuelve el código HTML que muestra los mensajes con las declaraciones de clases. Cambia esto: +Y ahora añade la clase `post` al `div` que contiene una entrada del blog. ```html -{% for post in posts %}

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

-{% endfor %} -``` +``` +Ahora añadiremos bloques de declaración a diferentes selectores. Los selectores que comienzan con `.` hacen referencia a las clases. Hay muchos tutoriales y explicaciones sobre CSS en la web que te ayudarán a entender el siguiente código. Por ahora, simplemente copia y pega este bloque de código en tu fichero `blog/static/css/blog.css`: -En `blog/templates/blog/post_list.html` con esto: +```css + .page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; + } + + .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; + } + + .content { + margin-left: 40px; + } + + h1, h2, h3, h4 { + font-family: 'Lobster', cursive; + } + + .date { + float: right; + color: #828282; + } + + .save { + float: right; + } + + .post-form textarea, .post-form input { + width: 100%; + } + + .top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; + } + + .post { + margin-bottom: 70px; + } + + .post h1 a, .post h1 a:visited { + color: #000000; + } +``` + +Luego rodea el código HTML que muestra las entradas con las declaraciones de clases. Sustituye esto: ```html -
-
-
- {% for post in posts %} -
-
- {{ post.published_date }} + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +en `blog/templates/blog/post_list.html` por esto: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- {% endfor %} + {% endfor %} +
-
-``` - +``` -Guarda los archivos y actualiza tu sitio. +Guarda los ficheros y actualiza tu sitio. ![Figure 14.4][8] [8]: images/final.png -Woohoo! Parece increíble, ¿verdad? El codigo que acabamos de pegar no es tan difícil de entender y debes de ser capaz de entender la mayoría sólo con leerlo. +¡Bien! Se ve increíble, ¿verdad? En realidad el código que acabamos de pegar no es tan difícil de entender y deberías ser capaz de entender la mayoría sólo con leerlo. -No tengas miedo de jugar un poco con este CSS e intentar cambiar algunas cosas. Si rompes algo, no te preocupes, siempre puedes deshacerlo! +No tengas miedo de jugar un poco con este CSS e intentar cambiar algunas cosas. Si rompes algo, no te preocupes, ¡siempre puedes deshacerlo! -De todos modos, recomendamos que realices el curso curso gratuito [Codeacademy HTML & CSS][2] como tarea que para aprendas todo lo que necesitas acerca de hacer tus sitios web bonitos con CSS. +De cualquier forma, te volvemos a recomendar que hagas el [curso de HTML y CSS de Codeacademy][2] como una tarea post-taller para que aprendas todo lo que necesitas saber para hacer tus sitios web más bonitos con CSS. ¡¿Lista para el siguiente capítulo?! :) diff --git a/es/deploy/README.md b/es/deploy/README.md index 279b82930cd..c85530aff05 100755 --- a/es/deploy/README.md +++ b/es/deploy/README.md @@ -1,237 +1,318 @@ -# Deploy! +# ¡Despliega! -> **Nota** El siguiente capítulo puede ser un poco difícil de seguir a veces. Se persistente y acábalo. El despliegue es una parte importante del proceso en el desarrollo web. Este capítulo está situado a la mitad del tutorial, de esta manera tu mentor puede ayudarte en el proceso de poner tu sitio web en línea. Esto significa que podrás acabar el tutorial por tu cuenta si se te acaba el tiempo. +> **Nota**: El siguiente capítulo puede ser a veces un poco difícil de superar. Se persistente y acábalo. El despliegue es una parte importante del proceso en el desarrollo web. Este capítulo está situado en el medio del tutorial para que tu tutor pueda ayudarte a poner tu sitio web en línea, lo que puede ser un proceso algo más complicado. Esto significa que podrás acabar el tutorial por tu cuenta si se te acaba el tiempo. -Hasta ahora tu sitio web estaba disponible sólo en tu ordenador, ahora aprenderás como desplegarlo! El despliegue es el proceso de publicar tu aplicación en internet para que la gente pueda acceder y ver tu aplicación :). +Hasta ahora tu sitio web estaba disponible sólo en tu ordenador, ¡ahora aprenderás cómo desplegarlo! El despliegue es el proceso de publicar tu aplicación en Internet para que la gente pueda acceder y ver tu aplicación :). -Como ya has aprendido, un sitio web tiene que estar en un servidor. Hay un montón de proveedores, pero usaremos el que tiene el proceso de despliegue más sencillo: [Heroku][1]. Heroku es gratis para pequeñas aplicaciones que no tienen demasiadas visitas, será más que suficiente por ahora. +Como ya has aprendido, un sitio web tiene que estar en un servidor. Hay muchos proveedores, pero usaremos uno que tiene un proceso de despliegue relativamente simple: [PythonAnywhere][1]. PythonAnywhere es gratis para pequeñas aplicaciones que no tienen demasiados visitantes, definitivamente suficiente para este caso. - [1]: http://heroku.com/ + [1]: https://pythonanywhere.com/ -Seguiremos este tutorial: https://devcenter.heroku.com/articles/getting-started-with-django, pero lo hemos copiado a continuación para que sea más fácil para ti. +El otro servicio externo que vamos a utilizar es [GitHub][2], un servicio de alojamiento de código. Hay otras opciones por ahí, pero hoy en día casi todos los programadores tienen una cuenta de GitHub, ¡y ahora tú también la vas a tener! -## El fichero `requirements.txt` + [2]: https://www.github.com -Necesitamos crear un fichero de requisitos `requirements.txt` para decirle a Heroku que paquetes Python necesitan ser instalados en nuestro servidor. +Usaremos GitHub como paso intermedio para transportar nuestro código desde y hasta PythonAnywhere. -Pero primero Heroku necesita que instalemos unos cuantos paquetes. Ves a tu consola con `virtualenv` activado y escribe esto: +# Git - (myvenv) $ pip install dj-database-url waitress whitenoise - +Git es un "sistema de control de versiones" usado por muchos programadores - es un sistema que registra los cambios en los archivos a través del tiempo de forma tal que puedas acceder a versiones específicas cuando lo desees. Es muy similar a la opción de "registrar cambios" en Microsoft Word, pero mucho más poderoso. -Cuando haya acabado la instalación, ves al directorio `djangogirls` y ejecuta el siguiente comando: +## Instalar Git - (myvenv) $ pip freeze > requirements.txt - +### Windows -Esto creará un fichero llamado `requirements.txt` con la lista de los paquetes que tienes instalados (i.e. librerías Python que estés utilizando, por ejemplo Django :)). +Puedes descargar Git de [git-scm.com][3]. Puedes hacer clic en "Next" para todos los pasos excepto en uno; en el quinto paso titulado "Adjusting your PATH environment", elije "Run Git and associated Unix tools from the Windows command-line" (la última opción). Aparte de eso, los valores por defecto funcionarán bien. "Checkout Windows-style, commit Unix-style line endings" también está bien. -> **Nota**: `pip freeze` devuelve una lista de todas las librerías Python instaladas en tu virtualenv y `>` toma la salida de `pip freeze` y la pone en un fichero. Prueba a ejecutar `pip freeze` sin el `> requirements.txt` para ver que pasa! + [3]: https://git-scm.com/ -Abre este archivo y añade la siguiente línea al final: +### MacOS - psycopg2==2.5.3 - +Descarga Git de [git-scm.com][3] y sigue las instrucciones. -Esta línea es necesaria para que tu aplicación funcione en Heroku. +### Linux -## Procfile +Si no lo tienes ya instalado, git debería estar disponible a través del administrador de paquetes, prueba con: -Otra cosa que necesitamos crear es un Procfile. Eso ayudará a Heroku a saber que comandos debe ejecutar para poner en marcha nuestro sitio web. Abre tu editor de código, crea un fichero llamado `Procfile` en el directorio `djangogirls` y añade esta línea: - - web: waitress-serve --port=$PORT mysite.wsgi:application + sudo apt-get install git + # o + sudo yum install git -Esta línea quiere decir que vamos a desplegar una aplicación `web` y para hacerlo ejecutaremos el comando `waitress-serve --port=$PORT mysite.wsgi:application` (`waitress-serve` es un programa que es como una versión más potente que el comando de Django `runserver`). - -Ahora salva los cambios. Hecho! +## Iniciar nuestro repositorio Git -## El fichero `runtime.txt` +Git rastrea los cambios realizados a un grupo determinado de ficheros en lo que llamamos un repositorio de código (o "repo" para abreviar). Iniciemos uno para nuestro proyecto. Abre la consola y ejecuta los siguientes comandos en el directorio de `djangogirls`: -Tenemos que decirle a Heroku que versión de Python queremos utilizar. Esto se hace creando un fichero `runtime.txt` en el directorio `djangogirls` usando el comando de tu editor "new file" y poniendo el siguiente texto (y nada más!) en él: +> **Nota**: Comprueba el directorio de trabajo actual con el comando `pwd` (OSX/Linux) o `cd` (Windows) antes de inicializar el repositorio. Deberías estar en la carpeta `djangogirls`. - python-3.4.2 + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config user.name "Tu nombre" + $ git config user.email tú@ejemplo.com -## mysite/local_settings.py +Inicializar el repositorio git es algo que sólo necesitamos hacer una vez por proyecto (y no tendrás que volver a poner tu usuario y correo electrónico nunca más) -Hay diferencias entre la configuración que utilizamos en local (en nuestro ordenador) y la configuración para nuestro servidor. Heroku utiliza una base de datos y tu ordenador utiliza otra diferente. Por eso necesitamos crear ficheros separados para la configuración de nuestro entorno local. +Git llevará un registro de los cambios realizados en todos los ficheros y carpetas en este directorio, pero hay algunos ficheros que queremos que ignore. Esto lo hacemos creando un fichero llamado `.gitignore` en el directorio base. Abre tu editor y crea un nuevo fichero con el siguiente contenido: -Crea el fichero `mysite/local_settings.py`. Debería contener la configuración de la `BASE DE DATOS` de tu fichero `mysite/settings.py`. Simplemente como esto: - - import os - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } - } - - DEBUG = True + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store -Ahora guarda los cambios! :) +Y guárdalo como `.gitignore` en la primera carpeta "djangogirls". -## mysite/settings.py +> **Nota**: ¡El punto al principio del nombre del fichero es importante! Si tienes dificultades para crearlo (a los Mac no les gusta que crees ficheros que empiezan por punto desde Finder, por ejemplo), usa la opción "Guardar como" en tu editor, eso no falla. -Otra cosa que tenemos que hacer es modificar el fichero `settings.py` de nuestro sitio web. Abre `mysite/settings.py` en tu editor y añade las siguientes líneas al final del fichero: +Es buena idea utilizar el comando `git status` antes de `git add` o cuando no estés segura de lo que va a hacer, para evitar cualquier sorpresa (por ejemplo, añadir o hacer commit de ficheros no deseados). El comando `git status` devuelve información sobre los ficheros sin seguimiento (untracked), modificados, preparados (staged), el estado de la rama y mucho más. La salida debería ser similar a: - import dj_database_url - DATABASES['default'] = dj_database_url.config() + $ git status + On branch master - SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + Initial commit - ALLOWED_HOSTS = ['*'] + Untracked files: + (use "git add ..." to include in what will be committed) - STATIC_ROOT = 'staticfiles' + .gitignore + blog/ + manage.py + mysite/ - DEBUG = False + nothing added to commit but untracked files present (use "git add" to track) -Al final del fichero `mysite/settings.py`, copia y pega esto: +Y finalmente guardamos nuestros cambios. Ve a la consola y ejecuta estos comandos: - try: - from .local_settings import * - except ImportError: - pass + $ git add --all . + $ git commit -m "Mi app Django Girls, primer commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py -Esto importará tu configuración local si el fichero existe. +## Enviar nuestro código a GitHub -Ahora guarda los cambios. +Visita [GitHub.com][4] y registra una nueva cuenta de usuario gratuita. Luego, crea un nuevo repositorio con el nombre "my-first-blog". Deja desmarcada la opción "Initialise with a README", deja la opción .gitignore en blanco (lo hemos hecho a mano) y deja la licencia como "None". -## mysite/wsgi.py + [4]: https://www.github.com -Abre el fichero `mysite/wsgi.py` y añade estas líneas al final: +![][5] - from whitenoise.django import DjangoWhiteNoise - application = DjangoWhiteNoise(application) - + [5]: images/new_github_repo.png -Genial! +> **Nota** El nombre `my-first-blog` es importante. Podrías elegir otra cosa, pero va a aparecer muchas veces en las instrucciones que siguen y tendrías que sustituirlo cada vez. Probablemente sea más sencillo quedarte con el nombre `my-first-blog`. -## Cuenta Heroku +En la próxima pantalla verás la URL para clonar tu repositorio. Elige la versión "HTTPS", cópiala y en un momento la pegaremos en la consola: -Necesitas instalar Heroku toolbelt, puedes encontrarlo aquí (puedes saltarte la instalación si ya lo has instalado durante la configuración): https://toolbelt.heroku.com/ +![][6] -> Cuando estés ejecutando la instalación de Heroku toolbel en Windows asegúrate de escoger la "Instalación personalizada" cuando te pregunte por los componentes que quieres instalar. En la lista de componentes que te aparecerá, selecciona adicionalmente la casilla de "Git and SSH". -> -> En Windows también debes ejecutar el siguiente comando para añadir Git y SSH a tu ruta `PATH`: `setx PATH "%PATH%;C:\Program Files\Git\bin"`. Reinicia la consola de línea de comandos después para que los cambios se hagan efectivos. + [6]: images/github_get_repo_url_screenshot.png -Por favor, crea también una cuenta gratis Heroku en: https://id.heroku.com/signup/www-home-top +Ahora tenemos que conectar el repositorio Git de tu ordenador con el que está en GitHub. + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + -Ahora autentícate en tu cuenta de Heroku en tu ordenador ejecutando el siguiente comando: +Escribe tu nombre de usuario y contraseña de GitHub y deberías ver algo así: - $ heroku login + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. -En el caso de no tener una clave SSH, este comando creará una automáticamente. Las claves SSH son necesarias para subir el código a Heroku. + -## Git +Tu código está ahora en GitHub. ¡Ve y míralo! Verás que está en buena compañía; [Django][7], el [Tutorial de Django Girls][8] y muchos otros grandes proyectos de código abierto también alojan su código en GitHub :) -Git es un sistema de control de versiones que usan muchos programadores-software que guarda el registro de cambios en el tiempo de un fichero o un conjunto de ficheros de manera que puedes volver a una versión anterior en el futuro. Heroku utiliza un repositorio git para administrar los ficheros de tus proyectos, así que también tenemos que utilizarlo. + [7]: https://github.com/django/django + [8]: https://github.com/DjangoGirls/tutorial -Crea un fichero llamado `.gitignore` en tu directorio `djangogirls` con el siguiente contenido: +# Configurar nuestro blog en PythonAnywhere - myvenv - __pycache__ - staticfiles - local_settings.py - db.sqlite3 - *.py[co] +Es hora de registrar una cuenta gratuita de tipo "Beginner" en PythonAnywhere. -y guarda los cambios. El punto al principio del nombre del fichero es importante! Como puedes ver, ahora le estamos diciendo a Heroku que ignore el fichero `local_settings.py` y no lo descargue, para que esté disponible solamente en tu ordenador (en local). +* [www.pythonanywhere.com][9] -A continuación crearemos un nuevo repositorio git y guardaremos nuestros cambios. Ve a la consola y ejecuta los siguientes comandos: + [9]: https://www.pythonanywhere.com/ - $ git init - Initialized empty Git repository in ~/djangogirls/.git/ - $ git config user.name "Your Name" - $ git config user.email you@example.com - +> **Nota**: Cuando elijas tu nombre de usuario ten en cuenta que la URL de tu blog tendrá la forma `nombredeusuario.pythonanywhere.com`, así que o bien elije tu propio apodo o bien un nombre que describa sobre qué trata tu blog. -Solo necesitamos inicializar el repositorio git una única vez por proyecto. +## Bajar nuestro código en PythonAnywhere -Y finalmente guardamos nuestros cambios. Ve a la consola y ejecuta estos comandos: +Cuando te hayas registrado en PythonAnywhere serás redirigida a tu panel de control o página "Consoles". Elije la opción para iniciar una consola "Bash", que es la versión PythonAnywhere de una consola, como la que tienes en tu PC - $ git add -A . - $ git commit -m "My Django Girls app" - [master (root-commit) 2943412] My Django Girls - 7 files changed, 230 insertions(+) - create mode 100644 .gitignore - create mode 100644 Procfile - create mode 100644 mysite/__init__.py - create mode 100644 mysite/settings.py - create mode 100644 mysite/urls.py - create mode 100644 mysite/wsgi.py - create mode 100644 manage.py - create mode 100644 requirements.txt - create mode 100644 runtime.txt - +> **Nota**: PythonAnywhere está basado en Linux, por lo que si estás en Windows la consola será un poco distinta a la que tienes en tu ordenador. -## Escoge un nombre de aplicación +Descarguemos nuestro código desde GitHub a PythonAnywhere mediante la creación de un "clon" del repositorio. Escribe lo siguiente en la consola de PythonAnywhere: -Tu blog estará disponible en la Web en `[el nombre de tu blog].herokuapp.com`, así que necesitas escoger un nombre que nadie haya cogido anteriormente. Este nombre no tiene porque estar relacionado con la aplicación `blog` de Django ni con `mysite` ni con nada de lo que hemos creado anteriormente. El nombre puede ser el que tu quieras, pero Heroku es un poco estricto en cuanto a los caracteres que puedes utilizar: solo puedes usar caracteres simples en minúscula (ni mayúsculas ni acentos) números y guiones (`-`). + $ git clone https://github.com//my-first-blog.git -Una vez hayas pensado en un nombre (quizás algo con tu nombre o tu alias), ejecuta este comando, remplazando `djangogirlsblog` con el nombre de tu aplicación: +> **Nota**: No pongas los símbolos < y >, solo escribe tu usuario. - $ heroku create djangogirlsblog +Esto va a descargar una copia de tu código en PythonAnywhere. Compruébalo escribiendo: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py -> **Nota**: Recuerda que tienes que reemplazar `djangogirlsblog` con el nombre de tu aplicación en Heroku. +### Crear un virtualenv en PythonAnywhere -Si no se te ocurre ningún nombre, puedes ejecutar +Tal y como hiciste en tu propio ordenador, puedes crear un virtualenv en PythonAnywhere. En la consola Bash, escribe: - $ heroku create + 20:20 ~ $ cd my-first-blog + + 20:20 ~ $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + 20:20 ~ $ source myvenv/bin/activate + + (myvenv)20:20 ~ $ pip install django==1.8 whitenoise + Collecting django + [...] + Successfully installed django-1.8 whitenoise-1.0.6 + + + + +### Recopilar ficheros estáticos -y Heroku escogerá un nombre para ti (probablemente algo como `enigmatic-cove-2527`). +¿Te estabas preguntando qué es eso de "whitenoise"? Es una herramienta para servir los llamados "ficheros estáticos". Los ficheros estáticos funcionan de distinta forma en los servidores en comparación con cómo lo hacen en nuestro propio ordenador y necesitamos una herramienta como "whitenoise" para servirlos. -Si en algún momento quisieras cambiar el nombre de tu aplicación Heroku, puedes hacerlo ejecutando el siguiente comando (reemplazando `tu-nuevo-nombre` por el nuevo nombre que quieras utilizar): +Aprenderemos un poco más sobre los ficheros estáticos más adelante, cuando editemos el CSS de nuestro sitio. - $ heroku apps:rename tu-nuevo-nombre +Por ahora sólo necesitamos ejecutar en el servidor un comando adicional llamado "collectstatic". Le dice a Django que recopile todos los ficheros estáticos que necesita en el servidor. Por el momento, principalmente son los ficheros estáticos que hacen que el panel de administración esté bonito. + + 20:20 ~ $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + Type 'yes' to continue, or 'no' to cancel: yes + + +Escribe "yes", ¡y ahí va! ¿No te encanta hacer que las computadoras impriman páginas y páginas de texto imposible de entender? Siempre hago ruiditos para acompañarlo. Brp, brp brp... -> **Nota**: Recuerda que después de haber cambiado el nombre de tu aplicación, tienes que acceder `el nuevo nombre].herokuapp.com` para ver tu sitio web. + Copying '/home/edith/.virtualenvs/myvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/.virtualenvs/myvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/.virtualenvs/myvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/.virtualenvs/myvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + -## Despliegue en Heroku! +### Crear la base de datos en PythonAnywhere -Hemos hecho un montón de configuración e instalación, verdad? Pero sólo tienes que hacer esto una única vez! Ahora ya puedes hacer el depliegue! +Aquí hay otra cosa que es diferente entre tu ordenador y el servidor: éste utiliza una base de datos diferente. Por lo tanto, las cuentas de usuario y las entradas pueden ser diferentes en el servidor y en tu ordenador. -Cuando ejecutaste `heroku create`, automáticamente se añadió el Heroku remoto para nuestra aplicación a nuestro repositorio. Ahora podemos hacer un simple <0>git push para desplegar nuestra aplicación: +Así que inicializamos la base de datos en el servidor igual que lo hicimos en nuestro ordenador, con `migrate` y `createsuperuser`: - $ git push heroku master + (myvenv)20:20 ~ $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (myvenv)20:20 ~ $ python manage.py createsuperuser -> **Nota**: Esto probablemente producirá una salida *muy larga* la primera vez, porque Heroku compila e instala psycopg. Sabrás que todo ha ido bien si ves algo como `https://elnombre detuaplicacion.herokuapp.com/ deployed to Heroku` hacia el final de la salida. +## Publicar nuestro blog como una aplicación web -## Accede a tu aplicación +Ahora que nuestro código está en PythonAnywhere, el virtualenv está listo, los ficheros estáticos han sido recopilados y la base de datos está inicializada, estamos listas para publicarla como una aplicación web. -Ya has desplegado tu código en Heroku y has especificado el tipo de proceso en un `Procfile` (especificamos un proces de tipo `web` anteriormente). Ahora ya podemos decirle a Heroku que inicie este `proceso web`. +Haz clic en el logo de PythonAnywhere para volver al panel principal, haz clic en la pestaña **Web** y pincha en **Add a new web app**. -Para hacer esto, ejecuta el siguiente comando: +En la ventana de diálogo, después de confirmar el nombre de dominio, elije **manual configuration** (configuración manual) (NB la opción "Django" *no*). Luego, elije **Python 3.4** y haz clic en "Next" para terminar con el asistente. - $ heroku ps:scale web=1 - +> **Nota** asegúrate de elegir la opción de "Manual configuration", no la de "Django". Somos demasiado buenas para la configuración por defecto de Django de PythonAnywhere ;-) -Esto le dice a Heroku que ejecute sólo una instancia de nuestro proceso `web`. Como la aplicación de nuestro blog es bastante sencilla, no necesitamos demasiado así que es suficiente ejecutar un solo proceso. Es posible decirle a Heroku que ejecute más procesos (por cierto, Heroku llama a estos procesos "Dynos" así que no te sorprendas si ves este término) pero entonces ya no será gratis. +### Configurar el virtualenv -Ahora podemos acceder a la aplicación en nuestro navegador con `heroku open`. +Serás redirigida a la pantalla de configuración de PythonAnywhere para tu aplicación web, a la que deberás acceder cada vez que quieras hacer cambios en la aplicación del servidor. - $ heroku open - +![][10] + + [10]: images/pythonanywhere_web_tab_virtualenv.png -> **Nota**: Verás una página de error! Hablaremos de esto en seguida +En la sección "Virtualenv", haz clic en el texto rojo que dice "Enter the path to a virtualenv" (Introduce la ruta a un virtualenv) y escribe: `/home//my-first-blog/myvenv/` -Esto abrirá una url como [https://djangogirlsblog.herokuapp.com/]() en tu navegador y probablemente verás una página de error. Como de momento sólo hemos creado la vista de administración para la aplicación, añade `admin/` a la url (i.e. [https://djangogirlsblog.herokuapp.com/admin/]()) para poder ver una versión de tu aplicación web funcionando. +> **Nota**: sustituye tu propio nombre de usuario como corresponda. Si cometes un error, PythonAnywhere te mostrará una pequeña advertencia. ¡No olvides no teclear los simbolos < y >! -El error que veías era debido a que cuando desplegamos en Heroku creamos una nueva base de dados y ésta está vacía. Necesitamos ejecutar el comando ~~~ migrate~~~ como hicimos cuando empezamos nuestro proyecto para configurar nuestra base de datos correctamente: +### Configurar el fichero WSGI - $ heroku run python manage.py migrate +Django funciona utilizando el "protocolo WSGI", un estándar para servir sitios web usando Python, que PythonAnywhere soporta. La forma de configurar PythonAnywhere para que reconozca nuestro blog Django es editar un fichero de configuración WSGI. + +Haz clic en el enlace "WSGI configuration file" (en la sección "Code" en la parte de arriba de la página; se llamará algo parecido a `/var/www/_pythonanywhere_com_wsgi.py`) y te redirigirá al editor. + +Elimina todo el contenido actual y reemplázalo con algo como esto: + +``` python + import os + import sys - $ heroku run python manage.py createsuperuser + path = '/home//my-first-blog' # aquí utiliza tu propio usuario, sin los simbolos < y > + if path not in sys.path: + sys.path.append(path) + os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + + from django.core.wsgi import get_wsgi_application + from whitenoise.django import DjangoWhiteNoise + application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Nota** no olvides sustituir tu propio nombre de usuario donde dice `` + +Este fichero se encarga de decirle a PythonAnywhere dónde vive nuestra aplicación web y cómo se llama el fichero de configuración de Django. También configura la herramienta para ficheros estáticos "whitenoise". + +Dale a **Save** y vuelve a la pestaña **Web**. + +¡Todo listo! Dale al botón verde grande que dice **Reload** y podrás ver tu aplicación. Verás un enlace a ella en la parte de arriba de la página. + +## Consejos de depuración + +Si aparece un error cuando intentas visitar tu sitio, el primer lugar que deberás revisar para obtener información de depuración es el **error log**; encontrarás un enlace a él en la pestaña Web de PythonAnywhere. Mira a ver si hay algún mensaje de error ahí. Los más recientes están al final. Los problemas más comunes incluyen + +* olvidar alguno de los pasos que hicimos en la consola: crear el virtualenv, activarlo, instalar Django en él, ejecutar collectstatic, inicializar la base de datos +* cometer un error en la ruta del virtualenv en la pestaña Web; suele haber un mensajito de error de color rojo, si hay algún problema +* cometer un error en el fichero de configuración WSGI; ¿has puesto bien la ruta a la carpeta my-first-blog? + +¡Tu tutor está ahí para ayudar! + +# ¡Estás en vivo! + +La página por defecto de tu sitio debería decir "Welcome to Django", igual que en tu PC local. Intenta añadir `/admin/` al final de la URL y te redirigirá al panel de administración. Ingresa con tu nombre de usuario y contraseña y verás que puedes añadir nuevas entradas en el servidor. -Ahora deberías poder acceder a tu sitio web desde el navegador! Felicidades :)! +*¡Buen trabajo!* - los despliegues en el servidor son una de las partes más complejas del desarrollo web y muchas veces a la gente le cuesta varios días tenerlo funcionando. Pero tú tienes tu sitio en vivo, en Internet de verdad, ¡así como suena! diff --git a/es/deploy/images/github_get_repo_url_screenshot.png b/es/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/es/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/es/deploy/images/new_github_repo.png b/es/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/es/deploy/images/new_github_repo.png differ diff --git a/es/deploy/images/pythonanywhere_web_tab_virtualenv.png b/es/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/es/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/es/django/README.md b/es/django/README.md index 597c81a2f28..782c575948f 100755 --- a/es/django/README.md +++ b/es/django/README.md @@ -2,7 +2,7 @@ Django (*gdh/ˈdʒæŋɡoʊ/jang-goh*) es un framework para aplicaciones web gratuito y open source, escrito en Python. Es un WEB framework - un conjunto de componentes que te ayudan a desarrollar sitios web más fácil y rápidamente. -Verás, cuando estás construyendo un sitio web, frecuentemente necesitas componentes similares: autenticación de usuario (iniciar sesion, cerrar sesion, registrarse), un panel de administración para su sitio web, formularios, una forma de subir archivos, etc. +Verás, cuando estás construyendo un sitio web, frecuentemente necesitas un conjunto de componentes similares: una manera de manejar la autenticación de usuarios (registrarse, iniciar sesión, cerrar sesión), un panel de administración para tu sitio web, formularios, una forma de subir archivos, etc. Por suerte para ti, hace tiempo varias personas notaron que los desarrolladores web enfrentan problemas similares cuando construyen un sitio nuevo, por eso juntaron cabezas y crearon frameworks (Django es uno de ellos) que te ofrecen componentes listos para usarse. @@ -16,12 +16,12 @@ Imagina un buzón (puerto) el cual es monitoreado por cartas entrantes (peticion ## ¿Qué sucede cuando alguien solicita una página web de tu servidor? -Cuando llega una petición a un servidor web es pasado a Django que intenta averiguar lo que realmente es solicitado. Toma primero una dirección de página web y trata de averiguar qué hacer. Esta parte es realizada por **urlresolver** de Django (tenga en cuenta que la dirección de un sitio web es llamada URL - Uniform Resource Locator - así que el nombre *urlresolver* tiene sentido). Este no es muy inteligente - toma una lista de patrones y trata de igualar la URL. Django comprueba los patrones de arriba hacia abajo y si algo se coincide entonces Django le pasa la solicitud a la función asociada (que se llama *vista*). +Cuando llega una petición a un servidor web, ésta es pasada a Django, el cual intenta averiguar lo que realmente es solicitado. Toma primero una dirección de página web y trata de averiguar qué hacer. Esta parte es realizada por el **urlresolver** de Django (ten en cuenta que la dirección de un sitio web es llamada URL - Uniform Resource Locator - así que el nombre *urlresolver* tiene sentido). Este no es muy inteligente - toma una lista de patrones y trata de encontrar la URL. Django comprueba los patrones de arriba hacia abajo y si algo coincide entonces Django le pasa la solicitud a la función asociada (que se llama *vista*). -Imagina a un cartero con una carta. Ella está caminando por la calle y comprueba cada número de casa contra el que está en la carta. Si coincide, ella pone la carta ahí. Así es como funciona el urlresolver! +Imagina a un cartero llevando una carta. Ella está caminando por la calle y comprueba cada número de casa con el que está en la carta. Si coincide, ella deja la carta allí. ¡Así es como funciona el urlresolver! -En la función de *vista* se hacen todas las cosas interesantes: podemos mirar a una base de datos para buscar alguna información. ¿Tal vez el usuario pidió cambiar algo en los datos? Como una carta diciendo "Por favor cambia la descripción de mi trabajo." La *vista* puede comprobar si tenes permitido hacer eso, entonces actualizar la descripción del trabajo para usted y devolverle un mensaje: "¡hecho!". Entonces la *vista* genera una respuesta y Django puede enviarla al navegador del usuario. +En la función de *vista* se hacen todas las cosas interesantes: podemos mirar a una base de datos para buscar alguna información. ¿Tal vez el usuario pidió cambiar algo en los datos? Como una carta diciendo "Por favor cambia la descripción de mi trabajo." La *vista* puede comprobar si tenes permitido hacer eso, entonces actualizar la descripción del trabajo para ti y devolverte un mensaje: "¡hecho!". Entonces la *vista* genera una respuesta y Django puede enviarla al navegador del usuario. -Por supuesto, la descripción anterior se simplifica un poco, pero no necesitas saber todas las cosas técnicas aun. Tener una idea general es suficiente. +Por supuesto, la descripción anterior esta simplificada un poco, pero no necesitas saber todas las cosas técnicas aun. Tener una idea general es suficiente. -Así que en lugar de meternos demasiado en los detalles, simplemente comenzaremos creando algo con Django y aprenderemos todas las piezas importantes en el camino! \ No newline at end of file +Así que en lugar de meternos demasiado en los detalles, ¡simplemente comenzaremos creando algo con Django y aprenderemos todas las piezas importantes en el camino! diff --git a/es/django_admin/README.md b/es/django_admin/README.md index 2e774056e85..c340823c749 100755 --- a/es/django_admin/README.md +++ b/es/django_admin/README.md @@ -1,29 +1,25 @@ # Administrador de Django -Para agregar, editar y borrar los mensajes que hemos modelamos, utilizaremos el administrador de Django. +Para agregar, editar y borrar los posts que hemos modelado, utilizaremos el administrador de Django. Vamos a abrir el archivo `blog/admin.py` y reemplazar su contenido con esto: +```python from django.contrib import admin from .models import Post - + admin.site.register(Post) - +``` Como puedes ver, importamos (incluimos) el modelo Post definido en el capítulo anterior. Para hacer nuestro modelo visible en la página del administrador, tenemos que registrar el modelo con `admin.site.register(Post)`. -Es hora de mirar a nuestro modelo de Post. Recuerde que debe ejecutar `python manage.py runserver` en la consola para ejecutar el servidor web. Vaya al navegador y escriba la dirección: - - http://127.0.0.1:8000/admin/ - - -Usted verá una página de inicio de sesión como esta: +Ok, es hora de ver tu modelo Post. Recuerda ejecutar `python manage.py runserver` en la consola para correr el servidor web. Ve al navegador y tipea la dirección http://127.0.0.1:8000/admin/. Verás una página de ingreso como la que sigue: ![Página de inicio de sesión][1] [1]: images/login_page2.png -Para poder entrar necesitas crear un *superusuario* - un usuario que tiene control sobre todo en el sitio. Vuelve a la línea de comandos y escribe `python manage.py createsuperuser`, presiona `enter` y escriba su nombre de usuario (en minúscula, sin espacios), dirección de correo electrónico y contraseña cuando te pregunten por ellos. La salida debe ser así (donde nombre de usuario y correo electrónico deben ser los tuyos): +Para poder ingresar deberás crear un *superusuario* - un usuario que tiene control sobre todo lo que hay en el sitio. Vuelve hacia atrás a tu línea de comandos y tipea `python manage.py createsuperuser`, presiona enter y tipea tu nombre de usuario (en minúsculas, sin espacios), dirección de email y contraseña cuando sean requeridos. No te preocupes que no puedes ver tu contraseña mientras la tipeas - así es como debe ser. Simplemente tipéala y presiona 'Enter' para continuar. La salida de este comando debería verse así (nombre de usuario y email deberían ser los tuyos): (myvenv) ~/djangogirls$ python manage.py createsuperuser Username: admin @@ -31,22 +27,22 @@ Para poder entrar necesitas crear un *superusuario* - un usuario que tiene contr Password: Password (again): Superuser created successfully. + - -Regresa a tu navegador e inicia sesión con las credenciales de superusuario que elegiste, deberías ver el tablero de administración de Django. +Vuelve a tu navegador e ingresa con las credenciales de super usuario que elegiste, ahora deberías poder ver el panel de administración de Django. ![Administrador de Django][2] [2]: images/django_admin3.png -Ve a Posts y experimentar un poco con él. Agrega cinco o seis entradas en el blog. No te preocupes por el contenido - puedes simplemente copiar y pegar algún texto de este tutorial como contenido de tus mensajes para ahorrar tiempo :). +Ve a Posts y experimenta un poco con esto. Agrega cinco o seis posts del blog. No te preocupes por el contenido - puedes simplemente copiar y pegar texto de este tutorial en el contenido de tus posts para ahorrar tiempo :). -Asegúrate que al menos dos o tres entradas (pero no todas) tengan la fecha de publicación. Será de ayuda más tarde. +Asegúrate de que por lo menos dos o tres posts (pero no todos) tienen la fecha de publicación. Será útil luego. ![Administrador de Django][3] [3]: images/edit_post3.png -Sí quieres sabes más sobre Django admin, deberías revisar la documentación de Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ +Si quieres saber más sobre el administrador de Django, puedes visitar la documentación de Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ -Probablemente sea un buen momento para tomar un café (o té) y comer algo dulce. Haz creado tu primer modelo Django - te mereces un regalito! +Este probablemente sea un buen momento para tomar un café (o té) o algo para comer y re-energizarte. Creaste tu primer modelo de Django - ¡mereces un pequeño recreo! diff --git a/es/django_forms/README.md b/es/django_forms/README.md index e29befd9dc1..8e9118ac1f1 100755 --- a/es/django_forms/README.md +++ b/es/django_forms/README.md @@ -1,6 +1,6 @@ # Formularios en Django -Por último, queremos crear un apartado en nuestra web para poder agregar y editar entradas en el blog. Django `admin` está bien, pero es bastante difícil de personalizar y hacerlo bonito. Con `forms` tendremos un poder absoluto sobre nuestra interfaz - podemos hacer casi cualquier cosa que podamos imaginar! +Lo último que haremos en nuestro website es crear un apartado para agregar y editar posts en el blog. Django `admin` está bien, pero es bastante difícil de personalizar y hacerlo bonito. Con `forms` tendremos un poder absoluto sobre nuestra interfaz - ¡podemos hacer casi cualquier cosa que podamos imaginar! Lo bueno de Django forms es que podemos definirlo desde cero o creando un `ModelForm` y se guardará el resultado del formulario en el modelo. @@ -12,109 +12,105 @@ Tenemos que crear un archivo con este nombre en el directorio `blog`. blog └── forms.py + - -Ok, vamos abrirlo y vamos a escribir el siguiente código: - +Ok, vamos a abrirlo y vamos a escribir el siguiente código: + ```python -from django import forms - -from .models import Post - -class PostForm(forms.ModelForm): - - class Meta: - model = Post - fields = ('title', 'text',) -``` - - -Primero necesitamos importar Django forms (`from django import forms`) y, obviamente, nuestro modelo de `Post` (`from .models import Post`). + from django import forms + + from .models import Post + + class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Primero necesitamos importar Django forms (`from django import forms`) y, obviamente, nuestro modelo `Post` (`from .models import Post`). `PostForm`, como probablemente sospechas, es el nombre del formulario. Necesitamos decirle a Django que este formulario es un `ModelForm` (así Django hará algo de magia para nosotros) - `forms.ModelForm` es responsable de ello. -A continuación, tenemos `class Meta`, donde le decimos a Django que modelo debe utilizar para crear este formulario (`model = Post`). +A continuación, tenemos `class Meta`, donde le decimos a Django qué modelo debe utilizar para crear este formulario (`model = Post`). -Finalmente, podemos decir que campo(s) que campos queremos en nuestro formulario. En este escenario sólo queremos `título` y `texto` - `autor` será la persona que se ha autenticado (tú!) y `fecha_de_creacion` se definirá automáticamente cuando creemos una entrada (es decir en el código), ¿si? +Finalmente, podemos decir que campo(s) queremos en nuestro formulario. En este escenario sólo queremos `title` y `text` - `author` será la persona que se ha autenticado (¡tú!) y `created_date` se definirá automáticamente cuando creemos un post (es decir en el código), ¿si? -Y eso es todo! Todo lo que necesitamos hacer ahora es usar el formulario en una *view* y mostrarla en una plantilla. +¡Y eso es todo! Todo lo que necesitamos hacer ahora es usar el formulario en una *view* y mostrarla en una plantilla. Una vez más vamos a crear: un enlace a la página, una dirección URL, una vista y una plantilla. ## Enlace a una página con el formulario -Es hora de abrir `blog/templates/blog/base.html`. Vamos a añadir un enlace en `div` llamado `encabezado de página`: +Es hora de abrir `blog/templates/blog/base.html`. Vamos a añadir un enlace en `div` llamado `page-header`: ```html - -``` + +``` Ten en cuenta que queremos llamar a nuestra nueva vista `post_new`. Después de agregar la línea, tu archivo html debería tener este aspecto: ```html -{% load staticfiles %} - - - Django Girls blog - - - - - - - - -
-
-
- {% block content %} - {% endblock %} + {% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
-
- - -``` + + +``` - -Después de guardar y actualizar la página `http://127.0.0.1:8000` obviamente podrá ver un error de `NoReverseMatch` familiar, ¿verdad? +Luego de guardar y actualizar la página `http://127.0.0.1:8000` obviamente verás un error `NoReverseMatch` familiar, ¿verdad? ## URL -Abrimos el `blog/urls.py` y añadimos una línea: +Abrimos `blog/urls.py` y añadimos una línea: ```python -url(r'^post/new/$', views.post_new, name='post_new'), -``` + url(r'^post/new/$', views.post_new, name='post_new'), +``` Y el código final tendrá este aspecto: ```python -from django.conf.urls import include, url -from . import views - -urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - url(r'^post/new/$', views.post_new, name='post_new'), -] -``` - + from django.conf.urls import url + from . import views + + urlpatterns = [ +     url(r'^$', views.post_list), +     url(r'^post/(?P[0-9]+)/$', views.post_detail), +     url(r'^post/new/$', views.post_new, name='post_new'), + ] +``` -Después de actualizar el sitio, veremos un `AttributeError`, puesto que no tenemos la vista `post_new` implementado. Vamos a añadir ahora. +Después de actualizar el sitio, veremos un `AttributeError`, puesto que no tenemos la vista `post_new` implementada. Vamos a añadirla ahora. -## vista post_new +## Vista post_new Es el momento de abrir el archivo `blog/views.py` y agregar las siguientes líneas al resto de las filas `from`: ```python -from .forms import PostForm -``` + from .forms import PostForm +``` y nuestra *vista*: @@ -122,217 +118,211 @@ y nuestra *vista*: def post_new(request): form = PostForm() return render(request, 'blog/post_edit.html', {'form': form}) -``` +``` -Para crear un nuevo formulario `Post`, tenemos que llamar a `PostForm()` y pasar a la plantilla. Volveremos a esta *vista*, pero por ahora, vamos a crear rápidamente una plantilla para el formulario. +Para crear un nuevo formulario `Post`, tenemos que llamar a `PostForm()` y pasarlo a la plantilla. Volveremos a esta *vista* pero, por ahora, vamos a crear rápidamente una plantilla para el formulario. ## Plantilla -Tenemos que crear un archivo `post_edit.html` en el directorio `blog/plantillas/blog`. Para hacer que un formulario funcione necesitamos varias cosas: +Tenemos que crear un archivo `post_edit.html` en el directorio `blog/templates/blog`. Para hacer que un formulario funcione necesitamos varias cosas: -* Tenemos que mostrar el formulario. Podemos hacerlo por ejemplo con un simple `{{ form.as_p }}`. -* la línea anterior tiene que estar dentro de una etiqueta de formulario HTML: `... ` -* Necesitamos un botón `Guardar`. Lo hacemos con un botón HTML: `` +* y finalmente justo después de la apertura de `` necesitamos agregar `{% raw %}{% csrf_token %}{% endraw %}`. ¡Esto es muy importante ya que hace que tus formularios sean seguros! Django se quejará si te olvidas de esta parte cuando intentes guardar el formulario. -![CSFR prohibida][1] +![CSFR Forbidden page][1] [1]: images/csrf2.png Bueno, vamos a ver cómo quedará el HTML en `post_edit.html`: ```html -{% extends 'blog/base.html' %} - -{% block content %} -

New post

-
{% csrf_token %} - {{ form.as_p }} - -
-{% endblock %} -``` - - -iEs hora de actualizar! ¡Si! El formulario se muestra! + {% extends 'blog/base.html' %} + + {% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+ {% endblock %} +``` + +¡Es hora de actualizar! ¡Si! ¡Tu formulario se muestra! ![Nuevo formulario][2] [2]: images/new_form2.png -Pero, ¡un momento! Si escribes algo en los campos `título` y `texto` y tratas de salvar-¿qué pasa? +Pero, ¡un momento! Si escribes algo en los campos `títle` y `text` y tratas de guardar los cambios - ¿qué pasará? -¡Nada! Una vez más estamos en la misma página y el texto se ha ido... no se añade ningún mensaje nuevo. Entonces, ¿qué ha ido mal? +¡Nada! Una vez más estamos en la misma página y el texto se ha ido... no se añade ningún post nuevo. Entonces, ¿qué ha ido mal? La respuesta es: nada. Tenemos que trabajar un poco más en nuestra *vista*. ## Guardar el formulario -Abre `blog/views.py` una vez más. De momento todo lo que tenemos en la vista `post_new` es: +Abre `blog/views.py` una vez más. Actualmente, lo que tenemos en la vista `post_new` es: ```python -def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) -``` + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Cuando enviamos el formulario, estamos en la misma vista, pero esta vez tenemos algunos datos más en la `request`, concretamente en `request.POST`. ¿Recuerdas que en el archivo HTML la definición de `
` tenía la variable `method = "POST"`? Todos los campos del formulario estan ahora en `request.POST`. No deberías renombrar la variable `POST` (el único nombre que también es válido para la variable `method` es `GET`, pero no tenemos tiempo para explicar cuál es la diferencia). +Cuando enviamos el formulario somos redirigidos a la misma vista, pero esta vez tenemos algunos datos adicionales en `request`, más específicamente en `request.POST` (el nombre no tiene nada que ver con un post del blog, se refiere a que estamos "publicando" -en inglés, posting- datos). ¿Recuerdas que en el archivo HTML la definición de `` tenía la variable `method="POST"`? Todos los campos del formulario estan ahora en `request.POST`. No deberías renombrar la variable `POST` (el único nombre que también es válido para la variable `method` es `GET`, pero no tenemos tiempo para explicar cuál es la diferencia). -En nuestra *vista* tenemos dos posibles situaciones a contemplar. Primera: cuando accedemos a la página por primera vez y queremos un formulario en blanco. Segundo: cuando volvemos a la *vista* con los datos del formulario que acabamos de escribir. Así que tenemos que añadir una condición (utilizaremos `if` para eso). +En nuestra *view* tenemos dos posibles situaciones a contemplar. Primero: cuando accedemos a la página por primera vez y queremos un formulario en blanco. Segundo: cuando volvemos a la *view* con los datos del formulario que acabamos de escribir. Así que tenemos que añadir una condición (utilizaremos `if` para eso). ```python -if request.method == "POST": - [...] -else: - form = PostForm() -``` - + if request.method == "POST": + [...] + else: + form = PostForm() +``` Es hora de llenar los puntos `[...]`. Si el `method` es `POST` queremos construir el `PostForm` con los datos del formulario, ¿no? Lo haremos con: ```python -form = PostForm(request.POST) -``` + form = PostForm(request.POST) +``` Fácil! Lo siguiente es verificar si el formulario es correcto (todos los campos necesarios están definidos y no hay valores incorrectos). Lo hacemos con `form.is_valid()`. -Comprobamos que el formulario es válido y si es así, lo podemos salvar. +Comprobamos que el formulario es válido y, si es así, ¡lo podemos salvar! ```python -if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() -``` - + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.save() +``` -Básicamente, tenemos que hacer dos cosas aquí: salvar el formulario con `form.save` y añadirle un autor (ya que no había ningún campo de `autor` en el `PostForm` y este campo es obligatorio). `cometer = False` significa que no queremos guardar el modelo `Post` todavía - queremos añadir el autor primero. La mayoría de las veces utilizarás `form.save()`, sin `commit = False`, pero en este caso, tenemos que hacerlo. `post.Save()` conservará los cambios (añadiendo a autor) y se creará una nueva entrada en el blog! +Básicamente, tenemos que hacer dos cosas aquí: guardamos el formulario con `form.save` y añadimos un autor (ya que no había ningún campo de `author` en el `PostForm` y este campo es obligatorio). `commit=False` significa que no queremos guardar el modelo `Post` todavía - queremos añadir el autor primero. La mayoría de las veces utilizarás `form.save()`, sin `commit=False`, pero en este caso, tenemos que hacerlo. `post.save()` conservará los cambios (añadiendo el autor) y se creará una nuevo post en el blog. -Por último, sería genial si podemos inmediatamente ir a la página `post_detail` de la entrada de blog que se acaba de crear, ¿no? Para hacerlo necesitamos una importación más: +Por último, sería genial si podemos inmediatamente ir a la página `post_detail` del nuevo post de blog, ¿no? Para hacerlo necesitamos importar algo más: ```python -from django.shortcuts import redirect -``` + from django.shortcuts import redirect +``` -Añádelo al principio del archivo. Y ahora podemos decir: ves a la página `post_detail` de la entrada recién creada. +Agrégalo al principio del archivo. Y ahora podemos decir: vé a la página `post_detail` del post recién creado. ```python -return redirect('blog.views.post_detail', pk=post.pk) -``` + return redirect('blog.views.post_detail', pk=post.pk) +``` -`blog.views.post_detail` es el nombre de la vista a la que queremos ir. ¿Recuerdas que esta *vista* requiere una variable `pk`? Para pasarlo a las vistas utilizamos `pk=post.pk`, donde `post` es la entrada recién creada! +`blog.views.post_detail` es el nombre de la vista a la que queremos ir. ¿Recuerdas que esta *view* requiere una variable `pk`? Para pasarlo a las vistas utilizamos `pk=post.pk`, donde `post` es el post recién creado. -Bien, hablamos mucho, pero probablemente queremos ver como es ahora la *vista*, verdad? +Bien, hablamos mucho, pero probablemente queremos ver como se ve ahora la *vista*, ¿verdad? ```python -def post_new(request): - if request.method == "POST": - form = PostForm(request.POST) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) -``` + def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Vamos a ver si funciona. Ves a la página `http://127.0.0.1:8000/post/new/`, añadir un `título` y un `texto`, guárdalo... ¡y voilá! Se añade la nueva entrada al blog y se nos redirige a la página de `post_detail`! +Vamos a ver si funciona. Ve a la página http://127.0.0.1:8000/post/new/, añade un `title` y un `text`, guardalo... ¡y voilà! Se añade el nuevo post al blog y se nos redirige a la página de `post_detail`. -Probablemente has visto que no hemos definido la fecha de publicación. Vamos a introducir un *botón publicar* en **Django girls Tutorial: extensiones**. +Probablemente has visto que no hemos definido la fecha de publicación. Vamos a introducir un *botón publicar* en **Django Girls Tutorial: Extensions**. -Eso es impresionante! +¡Eso es genial! ## Validación de formularios -Ahora, vamos a enseñarte cómo mola Django forms. Un blog debe tener `título` y `texto`. En nuestro modelo `Post` no dijimos (a diferencia de `published_date`) que estos campos son requeridos, así que Django, por defecto, espera ellos. +Ahora, vamos a enseñarte qué tan bueno es Django forms. Un post del blog debe tener los campos `title` y `text`. En nuestro modelo `Post` no dijimos (a diferencia de `published_date`) que estos campos son requeridos, así que Django, por defecto, espera que estén definidos. -Trata de guardar el formulario sin `title` y `text`. Adivina, qué pasará! +Trata de guardar el formulario sin `title` y `text`. ¡Adivina qué pasará! ![Validación de formularios][3] [3]: images/form_validation2.png -Django es cuidadoso de validar que todos los campos en el formulario estén correctos. ¿No es genial? +Django se encarga de validar que todos los campos en el formulario estén correctos. ¿No es genial? -> Como recientemente hemos utilizado la interfaz de administrador de Django, el sistema piensa que estamos logueados. Hay algunas situaciones que podrían llevarnos a quedar como no registrados (cerrando el navegador, reiniciando la base de datos etc.). Si estás recibiendo errores al crear un post que indican la falta de inicio de sesión de usuario, dirígete a la pagina de admin `http://127.0.0.1:8000/admin` e inicia sesión nuevamente. Esto resolverá el problema temporalmente. Hay un arreglo permanente en el capítulo **Tarea: ¡Añadir seguridad a tu sitio web!** después del tutorial principal. +> Como recientemente hemos utilizado la interfaz de administrador de Django, el sistema piensa que estamos conectadas. Hay algunas situaciones que podrían llevarnos a desconectarnos (cerrando el navegador, reiniciando la base de datos, etc.). Si estás recibiendo errores al crear un post que indican la falta de inicio de sesión de usuario, dirígete a la página de administración `http://127.0.0.1:8000/admin` e inicia sesión nuevamente. Esto resolverá el problema temporalmente. Hay un arreglo permanente esperándote en el capítulo **Tarea: ¡Añadir seguridad a tu sitio web!** después del tutorial principal. ![Error de inicio de sesión][4] [4]: images/post_create_error.png -## Editar formulario +## Editar el formulario -Ahora sabemos cómo agregar un nuevo formulario. Pero ¿qué pasa si queremos editar uno existente? Es muy similar a lo que hicimos anteriormente. Vamos a crear algunas cosas importantes rápidamente. (si no entiendes algo, pregúntalo a tu tutor o revisa lo capítulos anteriores, son temas que ya hemos cubierto). +Ahora sabemos cómo agregar un nuevo formulario. Pero, ¿qué pasa si queremos editar uno existente? Es muy similar a lo que acabamos de hacer. Vamos a crear algunas cosas importantes rápidamente (si no entiendes algo, pregúntale a tu tutor o revisa lo capítulos anteriores, son temas que ya hemos cubierto). Abre el archivo `blog/templates/blog/post_detail.html` y añade esta línea: -```html - -``` - +```python + +``` para que la plantilla quede: ```html -{% extends 'blog/base.html' %} - -{% block content %} -
- {% if post.published_date %} - {{ post.published_date }} - {% endif %} - -
-

{{ post.title }}

-

{{ post.text|linebreaks }}

-{% endblock %} -``` - + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} + {{ post.published_date }} + {% endif %} + +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+ {% endblock %} +``` En el archivo `blog/urls.py` añadimos esta línea: ```python -url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), -``` + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` Vamos a reusar la plantilla `blog/templates/blog/post_edit.html`, así que lo último que nos falta es una *view*. Abramos el archivo `blog/views.py` y añadamos al final esta línea: ```python -def post_edit(request, pk): - post = get_object_or_404(Post, pk=pk) - if request.method == "POST": - form = PostForm(request.POST, instance=post) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm(instance=post) - return render(request, 'blog/post_edit.html', {'form': form}) -``` + def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` Esto se ve casi exactamente igual a nuestra view `post_new`, ¿no? Pero no del todo. Primero: pasamos un parámetro extra `pk` de los urls. Luego: obtenemos el modelo `Post` que queremos editar con `get_object_or_404(Post, pk=pk)` y después, al crear el formulario pasamos este post como una `instancia` tanto al guardar el formulario: ```python -form = PostForm(request.POST, instance=post) -``` - + form = PostForm(request.POST, instance=post) +``` como al abrir un formulario con este post para editarlo: ```python -form = PostForm(instance=post) -``` - + form = PostForm(instance=post) +``` Ok, ¡vamos a probar si funciona! Dirígete a la página `post_detail`. Debe haber ahí un botón para editar en la esquina superior derecha: -![Botón Editar][5] +![Botón editar][5] [5]: images/edit_button2.png @@ -344,24 +334,35 @@ Al dar click ahí, debes ver el formulario con nuestro post del blog: ¡Siéntete libre de cambiar el título o el texto y guarda los cambios! -¡Felicitaciones.Tu aplicación está cada vez más completa! +¡Felicitaciones! ¡Tu aplicación está cada vez más completa! Si necesitas más información sobre los formularios de Django, debes leer la documentación: https://docs.djangoproject.com/en/1.8/topics/forms/ ## Una cosa más: ¡Tiempo de implementación! -Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: +Veamos si todo esto funciona en PythonAnywhere. ¡Tiempo de hacer otro despliegue! + +* Primero, haz un commit con tu nuevo código y súbelo a GitHub -```bash +``` $ git status -... -$ git add -A . +$ git add --all . $ git status -... $ git commit -m "Added views to create/edit blog post inside the site." -... -$ git push heroku master +$ git push +``` + +* Luego, en una [consola Bash de PythonAnywhere][7] + ``` +$ cd my-first-blog +$ git pull +[...] +``` + +* Finalmente, ve a la pestaña [Web][8] y haz click en **Reload**. + [7]: https://www.pythonanywhere.com/consoles/ + [8]: https://www.pythonanywhere.com/web_app_setup/ ¡Y eso debería ser todo! Felicidades :) diff --git a/es/django_installation/README.md b/es/django_installation/README.md index 5add1f3f0dc..51205bb952f 100755 --- a/es/django_installation/README.md +++ b/es/django_installation/README.md @@ -1,20 +1,20 @@ -# Instalacion de Django +# Instalación de Django -> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (http://django.carrots.pl/). +> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > -> Parte de este capítulo se basa en el [tutorial de django-marcador][1] bajo licencia de Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. +> Parte de este capítulo se basa en el [django-marcador tutorial][1] bajo licencia de Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. [1]: http://django-marcador.keimlink.de/ ## Entorno virtual -Antes de instalar Django, instalaremos una herramienta extremadamente útil que ayudará a mantener tu entorno de desarrollo ordenado en su computadora. Es posible omitir este paso, pero es muy recomendable no hacerlo, comenzar con la mejor configuración posible ayudara a evitar muchos problemas en el futuro! +Antes de instalar Django, instalaremos una herramienta extremadamente útil que ayudará a mantener tu entorno de desarrollo ordenado en su computadora. Es posible omitir este paso, pero es muy recomendable no hacerlo - ¡comenzar con la mejor configuración posible ayudar a evitar muchos problemas en el futuro! -Así que, vamos a crear un **entorno virtual** (también llamado un *virtualenv*). Aislará la configuración Python/Django en base de cada proyecto, lo que significa que cualquier cambio que realice en un sitio web no afectará a otros que también está desarrollando. Genial, no? +Así que, vamos a crear un **entorno virtual** (también llamado un *virtualenv*). Aislará la configuración Python/Django con base en cada proyecto, lo que significa que cualquier cambio que realices en un sitio web no afectará a otros que también estés desarrollando. Genial, ¿no? -Todo lo que necesita hacer es encontrar un directorio en el que desea crear el `virtualenv`; su directorio home, por ejemplo. En Windows puede parecer como `C:\Users\Name` (donde `nombre` es el nombre de tu login). +Todo lo que necesitas hacer es encontrar un directorio en el que desees crear el `virtualenv`; tu directorio home, por ejemplo. En Windows puede verse como `C:\Users\Name` (donde `nombre` es el nombre de tu usuario). -Para este tutorial usaremos un nuevo directorio `djangogirls` de tu directorio home: +Para este tutorial usaremos un nuevo directorio `djangogirls` en tu directorio home: mkdir djangogirls cd djangogirls @@ -22,7 +22,7 @@ Para este tutorial usaremos un nuevo directorio `djangogirls` de tu directorio h Haremos un virtualenv llamado `myvenv`. El comando general estará en el formato: - python -m venv myvenv + python3 -m venv myvenv ### Windows @@ -32,9 +32,9 @@ Para crear un nuevo `virtualenv`, debes abrir la consola (te lo indicamos unos c C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv -en donde `C:\Python34\python` es el directorio en donde instalaste Python previamente y `myvenv` es el nombre de tu `virtualenv`. Puedes usar cualquier otro nombre, pero mantén el uso de minúsculas y no incluyas espacios. También es una buena idea mantener el nombre corto. ¡Vas a referirte a él mucho! +en donde `C:\Python34\python` es el directorio en el que instalaste Python previamente y `myvenv` es el nombre de tu `virtualenv`. Puedes utilizar cualquier otro nombre, pero asegúrate de usar minúsculas y no dejar espacios, acentos o caracteres especiales. También es una buena idea mantener el nombre corto. ¡Vas a referirte a él mucho! -### Linux and OS X +### Linux y OS X Crear un `virtualenv` en Linux y OS X es tan simple como ejecutar `python3 -m venv myvenv`. Se verá así: @@ -43,12 +43,12 @@ Crear un `virtualenv` en Linux y OS X es tan simple como ejecutar `python3 -m ve `myvenv` es el nombre de tu `virtualenv`. Puedes usar cualquier otro nombre, pero mantén el uso de minúsculas y no incluyas espacios. También es una buena idea mantener el nombre corto. ¡Vas a referirte a él mucho! -> **NOTA:** Iniciar el entorno virtual en Ubuntu 14.04 de esta manera, actualmente produce el siguiente error: +> **Nota:** Actualmente, iniciar el entorno virtual en Ubuntu 14.04 de esta manera produce el siguiente error: > > Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 > > -> Para evitar esto, utilice el comando `virtualenv`. +> Para evitar esto, utiliza directamente el comando `virtualenv`. > > ~/djangogirls$ sudo apt-get install python-virtualenv > ~/djangogirls$ virtualenv --python=python3.4 myvenv @@ -70,12 +70,12 @@ en OS X y Linux. ¡Recuerda reemplazar `myvenv` con tu nombre de `virtualenv` que hayas elegido! -> **Nota:** a veces la `fuente` podría no estar disponible. En esos casos trata de hacerlo esto: +> **Nota:** a veces el comando `source` podría no estar disponible. En esos casos trata de hacerlo esto: > > ~/djangogirls$ . myvenv/bin/activate > -Sabrás que tienes `virtualenv` iniciado cuando veas que parece este mensaje en la consola: +Sabrás que tienes `virtualenv` iniciado cuando veas que aparece este mensaje en la consola: (myvenv) C:\Users\Name\djangogirls> @@ -93,7 +93,7 @@ Tenemos todas las dependencias importantes en su lugar. ¡Finalmente podemos ins ## Instalar Django -Ahora que tienes tu `virtualenv` iniciado, puedes instalar Django usando `pip`. En la consola, ejecuta `pip install django == 1.8` (fíjate que utilizamos un doble signo igual): `==`). +Ahora que tienes tu `virtualenv` iniciado, puedes instalar Django usando `pip`. En la consola, ejecuta `pip install django==1.8` (fíjate que utilizamos un doble signo igual: `==`). (myvenv) ~$ pip install django==1.8 Downloading/unpacking django==1.8 @@ -104,10 +104,10 @@ Ahora que tienes tu `virtualenv` iniciado, puedes instalar Django usando `pip`. En Windows -> Si se obtiene un error al llamar a pip en Windows, comprueba si la ruta a tu proyecto contiene espacios (es decir, `C:\Users\User Name\djangogirls`). Si es así, por favor considera moverla a otro lugar sin espacios (sugerencia: `C:\djangogirls`). Después de hacerlo ejecuta nuevamente el comando anterior. +> Si obtienes un error al ejecutar pip en Windows comprueba si la ruta de tu proyecto contiene espacios, acentos o caracteres especiales (por ejemplo, `C:\Users\User Name\djangogirls`). Si lo tiene, por favor considera moverla a otro lugar sin espacios, acentos o caracteres especiales (sugerencia: `C:\djangogirls`). Después de hacerlo ejecuta nuevamente el comando anterior. en Linux -> Si obtienes un error al correr pip en Ubuntu 12.04 ejecuta `python -m pip install- U - force-resintall pip` para arreglar la instalación de pip en el virtualenv. +> Si obtienes un error al correr pip en Ubuntu 12.04 ejecuta `python -m pip install -U --force-reinstall pip` para arreglar la instalación de pip en el virtualenv. -¡Eso es todo. Ahora estás listo (por fin) para crear una aplicación Django! Pero para hacer eso, necesitas un buen programa en el cual escribir código... +¡Eso es todo! ¡Ahora estás listo (por fin) para crear una aplicación Django! diff --git a/es/django_models/README.md b/es/django_models/README.md index b5426277f42..792ee596c23 100755 --- a/es/django_models/README.md +++ b/es/django_models/README.md @@ -1,6 +1,6 @@ # Modelos en Django -Lo que queremos crear ahora es algo que va a almacenar todas las entradas en nuestro blog. Pero para poder hacerlo tenemos que hablar un poco de acerca de algo llamado `objetos`. +Lo que queremos crear ahora es algo que va a almacenar todos los posts en nuestro blog. Pero para poder hacerlo tenemos que hablar un poco acerca de algo llamado `objetos`. ## Objetos @@ -8,85 +8,85 @@ Hay un concepto en el mundo de la programación llamado `programación orientada Entonces ¿Qué es un objeto? Es un conjunto de propiedades y acciones. Suena raro, pero te daremos un ejemplo. -Si queremos un modelar un gato crearemos un objeto `Gato` que tiene algunas propiedades, como son, `color`, `edad`, `estado de ánimo` (es decir, bueno, malo, sueño ;)), `dueño` (que es un objeto `persona` o tal vez, en el caso de que el gato sea callejero, esta propiedad estara vacía). +Si queremos modelar un gato crearemos un objeto `Gato` que tiene algunas propiedades, como son por ejemplo`color`, `edad`, `estado de ánimo` (es decir, bueno, malo, sueño ;)), `dueño` (que es un objeto `Persona` o, tal vez, en el caso de que el gato sea callejero, esta propiedad estará vacía). -Y luego el `Gato` tiene algunas acciones: `ronronear`, `rasguñar` o `alimentarse` (en la cual daremos el gato algunos `ComidaDeGato`, que podría ser un objeto independiente con propiedades, como por ejemplo, `sabor`). +Y luego el `Gato` tiene algunas acciones: `ronronear`, `rasguñar` o `alimentarse` (en la cual daremos al gato algunos `ComidaDeGato`, que podría ser un objeto independiente con propiedades, como por ejemplo, `sabor`). Gato --------- - color - edad - humor - dueño - ronronear() - rasguñar() - alimientarse(comida_de_gato) - + color + edad + humor + dueño + ronronear() + rasguñar() + alimentarse(comida_de_gato) + ComidaDeGato ---------- sabor + +Básicamente se trata de describir cosas reales en el código con propiedades (llamadas `propiedades del objeto`) y las acciones (llamadas `métodos`). -Básicamente se trata de describir cosas reales en el código con propiedades (llamadas `Propiedades del objeto`) y las acciones (llamadas `métodos`). - -y ahora ¿Cómo modelamos las entradas en el blog? Queremos construir un blog, ¿no? - -Tenemos primero que responder algunas preguntas: ¿Qué es una entrada de un blog? ¿Qué características debe tener? - -Bueno, seguro que nuestras entradas necesitan un texto con su contenido y un título, ¿Cierto? También sería bueno saber quién lo escribió, así que necesitamos un autor. Por último, queremos saber cuando fue creado y publicado dicha entrada. +Y ahora, ¿cómo modelamos los posts en el blog? Queremos construir un blog, ¿no? - Entrada - --------- +Tenemos primero que responder algunas preguntas: ¿Qué es un post de un blog? ¿Qué características debe tener? - título - texto - autor - fecha_creacion - fecha_publicacion +Bueno, seguro que nuestros posts necesitan un texto con su contenido y un título, ¿cierto? También sería bueno saber quién lo escribió, así que necesitamos un autor. Por último, queremos saber cuándo el post fue creado y publicado. + Post + -------- + title + text + author + created_date + published_date + ¿Qué tipo de cosas podría hacerse con una entrada del blog? Sería bueno tener algún `método` que publique la entrada, ¿no? Así que vamos a necesitar el método `publicar`. -Puesto que ya sabemos lo que queremos hacer, podemos empezar a crear nuestro Modelo en Django! +Puesto que ya sabemos lo que queremos lograr, ¡podemos empezar a moderlarlo en Django! ## Modelo en Django -Sabiendo que es un objeto, podemos crear un modelo en Django para nuestras entradas en el Blog. +Sabiendo qué es un objeto, podemos crear un modelo en Django para nuestros posts en el blog. -Un modelo en Django es un tipo especial de objeto, que se guarda en la `base de datos`. Una base de datos es un conjunto de datos. Allí es el lugar en el cual almacenarás la información sobre usuarios, entradas del blogs, etc. Utilizaremos una base de datos SQLite para almacenar nuestros datos. Este es el adaptador de base de datos predeterminada en Django -- será suficiente para nosotros por ahora. +Un modelo en Django es un tipo especial de objeto que se guarda en la `base de datos`. Una base de datos es una colección de datos. Allí es el lugar en el cual almacenarás la información sobre usuarios, posts del blog, etc. Utilizaremos una base de datos SQLite para almacenar nuestros datos. Este es el adaptador de base de datos predeterminada en Django -- será suficiente para nosotros por ahora. -Piensa en el modelo como una hoja de cálculo con columnas (campos) y filas (datos). +Piensa en el modelo en la base de datos como una hoja de cálculo con columnas (campos) y filas (datos). ### Creando una aplicación -Para mantener todo en orden, crearemos una aplicación separada dentro de nuestro proyecto. Es muy bueno tener todo organizado desde el principio. Para crear una aplicación necesitamos ejecutar el siguiente comando en la consola (dentro `djangogirls` donde está el archivo `manage.py`): +Para mantener todo en orden, crearemos una aplicación separada dentro de nuestro proyecto. Es muy bueno tener todo organizado desde el principio. Para crear una aplicación, necesitamos ejecutar el siguiente comando en la consola (dentro de la carpeta de `djangogirls` donde está el archivo `manage.py`): (myvenv) ~/djangogirls$ python manage.py startapp blog + - -Vas notar que se crea un nuevo directorio llamado `blog` y contiene una serie de archivos. Nuestros directorios y archivos en nuestro proyecto deberían parecerse a esto: +Vas a notar que se crea un nuevo directorio llamado `blog` y contiene una serie de archivos. Nuestros directorios y archivos en nuestro proyecto deberían parecerse a esto: djangogirls ├── mysite - | __init__.py - | settings.py - | urls.py - | wsgi.py + | __init__.py + | settings.py + | urls.py + | wsgi.py ├── manage.py └── blog - ├── migrations - | __init__.py - ├── __init__.py - ├── admin.py - ├── models.py - ├── tests.py - └── views.py - - -Después de crear una aplicación también necesitamos decirle a Django que debe utilizarla. Lo hacemos en el archivo `mysite/settings.py`. Tenemos que encontrar `INSTALLED_APPS` y añadir una línea que contiene `'blog',` justo por encima de `)`. El producto final debe tener este aspecto: - + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +Después de crear una aplicación también necesitamos decirle a Django que debe utilizarla. Lo hacemos en el archivo `mysite/settings.py`. Tenemos que encontrar `INSTALLED_APPS` y añadir una línea que contenga `'blog',` justo por encima de `)`. El producto final debe tener este aspecto: + +```python INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', @@ -96,17 +96,18 @@ Después de crear una aplicación también necesitamos decirle a Django que debe 'django.contrib.staticfiles', 'blog', ) +``` - -### Creando el Modelo post +### Creando el Modelo Post En el archivo `blog/models.py` definimos todos los objetos llamados `Models` - este es un lugar en el cual definiremos nuestro modelo post. Vamos abrir `blog/models.py`, quitamos todo y escribimos un código como este: +```python from django.db import models from django.utils import timezone - + class Post(models.Model): author = models.ForeignKey('auth.User') title = models.CharField(max_length=200) @@ -115,59 +116,59 @@ Vamos abrir `blog/models.py`, quitamos todo y escribimos un código como este: default=timezone.now) published_date = models.DateTimeField( blank=True, null=True) - + def publish(self): self.published_date = timezone.now() self.save() - + def __str__(self): return self.title +``` +> Vuelve a verificar que usaste dos guiones bajos (`_`) en cada lado del `str`. Estos se utilizan con frecuencia en Python y a veces también los llamamos "dunder" (diminutivo en inglés de "double-underscore"). -> Vuelva a verificar que usaste dos caracteres undescore (`_`) en cada lado del `str`. Los que se utilizan con frecuencia en Python y a veces también los llamamos "dunder" (diminutivo de "doble-subrayado"). - -Es aterrador, ¿cierto? Pero no te preocupes, vamos a explicar qué significan estas líneas! +Da un poco de miedo, ¿verdad? Pero no te preocupes, ¡vamos a explicar qué significan estas líneas! -Todas las líneas a partir `from` o de `import` son líneas para añadir algo de otros archivos. Así que en vez de copiar y pegar las mismas cosas en cada archivo, podemos incluir algunas partes con `from... import ...`. +Todas las líneas que comienzan con `from` o `import` son líneas para añadir algo de otros archivos. Así que en vez de copiar y pegar las mismas cosas en cada archivo, podemos incluir algunas partes con `from... import ...`. -`class Post(models.Model):` - esta linea define nuestro modelo (es un `objeto`). +`class Post(models.Model):` - esta línea define nuestro modelo (es un `objeto`). -* `class` Es una palabra clave que indica que estamos definiedo un objeto. -* `Post` Es el nombre de nuestro modelo, podemos darle un nombre diferente(pero debemos evitar espacios en blanco y caracteres especiales). Una clase siempre comienza con su primera letra en mayúscula. -* `models.Model` Significa que Post es un modelo de Django, así Django sabe que debe guardarlo en la base de datos. +* `class` es una palabra clave que indica que estamos definiendo un objeto. +* `Post` es el nombre de nuestro modelo. Podemos darle un nombre diferente (pero debemos evitar espacios en blanco y caracteres especiales). Una clase siempre comienza con su primera letra en mayúscula. +* `models.Model` significa que Post es un modelo de Django, así Django sabe que debe guardarlo en la base de datos. -Ahora definimos las propiedades que hablábamos: `title`, `text`, `created_date`, `published_date` y `author`. Para hacer eso tenemos que definir un tipo de campo (¿es texto? ¿Un número? ¿Una fecha? Una relación con otro objeto, es decir, un usuario?). +Ahora definimos las propiedades que hablábamos: `title`, `text`, `created_date`, `published_date` y `author`. Para hacer eso tenemos que definir un tipo de campo (¿es texto? ¿un número? ¿una fecha? ¿una relación con otro objeto - es decir, un usuario?). -* `models.CharField` - esto es como defines un texto con un numero limitado de caracteres. -* `modelos.TextField`-esto es para textos largos sin un límite. ¿Será ideal para un blog post contenido, verdad? -* `models.DateTimeField` - esta es la fecha y hora. -* `modelos.ForeignKey`-este es una relación a otro modelo. +* `models.CharField` - así es como defines un texto con un número limitado de caracteres. +* `models.TextField` - esto es para textos largos sin un límite. Será ideal para el contenido de un post, ¿verdad? +* `models.DateTimeField` - esto es fecha y hora. +* `modelos.ForeignKey` - este es un vínculo con otro modelo. -No vamos a explicar cada pedacito de código, ya que nos tomaría demasiado tiempo. Debes echar un vistazo a la documentación de Django. Si quieres saber más sobre los campos de Modelos y cómo definir cosas diferentes a las descritas anteriormente (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). +No vamos a explicar cada pedacito de código, ya que nos tomaría demasiado tiempo. Debes echar un vistazo a la documentación de Django si quieres saber más sobre los campos de los Modelos y cómo definir cosas diferentes a las descritas anteriormente (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). -¿Y qué sobre `def publish(self):`? Es exactamenteel método `publish` del que hablábamos antes. `def` significa que se trata de una función o método. `publish` es el nombre del método. Puedes cambiarlo, si quieres. La regla es que usamos minúscula y guiones bajos en lugar de espacios (es decir, si quieres tener un método que calcule el precio medio, este podría llamarse `calculate_average_price`). +¿Y qué sobre `def publish(self):`? Es exactamente nuestro método `publish` que mencionamos anteriormente. `def` significa que se trata de una función o método. `publish` es el nombre del método. Puedes cambiarlo, si quieres. La regla es que usamos minúsculas y guiones bajos en lugar de espacios (es decir, si quieres tener un método que calcule el precio medio, este podría llamarse `calculate_average_price`). Los métodos muy a menudo `devuelven` algo. Hay un ejemplo de esto en el método `__str__`. En este escenario, cuando llamamos a `__str__()` obtendremos un texto (**string**) con un título de Post. -Si algo todavía no está claro sobre modelos, ¡no dudes en preguntar a tu tutor! Sabemos que es muy complicado, sobre todo cuando estás entendiendo qué funciones y objetos son mientras sigues este documento. Con suerte, ¡todo tiene un poco más sentido para ti ahora! +Si algo todavía no está claro sobre modelos, ¡no dudes en preguntar a tu tutor! Sabemos que es muy complicado, sobre todo cuando estás entendiendo qué son funciones y objetos mientras sigues este documento. Con suerte, ¡todo tiene un poco más de sentido para ti ahora! ### Crear tablas para los modelos en tu base de datos -El último paso es añadir nuestro nuevo modelo a nuestra base de datos. Primero tenemos que hacer Django sepa que tenemos algunos cambios en nuestro modelo (acabamos de crearlo), escribe `python manage.py makemigrations blog`. Se verá así: +El último paso es añadir nuestro nuevo modelo a nuestra base de datos. Primero tenemos que hacer que Django sepa que tenemos algunos cambios en nuestro modelo (acabamos de crearlo), escribe `python manage.py makemigrations blog`. Se verá así: (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': 0001_initial.py: - Create model Post + - -Django nos prepara un archivo de migración que tenemos que aplicar ahora a nuestra base de datos, escribe `python manage.py migrate blog`, el resultado debe ser: +Django preparará un archivo de migración que tenemos que aplicar ahora a nuestra base de datos escribiendo `python manage.py migrate blog`. El resultado debe ser: (myvenv) ~/djangogirls$ python manage.py migrate blog Operations to perform: Apply all migrations: blog Running migrations: Applying blog.0001_initial... OK + - -¡Hurra! Nuestro modelo de Post está ahora en nuestra base de datos, sería bueno verlo, ¿no? Dirígete al siguiente capítulo para ver cómo luce tu Post! +¡Hurra! Nuestro modelo de Post está ahora en nuestra base de datos. Sería bueno verlo, ¿no? ¡Dirígete al siguiente capítulo para ver cómo luce tu Post! diff --git a/es/django_orm/README.md b/es/django_orm/README.md index b853891a757..c5890ec8f1f 100755 --- a/es/django_orm/README.md +++ b/es/django_orm/README.md @@ -4,7 +4,7 @@ En este capítulo aprenderás cómo Django se conecta a la base de datos y almac ## ¿Qué es un QuerySet? -Un QuerySet es, en esencia, una lista de objetos de un modelo determinado. Un QuerySet te permite leer los datos de base de datos, filtrarlos y ordenarlos. +Un QuerySet es, en esencia, una lista de objetos de un modelo determinado. Un QuerySet te permite leer los datos de una base de datos, filtrarlos y ordenarlos. Es más fácil de aprender con ejemplos. Vamos a intentarlo, ¿de acuerdo? @@ -13,146 +13,134 @@ Es más fácil de aprender con ejemplos. Vamos a intentarlo, ¿de acuerdo? Abre la consola y escribe este comando: (myvenv) ~/djangogirls$ python manage.py shell - + El resultado debería ser: (InteractiveConsole) >>> - + Ahora estás en la consola interactiva de Django. Es como la consola de Python, pero con un toque de magia Django :). Puedes utilizar todos los comandos Python aquí también, por supuesto. ### Ver todos los objetos -Vamos a mostrar todos nuestros objetos Posts primero. Puedes hacerlo con el siguiente comando: +Vamos a mostrar todos nuestros posts primero. Puedes hacerlo con el siguiente comando: >>> Post.objects.all() Traceback (most recent call last): File "", line 1, in NameError: name 'Post' is not defined + - -¡Uy! Apareció un error. Nos dice que no hay ningún objeto Post. Esto es correcto, nos olvidamos de importarlo primero! +¡Uy! Apareció un error. Nos dice que no hay ningún objeto Post. Esto es correcto, ¡nos olvidamos de importarlo primero! >>> from blog.models import Post + - -Esto es simple: importamos el modelo `Post` de `blog.models`. Vamos a intentar mostrar todos los Posts nuevamente: +Esto es simple: importamos el modelo `Post` de `blog.models`. Vamos a intentar mostrar todos los posts nuevamente: >>> Post.objects.all() - [] - + [, ] + -Es una lista vacía. Esto es correcto, ¿verdad?¡Todavía no hemos añadido ningún Post! Vamos a arreglarlo. +Esta es una lista de las posts creadas anteriormente. Hemos creado estos posts usando la interfaz del administrador de Django. Sin embargo, ahora queremos crear nuevos posts usando Python, ¿cómo lo hacemos? ### Crear objetos -Esta es la forma de crear un objeto Post en la base de datos: +Esta es la forma de crear un nuevo objeto Post en la base de datos: >>> Post.objects.create(author=me, title='Sample title', text='Test') - + Pero hay un ingrediente faltante: `me`. Necesitamos pasar una instancia del modelo `User` como autor. ¿Cómo hacemos eso? Primero importemos el modelo User: >>> from django.contrib.auth.models import User - + ¿Qué usuarios tenemos en nuestra base de datos? Veamos: - >>> User.objects.all() - [] - - -¡Ninguno! Creemos un usuario: - - >>> User.objects.create(username='ola') - - - -Veamos nuevamente qué usuarios tenemos: - >>> User.objects.all() [] + - -¡Genial! Ahora usemos una instancia del usuario: +Este es el super usuario que creamos anteriormente, Vamos a obtener una instancia de ese usuario ahora: me = User.objects.get(username='ola') + +Como puedes ver, hicimos un `get` de un `User` con el `username` que sea igual a 'ola'. ¡Genial! Acuérdate de poner tu nombre de usuario para obtener tu usuario. -Como puedes ver, ahora `get` un `User` con un `username` que es igual a 'ola'. Limpio! Por supuesto, tienes que ajustarlo a tu nombre de usuario. - -Ahora por fin podemos crear nuestro primer post: - - >>> Post.objects.create(author = me, title = 'Titulo simple', text = 'Test') +Ahora finalmente podemos crear nuestro primer post: + >>> Post.objects.create(author=me, title='Sample title', text='Test') + -¡Hurra! ¿Quieres comprobar si ha funcionado? +¡Hurra! ¿Quieres probar si funcionó? >>> Post.objects.all() - [] - + [, , ] + ### Agrega más posts -Ahora puedes divertirte un poco y añadir más posts para ver cómo funciona. Añade 2 - 3 más y avanzar a la siguiente parte. +Ahora puedes divertirte un poco y añadir más posts para ver cómo funciona. Añade 2 ó 3 más y avanza a la siguiente parte. -### Filtrar Objetos +### Filtrar objetos -En gran parte los QuerySets tienen la habilidad de filtrar. Digamos que queremos encontrar todos los mensajes que son escritos por el usuario ola. Utilizaremos el `filter` en lugar de `all` en `Post.objects.all()`. Entre paréntesis indicará qué condición(es) debe coincidir por una entrada de blog en nuestro queryset. En nuestra situación es `author` que es igual a `me`. La manera de escribirlo en Django es: `author = me`. Ahora nuestro código tiene este aspecto: +Una parte importante de los QuerySets es la habilidad para filtrarlos. Digamos que queremos encontrar todos los posts cuyo autor es el User ola. Usaremos `filter` en vez de `all` en `Post.objects.all()`. En los paréntesis estableceremos qué condición o conduciones deben cumplirse por un post del blog para terminar en nuestro queryset. En nuestro caso sería `author` es igual a `me`. La forma de escribirlo en Django es: `author=me`. Ahora nuestro bloque de código se ve como esto: >>> Post.objects.filter(author=me) [, , , ] + - -¿O tal vez queremos ver todos los mensajes que contienen una palabra 'título' en el campo `title`? +¿O tal vez querramos ver todos los posts que contengan la palabra 'title' en el campo `title`? >>> Post.objects.filter(title__contains='title') [, ] + +> **Nota** Hay dos guiones bajos (`_`) entre `title` y `contains`. Django ORM utiliza esta sintaxis para separar los nombres de los campos ("title") y operaciones o filtros ("contains"). Si sólo utilizas un guión bajo, obtendrás un error como "FieldError: Cannot resolve keyword title_contains". -> **Nota** Hay dos caracteres de subrayado (`_`) entre el `title` y `contains`. Django ORM utiliza esta sintaxis para separar los nombres de campo ("title") y operaciones o filtros ("contains"). Si sólo utilizas un carácter de subrayado, obtendrás un error como "FieldError: Cannot resolve keyword title_contains". +También puedes obtener una lista de todos los posts publicados. Lo hacemos filtrando los posts que tienen el campo `published_date` en el pasado: -También puedes obtener una lista de todos los mensajes publicados. Lo hacemos filtrando todos los post que tienen `published_date`: - - >>> Post.objects.filter(published_date__isnull=False) + >>> from django.utils import timezone + >>> Post.objects.filter(published_date__lte=timezone.now()) [] - -Lamentablemente, ninguno de nuestros mensajes son publicado todavía. Podemos cambiar eso. Primero obtener una instancia de un post que queremos publicar: +Desafortunadamente, ninguno de nuestros posts han sido publicados todavía. ¡Vamos a cambiar esto! Primero obtén una instancia de un post que querramos publicar: >>> post = Post.objects.get(id=1) + - -Y luego publicarlo con nuestro método de `publish`! +¡Luego utiliza el método `publish` para publicarlo! >>> post.publish() + +Ahora intenta obtener la lista de posts publicados nuevamente (presiona la tecla con la flecha hacia arriba 3 veces y presiona Enter): -Ahora intenta obtener lista de mensajes publicados otra vez (presiona 3 veces el botón de la flecha hacia arriba y pulse `enter`): - - >>> Post.objects.filter(published_date__isnull=False) + >>> Post.objects.filter(published_date__lte=timezone.now()) [] + +### Ordenando objetos -### Ordenando Objetos - -Los QuerySets también permite ordenar la lista de objetos. Tratemos de pedirlos por `created_date` : +Los QuerySets también te permiten ordenar la lista de objetos. Intentemos ordenarlos por el campo `created_date`: >>> Post.objects.order_by('created_date') [, , , ] + - -También podemos invertir el orden agregando `–` al principio: +También podemos invertir el ordenamiento agregando `-` al principio: >>> Post.objects.order_by('-created_date') [, , , ] + - -¡Genial! Ahora estás listo para la siguiente parte! Para cerrar el shell, escribe esto: +¡Genial! ¡Ahora estás lista para la siguiente parte! Para cerrar la consola, tipea: >>> exit() $ diff --git a/es/django_start_project/README.md b/es/django_start_project/README.md index a63aaf0d9bd..0034c086129 100755 --- a/es/django_start_project/README.md +++ b/es/django_start_project/README.md @@ -1,34 +1,33 @@ -# Tu primer proyecto en Django! +# ¡Tu primer proyecto en Django! -> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (http://django.carrots.pl/). +> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > > Parte de este capítulo se basa en el [django-marcador tutorial][1] bajo licencia de Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. [1]: http://django-marcador.keimlink.de/ -Vamos a crear un simple blog! +¡Vamos a crear un simple blog! -El primer paso para crearlo es para iniciar un nuevo proyecto en Django. Básicamente, esto significa que podrás correr algunos scripts proporcionados por Django que creará el esqueleto de un proyecto para nosotros: un montón de directorios y archivos que vamos a utilizar más adelante. +El primer paso para crearlo es iniciar un nuevo proyecto en Django. Básicamente, esto significa que podrás correr algunos scripts proporcionados por Django que crearán el esqueleto de un proyecto para nosotros: un montón de directorios y archivos que vamos a utilizar más adelante. Los nombres de algunos archivos y directorios son muy importantes para Django. No deberías renombrar los archivos que estamos a punto de crear. Moverlos a un lugar diferente tampoco es una buena idea. Django tiene que mantener una cierta estructura para ser capaz de encontrar cosas importantes. -En la consola debe ejecutar (Recuerde de no escribir `(myvenv) ~/djangogirls$`, OK?): - -> Recuerde correr to en el entorno virtual. Si no ves un prefijo `(myvenv)` en tu consola necesitas activar tu virtualenv. Explicamos cómo hacer eso en el capítulo de **instalación de Django** en el capitulo **Trabajando con virtualenv**. +> Recuerda correr todo en el virtualenv. Si no ves un prefijo `(myvenv)` en tu consola necesitas activar tu virtualenv. Explicamos cómo hacer eso en el capítulo de **Instalación de Django** en la sección **Trabajando con virtualenv**. Puedes hacerlo escribiendo el siguiente comando: `myvenv\Scripts\activate` en Windows o `source myvenv/bin/activate` en Mac OS / Linux. +> +> **Nota** Verifica dos veces que hayas incluido el punto (`.`) al final del comando, es importante porque le dice al script que instale Django en el directorio actual. -Ejecutar en Windows: +En la consola debes ejecutar (recuerda no escribir `(myvenv) ~/djangogirls$`, ¿ok?): - (myvenv) ~/djangogirls$ python myvenv\Scripts\django-admin.py startproject mysite . + (myvenv) ~/djangogirls$ django-admin startproject mysite . -o en Linux o Mac OS: +En Windows: - (myvenv) ~/djangogirls$ django-admin startproject mysite . + (myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . +> **Nota** Verifica dos veces que hayas incluido el punto (`.`) al final del comando, es importante porque le dice al script que instale Django en el directorio actual. -> **Nota** Verifica que incluiste el punto (`.`) al final del comando, es importante. - -`django-admin` es un script que creará los archivos y directorios para ti. Ahora debes tener un directorio de la estructura que se parece a esto: +`django-admin.py` es un script que creará los archivos y directorios para ti. Ahora deberías tener una estructura de directorios parecida a esto: djangogirls ├───manage.py @@ -39,41 +38,53 @@ o en Linux o Mac OS: __init__.py -`manage.py` es un script que ayuda con la administración del sitio. Con ello podremos iniciar un servidor web en nuestro ordenador sin necesidad de instalar nada, entre otras cosas. +`manage.py` es un script que ayuda con la administración del sitio. Con ello podremos iniciar un servidor web en nuestro ordenador sin necesidad de instalar nada más, entre otras cosas. -El archivo `settings.py` contiene la configuración de tu sitio Web. +El archivo `settings.py` contiene la configuración de tu sitio web. -¿Recuerdas cuando hablamos de un cartero que debía comprobar donde entregar una carta? `URLs.py` contiene una lista de los patrones utilizados por `urlresolver`. +¿Recuerdas cuando hablamos de un cartero que debía comprobar donde entregar una carta? El archivo `urls.py` contiene una lista de los patrones utilizados por `urlresolver`. -Ignoremos los otros archivos por ahora - no los cambiaremos. Lo único que debes recordar es no borrarlos por accidente! +Ignoremos los otros archivos por ahora - no los cambiaremos. ¡Lo único que debes recordar es no borrarlos por accidente! ## Cambiando la configuración Vamos a hacer algunos cambios en `mysite/settings.py`. Abre el archivo usando el editor de código que has instalado anteriormente. -Sería bueno tener la hora correcta en nuestra página web. Vaya a http://en.wikipedia.org/wiki/List_of_tz_database_time_zones y copia tu zona horaria correspondiente (TZ). (eg. `Europe/Berlin`) +Sería bueno tener el horario correcto en nuestro sitio web. Ve a la [lista de husos horarios de Wikipedia][2] y copia tu zona horaria (TZ). (por ejemplo, `Europe/Berlin` ) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones -Encuentra las líneas que contienen `USE_TZ` y `TIME_ZONE` y modificalas para parecerse a esto, sustituyendo `Europe/Berlin` con tu zona horaria correspondiente: +En settings.py, encuentra la línea que contiene `TIME_ZONE` y modifícala para elegir tu propia zona horaria: - USE_TZ = False +``` python TIME_ZONE = 'Europe/Berlin' - +``` + +Modificando "Europe/Berlin" como corresponda + +También necesitaremos agregar una ruta para los archivos estáticos (aprenderemos todo sobre los archivos estáticos y CSS más tarde en este tutorial). Ve hacia abajo hasta el *final* del archivo, y justo por debajo de la entrada `STATIC_URL`, agrega una nueva llamada `STATIC_ROOT`: + +``` python + STATIC_URL = '/static/' + STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` ## Configurar una base de datos -Hay un montón de software de base de datos diferente que puede almacenar datos para tu sitio. Utilizaremos uno por defecto, `sqlite3`. +Hay una gran variedad de opciones de bases de datos para almacenar los datos de tu sitio. Utilizaremos el que viene por defecto, `sqlite3`. -Este ya está configurado en esta parte del archivo `mysite/settings.py`: +Esto ya está configurado en esta parte de tu archivo `mysite/settings.py`: +``` python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } - +``` -Para crear una base de datos para nuestro blog, hagamos lo siguiente en la consola: `python manage.py migrate` (tenemos que estar en el directorio `djangogirls` que contiene el archivo `manage.py`). Si todo va bien, deberías ver algo como esto: +Para crear una base de datos para nuestro blog, ejecutemos lo siguiente en la consola: `python manage.py migrate` (necesitamos estar en el directorio de `djangogirls` que contiene el archivo `manage.py`). Si eso va bien, deberías ver algo así: (myvenv) ~/djangogirls$ python manage.py migrate Operations to perform: @@ -85,24 +96,24 @@ Para crear una base de datos para nuestro blog, hagamos lo siguiente en la conso Applying sessions.0001_initial... OK -Y terminamos! Tiempo para iniciar el servidor web y ver si está funcionando nuestro sitio web! +¡Y listo! ¡Es hora de iniciar el servidor web y ver si nuestro sitio web está funcionando! -Tienes que estar en el directorio que contiene el archivo `manage.py` (el directorio `djangogirls`). En la consola, podemos empezar el servidor web mediante la ejecución de `python manage.py runserver`: +Debes estar en el directorio que contiene el archivo `manage.py` (en la carpeta `djangogirls`). En la consola, podemos iniciar el servidor web ejecutando `python manage.py runserver`: (myvenv) ~/djangogirls$ python manage.py runserver -Ahora todo lo que necesitas hacer es verificar que tu sitio web esté ejecutándose - abre tu navegador (Firefox, Chrome, Safari, Internet Explorer o lo que utilices) e introduce la dirección: +Ahora todo lo que debes hacer es verificar que tu sitio esté corriendo - abre tu navegador (Firefox, Chrome, Safari, Internet Explorer o el que utilices) e ingresa la dirección: http://127.0.0.1:8000/ -El servidor web se encargará de su terminal de comando hasta detenerlo: para escribir más comandos abre una nueva ventana de terminal (y no te olvides de activar tu virtualenv en él también), o detener el servidor web y presionar CTRL + C - (en Windows, tendrás que presione Ctrl+Inter). +El servidor web se apropiará de tu consola hasta que lo termines manualmente: para tipear más comandos o abres una nueva terminal (y no te olvides de activar tu virtualenv allí también), o frena el servidor web yendo a la consola en la que está corriendo y presionando Ctrl+C - las teclas Control y C juntas (en Windows, deberás presionar Ctrl + Break). -¡Felicidades! Has creado tu primer sitio web y ejecutado un servidor web. ¿No es genial? +¡Felicitaciones! ¡Has creado tu primer sitio web y lo has ejecutado usando un servidor web! ¿No es genial? -![¡Funcionó!][2] +![¡Funcionó!][3] - [2]: images/it_worked2.png + [3]: images/it_worked2.png -¿Listo para el siguiente paso? Es hora de crear algo de contenido! \ No newline at end of file +¿Lista para el próximo paso? ¡Es momento de crear algo de contenido! diff --git a/es/django_templates/README.md b/es/django_templates/README.md index 99afe5b5767..d39a3bcdf87 100755 --- a/es/django_templates/README.md +++ b/es/django_templates/README.md @@ -1,24 +1,24 @@ # Plantillas de Django -Es hora de mostrar algunos datos! Django nos da algo de ayuda, construyendo **template tags** para ello. +¡Es hora de mostrar algunos datos! Django nos provee las útiles **template tags** para ello. -## ¿Qué son las etiquetas de plantilla? +## ¿Qué son las template tags? -Verás en HTML, no puedes realmente poner código Python, porque los navegadores no lo entienden. Ellos sólo saben HTML. Sabemos que HTML es algo estático, mientras que Python es mucho más dinámico. +Verás, en HTML no puedes realmente poner código Python, porque los navegadores no lo entienden. Ellos sólo saben HTML. Sabemos que HTML es algo estático, mientras que Python es mucho más dinámico. -**Etiquetas de plantilla Django** nos permiten transferir Python-como cosas en HTML, así que usted puede construir sitios web dinámicos más rápido y fácil. ¡Huy! +**Django template tags** nos permiten transferir cosas de Python como cosas en HTML, así que tu puedes construir sitios web dinámicos más rápido y fácil. -## Plantillas de listas de Post +## Mostrar la plantilla post list -En el capítulo anteriordimos a nuestra plantilla una lista de posts en la variable `posts`. Ahora lo mostraremos en HTML. +En el capítulo anterior dimos a nuestra plantilla una lista de posts en la variable `posts`. Ahora lo mostraremos en HTML. -Para imprimir una variable en la plantilla de Django, utilizamos llaves dobles con el nombre de la variable dentro, así: +Para imprimir una variable en una plantilla de Django, utilizamos llaves dobles con el nombre de la variable dentro, así: -```html -{{ posts }} -``` +``` html + {{ posts }} +``` -Prueba esto en tu plantilla `blog/templates/blog/post_list.html` (reemplaza todo entre la segunda etiqueta `
` con `{{ posts }}`), guarda el archivo y actualiza la página para ver el resultado: +Prueba esto en tu plantilla `blog/templates/blog/post_list.html` (reemplaza el segundo y el tercer par de etiquetas `
` con la línea `{{ posts }}`), guarda el archivo y actualiza la página para ver los resultados: ![Figura 13.1][1] @@ -26,70 +26,81 @@ Prueba esto en tu plantilla `blog/templates/blog/post_list.html` (reemplaza todo Como puedes ver, todo lo que obtenemos es esto: - [, ] - + [, ] + -Esto significa que Django lo entiende como una lista de objetos. ¿Recuerdas de **Introducción a Python,** ¿cómo podemos mostrar listas? Sí, con el ciclo for! En una plantilla de Django, los haces de esta manera: - -```html -{% for post in posts %} {{ post }}{% endfor %} -``` +Esto significa que Django lo entiende como una lista de objetos. ¿Recuerdas de **Introducción a Python** cómo podemos mostrar listas? Sí, ¡con los ciclos for! En una plantilla de Django, lo haces de esta manera: +``` html + {% for post in posts %} + {{ post }} + {% endfor %} +``` -Pruebe esto en tu plantilla. +Prueba esto en tu plantilla. ![Figura 13.2][2] [2]: images/step2.png -¡Funciona! Pero queremos que se muestre como los posts estáticos que creamos anteriormente en el capítulo de **Introducción a HTML**. Usted puede mezclar HTML y etiquetas de plantilla. Nuestro `body` se verá así: +¡Funciona! Pero queremos que se muestren como los posts estáticos que creamos anteriormente en el capítulo de **Introducción a HTML**. Puedes mezclar HTML y template tags. Nuestro `body` se verá así: -```html - -{% for post in posts %} +``` html
-

publicado: {{ post.published_date }}

-

- {{ post.title }} -

-

{{ post.text|linebreaks }}

+

Django Girls Blog

-{% endfor %} -``` - - -Todo lo que pones entre `{% for %}` y `{% endfor %}` se repetirá para cada objeto en la lista. Actualizar la página: + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +Todo lo que pones entre `{% for %}` y `{% endfor %}` se repetirá para cada objeto en la lista. Actualiza tu página: ![Figura 13.3][3] [3]: images/step3.png -¿Has notado que utilizamos una notación diferente esta vez `{{ post.title }}` o `{{ post.text }}`? Estamos accediendo a datos en cada uno de los campos definidos en nuestro modelo `Post`. También el `|linebreaks` es un filtro para convertir saltos de línea en los párrafos. +¿Has notado que utilizamos una notación diferente esta vez `{{ post.title }}` o `{{ post.text }}`? Estamos accediendo a datos en cada uno de los campos definidos en nuestro modelo `Post`. También el `|linebreaksbr` está dirigiendo el texto de los posts a través de un filtro para convertir saltos de línea en párrafos. ## Una cosa más -Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: +Sería bueno ver si tu sitio web seguirá funcionando en la Internet pública, ¿verdad? Intentemos desplegándola en PythonAnywhere nuevamente. Aquí te dejamos un ayuda memoria... -```bash +* Primero, sube tu código a GitHub + +``` $ git status -... -$ git add -A . +[...] +$ git add --all . $ git status -... -$ git commit -m "Used Django templates instead of static HTML." -... -$ git push heroku master +[...] +$ git commit -m "Modified templates to display posts from database." +[...] +$ git push ``` +* Luego, identifícate en [PythonAnywhere][4] y ve a tu **consola Bash** (o empieza una nueva), y ejecuta: + +``` +$ cd my-first-blog +$ git pull +[...] +``` + +* Finalmente, ve a la [pestaña Web][5] y presiona **Reload** en tu aplicación web. ¡Tu actualización debería poder verse! + + [4]: https://www.pythonanywhere.com/consoles/ + [5]: https://www.pythonanywhere.com/web_app_setup/ -¡Felicidades! Ahora seguir adelante y trata de agregar un nuevo post en tu administración de Django (recuerda añadir published_date!), luego actualizar tu página para ver si aparece el nuevo post. +¡Felicidades! Ahora sigue adelante, trata de agregar un nuevo post usando el panel de administrador de Django (¡recuerda añadir published_date!) y luego actualiza tu página para ver si aparece tu nuevo post. -¿Funciona bien? Estamos orgullosos! Regálate algo dulce, te lo has ganado :) +¿Funciona como un encanto? ¡Estamos orgullosos! Aléjate de tu computadora por un rato, te has ganado un descanso. :) -![Figura 13.4][4] +![Figura 13.4][6] - [4]: images/donut.png + [6]: images/donut.png diff --git a/es/django_urls/README.md b/es/django_urls/README.md index 80d694567d2..3ced93e3a42 100755 --- a/es/django_urls/README.md +++ b/es/django_urls/README.md @@ -1,100 +1,123 @@ # Django urls -Vamos a construir nuestra primera página web - una página para tu blog! Pero primero, vamos a aprender un poco sobre Django urls. +Vamos a construir nuestra primera página web -- ¡una página de inicio para tu blog! Pero primero, vamos a aprender un poco sobre Django urls. ## ¿Qué es una URL? -Una URL es simplemente una dirección web, puedes ver una URL cada vez que visitas cualquier sitio web - es visible en la barra de direcciones de tu navegador (¡Sí! `127.0.0.1:8000` es una URL. Y http://djangogirls.com es también una dirección URL): +Una URL es simplemente una dirección web, puedes ver una URL cada vez que visitas cualquier sitio web - es visible en la barra de direcciones de tu navegador (¡Sí! `127.0.0.1:8000` es una URL. Y http://djangogirls.org es también una URL): ![URL][1] [1]: images/url.png -Cada página en la Internet necesita su propia dirección URL. De esta manera su aplicación sabe lo que debe mostrar a un usuario que abre una dirección URL. En Django se usa algo llamado `URLconf` (configuración de URL), que es un conjunto de patrones que Django intentará hacer coincidir con la dirección URL recibida para encontrar la vista correcta. +Cada página en Internet necesita su propia URL. De esta manera tu aplicación sabe lo que debe mostrar a un usuario que abre una URL. En Django se usa algo llamado `URLconf` (configuración de URL), un conjunto de patrones que Django intentará hacer coincidir con la dirección URL recibida para encontrar la vista correcta. ## ¿Cómo funcionan las URLs en Django? -Vamos a abrir el archivo `mysite/urls.py` y ver lo que aparece: +Vamos a abrir el archivo `mysite/urls.py` y ver cómo es: +``` python from django.conf.urls import include, url from django.contrib import admin - + urlpatterns = [ # Examples: # url(r'^$', 'mysite.views.home', name='home'), # url(r'^blog/', include('blog.urls')), - + url(r'^admin/', include(admin.site.urls)), ] - +``` Como puedes ver, Django ya puso algo aquí para nosotros. -Las líneas que comienzan con `#` son comentarios - significa que esas líneas no serán ejecutadas por Python. Muy útil, verdad? +Las líneas que comienzan con `#` son comentarios - significa que esas líneas no serán ejecutadas por Python. Muy útil, ¿verdad? Ya está aquí la URL de admin, que visitaste en el capítulo anterior: - url(r'^admin/', include(admin.site.urls)), - +``` python + url(r'^admin/', include(admin.site.urls)), +``` -Esto significa que para cada URL que empieza con `admin /` Django encontrará un *view*. En este caso vamos a incluir muchas URLs a admin para que eso es mejor empacar todo en este pequeño archivo - es más legible y limpio. +Esto significa que para cada URL que empieza con `admin/` Django encontrará su correspondiente *view*. En este caso estamos incluyendo en una sola línea muchas URLs de admin, así no está todo comprimido en este pequeño archivo - es más limpio y legible. ## Regex -¿Te preguntas cómo Django coincide con las direcciones URL a las vistas? Bueno, esta parte es difícil. Django utiliza `regex`--expresiones regulares. Regex tiene muchos (un montón!) de normas que forman un patrón de búsqueda. No es tan fácil de entender así que no te preocupes hoy y sin duda los conocerás y utilizaras en el futuro. Hoy vamos a utilizar sólo los que necesitamos. +¿Te preguntas cómo Django coincide las direcciones URL con las vistas? Bueno, esta parte es difícil. Django utiliza `regex` -- expresiones regulares. Regex tiene muchas (¡un montón!) de normas que forman un patrón de búsqueda. Dado que las expresiones regulares son un tema avanzado, no entraremos en detalles sobre su funcionamiento. + +Si te interesa entender cómo creamos esos patrones, aquí hay un ejemplo del proceso - solamente necesitaremos un subconjunto de reglas limitado para expresar el patrón que estamos buscando: + + ^ denota el principio del texto + $ denota el final del texto + \d representa un dígito + + indica que el ítem anterior debería ser repetido por lo menos una vez + () para encerrar una parte del patrón + -Aquí hay un simple ejemplo para entender esta frase: imagina que tienes un sitio web con la dirección: `http://www.mysite.com/post/12345/`, donde `12345` es el número de tu post. Escribir vistas separadas para todos los números de post sería muy molesto. Django facilita permitiéndole escribir `http://www.mysite.com/post//`. Django se encargará del resto! +Cualquier otra cosa en la definición del URL será tomada literalmente. -## Tu primer url Django! +Ahora imagina que tienes un sitio web con una dirección como esta: `http://www.mysite.com/post/12345/`, donde `12345` es el número de post. -Es hora de crear nuestro primer URL! Queremos http://127.0.0.1:8000/ para ser una presentación de nuestro blog y mostrar una lista de posts. +Escribir vistas separadas para todos los números de post sería realmente molesto. Con las expresiones regulares podemos crear un patrón que coincidirá la URL y extraerá el número para nosotras: `^post/(\d+)/$`. Analicemos esta expresión parte por parte para entender qué es lo que estamos haciendo aquí: -También queremos limpiar el archivo `mysite/urls.py`, así que vamos a importar urls desde nuestra aplicación de `blog` en el archivo principal `mysite/urls.py`. +* **^post/** le está diciendo a Django que tome cualquier cosa que tenga `post/` al principio del URL (justo antes de `^`) +* **(\d+)** significa que habrá un número (de uno o más dígitos) y que queremos que ese número sea capturado y extraído +* **/** le dice a Django que otro caracter `/` debería venir a continuación +* **$** indica el final del URL, lo que significa que sólo cadenas finalizando con `/` coincidirán con este patrón -Adelante, eliminar las líneas comentadas (líneas que comienzan con `#`) y añadir una línea que va a importar en el principal (url `blog.urls``''`). +## ¡Tu primer URL de Django! -El archivo `mysite/urls.py` ahora debe verse así: +¡Es hora de crear nuestro primer URL! Queremos que 'http://127.0.0.1:8000/' sea la página de inicio de nuestro blog y que muestre una lista de posts. +También queremos mantener el archivo `mysite/urls.py` limpio, así que importaremos URLs de nuestro `blog` al archivo `mysite/urls.py` principal. + +Elimina las líneas comentadas (líneas comenzando con `#`) y agrega una línea que importará `blog.urls` en el url principal (`''`). + +Tu archivo `mysite/urls.py` debería verse como este: + +``` python from django.conf.urls import include, url from django.contrib import admin - + urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'', include('blog.urls')), ] +``` +Django ahora redirigirá todo lo que vaya hacia 'http://127.0.0.1:8000/' a `blog.urls` y buscará más instrucciones allí. -Django redirigirá ahora todo lo que entre en `http://127.0.0.1:8000/` a `blog.urls` y esperara para más instrucciones. +Cuando escribes expresiones regulares en Python acostúmbrate a poner `r` al principio de la cadena - esto es solamente una pista para que Python entienda que la cadena contenerá caracteres especiales que no son para ser interpretados por Python sino que son parte de la expresión regular. ## blog.urls -Cree un nuevo archivo vacío `blog/urls.py`. ¡Muy bien! Añade estas dos primeras líneas: +Crea un nuevo archivo vacío `blog/urls.py`. ¡Muy bien! Agrega estas primeras dos líneas: +``` python from django.conf.urls import include, url from . import views +``` +Aquí solo estamos importando los métodos de Django y todas nuestras `views` del `blog` (todavía no tenemos ninguna, pero lo haremos en un minuto) -Aquí nosotros sólo importaremos métodos de Django y todas nuestras `vistas` de aplicación `blog` (aún no tenemos ninguna, pero llegaremos a eso en un minuto!) - -Después de eso, podemos agregar nuestro primer patrón de URL: +Luego de esto, podemos agregar nuestro primer patrón URL: +``` python urlpatterns = [ url(r'^$', views.post_list), ] +``` +Como puedes ver, ahora estamos asignando una `view` llamada `post_list` al URL `^$`. Esta expresión regular coincidirá con `^` (un inicio) seguido de `$` (un final) - por lo tanto, sólo una cadena vacía coincidirá. Y esto es correcto, ya que en los URL resolvers de Django 'http://127.0.0.1:8000/' no es parte del URL. Este patrón mostrará a Django que `views.post_list` es el lugar correcto al que ir si alguien ingresa a tu sitio web con la dirección 'http://127.0.0.1:8000/'. -Como puedes ver, estamos asignando una `vista` denominada `post_list` a la `^ $` URL. Pero, ¿qué hace`^ $`? Es una magia regex :) Lo desglosemos:-`^` en regex significa "el principio"; de este signo podemos empezar buscando nuestro patrón - `$` si coincide sólo "el fin" de la cadena, lo que significa que vamos a terminar buscando nuestro patrón aquí - -Si pones estos dos signos juntos, parece que estamos buscando una cadena vacía! Y eso es correcto, porque en la resolución de Django url, `http://127.0.0.1:8000/` no es parte de la URL. Este patrón mostrará a Django que `views.post_list` es el lugar perfecto para ir si alguien entra en su sitio de Internet en la dirección `http://127.0.0.1:8000/`. - -¿Todo bien? Abre http://127.0.0.1:8000 en tu navegador para ver el resultado. +¿Todo bien? Abre http://127.0.0.1:8000/ en tu navegador para ver el resultado. ![Error][2] [2]: images/error1.png -No "funciona", ¿eh? No te preocupes, es sólo una página de error, nada que temer. Son en realidad muy útiles: +No hay más un "It works", ¿verdad? No te preocupes, es solamente una página de error, ¡nada que nos asuste! De hecho, son bastante útiles: -Se puede leer que no existe ningún atributo **'post_list'**. *¿Post_list* lo recuerdas? Esto es lo que llamamos nuestro punto de vista! Esto significa que todo esté en su lugar, simplemente no creamos nuestra *view* todavía. No te preocupes, llegaremos ahí. +Puedes leer que no hay ningún **atributo 'post_list'**. ¿*post_list* te recuerda algo? ¡Así es como llamamos a nuestra vista! Esto significa que todo está en su lugar, sólo que no creamos nuestra *view* todavía. No te preocupes, ya llegaremos a eso. > Si quieres saber más sobre Django URLconfs, mira la documentación oficial: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/es/django_views/README.md b/es/django_views/README.md index 32f81b78174..e62bd13fb42 100755 --- a/es/django_views/README.md +++ b/es/django_views/README.md @@ -1,37 +1,38 @@ -# Vistas de Django - es hora de crear! +# Vistas de Django - ¡Es hora de crear! -Es hora de deshacerse de el error que hemos creado en el último capítulo :) +Es hora de deshacerse del error que hemos creado en el capítulo anterior :) -Una *View* es un lugar donde ponemos la «lógica» de nuestra aplicación. Se solicitará información del `model` que se creo anteriormente y pasarlo a una `view` que va a crearse en el próximo capítulo. Las vistas son sólo métodos de Python que son un poco más complicados que lo que hicimos en el capítulo de **Introducción a Python**. +Una *View* es un lugar donde ponemos la "lógica" de nuestra aplicación. Se solicitará información del `model` que creaste anteriormente y se pasará a una `view` que crearás en el próximo capítulo. Las vistas son sólo métodos de Python que son un poco más complicados que lo que hicimos en el capítulo de **Introducción a Python**. -Las Vistas se colocan en el archivo `views.py`. Agregaremos nuestras *vistas* al archivo `blog/views.py`. +Las Vistas se colocan en el archivo `views.py`. Agregaremos nuestras *views* al archivo `blog/views.py`. ## blog/views.py Bien, vamos abrir este archivo y ver lo que contiene: +``` python from django.shortcuts import render - + # Create your views here. +``` +No demasiadas cosas aquí todavía. La *view* más simple puede ser como esto: -No, demasiadas cosas aquí todavía. La simple *view* puede verse como esto: - +``` python def post_list(request): - return render(request, 'blog/post_list.html', {}) +``` +Como puedes ver, hemos creado un método (`def`) llamado `post_list` que toma un `request` y hace un `return` de un método `render` que renderizará (construirá) nuestra plantilla `blog/post_list.html`. -Como puedes ver, hemos creado un método (`def`) llamado `post_list` que contiene un `request` y `return` de un método, el `render` se redirigira a nuestra plantilla `blog/post_list.html`. - -En seguida, guarde el archivo, y dirígete a tu navegador a http://127.0.0.1:8000/ para ver lo que tenemos ahora. +Guarda el archivo, dirígete a http://127.0.0.1:8000/ y veamos lo que tenemos ahora. -Otro error! Lee lo que está pasando ahora: +¡Otro error! Leamos lo que está pasando ahora: ![Error][1] [1]: images/error.png -Esto es fácil: *TemplateDoesNotExist*. Vamos a arreglar este error, creando una plantilla en el siguiente capítulo! +Este es uno fácil: *TemplateDoesNotExist*. ¡Vamos a arreglar este error creando una plantilla en el siguiente capítulo! -> Aprenda más acerca de las vistas de Django mediante la lectura de la documentación oficial: https://docs.djangoproject.com/en/1.8/topics/http/views/ +> Aprende más acerca de las views de Django leyendo la documentación oficial: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/es/domain/README.md b/es/domain/README.md index 5414fea3888..85d8363fca1 100755 --- a/es/domain/README.md +++ b/es/domain/README.md @@ -1,71 +1,76 @@ # Dominio -Heroku le entregó un dominio pero es largo, dificil de recordar y feo. Seria asombroso contar con un nombre de dominio que sea sencillo y facil de recordar, ¿verdad? +PythonAnywhere te ha dado un dominio gratuito, pero tal vez no quieras tener ".pythonanywhere.com" al final de la URL de tu blog. Quizás quieras que tu blog viva en "www.infinite-kitten-pictures.org" o "www.3d-printed-steam-engine-parts.com" o "www.antique-buttons.com" o "www.mutant-unicornz.net", o lo que quieras que sea. -En este capitulo te enseñaremos como adquirir un dominio dirigirlo a Heroku! +Aquí hablaremos brevemente sobre cómo obtener un dominio y veremos cómo vincularlo a tu aplicación web en PythonAnywhere. Sin embargo, deberías saber que la mayoría de los dominios son de pago, y PythonAnywhere te cobrará un valor adicional para usar tu propio nombre de dominio -- no es demasiado dinero en total, pero es probablemente algo que quieras hacer sólo si estás muy comprometida con la causa. ## ¿Donde registrar un dominio? -Un dominio normalmente cuesta alrededor de 15 dolares estadounidenses anuales. Existen opciones un poco mas baratas y otras un poco mas caras pero esto depende del proveedor. Existen muchas compañias donde puedes adquirir un dominio: una simple [busqueda en google][1] te dara miles de opciones. Hay opciones más baratas y más caras, dependiendo del proveedor. Hay una gran cantidad de empresas que se pueden comprar un dominio de: una simple [búsqueda en google][1] dará cientos de opciones. +Un dominio típico cuesta alrededor de 15 dólares estadounidenses anuales. Hay opciones más baratas y más caras, dependiendo del proveedor. Hay una gran cantidad de empresas a las que puedes comprar un dominio: una simple [búsqueda en google][1] dará cientos de opciones. [1]: https://www.google.com/search?q=register%20domain -Nuestra opción predilecta es [I Want my name][2]. Ellos se promueven como una opción "indolora para el manejo de dominios" y realmente lo son. +Nuestra opción favorita es [I want my name][2]. Ellos se promocionan como una opción "indolora para el manejo de dominios" y realmente lo son. - [2]: https://iwantmyname.com + [2]: https://iwantmyname.com/ -## ¿Como registrar un dominio en IWantMyName? +También puedes obtener dominios gratuitos. [dot.tk][3] es un lugar para obtener uno, pero deberíamos advertirte que los dominios gratuitos a veces se sienten algo "baratos" -- si tu sitio va a ser un sitio para un negocio profesional, seguramente quieras considerar comprar un dominio "apropiado" que termine en `.com`. -Dirígete a [iwantmyname][3] y escriba un dominio que deseas tener en el cuadro de búsqueda. + [3]: http://www.dot.tk - [3]: http://iwantmyname.com +## Cómo apuntar tu dominio a PythonAnywhere + +Si elegiste la opción de *iwantmyname.com*, haz click en `Domains` en el menú y elije tu nuevo dominio. Luego encuentra el vínculo a `manage DNS records`: ![][4] - [4]: images/1.png + [4]: images/4.png -Ahora deberías ver una lista de todos los dominios disponibles con el término que pusiste en el cuadro de búsqueda. Como puedes ver, una cara sonriente indica que el dominio está disponible para comprarlo, y una cara triste indica que no se encuentra disponible. +Ahora necesitas encontrar este formulario: ![][5] - [5]: images/2.png + [5]: images/5.png -Hemos decidido comprar `djangogirls.in`: +Y completarlo con los siguientes detalles: - Hostname: www - Type: CNAME - Value: tu dominio de PythonAnywhere (por ejemplo, djangogirls.pythonanywhere.com) - TTL: 60 ![][6] - [6]: images/3.png - -Dirígete a la caja. Ahora debes registrare en iwantmyname, si todavía no tienes una cuenta. Después de eso, debes de proporcionar la información de tu tarjeta de crédito y finalmente podrás comprar el dominio! + [6]: images/6.png -Después de eso, Haz clic en `Dominios` en el menú y elige el dominio que acabas de adquirir. A continuación, busca y da clic en el enlace de `manage DNS records`: +En la parte inferior, haz click en el botón "Agregar" y guarda los cambios. -![][7] +> **Nota** Si utilizaste un proveedor de dominios diferente, la interfaz exacta para encontrar tus configuraciones de DNS / CNAME será diferente, pero tu objetivo es el mismo: configurar un CNAME que apunte a tu nuevo dominio en `yourusername.pythonanywhere.com`. - [7]: images/4.png +Puede tomar unos minutos para tu dominio para empezar a funcionar, ¡sé paciente! -Ahora necesitas localizar este formulario: +## Configura el dominio a través de la aplicación web en PythonAnywhere -![][8] +También necesitarás decirle a PythonAnywhere que quieres usar tu dominio personalizado. - [8]: images/5.png +Ve a la página [PythonAnywhere Accounts][7] y haz una actualización del tipo de cuenta. La opción más económica (el plan "Hacker") está bien para empezar. Siempre puedes elegir un plan con mayores prestaciones después cuando te vuelvas super-famosa y tengas millones de visitas. -Y llenarlo con los siguientes datos: - Nombre de hosting: www - Tipo: CNAME - Valor: tu dominio de Heroku (por ejemplo djangogirls.herokuapp.com) - TTL: 3600 + [7]: https://www.pythonanywhere.com/account/ -![][9] +Luego, ve a la pestaña [Web][8] y anota un par de cosas: - [9]: images/6.png + [8]: https://www.pythonanywhere.com/web_app_setup/ -En la parte inferior, da clic en el botón Agregar y poder guardar los cambios. +* Copia la **ruta a tu virtualenv** y ponla en algún lugar seguro +* Abre tu **archivo de configuración WSGI**, copia el contenido, y pégalo en algún lugar seguro -Puede tomar un par de horas para que tu dominio empece a trabajar, así que mantente paciente! +Luego, haz click en **Delete** de tu vieja aplicación web. No te preocupes, esto no eliminará tu código, solamente cambiará el dominio *yourusername.pythonanywhere.com*. Luego, crea una nueva aplicación web y sigue estos pasos: -## Configurar dominio en Heroku +* Ingresa tu nombre de dominio +* Elije "configuración manual" +* Elije Python 3.4 +* ¡Y listo! -También tienes que decirle a Heroku que deseas utilizar su dominio personalizado. +Cuando seas redirigida a la pestaña web. -Dirígete a [Heroku Dashboard][10], inicia sesión con tu cuenta de Heroku y elije tu aplicación. Enseguida, configura tu aplicación y agrega tu dominio en la sección de `dominios` y guardar los cambios. +* Pega la ruta al virtualenv que guardaste anteriormente +* Abre tu nuevo archivo de configuración WSGI y pega el contenido de tu viejo archivo de configuración - [10]: https://dashboard.heroku.com/apps +Haz click en actualizar, ¡deberías ver que tu sitio está en línea en el nuevo dominio! -Eso es todo! \ No newline at end of file +Si te encuentras con algún problema, haz click en el vínculo "Send feedback" en el sitio de PythonAnywhere, y uno de sus amigables administradores te contactará para ayudarte en breve. diff --git a/es/dynamic_data_in_templates/README.md b/es/dynamic_data_in_templates/README.md index bd0e7026cc7..f991de7c0b5 100755 --- a/es/dynamic_data_in_templates/README.md +++ b/es/dynamic_data_in_templates/README.md @@ -1,24 +1,26 @@ -# Querysets de Django +# Datos dinámicos en las plantillas -Tenemos diferentes piezas en su lugar: el modelo `Post` está definido en `models.py`, tenemos a `post_list` en `views.py` y la plantilla agregada. ¿Pero cómo le haremos realmente para que nuestras publicaciones aparezcan en nuestra plantilla de HTML? Porque eso es lo que queremos hacer: tomar algún contenido (modelos guardados en la base de datos) y mostrarlo adecuadamente en nuestra plantilla, ¿no? +Tenemos diferentes piezas en su lugar: el modelo `Post` está definido en `models.py`, tenemos a `post_list` en `views.py` y la plantilla agregada. ¿Pero cómo haremos realmente para que nuestros posts aparezcan en nuestra plantilla HTML? Porque eso es lo que queremos hacer: tomar algún contenido (modelos guardados en la base de datos) y mostrarlo adecuadamente en nuestra plantilla, ¿no? -Esto es exactamente lo que las *vistas* (views) se supone que hacen: conectar modelos con plantillas. En nuestra *vista* `post_list` necesitaremos tomar los modelos que deseamos mostrar y pasarlos a una plantilla. Así que básicamente en una *vista* decidimos qué (modelo) se mostrará en una plantilla. +Esto es exactamente lo que las *views* se supone que hacen: conectar modelos con plantillas. En nuestra *view* `post_list` necesitaremos tomar los modelos que deseamos mostrar y pasarlos a una plantilla. Así que básicamente en una *view* decidimos qué (modelo) se mostrará en una plantilla. Muy bien, ahora ¿cómo lo hacemos? -Necesitamos abrir nuestro archivo `blog/views.py`. Hasta ahora la *vista* `post_list` se ve así: +Necesitamos abrir nuestro archivo `blog/views.py`. Hasta ahora la *view* `post_list` se ve así: +```python from django.shortcuts import render def post_list(request): return render(request, 'blog/post_list.html', {}) - +``` -¿Recuerdas cuando hablamos de incluir código en diferentes archivos? Ahora tenemos que incluir el modelo que definimos en el archivo `models.py`. Agregaremos la linea `from .models import Post` de la siguiente forma: +¿Recuerdas cuando hablamos de incluir código en diferentes archivos? Ahora tenemos que incluir el modelo que definimos en el archivo `models.py`. Agregaremos la línea `from .models import Post` de la siguiente forma: +```python from django.shortcuts import render from .models import Post - +``` El punto después de `from` indica el *directorio actual* o la *aplicación actual*. Como `views.py` y `models.py` están en el mismo directorio, simplemente usamos `.` y el nombre del archivo (sin `.py`). Ahora importamos el nombre del modelo (`Post`). @@ -26,40 +28,44 @@ El punto después de `from` indica el *directorio actual* o la *aplicación actu ## QuerySet -Ya debes estar familiarizado con la forma en que funcionan los QuerySets. Hablamos de ellos en el [capítulo Django ORM (QuerySets)][1]. +Ya debes estar familiarizada con la forma en que funcionan los QuerySets. Hablamos de ellos en el capítulo [Django ORM (QuerySets)][1]. - [1]: /django_orm/README.html + [1]: ../django_orm/README.md -Entonces ahora nos interesa una lista de entradas del blog que han sido publicadas y ordenadas por `published_date` (fecha de publicación), no? Ya hicimos eso en el capítulo QuerySets! +Entonces ahora nos interesa obtener una lista de entradas del blog que han sido publicadas y ordenadas por `published_date` (fecha de publicación), ¿no? ¡Ya hicimos eso en el capítulo QuerySets! - Post.objects.filter(published_date__isnull=False).order_by('published_date') + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') -Ahora agregamos esta parte del código en el archivo `blog/views.py`, agregándolo a la función `def post_list(request)`: +Ahora pondremos este bloque de código en el archivo `blog/views.py`, agregándolo a la función `def post_list(request)`: +```python from django.shortcuts import render + from django.utils import timezone from .models import Post def post_list(request): - posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') return render(request, 'blog/post_list.html', {}) - +``` -Observa que creamos una *variable* en nuestro QuerySet: `posts`. Tómalo como el nombre de nuestro QuerySet. De aquí en adelante vamos a referirnos al QuerySet con ese nombre. +Observa que creamos una *variable* en nuestro QuerySet: `posts`. Tómala como el nombre de nuestro QuerySet. De aquí en adelante vamos a referirnos al QuerySet con ese nombre. La última parte es pasar el QuerySet `posts` a la plantilla (veremos cómo mostrarla en el siguiente capítulo). -En la función `render` ya tenemos el parámetro `request` (todo lo que recibimos del usuario via Internet) y el archivo `'blog/post_list.html'` como plantilla. El último parámetro, que se ve así: `{}` es un campo en el que podemos agregar algunas cosas para que la plantilla las use. Necesitamos nombrarlos (le seguiremos llamando `'posts'` por mientras :)). Se debe ver así: `{'posts': posts}`. Observa que la parte que va antes de `:` está en comillas `''`. +En la función `render` ya tenemos el parámetro `request` (todo lo que recibimos del usuario via Internet) y el archivo `'blog/post_list.html'` como plantilla. El último parámetro, que se ve así: `{}` es un campo en el que podemos agregar algunas cosas para que la plantilla las use. Necesitamos nombrarlos (los seguiremos llamando `'posts'` por ahora :)). Se debería ver así: `{'posts': posts}`. Observa que la parte que va antes de `:` está entre comillas `''`. -Finalmente nuestro archivo `blog/views.py` debe verse así: +Finalmente nuestro archivo `blog/views.py` debería verse así: +```python from django.shortcuts import render + from django.utils import timezone from .models import Post def post_list(request): - posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') return render(request, 'blog/post_list.html', {'posts': posts}) - +``` ¡Terminamos! Ahora regresemos a nuestra plantilla y mostremos este QuerySet. diff --git a/es/extend_your_application/README.md b/es/extend_your_application/README.md index 3802798961d..82b030b1aaf 100755 --- a/es/extend_your_application/README.md +++ b/es/extend_your_application/README.md @@ -1,64 +1,55 @@ -# Extiende tu aplicación +# Amplía tu aplicación -Ya hemos completado todos los pasos necesarios para la creación de nuestro sitio web: sabemos cómo escribir un model, url, view y template. También sabemos cómo hacer que nuestro sitio web. +Ya hemos completado todos los pasos necesarios para la creación de nuestro sitio web: sabemos cómo escribir un model, url, view y template. También sabemos cómo hacer que nuestro sitio web se vea lindo. -Tiempo para practicar! +¡Hora de practicar! -Lo primero que necesitamos en nuestro blog, es obviamente, una página para mostrar un post, ¿cierto? +Lo primero que necesitamos en nuestro blog es, obviamente, una página para mostrar un post, ¿cierto? Ya tenemos un modelo `Post`, así que no necesitamos añadir nada a `models.py`. ## Crea un enlace en la plantilla -Vamos a empezar añadiendo un enlace dentro del archivo `blog/templates/blog/post_list.html`. Hasta el momento debe verse así: - -```html -{% extends 'blog/base.html' %} - -{% block content %} - {% for post in posts %} -
-
- {{ post.published_date }} +Vamos a empezar añadiendo un enlace dentro del archivo `blog/templates/blog/post_list.html`. Hasta el momento debería verse así: +``` html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- {% endfor %} -{% endblock content %} + {% endfor %} + {% endblock content %} ``` - -Queremos tener un enlace a una página de detalle sobre el título del post. Vamos a cambiar `

{{ post.title }}

` dentro del enlace: - -```html -

{{ post.title }}

+Queremos tener un enlace a una página de detalle sobre el título del post. Vamos a cambiar `

{{ post.title }}

` dentro del enlace: ``` +

{{ post.title }}

+``` +Es hora de explicar el misterioso `{% url 'blog.views.post_detail' pk=post.pk %}`. Como probablemente sospeches, la notación `{% %}` significa que estamos utilizando Django template tags. ¡Esta vez vamos a utilizar uno que va a crear una dirección URL para nosotros! -{% raw %}Tiempo para explicar lo misterioso `{% url 'blog.views.post_detail' pk=post.pk %}`. Como sospechas, la notación `{% %}` significa que estamos utilizando Django template tags. Esta vez vamos a utilizar uno que va a crear una dirección URL para nosotros!{% endraw %} - -`blog.views.post_detail` es una ruta hacia `post_detail` *view* que queremos crear. Por favor nota: `blog` es el nombre de nuestra aplicación (el `blog` de directorio), `views` es el nombre del archivo `views.py` y `post_detail` - es el nombre de la *view*. - -Ahora cuando vayamos a: +`blog.views.post_detail` es una ruta hacia `post_detail` *view* que queremos crear. Por favor nota: `blog` es el nombre de nuestra aplicación (el `blog` de directorio), `views` es el nombre del archivo `views.py` y `post_detail` es el nombre de la *view*. - http://127.0.0.1:8000/ - - -Tendremos un error (como era de esperar, ya que no tenemos una dirección URL o una *viwe* para `post_detail`). Se verá así: +Ahora cuando vayamos a: http://127.0.0.1:8000/ tendremos un error (como era de esperar, ya que no tenemos una dirección URL o una *view* para `post_detail`). Se verá así: ![NoReverseMatch error][1] [1]: images/no_reverse_match2.png -Vamos a crear una dirección URL en `urls.py` para nuestro `post_detail` *view*! +¡Vamos a crear una URL en `urls.py` para nuestro *view* `post_detail`! ### URL: http://127.0.0.1:8000/post/1/ -Queremos crear una dirección URL de Django a una *view* denominada `post_detail`, que mostrará una entrada del blog. ¿Agrega la línea `url (r'^ poste / (?P [0-9] +) / $', views.post_detail),` en el archivo `blog/urls.py`. Debe tener este aspecto: +Queremos crear una URL que apunte a Django a una *view* denominada `post_detail`, que mostrará una entrada del blog. Agrega la línea `url (r'^post/(?P[0-9]+)/$', views.post_detail),` al archivo `blog/urls.py`. Debería tener este aspecto: -```python -from django.conf.urls import include, url +``` python +from django.conf.urls import url from . import views urlpatterns = [ @@ -67,102 +58,108 @@ urlpatterns = [ ] ``` +Ese da un poco de miedo, pero no te preocupes - lo explicaremos para +ti: +- comienza con `^` otra vez, "el principio". +- `post/` sólo significa que después del comienzo, la dirección URL debe contener la palabra **post** y **/**. Hasta ahora, bien. +- `(?P[0-9]+)` - esta parte es más complicada. Significa que Django llevará todo lo que coloques aquí y lo transferirá a una vista como una variable llamada `pk`. `[0-9]` también nos dice que sólo puede ser un número, no una letra (todo debería estar entre 0 y 9). `+` significa que tiene que haber uno o más dígitos. Entonces algo como `http://127.0.0.1:8000/post//` no es válido, pero `http://127.0.0.1:8000/post/1234567890/` es perfectamente aceptable! +- `/` - entonces necesitamos **/** de nuevo +- `$` - ¡"el final"! -Da miedo, pero no te preocupes - lo explicaremos para ti: - comienza con `^` otra vez, "el principio" - `post /` sólo significa que después del comienzo, la dirección URL debe contener la palabra **post** y **/**. Hasta ahora, bien. - `(?P [0-9] +)`-esta parte es más complicada. Significa que Django llevará todo lo que coloques aquí y lo transferirá a una vista como una variable llamada `pk`. `[0-9]` también nos dice que sólo puede ser un número, no es una carta (entre 0 y 9). `+` significa que tiene que haber uno o más dígitos. Por algo como `http://127.0.0.1:8000/post / /` no es válido, pero `1234567890/post/http://127.0.0.1:8000/` es perfectamente aceptable! -`/` - entonces necesitamos **/** de nuevo - `$` - "the end"! - -Eso significa que si entras en `http://127.0.0.1:8000/post/5/` en tu navegador, Django entenderá que estás buscando una *view* denominada `post_detail` y transferirá la información de `pk` que es igual a `5` a la *view*. +Eso significa que si entras en `http://127.0.0.1:8000/post/5/` en tu navegador, Django entenderá que estás buscando una *view* denominada `post_detail` y transferirá la información de `pk` que es igual a `5` a esa *view*. -`PK` es atajo para la `llave principal`. Este nombre se utiliza a menudo en proyectos de Django. Pero puedes nombrar tus variable como te gusta (Recuerda: minúscula y `_` en lugar de espacios en blanco!). Por ejemplo en lugar de `(?.¿P [0-9] +)` podríamos tener variable `post_id`, así que esto lo verías como: `(?P [0-9] +)`. +`pk` es la abreviación de `primary key`. Este nombre se utiliza a menudo en proyectos de Django. Pero puedes nombrar tus variables como te guste (recuerda: ¡minúsculas y `_` en lugar de espacios en blanco!). Por ejemplo en lugar de `(?.¿P[0-9]+)` podríamos tener la variable `post_id`, así que esto lo verías como: `(?P [0-9]+)`. -¡Bien! Vamos a actualizar la página: - - http://127.0.0.1:8000/ - - -¡Boom! Sin embargo otro error! Como era de esperarse! +¡Bien! ¡Actualiza la página: http://127.0.0.1:8000/ ¡Boom! ¡Sin embargo vemos otro error! Como era de esperarse. ![AttributeError][2] [2]: images/attribute_error2.png -¿Te acuerdas del próximo paso? Por supuesto: agregar una view! +¿Te acuerdas del próximo paso? Por supuesto: ¡agregar una view! ## post_detail view -Esta vez nuestra *view* tendrá un parámetro adicional `pk`. ¿Nuestra *view* necesita atraparla, cierto? Entonces definiremos nuestra función como `def post_detail (petición, pk):`. Ten en cuenta que tenemos que usar exactamente el mismo nombre que especificamos en las urls (`pk`). Omitir esta variable es incorrecto y resultará en un error! +Esta vez nuestra *view* tomará un parámetro adicional `pk`. Nuestra *view* necesita recibirla, ¿cierto? Entonces definiremos nuestra función como `def post_detail (request, pk):`. Ten en cuenta que tenemos que usar exactamente el mismo nombre que especificamos en las urls (`pk`). ¡Omitir esta variable es incorrecto y resultará en un error! + +Ahora, queremos sólo un post del blog. Para ello podemos usar querysets como este: -Ahora, queremos sólo una entrada del blog. Para ello podemos usar querysets como esta: +``` python Post.objects.get(pk=pk) +``` -Pero este código tiene un problema. Si no hay ningún `Post` con `llave primaria` (`pk`) tendremos un error muy feo! +Pero este código tiene un problema. Si no hay ningún `Post` con `llave primaria` (`pk`) tendremos un error muy feo. ![DoesNotExist error][3] [3]: images/does_not_exist2.png -No queremos eso! Pero, por supuesto, Django viene con algo que se encargará de ese problema por nosotros: `get_object_or_404`. En caso de que no haya ningún `Post` con el dado `pk` se mostrará una más agradable página ( llamada `Page Not Found 404`). +¡No queremos eso! Pero, por supuesto, Django viene con algo que se encargará de ese problema por nosotros: `get_object_or_404`. En caso de que no haya ningún `Post` con el dado `pk` se mostrará una más agradable página (`Page Not Found 404`). ![Page not found][4] [4]: images/404_2.png -La buena noticia es que puedes crear tu propia página `Page Not Found` y diseñarla como desees. Pero por ahora, no es súper importante. - -Es hora de agregar una *view* a nuestro archivo `views.py`! +La buena noticia es que puedes crear tu propia página `Page Not Found` y diseñarla como desees. Pero por ahora no es tan importante, así que lo omitiremos. -Deberíamos abrir `blog/views.py` y agregue el siguiente código: +¡Es hora de agregar una *view* a nuestro archivo `views.py`! - from django.shortcuts import render, get_object_or_404 +Deberíamos abrir `blog/views.py` y agregar el siguiente código: +```python -Cerca de la líneas `from`. Y en el final del archivo añadimos nuestra *view*: + from django.shortcuts import render, get_object_or_404 - def post_detail(request, pk): - post = get_object_or_404(Post, pk=pk) - return render(request, 'blog/post_detail.html', {'post': post}) +``` +Cerca de otras líneas `from`. Y en el final del archivo añadimos nuestra *view*: -Sí. Es hora de actualizar la página: +```python +def post_detail(request, pk): +     post = get_object_or_404(Post, pk=pk) +     return render(request, 'blog/post_detail.html', {'post': post}) - http://127.0.0.1:8000/ +``` +Sí. Es hora de actualizar la página: http://127.0.0.1:8000/ ![Post list view][5] [5]: images/post_list2.png -¡Funcionó! Pero ¿qué pasa cuando haces clic en un enlace en el título del post? +¡Funcionó! Pero ¿qué pasa cuando haces click en un enlace en el título del post? ![TemplateDoesNotExist error][6] [6]: images/template_does_not_exist2.png -¡Oh no! Otro error! Pero ya sabemos cómo lidiar con eso, ¿no? Tenemos que añadir una plantilla! +¡Oh no! ¡Otro error! Pero ya sabemos cómo lidiar con eso, ¿no? ¡Tenemos que añadir una plantilla! Crearemos un archivo en `blog/templates/blog` llamado `post_detail.html`. Se verá así: ```html -{% extends 'blog/base.html' %} - -{% block content %} -
- {% if post.published_date %} - {{ post.published_date }} - {% endif %} -
-

{{ post.title }}

-

{{ post.text|linebreaks }}

-{% endblock %} + {% extends 'blog/base.html' %} + + {% block content %} +     
+         {% if post.published_date %} +             
+                 {{ post.published_date }} +             
+         {% endif %} +         

{{ post.title }}

+         

{{ post.text|linebreaksbr }}

+     
+ {% endblock %} ``` +Una vez más estamos extendiendo `base.html`. En el bloque `content` queremos mostrar la fecha de publicación (si existe), título y texto de nuestros posts. Pero deberíamos discutir algunas cosas importantes, ¿cierto? -Una vez más estamos extendiendo `base.html`. En el bloque de `content` queremos mostrar un post published_date (si existe), título y texto. Pero deberíamos discutir algunas cosas importantes, ¿cierto? - -{% raw %}`{% if ... %} ... {% endif %}` es una template tag que podemos usar cuando queramos ver algo (recuerdas `if... else...` desde el capítulo de **Introducción a Python**?). En este escenario queremos comprobar si `published_date de un post` no está vacío.{% endraw %} +`{% if ... %} ... {% endif %}` es un template tag que podemos usar cuando querramos ver algo (¿recuerdas if ... else... del capítulo de **Introducción a Python**?). En este escenario queremos comprobar si el campo `published_date` de un post no está vacío. Bien, podemos actualizar nuestra página y ver si `Page Not Found` se ha ido. @@ -174,18 +171,28 @@ Bien, podemos actualizar nuestra página y ver si `Page Not Found` se ha ido. ## Una cosa más: ¡Tiempo de implementación! -Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Added more views to the website." -... -$ git push heroku master +Sería bueno verificar que tu sitio web aún funcionará en PythonAnywhere, ¿cierto? Intentemos desplegar de nuevo. + +``` + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push + +``` + +* Luego, en una [consola Bash de PythonAnywhere][8] + ``` + $ cd my-first-blog + $ git pull [...] +``` + +* Finalmente, ve a la pestaña [Web][9] y haz click en **Reload**. + [8]: https://www.pythonanywhere.com/consoles/ + [9]: https://www.pythonanywhere.com/web_app_setup/ ¡Y eso debería ser todo! Felicidades :) diff --git a/es/extend_your_application/images/no_reverse_match2.png b/es/extend_your_application/images/no_reverse_match2.png index db65a5dc70a..306926206f8 100644 Binary files a/es/extend_your_application/images/no_reverse_match2.png and b/es/extend_your_application/images/no_reverse_match2.png differ diff --git a/es/how_the_internet_works/README.md b/es/how_the_internet_works/README.md index 119c5036ab6..8a5e936cb93 100755 --- a/es/how_the_internet_works/README.md +++ b/es/how_the_internet_works/README.md @@ -1,53 +1,55 @@ -# Cómo funciona internet +# ¿Cómo funciona Internet? > Este capitulo está inspirado por la charla "How the Internet works" de Jessica McKellar (http://web.mit.edu/jesstess/www/). -Apostamos que utilizas Internet cada día. Pero, ¿sabes lo que pasa cuando escribe una dirección como http://djangogirls.org en tu navegador y presionas `enter`? +Apostamos que utilizas Internet todos los días. Pero, ¿sabes lo que pasa cuando escribes una dirección como https://djangogirls.org en tu navegador y presionas 'Enter'? Lo primero que tienes que entender es que un sitio web es sólo un montón de archivos guardados en un disco duro. Al igual que tus películas, música o fotos. Sin embargo, los sitios web poseen una peculiaridad: ellos incluyen un código de computadoras llamado HTML. -Si no estás familiarizado con la programación, puede ser difícil de captar HTML al principio, pero tus navegadores web (como Chrome, Safari, Firefox, etc.) lo aman. Los navegadores web están diseñados para entender este código, seguir sus instrucciones y mostrar todos esos archivos de los cuales está hecho de la manera exacta como tu quieres que se muestren. +Si no estás familiarizada con la programación, puede ser difícil de captar HTML al principio, pero tus navegadores web (como Chrome, Safari, Firefox, etc.) lo aman. Los navegadores web están diseñados para entender este código, seguir sus instrucciones y mostrar todos esos archivos de los cuales tu sitio web está hecho de la manera exacta como tu quieres que se muestren. -Como cualquier otro archivo, tenemos que guardar los archivos HTML en algún lugar de un disco duro. Para Internet, usamos unos especiales y poderosos computadores llamados* servidores*. Ellos no tienen una pantalla, ratón o teclado, debido a que su propósito es almacenar datos y servirlos. Por esa razón son llamados *servidores* -- porque ellos *sirven* los datos. +Como cualquier otro archivo, tenemos que guardar los archivos HTML en algún lugar de un disco duro. Para Internet, usamos unas computadoras especiales y poderosas llamadas *servidores*. Ellas no tienen una pantalla, mouse o teclado, debido a que su propósito es almacenar datos y servirlos. Por esa razón son llamados *servidores* -- porque ellos *sirven* los datos. -OK, quizás te preguntes ¿como luce Internet, cierto? +Ok, quizás te preguntes cómo luce Internet, ¿cierto? -Te hemos hecho una imagen! luce algo como esto: +¡Te hemos hecho una imagen! Luce algo así: ![Figura 1.1][1] [1]: images/internet_1.png -Parece un lío, ¿no? En realidad es una red de máquinas conectadas (los mencionados *servidores*). ¡Cientos de miles de máquinas! Muchas, muchos kilómetros de cables alrededor del mundo! Puedes visitar el siguiente sitio web donde muestra las conexiones de cables submarinos al rededor del mundo(http://submarinecablemap.com/) para ver lo complicado que es la red. Aquí hay una captura de pantalla de la página web: +Parece un lío, ¿no? En realidad es una red de máquinas conectadas (los mencionados *servidores*). ¡Cientos de miles de máquinas! ¡Muchos, muchos kilómetros de cables alrededor del mundo! Puedes visitar el sitio web [Submarine Cable Map][2] (http://submarinecablemap.com/) donde se muestran las conexiones de cables submarinos alrededor del mundo y ver lo complicada que es la red. Aquí hay una captura de pantalla de la página web: -![Figura 1.2][2] + [2]: http://submarinecablemap.com/ - [2]: images/internet_3.png +![Figura 1.2][3] -Es fascinante, ¿no? Pero obviamente, no es posible tener un cable entre cada máquina conectada a Internet. Así que, para llegar a una máquina (por ejemplo la aloja a http://djangogirls.org) tenemos que pasar una solicitud a través de muchas máquinas diferentes. + [3]: images/internet_3.png + +Es fascinante, ¿no? Pero, obviamente, no es posible tener un cable entre cada máquina conectada a Internet. Así que, para llegar a una máquina (por ejemplo la que aloja a https://djangogirls.org) tenemos que pasar una solicitud a través de muchas máquinas diferentes. Se parece a esto: -![Figura 1.3][3] +![Figura 1.3][4] - [3]: images/internet_2.png + [4]: images/internet_2.png -imagina que cuando escribes http://djangogirls.org, estas escribiendo una carta que dice: "Queridos jango Girls, me gustaría ver su sitio web djangogrils.org. Por favor, envíenmelo!" +Imagina que cuando escribes https://djangogirls.org, estas enviando una carta que dice: "Queridos Django Girls, me gustaría ver su sitio web djangogrils.org. Por favor, envíenmelo!" -Tu carta va hacia la oficina de correo más cercana. Luego va a otra un poco más cercana de su destinatario, luego a otra y a otra hasta que es entregada en su destino. Lo único es que si usted envía cartas (*paquetes de datos*) con frecuencia al mismo lugar, cada carta puede pasar por oficinas de correos (*routers*) totalmente diferentes, dependiendo de cómo se distribuyen en cada oficina. +Tu carta va hacia la oficina de correo más cercana. Luego va a otra un poco más cercana de su destinatario, luego a otra y a otra hasta que es entregada en su destino. La única cosa diferente es que si tu envías cartas (*paquetes de datos*) con frecuencia al mismo lugar, cada carta puede pasar por oficinas de correos (*routers*) totalmente diferentes, dependiendo de cómo se distribuyen en cada oficina. -![Figura 1.4][4] +![Figura 1.4][5] - [4]: images/internet_4.png + [5]: images/internet_4.png -Sí, es tan simple como eso. Enviar mensajes y esperar alguna respuesta. Por supuesto, en vez de papel y pluma usas bytes de datos, pero la idea es la misma! +Sí, es tan simple como eso. Enviar mensajes y esperar alguna respuesta. Por supuesto, en vez de papel y lapicera usas bytes de datos, ¡pero la idea es la misma! -En lugar de direcciones con el nombre de la calle, ciudad, código postal y nombre del país, utilizamos direcciones IP. tu computador pide primero el DNS (Domain Name System, en español "Sistema de Nombres de Dominio") para traducir djangogirls.org a una dirección IP. funciona un tanto parecido a los directorio telefónicos donde se busca el nombre de la persona que se desea contactar y este nos muestra su número de teléfono y dirección. +En lugar de direcciones con el nombre de la calle, ciudad, código postal y nombre del país, utilizamos direcciones IP. Tu computadora pide primero el DNS (Domain Name System - en español Sistema de Nombres de Dominio) para traducir djangogirls.org a una dirección IP. Funciona como los viejos directorios telefónicos donde puedes buscar el nombre de la persona que se deseas contactar y este nos muestra su número de teléfono y dirección. -Cuando envías una carta, ésta necesita tener ciertas características para ser entregada correctamente: una dirección, sello etc. También utilizas un lenguaje que el receptor pueda entender, ¿cierto? Lo mismo sucede con *los paquetes de daots* que envías para ver un sitio web: utilizas un protocolo llamado HTTP (Hypertext Transfer Protocol, en español protocolo de transferencia de hipertexto). +Cuando envías una carta, ésta necesita tener ciertas características para ser entregada correctamente: una dirección, sello, etc. También utilizas un lenguaje que el receptor pueda entender, ¿cierto? Lo mismo sucede con los *paquetes de datos* que envías para ver un sitio web: utilizas un protocolo llamado HTTP (Hypertext Transfer Protocol - en español Protocolo de Transferencia de Hipertexto). -Así que, básicamente, cuando tienes un sitio web necesitas tener un *servidor* (la máquina) donde vive. El *servidor* está esperando cualquier *solicitud entrante* (cartas que piden al servidor para que envié tu sitio web) y éste responde enviado tu sitio web (en otra carta). +Así que, básicamente, cuando tienes un sitio web necesitas tener un *servidor* (la máquina) donde vive. El *servidor* está esperando cualquier *solicitud* entrante (cartas que piden al servidor que envíe tu sitio web) y éste responde enviando tu sitio web (en otra carta). -Puesto que este es un tutorial de Django, seguro te preguntarás qué es lo que hace Django. Bueno, cuando envías una respuesta, no siempre quieres enviar lo mismo a todo el mundo. Es mucho mejor si tus cartas son personalizados, especialmente para la persona que acaba de escribir, ¿cierto? Django nos ayuda con la creación de estas cartas personalizadas, interesante :). +Puesto que este es un tutorial de Django, seguro te preguntarás qué es lo que hace Django. Bueno, cuando envías una respuesta, no siempre quieres enviar lo mismo a todo el mundo. Es mucho mejor si tus cartas son personalizadas, especialmente para la persona que acaba de escribir, ¿cierto? Django nos ayuda con la creación de estas cartas personalizadas :). -así que basta de charlas y pongamos manos a la obra! +Basta de charlas, ¡pongamos manos a la obra! diff --git a/es/how_the_internet_works/images/internet_4.png b/es/how_the_internet_works/images/internet_4.png index 05f1aed562f..2661cec1b61 100644 Binary files a/es/how_the_internet_works/images/internet_4.png and b/es/how_the_internet_works/images/internet_4.png differ diff --git a/es/html/README.md b/es/html/README.md index 7d4f1379a9f..acfc1e723ae 100755 --- a/es/html/README.md +++ b/es/html/README.md @@ -1,33 +1,33 @@ # Introducción a HTML -Qué es una plantilla, te estarás preguntando? +Te estarás preguntando, ¿qué es una plantilla? -Una plantilla es un archivo que podemos utilizar nuevamente para presentar información en un formato homogéneo - por ejemplo, se podría utilizar una plantilla para ayudarte a escribir una carta, porque aunque cada carta puede contener un mensaje distinto y dirigirse a una persona diferente, compartirán el mismo formato. +Una plantilla es un archivo que podemos reutilizar para presentar información diferente de forma consistente - por ejemplo, se podría utilizar una plantilla para ayudarte a escribir una carta, porque aunque cada carta puede contener un mensaje distinto y dirigirse a una persona diferente, compartirán el mismo formato. -El formato de una plantilla de Django se describe en un lenguaje llamado HTML (que es el código HTML que mencionamos en el primer capítulo **Como funciona Internet**). +El formato de una plantilla de Django se describe en un lenguaje llamado HTML (que es el código HTML que mencionamos en el primer capítulo **Cómo funciona Internet**). ## ¿Qué es HTML? -HTML es un simple código que es interpretado por el navegador web - como Chrome, Firefox o Safari - para mostrar una página web al usuario. +HTML es un simple código que es interpretado por tu navegador web - como Chrome, Firefox o Safari - para mostrar una página web al usuario. -HTML por separado es "Lenguaje Marcado de HiperTexto". **HiperTexto** significa que es un tipo de texto que soporta hipervínculos entre páginas. **Marcado** significa que hemos tomado un documento y lo marca con código para decirte cómo interpretar la página (en este caso, un navegador). El código HTML está construido con las **etiquetas**, cada uno a partir de `<` y terminando con `>`. Estas etiquetas de marcado son **elementos**. +HTML significa HyperText Markup Language - en español, Lenguaje de Marcas de HyperTexto. **HyperText** significa que es un tipo de texto que soporta hipervínculos entre páginas. **Markup** significa que hemos tomado un documento y lo hemos marcado con código para decirle a algo (en este caso, un navegador) cómo interpretar la página. El código HTML está construido con **etiquetas**, cada una comenzando con `<` y terminando con `>`. Estas etiquetas de marcado son **elementos**. -## Tu primera plantilla! +## ¡Tu primera plantilla! Crear una plantilla significa crear un archivo de plantilla. Todo es un archivo, ¿verdad? Probablemente hayas notado esto ya. -Las plantillas se guardan en el directorio de `blog/templates/blog`. Así que primero crear un directorio llamado `templates` dentro de tu directorio de blog. Luego cree otro directorio llamado `blog` dentro de su directorio de templates: +Las plantillas se guardan en el directorio de `blog/templates/blog`. Así que primero crea un directorio llamado `templates` dentro de tu directorio blog. Luego crea otro directorio llamado `blog` dentro de tu directorio de templates: blog └───templates └───blog + +(Tal vez te preguntes por qué necesitamos dos directorios llamados `blog` - como descubrirás más adelante, esto es simplemente una útil convención de nomenclatura que hace la vida más fácil cuando las cosas empiezan a complicarse más.) -(Tal vez te preguntes por qué necesitamos dos directorios llamados `blog` - como usted descubrirá más adelante, esto es simplemente una útil convención de nomenclatura que hace la vida más fácil cuando las cosas empiezan a complicarse más.) +Y ahora crea un archivo `post_list.html` (déjalo en blanco por ahora) dentro de la carpeta `blog/templates/blog`. -Y ahora a crear un archivo `post_list.html` (Déjalo en blanco por ahora) dentro del directorio de `blog/templates/blog`. - -Cómo se ve su sitio web ahora: http://127.0.0.1:8000/ +Mira cómo se ve su sitio web ahora: http://127.0.0.1:8000/ > Si todavía tienes un error `TemplateDoesNotExists`, intenta reiniciar el servidor. Ve a la línea de comandos, detén el servidor pulsando Ctrl + C (teclas Control y C juntas) y comienza de nuevo mediante la ejecución del comando `python manage.py runserver`. @@ -35,17 +35,18 @@ Cómo se ve su sitio web ahora: http://127.0.0.1:8000/ [1]: images/step1.png -Ningún error ya! Felicidades :) Sin embargo, tu sitio de Internet en realidad no publica nada, excepto una página en blanco, porque la plantilla también está vacía. Tenemos que arreglarlo. +¡Ningún error más! Felicidades :) Sin embargo, por ahora, tu sitio web no está publicando nada excepto una página en blanco, porque la plantilla también está vacía. Tenemos que arreglarlo. -Añade lo siguiente a su archivo de plantilla: +Añade lo siguiente a tu archivo de plantilla: +``` html

Hi there!

It works!

+``` - -¿Cómo luce ahora tu sitio de Internet? Haga clic para ver: http://127.0.0.1:8000/ +¿Cómo luce ahora tu sitio web? Haz click para ver: http://127.0.0.1:8000/ ![Figura 11.2][2] @@ -53,21 +54,22 @@ Añade lo siguiente a su archivo de plantilla: ¡Funcionó! Buen trabajo :) -* La etiqueta más básica, ``, es siempre el principio de cualquier página web y `` es siempre el final. Como puedes ver, todo el contenido de la página web va al principio de la etiqueta `` y entre la etiqueta de cierre `` +* La etiqueta más básica, ``, es siempre el principio de cualquier página web y `` es siempre el final. Como puedes ver, todo el contenido de la página web va desde el principio de la etiqueta `` y hasta la etiqueta de cierre `` * `

` es una etiqueta para los elementos de párrafo; `

` cierra cada párrafo -## Cabeza & Cuerpo +## Cabeza & cuerpo Cada página HTML también se divide en dos elementos: **head** y **body**. -* **head** es un elemento que contiene información sobre el documento que no aparece en la pantalla. +* **head** es un elemento que contiene información sobre el documento que no se muestra en la pantalla. * **body** es un elemento que contiene todo lo que se muestra como parte de la página web. -Usamos `` para decirle el navegador acerca de la configuración de la página y `` para decir lo que realmente está en la página. +Usamos `` para decirle al navegador acerca de la configuración de la página y `` para decir lo que realmente está en la página. Por ejemplo, puedes ponerle un título a la página web dentro de la ``, así: +``` html Ola's blog @@ -77,7 +79,7 @@ Por ejemplo, puedes ponerle un título a la página web dentro de la ``, a

It works!

- +``` Guarda el archivo y actualiza tu página. @@ -85,30 +87,31 @@ Guarda el archivo y actualiza tu página. [3]: images/step4.png -¿Observa cómo el navegador ha comprendido que "Ola's Blog" es el título de su página? Ha interpretado `Ola's blog` y coloca el texto en la barra de título del navegador (también se utilizará para marcadores y así sucesivamente). +¿Observas cómo el navegador ha comprendido que "Ola's blog" es el título de tu página? Ha interpretado `Ola's blog` y colocó el texto en la barra de título de tu navegador (también se utilizará para marcadores y así sucesivamente). -Probablemente también hayas notado que cada etiqueta de apertura es comparable con una *etiqueta de cierre*, con un `/`, y que elementos *anidados* (es decir, no puede cerrar una etiqueta particular hasta que todos los que estaban en su interior se hayan cerrado también). +Probablemente también hayas notado que cada etiqueta de apertura coincide con una *etiqueta de cierre*, con un `/`, y que los elementos son *anidados* (es decir, no puedes cerrar una etiqueta particular hasta que todos los que estaban en su interior se hayan cerrado también). -Es como poner las cosas en cajas. Tienes una caja grande, ``; en su interior hay ``, y que contiene las cajas aún más pequeñas: `

`. +Es como poner cosas en cajas. Tienes una caja grande, ``; en su interior hay ``, y que contiene las cajas aún más pequeñas: `

`. -Tienes que seguir estas reglas de etiquetas *de cierre* y de *anidar* elementos - si no lo haces, el navegador puede no ser capaz de interpretarlos correctamente y tu página se mostrará incorrectamente. +Tienes que seguir estas reglas de etiquetas de *cierre* y de *anidación* de elementos - si no lo haces, el navegador puede no ser capaz de interpretarlos correctamente y tu página se mostrará incorrectamente. ## Personaliza tu plantilla -Ahora puedes divertirte un poco y tratar de personalizar tu plantilla! Aquí están algunas etiquetas útiles para eso: +¡Ahora puedes divertirte un poco y tratar de personalizar tu plantilla! Aquí hay algunas etiquetas útiles para eso: -* `

Un Titulo

` - para tu titulo más importante -* `

Un sub-titulo

` para el siguiente nivel -* `

Un sub-sub-titulo

` ... y así hasta `
` -* `texto` Pone en cursiva tu texto -* `texto` Pone en negrita tu texto -* `
` Un salto de línea (No puedes colocar nada dentro de br) -* `link` crea un link -* `
  • primer elemento
  • segundo elemento
` crea una lista, igual que esta! -* `
` defina una sección de la página +* `

Un título

` - para tu título más importante +* `

Un subtítulo

` - para el título del siguiente nivel +* `

Un subsubtítulo

` - ... y así hasta `
` +* `texto` - pone en cursiva tu texto +* `texto` - pone en negrita tu texto +* `
` - un salto de línea (no puedes colocar nada dentro de br) +* `link` - crea un vínculo +* `
  • primer elemento
  • segundo elemento
` - crea una lista, ¡igual que esta! +* `
` - define una sección de la página Aquí hay un ejemplo de una plantilla completa: +``` html Django Girls blog @@ -117,13 +120,13 @@ Aquí hay un ejemplo de una plantilla completa: - +

published: 14.06.2014, 12:14

My first post

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

- +

published: 14.06.2014, 12:14

My second post

@@ -131,12 +134,12 @@ Aquí hay un ejemplo de una plantilla completa:
+``` +Aquí hemos creado tres secciones `div`. -Hemos creado tres secciones `div` aquí. - -* El primer elemento `div` contiene el título de nuestro post - es un encabezado y un enlace -* Otros dos elementos `div` contengan nuestro blog con fecha publicada, `h2` con un título puesto que es clicable y dos s `p` (párrafo) de texto, uno para la fecha y uno de nuestro blogpost. +* El primer elemento `div` contiene el título de nuestro blog - es un encabezado y un enlace +* Otros dos elementos `div` contienen nuestros posts con la fecha de publicación, `h2` con un título que es clickeable y dos `p` (párrafo) de texto, uno para la fecha y uno para nuestro post. Nos da este efecto: @@ -144,41 +147,64 @@ Nos da este efecto: [4]: images/step6.png -Yaaay! Pero hasta el momento, nuestra plantilla sólo muestra exactamente **la misma información** - considerando que antes hablábamos de plantillas como permitiéndonos Mostrar información **diferente** en el **mismo formato**. +¡Yaaay! Pero hasta el momento, nuestra plantilla sólo muestra exactamente **la misma información** - considerando que antes hablábamos de plantillas que nos permitirían mostrar información **diferente** en el **mismo formato**. + +Lo que queremos realmente es mostrar posts reales añadidos en nuestra página de administración de Django - y ahí es a donde vamos a continuación. -Lo que queremos realmente es mostrar mensajes reales añadidos en nuestra administración de Django - y eso es a donde vamos. +## Una cosa más: ¡despliega! -## Una cosa más +Sería bueno ver todo esto disponible en Internet, ¿no? Hagamos otro despliegue en PythonAnywhere: -¿Sería bueno ver si tu sitio de Internet esta trabajando todavía en Heroku, cierto? Vamos a intentar implementar otra vez. +### Haz un commit y sube tu código a GitHub -En primer lugar, veamos qué archivos han cambiado desde que hicimos deploy: +En primer lugar, veamos qué archivos han cambiado desde que hicimos el despliegue por última vez: $ git status + +Asegúrate de que estás en el directorio `djangogirls` y vamos a decirle a `git` que incluya todos los cambios dentro de este directorio: -Vamos a decirle a `git` para incluir todos los cambios desde el directorio actual: + $ git add --all . + - $ git add -A . +> **Nota** `-A` (abreviatura de "all") significa que `git` también reconocerá si has eliminado archivos (por defecto, sólo reconoce archivos nuevos/modificados). También recuerda (del capítulo 3) que `.` significa el directorio actual. +Antes de que subamos todos los archivos, vamos a ver qué es lo que `git` subirá (todos los archivos que `git` cargará deberían aparecer en verde): -> **Nota** `-A` (abreviatura de "all") significa que `git` también reconocerá si se han eliminado los archivos (de forma predeterminada, sólo reconoce archivos nuevos/modificados). También recuerda (capítulo 3) que `.` significa el directorio actual. + $ git status + -Antes de que subamos todos los archivos, vamos a ver qué `git` va subiendo (todos los archivos que `git` cargará ahora deberían aparecer en verde): +Ya casi estamos, ahora es tiempo de decirle que guarde este cambio en su historial. Vamos a darle un "mensaje de commit" donde describimos lo que hemos cambiado. Puedes escribir cualquier cosa que te gustaría en esta etapa, pero es útil escribir algo descriptivo para que puedes recordar lo que has hecho en el futuro. - $ git status + $ git commit -m "Cambie el HTML para la página." + + +> **Nota** Asegúrate de usar comillas dobles alrededor del mensaje de commit. +Una vez que hicimos esto, subimos (push) nuestros cambios a PythonAnywhere: -Ya casi estamos, ahora es tiempo de decirle que guarde estos cambios en su historial. Vamos a dar un "mensaje de comentar" donde se describe lo que hemos cambiado. Puedes escribir cualquier cosa que te gustaría en esta etapa, pero es útil escribir algo descriptivo para que puedes recordar lo que has hecho en el futuro. + git push + - $ git commit -m "Cambiando el html para la página." +### Descarga tu nuevo código a PythonAnywhere y actualiza tu aplicación web +* Abre la [página de consolas de PythonAnywhere][5] y ve a tu **consola Bash** (o comienza una nueva). Luego, ejecuta: + +``` +$ cd ~/my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` -> **Nota** Asegúrate de usar comillas dobles alrededor del mensaje de confirmación. + [5]: https://www.pythonanywhere.com/consoles/ -Una vez que hemos hecho eso, por fin podemos subir (push) nuestros cambios en el sitio web en heroku: +Y mira cómo tu código se descarga. Si quieres comprobar que ya ha terminado, puedes ir a la pestaña **Files** y ver tu código en PythonAnywhere. - git push heroku master +* Finalmente, dirígete a la pestaña [Web][6] y selecciona **Reload** en tu aplicación web. + [6]: https://www.pythonanywhere.com/web_app_setup/ -Y eso es todo! Una vez terminado Heroku, tu puedes seguir adelante y actualizar tu sitio web en el navegador. Los cambios deberian ser visibles! +¡Tu actualización debería estar en línea! Actualiza tu sitio web en el navegador. Ahora deberías poder ver tus cambios :) diff --git a/es/intro_to_command_line/README.md b/es/intro_to_command_line/README.md index d283c446d85..de1565f63c0 100755 --- a/es/intro_to_command_line/README.md +++ b/es/intro_to_command_line/README.md @@ -2,68 +2,68 @@ Es emocionante, ¿verdad? Vas a escribir tu primera línea de código en pocos minutos :) -**Permítenos presentarte a tu primer nuevo amigo: la línea de comandos!** +**Permítenos presentarte a tu primer nuevo amigo: ¡la línea de comandos!** -En los siguientes pasos te mostraran como usar aquella ventana negra que todos los hackers usan. Puede parecer un aterrador al principio pero es solo un mensaje en pantalla que espera a que le des órdenes. +Los siguientes pasos te mostrarán cómo usar aquella ventana negra que todos los hackers usan. Puede parecer un poco aterrador al principio pero es solo un mensaje en pantalla que espera a que le des órdenes. ## ¿Qué es la línea de comandos? -La ventana, que generalmente es llamada **línea de comandos** o **interfaz de línea de comandos**, es una aplicación basada en texto para la ver, manejar y manipular archivos en tu computadora (como por ejemplo el Explorador de Windows o Finder en Mac, pero sin la interfaz gráfica). Otros nombres para la línea de comandos son: *cmd*, *CLI*, *el símbolo del sistema*, *consola* o *terminal*. +La ventana, que generalmente es llamada **línea de comandos** o **interfaz de línea de comandos**, es una aplicación basada en texto para ver, manejar y manipular archivos en tu computadora (como por ejemplo el Explorador de Windows o Finder en Mac, pero sin la interfaz gráfica). Otros nombres para la línea de comandos son: *cmd*, *CLI*, *símbolo del sistema*, *consola* o *terminal*. ## Abrir la interfaz de línea de comandos -para empezar a experimentar con nuestra interfaz de linea de comandos lo primero que debemos hacer es abrirla. +Lo primero que debemos hacer para empezar a experimentar con nuestra interfaz de linea de comandos es abrirla. ### Windows -Ir al menú Inicio → todos los programas → accesorios → Command Prompt. +Ir al menú Inicio → Todos los programas → Accesorios → Command Prompt ### Mac OS X -Aplicaciones → Servicios → Terminal. +Aplicaciones → Servicios → Terminal ### Linux -Esta probablemente en Aplicaciones → Accesorios → Terminal, pero eso depende de su distribución. Si no existe, Googlelo :) +Está probablemente en Aplicaciones → Accesorios → Terminal, pero eso depende de tu distribución. Si no lo encuentras, Googlealo :) ## Prompt Ahora deberías ver una ventana blanca o negra que está esperando tus órdenes. -Si estás en Mac o Linux, probablemente veráz `$`, como este: +Si estás en Mac o Linux, probablemente verás `$`, así: $ - + En Windows, es un signo así `>`, como este: > + +Cada comando será precedido por este signo y un espacio, pero no tienes que escribirlo. Tu computadora lo hará por ti :) -Cada comando sera antepuesto por este signo y un espacio, pero no tienes que escribirlo. Tu computadora lo hará por ti :) - -> Sólo una pequeña nota: en su caso, tal vez hay algo como `C:\Users\ola>` o `Olas-MacBook-Air:~ ola$` antes del prompt y eso es 100% correcto. En este tutorial sólo lo hemos simplificado a lo mínimo. +> Sólo una pequeña nota: en tu caso, tal vez hay algo como `C:\Users\ola>` o `Olas-MacBook-Air:~ ola$` antes del prompt y eso es 100% correcto. En este tutorial lo simplificaremos lo más posible. ## Tu primer comando (¡YAY!) Vamos a empezar con algo simple. Escribe este comando: $ whoami - + o > whoami + - -Y luego oprime la tecla `enter`. Este es el resultado: +Y luego oprime la tecla Enter. Este es el resultado: $ whoami olasitarska + +Como puedes ver, la computadora sólo te presentó tu nombre de usuario. Bien, ¿eh? :) -Como puedes ver, la computadora sólo te presento su nombre de usuario. Bien, eh? :) - -> Trato de escribir cada comando, no copiar pegar. Te acordarás de más de esta manera! +> Trata de escribir cada comando, no copies y pegues. ¡Te acordarás más de esta manera! ## Básicos @@ -71,27 +71,27 @@ Cada sistema operativo tiene un conjunto diferente de comandos para la línea de ### Directorio actual -Sería bueno saber dónde estamos ahora, ¿cierto? Vamos a ver. Escribe este comando y oprime `enter`: +Sería bueno saber dónde estamos ahora, ¿cierto? Vamos a ver. Escribe este comando y oprime Enter: $ pwd - /usuarios/olasitarska - + /Users/olasitarska + Si estás en Windows: - > cd + > cd C:\Users\olasitarska + +Probablemente verás algo similar en tu máquina. Una vez que abres la línea de comandos generalmente empiezas en el directorio home de tu usuario. -Probablemente verás algo similar en tu máquina. Una vez que abres la línea de comandos generalmente empiezan en el directorio home del usuario. - -> Nota: 'pwd' significa 'mostrar directorio de trabajo'. +> Nota: 'pwd' significa 'print working directory' - en español, 'mostrar directorio de trabajo'. * * * ### Lista de archivos y directorios -¿Qué es? Sería bueno saber. Veamos: +¿Qué hay aquí? Sería bueno saber. Veamos: $ ls Applications @@ -99,7 +99,7 @@ Probablemente verás algo similar en tu máquina. Una vez que abres la línea de Downloads Music ... - + Windows: @@ -110,166 +110,166 @@ Windows: 05/08/2014 07:28 PM Downloads 05/08/2014 07:28 PM Music ... - + * * * -### Cambie el directorio actual +### Cambia el directorio actual -¿Quizás podemos ir a nuestro directorio de escritorio? +¿Quizás podemos ir a nuestro escritorio? $ cd Desktop - + Windows: > cd Desktop + +Comprueba si realmente ha cambiado: -Comprobar si realmente ha cambiado: - - $ pwd + $ pwd /Users/olasitarska/Desktop - + Windows: - > cd + > cd C:\Users\olasitarska\Desktop - + ¡Aquí está! -> PRO tip: si escribes `cd D` y luego oprimes `tab` en el teclado, la línea de comandos automáticamente Autorrellenara el resto del nombre para que puedas navegar más rápido. Si hay más de una carpeta a partir de "D", presiona el botón `tab` dos veces para obtener una lista de opciones. +> Pro tip: si escribes `cd D` y luego oprimes `tab` en el teclado, la línea de comandos automáticamente completará el resto del nombre para que puedas navegar más rápido. Si hay más de una carpeta que empiece con "D", presiona el botón `tab` dos veces para obtener una lista de opciones. * * * ### Crear directorio -¿Cómo crear un directorio de Django Girls en tu escritorio? Puedes hacerlo de esta manera: +¿Qué tal si creamos un directorio de Django Girls en tu escritorio? Puedes hacerlo de esta manera: $ mkdir djangogirls - + Windows: > mkdir djangogirls + +Este pequeño comando creará una carpeta con el nombre `djangogirls` en tu escritorio. ¡Puedes comprobar si está allí buscando en tu escritorio o ejecutando el comando `ls` (si estás usando Mac o Linux) o `dir` (si estás usando Windows)! Inténtalo :) -Este pequeño comando creará una carpeta con el nombre `djangogirls` en tu escritorio. Puede comprobar si está allí buscando en tu escritorio o ejecutando un `ls/dir`! Inténtalo :) - -> PRO tip: Si no quieres escribir una y otra vez los mismos comandos, prueba oprimiendo la `flecha arriba` y `flecha abajo` de tu teclado para recorrer a recientes comandos utilizados. +> Pro tip: Si no quieres escribir una y otra vez los mismos comandos, prueba oprimiendo la `flecha arriba` y `flecha abajo` de tu teclado para ver recientes comandos utilizados. * * * -### Ejercicios! +### ¡Ejercicios! -Un pequeño reto para ti: en el directorio recién creado `djangogirls` crear un directorio llamado `test`. Utilice los comandos `cd` y `mkdir`. +Un pequeño reto para ti: en el directorio recién creado `djangogirls` crea un directorio llamado `test`. Utiliza los comandos `cd` y `mkdir`. #### Solución: - $ cd djangogirls + $ cd djangogirls $ mkdir test $ ls - + Windows: - > cd djangogirls + > cd djangogirls > mkdir test - > dir - 08/05/2014 19:28 test - + > dir + 08/05/2014 19:28 < DIR > test + -¡Felicidades! :) +¡Felicitaciones! :) * * * ### Limpiar -No queremos dejar un desorden, así que vamos a eliminar todo lo que hicimos hasta ese momento. +No queremos dejar un desorden, así que vamos a eliminar todo lo que hicimos hasta este momento. En primer lugar, tenemos que volver al escritorio: $ cd .. - + Windows: > cd .. + - -Haciendo `cd` `..` cambiará el directorio actual al directorio padre (que significa el directorio que contiene el directorio actual). +`cd` `..` cambiará el directorio actual al directorio padre (que significa el directorio que contiene el directorio actual). Revisa dónde estás: - $ pwd + $ pwd /Users/olasitarska/Desktop - + Windows: - > cd + > cd C:\Users\olasitarska\Desktop - + Ahora es hora de eliminar el directorio `djangogirls`. -> **Atención**: eliminar archivos utilizando `del`, `rmdir` o `rm` es irrecuperable, lo que significa *archivos borrados desaparecerá para siempre*! Entonces, ser muy cuidadosa con este comando. - - $ rm - r djangogirls +> **Atención**: Eliminar archivos utilizando `del`, `rmdir` o `rm` hace que no puedan recuperarse, lo que significa que los *archivos borrados desaparecerán para siempre* Debes ser muy cuidadosa con este comando. + $ rm -r djangogirls + Windows: - > rmdir/s djangogirls - djangogirls, ¿estás seguro ? Y - + > rmdir/s djangogirls + djangogirls, ¿Estás seguro ? Y + Hecho! Asegurémonos que en verdad fueron borrados, vamos a ver: $ ls - + Windows: > dir - + ### Salida -Eso es todo por ahora! Ahora con seguridad puedes cerrar la línea de comandos. Vamos a hacerlo al estilo hacker, bien? :) +¡Esto es todo por ahora! Ahora puedes cerrar la línea de comandos sin problemas. Vamos a hacerlo al estilo hacker, ¿bien? :) $ exit - + Windows: > exit + - -Bueno, no? :) +Genial, ¿no? :) ## Índice -Aquí está una lista de algunos comandos útiles: +Aquí hay una lista de algunos comandos útiles: -| Comando (Windows) | Comando (Mac OS / Linux) | Descripción | Ejemplo | -| ----------------- | ------------------------ | ----------------------------- | ------------------------------------------------- | -| exit | exit | cierra la ventana | **exit** | -| cd | cd | Cambia el directorio | **cd test** | -| dir | ls | lista de directorios/archivos | **dir** | -| copy | cp | copia el archivo | **copy c:\test\test.txt c:\windows\test.txt** | -| move | mv | mueve el archivo | **move c:\test\test.txt c:\windows\test.txt** | -| mkdir | mkdir | Crea un nuevo directorio | **mkdir testdirectory** | -| del | rm | elimina un archivo/directorio | **del c:\test\test.txt** | +| Comando (Windows) | Comando (Mac OS / Linux) | Descripción | Ejemplo | +| ----------------- | ------------------------ | ---------------------------- | ------------------------------------------------- | +| exit | exit | Cierra la ventana | **exit** | +| cd | cd | Cambia el directorio | **cd test** | +| dir | ls | Lista directorios/archivos | **dir** | +| copy | cp | Copia de archivos | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | Mueve archivos | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | Crea un nuevo directorio | **mkdir testdirectory** | +| del | rm | Elimina archivos/directorios | **del c:\test\test.txt** | -Estos son sólo muy pocos de los comandos en la línea de comandos que puedes utilizar pero no vas a usar algo más hoy. +Estos son solo algunos de los comandos que puedes ejecutar en la línea de comandos. No vas a usar nada más que esos por ahora. Si tienes curiosidad, [ss64.com][1] contiene una referencia completa de comandos para todos los sistemas operativos. [1]: http://ss64.com -## Listo? +## ¿Lista? -Vamos a sumergirnos en Python! +¡Vamos a sumergirnos en Python! diff --git a/es/python_installation/README.md b/es/python_installation/README.md index a95c411d8fd..0fd71bdf85d 100755 --- a/es/python_installation/README.md +++ b/es/python_installation/README.md @@ -1,65 +1,67 @@ # Vamos a empezar con Python -Por fin estamos aquí! +¡Por fin estamos aquí! -Pero primero, déjenos decirte qué es Python. Python es un lenguaje de programación muy popular que puede utilizarse para la creación de sitios web, juegos, software de cálculo, gráficos y mucho más. - -Python se originó en la década de 1980 y su objetivo principal es ser legible por los seres humanos (no sólo las máquinas!), por eso parece mucho más simple que otros lenguajes de programación. Esto lo hace fácil de aprender, pero no te preocupes, Python es también muy poderoso! +Pero primero, déjenos decirte qué es Python. Python es un lenguaje de programación muy popular que puede utilizarse para la creación de sitios web, juegos, software académico, gráficos y mucho, mucho más. +Python se originó en la década de 1980 y su objetivo principal es ser legible por los seres humanos (¡no sólo para las máquinas!), por eso parece mucho más simple que otros lenguajes de programación. Esto hace que sea más fácil de aprender, pero no te preocupes, ¡Python es también muy poderoso! # Instalación de Python -> Este subcapítulo se basa en un tutorial de Geek Girls Carrots (http://django.carrots.pl/) - -Django está escrito en Python. Necesitamos Python para cualquier cosa en Django. Vamos a empezar con la instalación! Queremos que instales Python 3.4, así que si tienes alguna versión anterior, deberás actualizarla. +> Este subcapítulo se basa en un tutorial de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots/) +Django está escrito en Python. Necesitamos Python para cualquier cosa en Django. ¡Vamos a empezar con la instalación! Queremos que instales Python 3.4, así que si tienes alguna versión anterior, deberás actualizarla. ### Windows -Puedes descargar Python para Windows desde el sitio web https://www.python.org/downloads/release/python-342/. Después de descargar el archivo ***.msi**, debes ejecutarlo (has doble clic en el archivo) y sige las instrucciones. Es importante recordar el camino (el directorio) donde se ha instalado Python. Será necesario más adelante! +Puedes descargar Python para Windows desde el sitio web https://www.python.org/downloads/release/python-343/. Después de descargar el archivo ***.msi**, debes ejecutarlo (haz doble click en el archivo) y sigue las instrucciones. Es importante recordar la ruta (el directorio) donde se ha instalado Python. ¡Será necesario más adelante! + +Algo para tener en cuenta: en la segunda pantalla del asistente de instalación, llamada "Customize", asegúrate de ir hacia abajo y elegir la opción "Add python.exe to the Path", como en +![No te olvides de agregar Python al Path][1] + + [1]: images/add_python_to_windows_path.png ### Linux -Es muy probable que ya tengas Python instalado. Para verificar si lo tienes (y que versión es), abrir la consola y escribe el siguiente comando: +Es muy posible que ya tengas Python instalado. Para verificar que ya lo tienes instalado (y qué versión es), abre una consola y tipea el siguiente comando: $ python3 --version Python 3.4.2 -Si no tienes instalado Python o si deseas una versión diferente, se puede instalar de la siguiente manera: - +Si no tienes Python instalado o si quieres una versión diferente, puedes instalarlo como sigue: -#### Debian o Ubuntu +#### Ubuntu -Escribe este comando en la consola: +Tipea este comando en tu consola: - $ sudo apt-get install python3.4 - - -#### Fedora (<=21) + sudo apt-get install python3.4 + -Usa este comando en la consola: +#### Fedora - $ sudo yum install python3.4 +Usa este comando en tu consola: + sudo yum install python3.4 + -#### Fedora (22+) +#### openSUSE -Usa este comando en la consola: +Usa este comando en tu consola: - $ sudo yum install python3.4 + sudo zypper install python3 ### OS X -Tienes que ir a la página web https://www.python.org/downloads/release/python-342/ y descargar al instalador de Python: +Debes ir al sitio web https://www.python.org/downloads/release/python-342/ y descargar el instalador de Python: -* descarga el archivo *DMG* titulado *Mac OS X 64-bit/32-bit installer*, -* has doble click para abrirlo, -* Doble click en *Python.mpkg* para ejecutar al instalador. +* descarga el archivo *DMG* *Mac OS X 64-bit/32-bit installer*, +* haz doble click para abrirlo, +* doble click en *Python.mpkg* para ejecutar al instalador. -Verifica que la instalación se realizó correctamente abriendo la aplicación *Terminal* y ejecutando el comando `python3`: +Verifica que la instalación fue exitosa abriendo la *Terminal* y ejecutando el comando `python3`: $ python3 --version Python 3.4.2 @@ -67,4 +69,4 @@ Verifica que la instalación se realizó correctamente abriendo la aplicación * * * * -Si tienes alguna duda o si algo salió mal y no tienes ni idea de qué hacer - por favor, preguntale a tu coach! A veces las cosas no van bien y que es mejor pedir ayuda a alguien con más experiencia. \ No newline at end of file +Si tienes alguna duda o si algo salió mal y no sabes cómo resolverlo - ¡pide ayuda a tu tutor! Algunas veces las cosas no salen tan fácilmente y es mejor pedir ayuda a alguien con más experiencia. diff --git a/es/python_installation/images/add_python_to_windows_path.png b/es/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/es/python_installation/images/add_python_to_windows_path.png differ diff --git a/es/python_introduction/README.md b/es/python_introduction/README.md index 3ad77b4dfbc..0aebf758cb5 100755 --- a/es/python_introduction/README.md +++ b/es/python_introduction/README.md @@ -1,8 +1,8 @@ # Introducción a Python -> Parte de este capítulo se basa en tutoriales por Geek Girls Carrots (http://django.carrots.pl/). +> Parte de este capítulo se basa en tutoriales por Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). -Vamos a escribir algo de código! +¡Vamos a escribir algo de código! ## Python prompt @@ -10,168 +10,168 @@ Para empezar a jugar con Python, tenemos que abrir una *línea de comandos* en n [1]: /intro_to_command_line/README.html -Una vez que estés listo, sigue las siguientes instrucciones. +Una vez que estés lista, sigue las siguientes instrucciones. -Queremos abrir una consola de Python, así que escribe `python3` y pulsa `enter`. +Queremos abrir una consola de Python, así que escribe `python3` y pulsa Enter. $ python3 Python 3.4.2 (...) Type "copyright", "credits" or "license" for more information. >>> + +## ¡Tu primer comando en Python! -## Tu primer comando en Python! +Después de ejecutar el comando de Python, el cursor cambia a `>>>`. Para nosotros esto significa que por ahora sólo podemos utilizar comandos en el lenguaje Python. No tienes que escribir el `>>>` - Python lo hará por ti. -Después de ejecutar el comando de Python, el cursor cambia a `>>>`. Para nosotros esto significa que por ahora sólo podemos utilizar comandos en el lenguaje Python. No tienes que escribir en `>>>`-Python lo hará por ti. +Si deseas salir de la consola de Python en cualquier momento, simplemente escribe `exit()` o usa el atajo `Ctrl + Z` para Windows y `Ctrl + D` para Mac/Linux. Luego no verás más `>>>`. -Si deseas salir de la consola de Python en cualquier momento, simplemente escribe `exit()` o usar el atajo `Ctrl + Z` para Windows y `Ctrl + D` para Mac/Linux. Entonces no verás `>>>`. - -Pero ahora, no queremos salir de la consola de Python. Queremos aprender más sobre él. Vamos a empezar con algo muy simple. Por ejemplo, trata de escribir algo de matemáticas, como `2 + 3` y pulsa `enter`. +Pero ahora no queremos salir de la consola de Python. Queremos aprender más sobre ella. Vamos a empezar con algo muy simple. Por ejemplo, trata de escribir algo de matemáticas, como `2 + 3` y pulsa Enter. >>> 2 + 3 5 + +¡Bien! ¿Ves como salió la respuesta? ¡Python sabe matemáticas! Podrías intentar otros comandos como: - `4 * 5` - `5 - 1` - `40 / 2` -Bien! ¿Ves como salió la respuesta? Python sabe matemáticas! Podrías intentar otros comandos como: - `4 * 5` - `5 - 1` - `40 / 2` - -Diviértete con esto por un tiempo y luego vuelve aquí :). +Diviértete con esto por un momento y luego vuelve aquí :). Como puedes ver, Python es una gran calculadora. Si te estás preguntando qué más puede hacer... ## Strings -¿Y tu nombre? Escriba tu nombre de pila en frases como ésta: +¿Y tu nombre? Escribe tu nombre de pila en frases como ésta: >>> "Ola" 'Ola' + - -Ahora has creado tu primer string! Es un conjunto de caracteres que pueden ser procesadas por una computadora. La cadena debe comenzar y terminar con el mismo carácter. Esto puede ser comillas simples (`'`) o dobles (`"`) - Python dice que lo que esta dentro de ellas es un string(texto). +¡Has creado tu primer string! Es una secuencia de caracteres que puede ser procesada por una computadora. El string (o en español, cadena) debe comenzar y terminar con el mismo carácter. Esto puede ser comillas simples (`'`) o dobles (`"`) - ellas le dicen a Python que lo que esta dentro es una cadena. Las cadenas pueden ser concatenadas. Prueba esto: - >>> "Hola alli " + "Ola" - 'Hola alli Ola' - + >>> "Hola " + "Ola" + 'Hola Ola' + También puedes multiplicar las cadenas con un número: >>> "Ola" * 3 'OlaOlaOla' - + Si necesitas poner un apóstrofe dentro de tu cadena, tienes dos maneras de hacerlo. -Usar comillas dobles: +Usando comillas dobles: >>> "Runnin' down the hill" "Runnin' down the hill" + - -o escapa el apóstrofo con una barra invertida (``): +o escapando el apóstrofe con una barra invertida (`\`): >>> 'Runnin\' down the hill' "Runnin' down the hill" - + Bien, ¿eh? Para ver tu nombre en letras mayúsculas, simplemente escribe: >>> "Ola".upper() 'OLA' + - -Usaste la **función** `upper` en tu cadena! Una función (como `upper()`) es un conjunto de instrucciones que Python tiene que realizar a un objeto determinado (`"Ola"`) una vez que se llama. +¡Usaste la **función** `upper` en tu cadena! Una función (como `upper()`) es un conjunto de instrucciones que Python tiene que realizar sobre un objeto determinado (`"Ola"`) una vez que se llama. Si quisieras saber el número de letras que contiene tu nombre, también existe una función para esto. >>> len("Ola") 3 + - -Te preguntarás porque a veces se llama a las funciones con un `.` al final de un string (p. ej. `"Ola".upper()`), y a veces primero se llama a una función y se coloca el string entre paréntesis. Bueno, en algunos casos las funciones pertenecen a objetos, como `upper()`, que pueden solo ser utilizadas en strings (cadena de caracteres) En este caso, llamamos a la función de un **método**. Otra veces, las funciones no pertenecen a ninguno especifico y pueden ser usados en diferentes objetos, como `len()`. Eso es porque estamos dando `"Ola"` cono un parámetro a la función `len`. +Te preguntarás por qué a veces se llama a las funciones con un `.` al final de una cadena (como `"Ola".upper()`) y a veces se llama a una función y colocas la cadena entre paréntesis. Bueno, en algunos casos las funciones pertenecen a objetos, como `upper()`, que sólo puede ser utilizado sobre cadenas (upper() es una función de los objetos string). En este caso, llamamos **método** a esta función. Otra veces, las funciones no pertenecen a ningún objeto específico y pueden ser usados en diferentes objetos, como `len()`. Esta es la razón de por qué estamos pasando `"Ola"` como un parámetro a la función `len`. ### Resumen -Ok, suficiente de strings. Hasta ahora has aprendido sobre: +Ok, suficiente sobre las cadenas. Hasta ahora has aprendido sobre: -* **la terminal** - teclea comandos (código) dentro de la terminal de Python para obtener resultados en preguntas en Python +* **la terminal** - teclear comandos (código) dentro de la terminal de Python resulta en respuestas de Python * **números y strings** - en Python los números son usados para matemáticas y strings para objetos de texto -* **operadores** - como + y \*, combinan valores para producir uno nuevo -* **funciones** como upper() y len(), realizan opciones sobre los objetos. +* **operadores** - como + y *, combina valores para producir uno nuevo +* **funciones** - como upper() y len(), realizan opciones sobre los objetos. -Estos son los conocimientos básicos que puedes aprender de cualquier lenguaje de programación. ¿Listo para algo un poco más fuerte? ¡Apostamos que lo estás! +Estos son los conocimientos básicos que puedes aprender de cualquier lenguaje de programación. ¿Lista para algo un poco más difícil? ¡Apostamos que lo estás! ## Errores -Intentemos con algo nuevo. ¿Podríamos obtener la longitud de un número de la misma manera que obtuvimos la longitud de nuestro nombre? Teclea `len(304023)` y presiona `enter`: +Intentemos con algo nuevo. ¿Podríamos obtener la longitud de un número de la misma manera que obtuvimos la longitud de nuestro nombre? Teclea `len(304023)` y presiona Enter: >>> len(304023) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() + - -Tenemos nuestro primer error! Dice que los objetos de tipo "int" (números enteros) no tienen ninguna longitud. ¿Qué podemos hacer ahora? Quizás podemos escribir el numero como un string. Strings tienen longitud, ¿cierto? +¡Obtuvimos nuestro primer error! Dice que los objetos de tipo "int" (números enteros) no tienen ninguna longitud. ¿Qué podemos hacer ahora? Quizás podemos escribir el numero como un string. Los strings tienen longitud, ¿cierto? >>> len(str(304023)) 6 + - -¡Funcionó! Utilizamos la función `str` dentro de la función `len` . `str()` convierte todo a strings. +¡Funcionó! Utilizamos la función `str` dentro de la función `len`. `str()` convierte todo a strings. * La función `str` convierte cosas en **strings** * La función `int` convierte cosas en **integers** -> Importante: podemos convertir números en texto, pero no podemos necesariamente convertir texto en números - ¿qué sería de `int('hello')`? +> Importante: podemos convertir números en texto, pero no podemos necesariamente convertir texto en números - ¿qué sería `int('hello')`? ## Variables -Un concepto importante en programación son las variables. Una variable no es más que un nombre para alguna cosa que tu puedes usar más tarde. Los programadores usan estas variables para almacenar datos, hacer su código más legible y así no tener que seguir recordando que hace cada cosa. +Un concepto importante en programación son las variables. Una variable no es más que un nombre para alguna cosa para que puedas usarla más tarde. Los programadores usan estas variables para almacenar datos, hacer su código más legible y así no tener que seguir recordando qué hace cada cosa. -Supongamos que queremos crear una nueva variable llamada `nombre`: +Supongamos que queremos crear una nueva variable llamada `name`: >>> name = "Ola" - + ¿Ves? ¡Es fácil! Es simplemente: name equivale a Ola. -Como te has dado cuenta, el programa no regresa algo como lo hacia antes. Entonces, ¿Cómo sabemos que la variable existe realmente? Simplemente introduce `name` y pulsa `enter`: +Como te has dado cuenta, el programa no regresa algo como lo hacia antes. Entonces, ¿Cómo sabemos que la variable existe realmente? Simplemente introduce `name` y pulsa Enter: >>> name 'Ola' + - -Súper! La primera variable :). Siempre podrás cambiar lo que se refiere a: +¡Súper! Tu primer variable :). Siempre podrás cambiar a lo que se refiere: >>> name = "Sonja" >>> name 'Sonja' + - -Puedes usarla dentro de las funciones: +Puedes usarla dentro de funciones también: >>> len(name) 5 + - -¿Increíble, cierto? Por supuesto, las variables pueden ser cualquier cosa, también números! Prueba esto: +Increíble, ¿verdad? Por supuesto, las variables pueden ser cualquier cosa, ¡también números! Prueba esto: >>> a = 4 >>> b = 6 >>> a * b 24 + - -Pero ¿qué pasa si usamos el nombre equivocado? ¿Puedes adivinar qué pasaría? Vamos a probar! +Pero ¿qué pasa si usamos el nombre equivocado? ¿Puedes adivinar qué pasaría? ¡Vamos a probar! >>> city = "Tokyo" >>> ctiy Traceback (most recent call last): - File "", line 1, in +   File "", line 1, in NameError: name 'ctiy' is not defined + - -Un error! Como puedes ver, Python tiene diferentes tipos de errores y estos se llaman **NameError**. Python te dará este error si intenta utilizar una variable que no ha sido definida aún. Si más adelante te encuentra con este error, verifica tu código para ver si es que no haya ningún nombre. +¡Un error! Como puedes ver, Python tiene diferentes tipos de errores y este se llama **NameError**. Python te dará este error si intentas utilizar una variable que no ha sido definida aún. Si más adelante te encuentras con este error, verifica tu código para ver si no has escrito mal una variable. Juega con esto por un rato y mira que puedes hacer! @@ -184,163 +184,163 @@ Intenta esto: 'Maria' >>> print(name) Maria + +Cuando sólo escribes `name`, el intérprete de Python responde con la *representación* del string de la variable 'name', que son las letras M-a-r-i-a, rodeadas de comillas simples ''. Cuando dices `print(name)`, Python va a "imprimir" el contenido de la variable a la pantalla, sin las comillas, que es mejor. -Cuando sólo se escribe `name`, el intérprete de Python responde con la *representación* de la variable 'name', que es las letras M-a-r-i-a, rodeadas de comillas simples ''. Cuando dices `print(name)`, Python va a "Imprimir" el contenido de la variable a la pantalla, sin las comillas, que es mejor. - -Como veremos después, print() también es útil cuando queremos imprimir cosas dentro de las funciones, o bien cuando queremos imprimir cosas en múltiples lineas. +Como veremos después, `print()` también es útil cuando queremos imprimir cosas desde adentro de las funciones, o bien cuando queremos imprimir cosas en múltiples líneas. ## Listas -Entre string e integers, Python tiene todo tipo de diferentes tipos de objetos. Ahora vamos a introducir una llamada **list**. Las listas son exactamente lo que piensas que son: son objetos que son listas de otros objetos :) +Además de string e integers, Python tiene toda clase de diferentes tipos de objetos. Ahora vamos a introducir uno llamado **list**. Las listas son exactamente lo que piensas que son: son objetos que son listas de otros objetos :) -Adelante y crear una lista: +Anímate y crea una lista: >>> [] [] + - -Sí, esta lista está vacía. No es muy útil, ¿verdad? Vamos a crear una lista de números de la lotería. No queremos repetirlos todo el tiempo, así que lo pondremos en una variable, también: +Sí, esta lista está vacía. No es muy útil, ¿verdad? Vamos a crear una lista de números de lotería. No queremos repetir todo el tiempo, así que los pondremos en una variable también: >>> lottery = [3, 42, 12, 19, 30, 59] + - -Muy bien, tenemos una lista! ¿Qué podemos hacer con él? Vamos a ver cuántos números de la lotería. ¿Tienes alguna idea de función que debe usar para eso? Ya sabes esto! +Muy bien, ¡tenemos una lista! ¿Qué podemos hacer con ella? Vamos a ver cuántos números de lotería hay en la lista. ¿Tienes alguna idea de qué función deberías usar para eso? ¡Ya sabes esto! >>> len(lottery) 6 + - -¡Sí! `Len()` puede dar un número de objetos en una lista. ¿Wow, verdad? Tal vez lo resolvamos ahora: +¡Sí! `len()` puede darte el número de objetos en una lista. Útil, ¿verdad? Tal vez la ordenemos ahora: >>> lottery.sort() + - -Esto no devuelve nada, sólo cambia el orden en que los números aparecen en la lista. Vamos a imprimir otra vez y ver que pasó: +Esto no devuelve nada, sólo cambió el orden en que los números aparecen en la lista. Vamos a imprimir la lista otra vez y ver que pasó: >>> print(lottery) [3, 12, 19, 30, 42, 59] + +Como puedes ver, los números en tu lista ahora están ordenados de menor a mayor. ¡Felicidades! -Como puedes ver, los números en la lista ahora están ordenados de menor a mayor. ¡Felicidades! - -¿Tal vez queremos invertir ese orden? Vamos a hacerlo! +¿Te gustaría invertir ese orden? ¡Vamos a hacerlo! >>> lottery.reverse() >>> print(lottery) [59, 42, 30, 19, 12, 3] + - -Fácil, verdad? Si quieres añadir algo a tu lista, puedes hacerlo escribiendo este comando: +Fácil, ¿no? Si quieres añadir algo a tu lista, puedes hacerlo escribiendo este comando: >>> lottery.append(199) >>> print(lottery) [59, 42, 30, 19, 12, 3, 199] + - -Si desea mostrar sólo el primer número, puede hacerlo mediante el uso de **indixes**. Un index es el numero que se muestra en una lista como una ocurrencia. La computadora inicia la cuenta en 0, así que el primer objeto en la lista es en el índice 0, el siguiente es 1, y así sucesivamente. Intenta esto: +Si deseas mostrar sólo el primer número, puedes hacerlo mediante el uso de **indexes** (en español, índices). Un índice es el número que te dice dónde en una lista aparece un ítem. La computadora inicia la cuenta en 0, así que el primer objeto en tu lista está en el índice 0, el siguiente es 1, y así sucesivamente. Intenta esto: >>> print(lottery[0]) 59 >>> print(lottery[1]) 42 + +Como puedes ver, puedes acceder a diferentes objetos en tu lista utilizando el nombre de la lista y el índice del objeto dentro de corchetes. -Como puedes ver, puedes acceder a diferentes objetos en la lista utilizando el nombre de la lista y el índice del objeto dentro de corchetes. - -Para diversión adicional, prueba algunos otros índices: 6, 7, 1000, -1, -6 ó -1000. A ver si se puede predecir el resultado antes de intentar el comando. ¿Tienen sentido los resultados? +Para diversión adicional, prueba algunos otros índices: 6, 7, 1000, -1, -6 ó -1000. A ver si se puedes predecir el resultado antes de intentar el comando. ¿Tienen sentido los resultados? -Puedes encontrar una lista de todos los métodos disponibles de la lista en este capítulo de la documentación de Python: https://docs.python.org/3/tutorial/datastructures.html +Puedes encontrar una lista de todos los métodos disponibles para listas en este capítulo de la documentación de Python: https://docs.python.org/3/tutorial/datastructures.html ## Diccionarios -Un diccionario es similar a una lista, pero accedes a valores mediante una llave en lugar de un índice. Una llave puede ser cualquier cadena o número. La sintaxis para definir un diccionario vacío es: +Un diccionario es similar a una lista, pero accedes a valores usando una clave en vez de un índice. Una clave puede ser cualquier cadena o número. La sintaxis para definir un diccionario vacío es: >>> {} {} - + Esto demuestra que acabas de crear un diccionario vacío. ¡Hurra! -Ahora, trata de escribir el siguiente comando (trata de reemplazando tu propia información): +Ahora, trata escribiendo el siguiente comando (intenta reemplazando con propia información): >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + +Con este comando, acabas de crear una variable `participant` con tres pares clave-valor: -Con este comando, que acaba de crear una variable denominada `participante` con tres pares de clave y valor: - -* El `name` apunta al valor `'Ola'` (un objeto `string`), +* La clave `name` apunta al valor `'Ola'` (un objeto `string`), * `country` apunta a `'Poland'` (otro `string`), -* y `favorite_numbers` apunta a `[7, 42, 92]` (una `list` con tres números en el). +* y `favorite_numbers` apunta a `[7, 42, 92]` (una `list` con tres números en ella). -Puedes verificar el contenido de llaves individuales con esta sintaxis: +Puedes verificar el contenido de claves individuales con esta sintaxis: >>> print(participant['name']) Ola + +Lo ves, es similar a una lista. Pero no necesitas recordar el índice - sólo el nombre. -Mira, es similar a una lista. Pero no necesitas recordar el índice - sólo el nombre. - -¿Qué pasa si pedimos a Python el valor de una llave que no existe? ¿Puedes adivinar? ¡Pruébalo y verá! +¿Qué pasa si le pedimos a Python el valor de una clave que no existe? ¿Puedes adivinar? ¡Pruébalo y verás! >>> participant['age'] Traceback (most recent call last): File "", line 1, in KeyError: 'age' + +¡Mira, otro error! Este es un **KeyError**. Python te ayuda y te dice que la llave `'age'` no existe en este diccionario. -¡Mira, otro error! Este es un **KeyError**. Python es de ayuda y te dice que la llave `'age'` no existe en este diccionario. - -¿Cuándo utilizar un diccionario o una lista? Bueno, eso es un buen punto para reflexionar. Sólo ten una solución en mente antes de mirar la siguiente respuesta. +¿Cuándo utilizar un diccionario o una lista? Bueno, eso es un buen punto para reflexionar. Sólo ten una solución en mente antes de mirar la respuesta en la siguiente línea. * ¿Sólo necesitas una secuencia ordenada de elementos? Usa una lista. -* ¿Necesita asociar valores claves, así que puedas consultarlos eficientemente (por llaves) más adelante? Utiliza un diccionario. +* ¿Necesitas asociar valores con claves, así puedes buscarlos eficientemente (usando las claves) más adelante? Utiliza un diccionario. -Diccionarios, parecen listas, son *mutables*, lo que significa que pueden ser cambiados después de ser creados. Puedes agregar nuevos pares clave-valor en el diccionario después de que se crea, ejemplo: +Los diccionarios, como las listas, son *mutables*, lo que significa que pueden ser cambiados después de ser creados. Puedes agregar nuevos pares clave/valor en el diccionario después de que ha sido creado, por ejemplo: >>> participant['favorite_language'] = 'Python' + - -Como listas, método en los diccionarios, `len()` devuelve el número de pares clave-valor en el diccionario. Adelante, escribe el comando: +Como en las listas, el método `len()` en los diccionarios, devuelve el número de pares clave-valor en el diccionario. Adelante, escribe el comando: >>> len(participant) 4 - + Espero tenga sentido hasta ahora. :) ¿Lista para más diversión con los diccionarios? Salta a la siguiente línea para algunas cosas sorprendentes. -Puedes utilizar el comando `del` para borrar un elemento en el diccionario. Si deseas eliminar la entrada correspondiente a la clave `'favorite_numbers'`, sólo tienes que escribir el siguiente comando: +Puedes utilizar el comando `pop()` para borrar un elemento en el diccionario. Por ejemplo, si deseas eliminar la entrada correspondiente a la clave `'favorite_numbers'`, sólo tienes que escribir el siguiente comando: - >>> del participant['favorite_numbers'] + >>> participant.pop('favorite_numbers') >>> participant {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + +Como puedes ver en la salida, el par de clave-valor correspondiente a la clave 'favorite_numbers' ha sido eliminado. -Como puedes ver en la salida, el par de clave y valor correspondiente a la tecla de 'favorite_numbers' ha sido eliminado. - -Además, también puedes cambiar un valor asociado a una clave ya creada en el diccionario. Teclea: +Además de esto, también puedes cambiar un valor asociado a una clave ya creada en el diccionario. Teclea: >>> participant['country'] = 'Germany' >>> participant {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + - -Como puedes ver, el valor de la clave `'country'` ha sido alterado de `'Poland'` a `'Germany'`. :) ¿Emocionante? ¡Hurra! Has aprendido otra cosa asombrosa. +Como puedes ver, el valor de la clave `'country'` ha sido modificado de `'Poland'` a `'Germany'`. :) ¿Emocionante? ¡Hurra! Has aprendido otra cosa asombrosa. ### Resumen -Impresionante! Sabes mucho sobre programación ahora. En esta última parte aprendiste sobre: +¡Genial! Sabes mucho sobre programación ahora. En esta última parte aprendiste sobre: -* **errors** - ahora sabe cómo leer y entender los errores que aparecen si Python no entiende un comando que has dado -* **variables** - nombres para los objetos que permiten codificar más fácilmente y hacer el código más legible -* **lists** - las listas de objetos almacenados en un orden determinado -* **dictionaries** - objetos almacenados como pares de clave y valor +* **errors** - ahora sabes cómo leer y entender los errores que aparecen si Python no entiende un comando que le has dado +* **variables** - nombres para los objetos que te permiten codificar más fácilmente y hacer el código más legible +* **lists** - listas de objetos almacenados en un orden determinado +* **dictionaries** - objetos almacenados como pares clave-valor ¿Emocionada por la siguiente parte? :) ## Compara cosas -Una gran parte de la programación incluye comparar cosas. ¿Qué es más fácil comparar? Números, por supuesto. Vamos a ver cómo funciona: +Una gran parte de la programación incluye comparar cosas. ¿Qué es lo más fácil para comparar? Números, por supuesto. Vamos a ver cómo funciona: >>> 5 > 2 True @@ -350,41 +350,43 @@ Una gran parte de la programación incluye comparar cosas. ¿Qué es más fácil True >>> 1 == 1 True + >>> 5 != 2 + True + +Le dimos a Python algunos números para comparar. Como puedes ver, Python no sólo puede comparar números, sino que también puede comparar resultados de método. Bien, ¿eh? -Le dimos a Python algunos números para comparar. Como puedes ver, Python puede comparar no sólo números, pero también puede comparar resultados de método. Bien, ¿eh? - -¿Te preguntas por qué pusimos dos signos de igual `==` al lado del otro para comparar si los números son iguales? Utilizamos un solo `=` para asignar valores a las variables. Siempre, **siempre** es necesario poner dos `==` Si desea comprobar si las cosas son iguales entre sí. +¿Te preguntas por qué pusimos dos signos igual `==` al lado del otro para comparar si los números son iguales? Utilizamos un solo `=` para asignar valores a las variables. Siempre, **siempre** es necesario poner dos `==` Si deseas comprobar que las cosas son iguales entre sí. También podemos afirmar que las cosas no son iguales a otras. Para eso, utilizamos el símbolo `!=`, como mostramos en el ejemplo anterior. -Dan a Python dos tareas más: +Da dos tareas más a Python: >>> 6 >= 12 / 2 True >>> 3 <= 2 False + +`>` y `<` son fáciles, pero ¿qué es significa `> =` y `< =`? Se leen así: -`>` y `<` son fáciles, pero ¿qué es significa `>=` y `<=`? Se leen así: - -* x `>` y significa: x es mayor grande que y +* x `>` y significa: x es mayor que y * x `<` y significa: x es menor que y -* x `<=` y significa: x es menor o igual a y -* x `>=` y significa: x es mayor o igual a y +* x `<=` y significa: x es menor o igual que y +* x `>=` y significa: x es mayor o igual que y ¡Genial! ¿Quieres hacer uno mas? Intenta esto: - >>> 6 > 2 y 2 < 3 + >>> 6 > 2 and 2 < 3 True - >>> 3 > 2 y 2 < 1 + >>> 3 > 2 and 2 < 1 False - >>> 3 > 2 ó 2 < 1 + >>> 3 > 2 or 2 < 1 True + +Puedes darle a Python todos los números para comparar que quieras, y siempre te dará una respuesta. Muy inteligente, ¿verdad? -Puedes darle a Python muchos números para comparar, y te dará una respuesta! Muy inteligente, verdad? - -* **and** - Si utilizas el operador `and`, las comparaciones deben estar en orden para que sea True -* **or** - Si utilizas el operador `or`, sólo una de las comparaciones tiene que ser verdadera para ser True +* **and** - si utilizas el operador `and`, ambas comparaciones deben ser True para que el resultado de todo el comando sea True +* **or** - si utilizas el operador `or`, sólo una de las comparaciones tiene que ser True para que el resultado de todo el comando sea True ¿Has oído la expresión "comparar manzanas con naranjas"? Vamos a probar el equivalente en Python: @@ -392,147 +394,154 @@ Puedes darle a Python muchos números para comparar, y te dará una respuesta! M Traceback (most recent call last): File "", line 1, in TypeError: unorderable types: int() > str() + - -Aquí verás que al igual que en la expresión, Python no es capaz de comparar un número (`int`) y una string (`str`). En cambio, se muestra un **TypeError** y nos dice que no se puede comparar los dos tipos. +Aquí verás que al igual que en la expresión, Python no es capaz de comparar un número (`int`) y un string (`str`). En cambio, muestra un **TypeError** y nos dice que los dos tipos no se pueden comparar. ## Boolean -Por cierto, acabas de aprender acerca de un nuevo tipo de objeto en Python. Se llama un **boolean**--y es probable el más sencillo. +Por cierto, acabas de aprender acerca de un nuevo tipo de objeto en Python. Se llama un **Boolean** -- y es probablemente el tipo más simple que existe. Hay sólo dos objetos Boolean: - True - False -Pero para que Python entender esto, es necesario siempre escribir como True (primera letra mayúscula, con el resto de la letra minúscula). **true, TRUE, tRUE no funcionan -- sólo True es correcto.** (Lo mismo aplica a False, por supuesto.) +Pero para que Python entienda esto, es necesario que siempre lo escribas como True (primera letra mayúscula, con el resto de la letras minúsculas). **true, TRUE, tRUE no funcionarán -- sólo True es correcto.** (Lo mismo aplica a False también, por supuesto.) -Valores booleans pueden ser variables, también! Ve aquí: +Los valores booleanos pueden ser variables, también. Ve el siguiente ejemplo: >>> a = True >>> a True - + También puedes hacerlo de esta manera: >>> a = 2 > 5 >>> a False + - -Practica y diviértete con booleanos corriendo los siguientes comandos: +Practica y diviértete con los booleanos ejecutando los siguientes comandos: * `True and True` * `False and True` * `True or 1 == 1` * `1 != 2` -¡Felicidades! Los booleans son de las mejores funciones en la programación y acabas de aprender como usarlos. +¡Felicidades! Los booleanos son una de las funciones más geniales en programación y acabas de aprender cómo usarlos. # ¡Guárdalo! -Hasta ahora hemos estado escribiendo nuestro código de python en el intérprete, lo cual nos limita a una línea de código a la vez. Programas normales son guardados en archivos y ejecutados por el **intérprete** o **compiler** de nuestro idioma de programación. Hemos estado corriendo nuestros programas una linea a la vez en el **intérprete** de Python. Necesitaremos mas de una linea de código para las siguientes tareas, entonces necesitaremos hacer rápidamente lo siguiente: +Hasta ahora hemos estado escribiendo nuestro código Python en el intérprete, lo cual nos limita a una línea de código a la vez. Normalmente los programas son guardados en archivos y son ejecutados por el **intérprete** o **compilador** de nuestro lenguaje de programación. Hasta ahora, hemos estado corriendo nuestros programas de a una línea por vez en el **intérprete** de Python. Necesitaremos más de una línea de código para las siguientes tareas, entonces necesitaremos hacer rápidamente lo que sigue: * Salir del intérprete de Python * Abrir el editor de texto de nuestra elección -* Guardar algo de código en un nuevo archivo de python -* ¡Correrlo! +* Guardar algo de código en un nuevo archivo de Python +* ¡Ejecutarlo! -Para salir del interprete de Python que hemos estado usando, simplemente escribe la función de ~~~ exit() ~~~: +Para salir del intérprete de Python que hemos estado usando, simplemente escribe la función exit(): >>> exit() $ + +Esto te llevará de vuelta a la línea de comandos. -Esto te llevará de vuelta a la linea de comando. +Anteriormente, elegimos un editor de código en la sección de [Editor de código][2]. Tendremos que abrir el editor ahora y escribir algo de código en un archivo nuevo: -Anteriormente, elegimos un editor de código en la sección de [code editor][2]. Tendremos que abrir el editor ahora y escribir algo de código en un archivo nuevo: - - [2]: code_editor/README.md + [2]: ../code_editor/README.md +``` python print('Hello, Django girls!') +``` +> **Nota** Deberías notar una de las cosas más geniales de los editores de código: ¡los colores! En la consola de Python, todo era del mismo color, pero ahora puedes ver que la función `print` es de un color diferente del string que está adentro de ella. Eso se denomina "resaltado de sintaxis", y es una gran ayuda cuando estás programando. Presta atención a los colores, y obtendrás una pista cuando te olvides de cerrar un string o cometes un error al escribir una palabra clave (como el `def` en una función, que veremos abajo). Esta es una de las razones por las cuales usar un editor de código :) -Obviamente, ahora eres una desarrolladora Python muy experimentada, así que siéntete libre de escribir algún código que has aprendido hoy. +Obviamente, ahora eres una desarrolladora Python muy experimentada, así que siéntete libre de escribir algo del código que has aprendido hoy. -Ahora tenemos que guardar el archivo y asignarle un nombre. Vamos a llamar al archivo **python_intro.py** y guárdalo en tu escritorio. Podemos nombrar el archivo de cualquier manera que queramos, lo importante aquí es asegurarse que el archivo finalice con **.py**, esto indica nuestro ordenador que este es un **archivo ejecutable de Python**. +Ahora tenemos que guardar el archivo y asignarle un nombre descriptivo. Vamos a llamar al archivo **python_intro.py** y guardarlo en tu escritorio. Podemos nombrar el archivo de cualquier manera que queramos, lo importante aquí es asegurarse que el archivo finalice con **.py**, esto le indica a nuestra computadora que este es un **archivo ejecutable de Python** y que Python puede correrlo. -Con el archivo guardado, es hora de ejecutarlo. Utilizando las habilidades que has aprendido en la sección de línea de comandos, utiliza la terminal para **cambiar los directorios** al escritorio. +Con el archivo guardado, ¡es hora de ejecutarlo! Utilizando las habilidades que has aprendido en la sección de línea de comandos, utiliza la terminal para **cambiar los directorios** e ir al escritorio. -En un Mac, el comando se verá algo como esto: +En una Mac, el comando se verá algo como esto: cd /Users//Desktop + - -En Linux, va a ser así (la palabra "Desktop" puede ser traducido a su idioma): +En Linux, va a ser así (la palabra "Desktop" puede estar traducida a tu idioma): cd /home//Desktop + - -Y en windows, será así: +Y en Windows, será así: cd C:\Users\\Desktop - + Si te quedas atascada, sólo pide ayuda. -y luego usa Python para ejecutar el código en el archivo como este: +y luego usa Python para ejecutar el código en el archivo como sigue: $ python3 python_intro.py Hello, Django girls! + - -Muy bien! Ejecutaste tu primer programa de Python. ¿Se siente increíble? +¡Muy bien! Ejecutaste tu primer programa de Python desde un archivo. ¿No se siente increíble? Ahora puedes moverte a una herramienta esencial en la programación: ## If...elif...else -Un montón de cosas en el código sólo son ejecutadas cuando se cumplen las condiciones. Por eso Python tiene algo llamado **sentencias if**. +Un montón de cosas en el código sólo son ejecutadas cuando se cumplen las condiciones dadas. Por eso Python tiene algo llamado **sentencias if**. -Reemplace el código en el archivo **python_intro.py** por esto: +Reemplaza el código en tu archivo **python_intro.py** por esto: +``` python if 3 > 2: +``` - -Si guardamos y ejecutams, veríamos un error como este: +Si lo guardáramos y lo ejecutáramos, veríamos un error como este: $ python3 python_intro.py File "python_intro.py", line 2 ^ SyntaxError: unexpected EOF while parsing + +Python espera que le demos más instrucciones que se supone serán ejecutadas si la condición `3 > 2` resulta ser verdadera (o `True` en este caso). Intentemos hacer que Python imprima "It works!". Cambia tu código en el archivo **python_intro.py** para que se vea como esto: -Python da más instrucciones para lo que se suponen se ejecutará si la condición `3 > 2` resulta ser verdadera (o `True` para el caso). Intentemos hacer Python print "¡funciona!". Cambiar tu código en el archivo **python_intro.py** a esto: - +``` python if 3 > 2: print('It works!') +``` +¿Observas cómo hemos indentado la siguiente línea de código con 4 espacios? Tenemos que hacer esto para que Python sepa qué código ejecutar si la comparación resulta verdadera. Puedes poner un espacio, pero casi todos los programadores Python hacen 4 espacios para hacer que el código sea más legible. Un solo tab también contará como 4 espacios. -¿Ves cómo nos hemos puesto una sangría en la siguiente línea de código con 4 espacios? Tenemos que hacer esto para que Python sepa que el código resulta ser verdad. Puedes hacer un espacio, pero casi todos los programadores Python hacen 4 para hacerlo más legible. Un solo `tab` también contará como 4 espacios. - -Guarda y ejecútalo de nuevo: +Guárdalo y ejecútalo de nuevo: $ python3 python_intro.py It works! + - -### ¿Qué pasa si no? +### ¿Qué pasa si la condición no es verdadera? En ejemplos anteriores, el código fue ejecutado sólo cuando las condiciones eran ciertas. Pero Python también tiene declaraciones `elif` y `else`: +```python if 5 > 2: print('5 is indeed greater than 2') else: print('5 is not greater than 2') +``` - -Cuando esto se ejecute imprimiría: +Al ejecutar esto se imprimirá: $ python3 python_intro.py 5 is indeed greater than 2 + +Si 2 fuera un número mayor que 5, entonces el segundo comando sería ejecutado. Fácil, ¿verdad? Vamos a ver cómo funciona `elif`: -Si 2 fuera un número mayor que 5, entonces el segundo comando sería ejecutado. Fácil, verdad? Vamos a ver cómo funciona `elif`: - +``` python name = 'Sonja' if name == 'Ola': print('Hey Ola!') @@ -540,13 +549,13 @@ Si 2 fuera un número mayor que 5, entonces el segundo comando sería ejecutado. print('Hey Sonja!') else: print('Hey anonymous!') +``` - -y ejecutado: +y al ejecutarlo: $ python3 python_intro.py Hey Sonja! - + ¿Ves lo que pasó ahí? @@ -554,44 +563,47 @@ y ejecutado: En los últimos tres ejercicios aprendiste acerca de: -* **comparando cosas** - en Python puedes comparar cosas mediante el uso de `>`, `>=`, `==`, `<=`, `<` y los operadores `y` y `o` +* **Comparar cosas** - en Python puedes comparar cosas haciendo uso de `>`, `>=`, `==`, `<=`, `<` y de los operatores `and` y `or` * **Boolean** - un tipo de objeto que sólo puede tener uno de dos valores: `True` o `False` -* **Guardar archivos** - almacenar código en archivos y puede ejecutar programas más grandes. -* **si... elif... else** - las sentencias permiten ejecutar código sólo cuando se cumplan ciertas condiciones. +* **Guardar archivos** - cómo almacenar código en archivos así puedes ejecutar programas más grandes +* **if... elif... else** - sentencias que te permiten ejecutar código sólo cuando se cumplen ciertas condiciones -Sigue la última parte de este capítulo. +¡Es hora de leer la última parte de este capítulo! -## Tus propias funciones! +## ¡Tus propias funciones! -¿Recuerdas las funciones como `len()` que puedes ejecutar en Python? Buenas noticias, aprenderás cómo escribir tus propias funciones ahora! +¿Recuerdas las funciones como `len()` que puedes ejecutar en Python? Bien, buenas noticias, ¡ahora aprenderás cómo escribir tus propias funciones! -Una función es un conjunto de instrucciones que deben ser ejecutadas en Python. Cada función en Python comienza con la palabra clave `def`, se asigna un nombre y puede tener algunos parámetros. Vamos a empezar con algo fácil. Reemplace el código en **python_intro.py** con lo siguiente: +Una función es una secuencia de instrucciones que Python debe ejecutar. Cada función en Python comienza con la palabra clave `def`, se le asigna un nombre y puede tener algunos parámetros. Vamos a empezar con algo fácil. Reemplaza el código en **python_intro.py** con lo siguiente: +``` python def hi(): print('Hi there!') print('How are you?') - + hi() +``` +Bien, ¡nuestra primera función está lista! -Bien, nuestra primera función está lista! +Te preguntarás por qué hemos escrito el nombre de la función en la parte inferior del archivo. Esto es porque Python lee el archivo y lo ejecuta desde arriba hacia abajo. Así que para poder utilizar nuestra función, tenemos que reescribir su nombre en la parte inferior. -Te preguntarás por qué hemos escrito el nombre de la función en la parte inferior del archivo. Esto es porque Python lee el archivo y ejecuta desde arriba hacia abajo. Así que para poder utilizar nuestra función, tenemos que escribirla en la parte inferior. - -Hay que ejecutar esto y ver lo que sucede: +Ejecutemos esto y veamos qué sucede: $ python3 python_intro.py Hi there! How are you? + +¡Eso fue fácil! Vamos a construir nuestra primera función con parámetros. Utilizaremos el ejemplo anterior - una función que dice 'Hi' a la persona que ejecuta el programa - con un nombre: -Eso fue fácil! Vamos a construir nuestra primera función con parámetros. Utilizaremos el ejemplo anterior - una función que dice 'Hi' a la persona - con un nombre: - +``` python def hi(name): - +``` Como puedes ver, ahora dimos a nuestra función un parámetro que llamamos `name`: +``` python def hi(name): if name == 'Ola': print('Hi Ola!') @@ -599,94 +611,100 @@ Como puedes ver, ahora dimos a nuestra función un parámetro que llamamos `name print('Hi Sonja!') else: print('Hi anonymous!') - + hi() +``` - -Como puedes ver, teníamos que poner dos guiones antes de la función `print`, porque `if` necesita saber lo que debe ocurrir cuando se cumple la condición. Vamos a ver cómo funciona: +Como puedes notar, tuvimos que poner dos indentaciones antes de la función `print` porque `if` necesita saber lo que debería ocurrir cuando se cumple la condición. Vamos a ver cómo funciona: $ python3 python_intro.py Traceback (most recent call last): File "python_intro.py", line 10, in hi() TypeError: hi() missing 1 required positional argument: 'name' + +Oops, un error. Por suerte, Python nos da un mensaje de error bastante útil. Nos dice que la función `hi()` (la que definimos) tiene un argumento requerido (llamado `name`) y que se nos olvidó pasarlo al llamar a la función. Vamos a arreglarlo en la parte inferior del archivo: -Ops, un error. Por suerte, Python nos da un mensaje de error bastante útil. Nos dice que la función `hi()` tiene un argumento requerido `(name)` y que se nos olvidó pasarlo al llamar a la función. Vamos a arreglarlo en la parte inferior del archivo: - +``` python hi("Ola") +``` - -y otra vez: +y lo ejecutamos otra vez: $ python3 python_intro.py Hi Ola! - + ¿Y si cambiamos el nombre? +``` python hi("Sonja") +``` - -y ejecutamos: +y lo corremos: $ python3 python_intro.py Hi Sonja! + - -Ahora ¿qué crees que pasará si escribes otro nombre allí? (No Ola o Sonja) Prueba y verás si tienes razón. Esto debe imprimir: +Ahora, ¿qué crees que pasará si escribes otro nombre allí? (No Ola o Sonja). Pruébalo y verás si tienes razón. Esto debería imprimir: Hi anonymous! + - -Esto es increíble, ¿verdad? Así no tienes que repetirlo cada vez que deseas cambiar el nombre de la persona. Y eso es exactamente por qué necesitamos funciones - para no repetir tu código! +Esto es increíble, ¿verdad? De esta forma no tienes que repetir todo cada vez que deseas cambiar el nombre de la persona a la que la función debería saludar. Y eso es exactamente el por qué necesitamos funciones - ¡para no repetir tu código! Vamos a hacer algo más inteligente - hay más de dos nombres, y escribir una condición para cada uno sería difícil, ¿no? +``` python def hi(name): print('Hi ' + name + '!') - + hi("Rachel") - +``` Ahora vamos a llamar al código: $ python3 python_intro.py Hi Rachel! - + ¡Felicidades! Acabas de aprender cómo escribir funciones :) -## Loops +## Bucles -Ya es la última parte. ¿Eso fue rápido, verdad? :) +Esta ya es la última parte. ¿Eso fue rápido, verdad? :) -Como hemos mencionado, los programadores son perezosos, no les gusta repetir. Programación es automatizar las cosas, así que no queremos saludar a cada persona por su nombre manualmente, ¿verdad? Es ahí donde los ciclos son muy útil. +Como hemos mencionado, los programadores son perezosos, no les gusta repetir cosas. La programación intenta automatizar las cosas, así que no queremos saludar a cada persona por su nombre manualmente, ¿verdad? Es ahí donde los bucles se vuelven muy útiles. -¿Todavía recuerda las listas? Hagamos una lista de las chicas: +¿Todavía recuerdas las listas? Hagamos una lista de las chicas: +``` python girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` +Queremos saludar a todas ellas por su nombre. Tenemos la función `hi` que hace eso, así que vamos a usarla en un bucle: -Queremos saludar a todas ellas por su nombre. Tenemos la función `Hi` que hace eso, así que vamos a usarlo en un ciclo: - +``` python for name in girls: +``` - -La sentencia ~ ~ ~ for ~ ~ ~ se comporta de manera similar a la sentencia ~ ~ ~ if ~ ~ ~, ve el código a continuación ambos necesitan ser ident a cuatro espacios. +La sentencia for se comporta de manera similar a la sentencia if, el código que sigue a continuación debe estar indentado usando cuatro espacios. Aquí está el código completo que estará en el archivo: +``` python def hi(name): print('Hi ' + name + '!') - + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] for name in girls: hi(name) print('Next girl') +``` - -y cuando lo eejcutamos: +y cuando lo ejecutamos: $ python3 python_intro.py Hi Rachel! @@ -699,34 +717,34 @@ y cuando lo eejcutamos: Next girl Hi You! Next girl + +Como puedes ver, todo lo que pones con una indentación dentro de una sentencia `for` será repetido para cada elemento de la lista `girls`. -Como puedes ver, se repetirá todo lo que pones dentro de una instrucción `for` con una sangría para cada elemento de la lista de `girls`. - -También puedes usar `for` en números usando el método `range`: +También puedes usar el `for` en números usando la función `range`: for i in range(1, 6): print(i) + - -Lo cual imprime: +Lo que imprimirá: 1 2 3 4 5 - + `range` es una función que crea una lista de números en serie (estos números son proporcionados por ti como parámetros). -Ten en cuenta que la segunda de estas dos cifras no está incluida en la lista que es de salida en Python (significado `range(1, 6)` cuenta desde 1 a 5, pero no incluye el número 6). +Ten en cuenta que el segundo de estos dos números no será incluido en la lista que retornará Python (es decir, `range(1, 6)` cuenta desde 1 a 5, pero no incluye el número 6). ## Resumen -Eso es todo. **Eres totalmente genial!** Esto realmente no fue tan fácil, así que deberías sentirte orgullosa de ti misma. Estamos definitivamente orgullosos de que hayas llegado hasta aquí! +Eso es todo. **¡Eres genial!** Esto no fue tan fácil realmente, así que deberías sentirte orgullosa de ti misma. ¡Estamos muy orgullosos de que hayas llegado hasta aquí! -Agarra un cupcake y vamos al siguiente capítulo :) +Tal vez quieras hacer algo distinto por un momento - estirarte, caminar un poco, descansar tus ojos - antes de pasar al siguiente capítulo. :) ![Cupcake][3] diff --git a/es/template_extending/README.md b/es/template_extending/README.md index a7891a6d2f4..a7fb7d7a133 100755 --- a/es/template_extending/README.md +++ b/es/template_extending/README.md @@ -1,12 +1,12 @@ # Extendiendo Plantillas -Otra cosa buena que Django tiene para tí es la **extensión de plantillas** ¿Qué significa esto? Significa que puedes usar las mismas partes de tu HTML en diferentes páginas de tu sitio. +Otra cosa buena que Django tiene para tí es la **extensión de plantillas**. ¿Qué significa esto? Significa que puedes usar las mismas partes de tu HTML para diferentes páginas de tu sitio web. -De esta manera no tienes que repetir lo mismo en cada archivo, cuando quieras usar la misma información/layout. Y si quieres cambiar algo,no tienes que hacerlo en cada plantilla, ¡solo una vez! +De esta forma no tienes que repetir el código en cada uno de los archivos cuando quieres usar una misma información o un mismo esquema. Y si quieres cambiar algo, no necesitas hacerlo en cada plantilla. ## Creando una plantilla base -Una plantilla base es la más básica de las plantillas que quieras extender en cada página de tu sitio. +Una plantilla base es la plantilla más básica que extiendes en cada página de tu sitio web. Vamos a crear un archivo `base.html` en `blog/templates/blog/`: @@ -17,114 +17,106 @@ Vamos a crear un archivo `base.html` en `blog/templates/blog/`: post_list.html -Luego abrelo y copia todo de `post_list.html` al archivo `base.html`, de la siguiente manera: +Luego ábrelo y copia todo lo que hay en `post_list.html` al archivo `base.html`, de la siguiente manera: ```html -{% load staticfiles %} - - - Django Girls blog - - - - - - + {% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Luego, en `base.html` reemplaza por completo tu `` (todo lo que haya entre `` and ``) con esto: + +``` html -
- {% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- {% endfor %} + {% block content %} + {% endblock %}
- ``` +Básicamente remplazamos todo entre `{% for post in posts %}{% endfor %}` con: -Luego en `base.html`, remplaza completamente tu `` (todo entre `` and ``) con esto: - -```html - - -
-
-
- {% block content %} - {% endblock %} -
-
-
- -``` - - -{% raw %}Nosotros básicamente remplazamos todo entre `{% for post in posts %}{% endfor %}` con:{% endraw %} - -```html -{% block content %} -{% endblock %} +``` html + {% block content %} + {% endblock %} ``` - -¿Qué significa esto? Acabas de crear un `block`, el cual es una etiqueta de plantilla que te permite insertar HTML en este bloque en otros templates que extiendan de `base.html`. Te mostraremos como hacer esto en un momento. +¿Qué significa esto? Acabas de crear un `block`, una template tag que te permite insertar HTML en este bloque en otras plantillas que extiendan a `base.html`. Te mostraremos como hacer esto en un momento. -Ahora guardalo, y abre `blog/templates/blog/post_list.html` de nuevo. Elimina todo lo demás que está dentro del body y luego elimina ``, de forma que el archivo se vea de la siguiente manera: +Ahora guárdalo y abre tu archivo `blog/templates/blog/post_list.html` de nuevo. Elimina todo lo que no esté dentro del body y luego elimina también ``, de forma que tu archivo se verá asi: -```html -{% for post in posts %} -
-
- {{ post.published_date }} -
-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
-{% endfor %} -``` - - -Y ahora agrega esta linea al inicio del archivo: - -```html -{% extends 'blog/base.html' %} -``` - - -Significa que ahora estamos extendiendo del template `base.html` en `post_list.html`. Solo nos falta una cosa: poner todo (excepto la línea que acabamos de agregar) entre `{% block content %}` y `{% endblock content %}`. Como esto: - -```html -{% extends 'blog/base.html' %} - -{% block content %} +``` html {% for post in posts %}
{{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} -{% endblock content %} ``` + +Y ahora agrega esta línea al inicio del archivo: +``` + {% extends 'blog/base.html' %} +``` + +Significa que ahora estamos extendiendo de la plantilla `base.html` en `post_list.html`. Sólo nos falta una cosa: poner todo (excepto la línea que acabamos de agregar) entre `{% block content %}` y `{% endblock content %}`. Como esto: + +``` html + {% extends 'blog/base.html' %} + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` ¡Eso es todo! Verifica que tu sitio web aún funcione apropiadamente :) -> Si tienes un error `TemplateDoesNotExists` que diga que no hay un archivo `blog/base.html` y tienes `runserver` ejecutandose en la consola, intenta pararlo (presionando Ctrl+C - Botones Control y C juntos) y reinicialo ejecutando el comando `python manage.py runserver`. +> Si tienes un error `TemplateDoesNotExists` que diga que no hay un archivo `blog/base.html` y tienes `runserver` ejecutándose en la consola, intenta pararlo (presionando Ctrl+C - las teclas Control y C juntas) y reinicialo ejecutando el comando `python manage.py runserver`. diff --git a/es/whats_next/README.md b/es/whats_next/README.md index 838263e8159..87742cd4c78 100755 --- a/es/whats_next/README.md +++ b/es/whats_next/README.md @@ -1,40 +1,40 @@ # ¿Qué sigue? -Felicitaciones! **Eres increible**. Estamos orgullosos! <3 +¡Date muchas felicitaciones! **¡Eres increíble!**. ¡Estamos orgullosos! <3 ### ¿Qué hacer ahora? -Toma un descanso y relajate. Acabas de hacer algo realmente grande. +Toma un descanso y relájate. Acabas de hacer algo realmente grande. Después de eso, asegúrate de: * Seguir a Django Girls en [Facebook][1] o [Twitter][2] para estar al día [1]: http://facebook.com/djangogirls - [2]: http://twitter.com/djangogirls + [2]: https://twitter.com/djangogirls -### ¿Me puede recomendar cualquier recurso adicional? +### ¿Me puedes recomendar recursos adicionales? ¡Sí! En primer lugar, sigue adelante y prueba nuestro libro llamado [Django Girls Tutorial: Extensiones][3]. [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ -Más adelante, puedes intentar los recursos enumerados a continuación. Todos muy recomendados! +Más adelante, puedes intentar los recursos listados a continuación. ¡Son todos muy recomendables! -- [Django's official tutorial][4] -- [New Coder tutorials][5] -- [Code Academy Python course][6] -- [Code Academy HTML & CSS course][7] -- [Django Carrots tutorial][8] -- [Learn Python The Hard Way book][9] -- [Getting Started With Django video lessons][10] -- [Two Scoops of Django: Best Practices for Django book][11] +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django book][11] [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ [5]: http://newcoder.io/tutorials/ - [6]: http://www.codecademy.com/en/tracks/python - [7]: http://www.codecademy.com/tracks/web - [8]: http://django.carrots.pl/en/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ [9]: http://learnpythonthehardway.org/book/ [10]: http://gettingstartedwithdjango.com/ - [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6 + [11]: https://twoscoopspress.org/products/two-scoops-of-django-1-6 diff --git a/fr/CONTRIBUTING.md b/fr/CONTRIBUTING.md deleted file mode 100755 index 3ea54d5bc00..00000000000 --- a/fr/CONTRIBUTING.md +++ /dev/null @@ -1,109 +0,0 @@ -# How to contribute - -The Django Girls Tutorial is licensed under a *Creative Commons Attribution-ShareAlike 4.0* license. Everyone is free to add, edit and correct the tutorial. - -# Editing basics - -The source code of the tutorial is [hosted on Github](http://github.com/DjangoGirls/tutorial). The Github [Fork & Pull workflow](https://help.github.com/articles/using-pull-requests) is used to accept and review changes. - -The tutorial uses the [GitBook](https://www.gitbook.io/) service for publishing its documentation. [See more information about how Gitbook works](http://help.gitbook.io/). - -The tutorial is written in [Markdown mark up language](https://help.github.com/articles/markdown-basics). - -You can find any discussions about the contents of the tutorial on the [Github issue tracker](https://github.com/DjangoGirls/tutorial/issues). - -# Getting started and prerequisites - -For contributing to the tutorial the following is needed to get started: - - * a [Github account](https://github.com) - * in the case of complex edits familiarity with [Git command line basics](https://help.github.com/articles/set-up-git) or familiarity with an app ([Windows](https://windows.github.com/), [Mac](https://mac.github.com/)) to push your edits made on your computer to Github. - -## Fork the repository - -First fork the [DjangoGirls/tutorial](https://github.com/DjangoGirls/tutorial) repository to your personal Github account: - -![Fork button](contributing/images/fork.png) - -# Editing chapter content - -## Simple changes - -For simple changes like typo corrections you can use the Github online editor: - - * Open your local fork page on Github, - * go to *README.md* file in any chapter, - * press the *Edit* icon (pen) - -and you can edit the chapter directly on github.com. - -![Bouton d'édition](contributing/images/edit.png) - -Markdown syntax is used to edit the individual pages of the tutorial. - -![Github editor](contributing/images/github_editor.png) - -Save your changes and create a pull request as explained below. - -## New content and complex changes - -For adding new chapters, writing longer snippets of text or adding images, you need to get a copy of the tutorial to your local computer. - -Either use the Github app for your operating system (mentioned above) or `git` command line to get the repository locally. You get the repository address from the front page of your own Github repository fork: - - git clone git@github.com:yourgithubusername/tutorial.git - - -Download the [Gitbook Editor](http://help.gitbook.io/editor/README.html) app to your computer. - -Then you can open the tutorial in Gitbook Editor (*File* > *Open book*). - -![Gitbook](contributing/images/gitbook.png) - -Make any changes in the tutorial using the editor and then save changes (*Book* > *Save all*). - -Then commit the changes using `git` and push the changes to your remote Github repository. - -Example: - - $ git status - On branch contributing - Untracked files: - (use "git add ..." to include in what will be committed) - - contributing_and_editing_this_book/images/gitbook.png - - $ git add contributing_and_editing_this_book/images/gitbook.png - - $ git commit -m "Added gitbook editor screenshot" - [contributing fe36152] Added gitbook screenshot - 1 file changed, 0 insertions(+), 0 deletions(-) - create mode 100644 contributing_and_editing_this_book/images/gitbook.png - - $ git push - Counting objects: 11, done. - Delta compression using up to 8 threads. - Compressing objects: 100% (5/5), done. - Writing objects: 100% (5/5), 266.37 KiB | 0 bytes/s, done. - Total 5 (delta 1), reused 0 (delta 0) - To git@github.com:miohtama/tutorial.git - b37ca59..fe36152 contributing -> contributing - - -# Making a pull request - -After you have finished your changes you need to create [a pull request](https://help.github.com/articles/using-pull-requests) on Github. DjangoGirls will get notified about the pull request, review your changes, suggest any corrections if needed and then *pull* your changes to the master version. - -In your own repository on Github press do *Compare & pull request* - -![Gitbook](contributing/images/pull_request.png) - -Fill in the information *why* this change is being made. The reviewer can see the details of the actual change, so you don't need repeat the content of the change. - -Then press *Create pull request*. - -Github emails will notify you for the follow up process. - -# Further information and help - -For any questions please [contact DjangoGirls](http://djangogirls.org/). \ No newline at end of file diff --git a/fr/GLOSSARY.md b/fr/GLOSSARY.md new file mode 100644 index 00000000000..17c69c4d382 --- /dev/null +++ b/fr/GLOSSARY.md @@ -0,0 +1,3 @@ +# Éditeur de texte + +L'éditeur de texte est une application qui permet d'écrire et d'enregistrer du code que vous pourrez ré-utiliser plus tard. Vous pouvez apprendre comment s'en procurer un grâce au chapitre [Éditeur de Texte](./code_editor/README.md) diff --git a/fr/README.md b/fr/README.md index 9593a275d26..f45ef9780cd 100755 --- a/fr/README.md +++ b/fr/README.md @@ -1,26 +1,26 @@ -# Tutoriel Django Girls +# Tutoriel de Django Girls [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -> Cette œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution-ShareAlike 4.0 International. Pour obtenir une copie de cette licence, visitez http://creativecommons.org/licenses/by-sa/4.0/ +> Cette œuvre est mise à disposition selon les termes de la Licence Creative Commons Attribution-ShareAlike 4.0 International. Pour obtenir une copie de cette licence, visitez https://creativecommons.org/licenses/by-sa/4.0/ ## Translation -This tutorial has been translated from English to French by a group of awesome volunteers. Special thanks for help go to Lucie Daeye and Georges Dubus. <3 <3 +This tutorial has been translated from English to French by a group of awesome volunteers. Special thanks for help go to Lucie Daeye, Georges Dubus, Emmanuelle Delescolle, Leila, MadCath, Mélanie Chauvel and Sebastien Barbier. <3 <3 ## Introduction -Avez vous déjà eu l'impression que la technologie prend une place de plus en plus importante, mais que vous êtes en quelque sort laissé·e à la traîne ? Avez vous déjà été curieux·se de comment créer un site web, sans jamais avoir le courage de vous plonger dedans ? Vous êtes vous déjà dit que le monde du logiciel est trop compliqué pour savoir ne serait-ce que par où l'attaquer ? +Avez-vous déjà eu l'impression que la technologie prend une place de plus en plus importante, mais que vous êtes en quelque sorte laissée à la traine ? Avez-vous déjà été curieuse de comment créer un site web, sans jamais avoir le courage de vous plonger dedans ? Vous êtes-vous déjà dit que le monde du logiciel est trop compliqué pour savoir ne serait-ce que par où l'attaquer ? -Hé bien, bonne nouvelle ! Programmer n'est pas aussi dur que ça en a l'air, et nous sommes là pour vous montrer à quel point ça peut être fun. +Hé bien, bonne nouvelle ! Programmer n'est pas aussi dur que ça en a l'air, et nous sommes là pour vous montrer à quel point ça peut être amusant. -Ce tutoriel ne va pas vous transformer en programmeur·se du jour au lendemain. Devenir vraiment bon·ne peut prendre des mois, voire même des années d'apprentissage et de pratique. Mais nous voulons vous montrer que programmer ou créer des sites web n'est pas aussi compliqué que ça en a l'air. Nous allons essayer de notre mieux de vous expliquer différents morceaux de la technologie, pour la rendre moins intimidante. +Ce tutoriel ne va pas vous transformer en programmeuse du jour au lendemain. Devenir vraiment bonne peut prendre des mois, voire même des années d'apprentissage et de pratique. Mais nous voulons vous montrer que programmer ou créer des sites web n'est pas aussi compliqué que ça en ait l'air. Nous allons essayer de vous expliquer différents morceaux afin de rendre la technologie moins intimidante. Nous espérons arriver à vous faire aimer la technologie autant que nous l'aimons ! -## Qu'apprendrez vous au cours de ce tutoriel ? +## Qu'apprendrez-vous au cours de ce tutoriel ? -À la fin de ce tutoriel, vous aurez une application toute simple et pleinement fonctionnelle : votre propre blog. Nous allons vous montrer comment le mettre en ligne, pour pouvoir montrer le résultat à d'autres personnes. +À la fin de ce tutoriel, vous aurez une application toute simple et pleinement fonctionnelle : votre propre blog. Nous allons vous montrer comment le mettre en ligne afin de pouvoir montrer le résultat à d'autres personnes ! Ça devrait ressembler plus ou moins à ça : @@ -28,22 +28,22 @@ Nous espérons arriver à vous faire aimer la technologie autant que nous l'aimo [2]: images/application.png -> Si vous travaillez sur ce tutoriel dans votre coin et que vous n'avez pas de coach pour vous aider en cas de problème, venez sur le chat: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Nous avons demandé aux coachs et participant·e·s des précédentes éditions de passer de temps en temps pour aider les autres avec le tutoriel. N'aillez pas peur d'y poser vos questions ! +> Si vous travaillez sur ce tutoriel dans votre coin et que vous n'avez pas de coach pour vous aider, venez sur le chat : [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) en cas de problème. Nous avons demandé aux coachs et participant·e·s des précédentes éditions de passer de temps en temps pour aider les autres avec le tutoriel. N'aillez pas peur et allez poser vos questions ! -Okay, [commençons par le commencement...][3] +Alors, [commençons par le commencement...][3] - [3]: how_internet_works/README.md + [3]: how_the_internet_works/README.md -## À propos, et contributions +## À propos et contributions -Ce tutoriel est maintenu par [DjangoGirls][4]. Si vous trouvez des erreurs ou souhaitez mettre à jour le tutoriel veuillez [suivre les instructions de contribution][5]. +Ce tutoriel est maintenu par [DjangoGirls][4]. Si vous rencontrez des erreurs ou souhaitez simplement suggérer une amélioration du tutoriel, il est important de respecter [les règles de contribution][5]. - [4]: http://djangogirls.org/ + [4]: https://djangogirls.org/ [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md -## Voulez vous nous aider à traduire le tutoriel dans d'autres langues ? +## Voulez-vous nous aider à traduire le tutoriel dans d'autres langues ? -Pour l'instant, les traductions sont maintenue sur crowdin.com. +Pour l'instant, les traductions sont stockées sur la plate-forme crowdin.com dans : https://crowdin.com/project/django-girls-tutorial diff --git a/fr/SUMMARY.md b/fr/SUMMARY.md index 530f0fdc542..4eabc020e6f 100755 --- a/fr/SUMMARY.md +++ b/fr/SUMMARY.md @@ -1,26 +1,26 @@ # Résumé * [Introduction](README.md) -* [Comment marche l'Internet?](how_internet_works/README.md) +* [Installation](installation/README.md) +* [Comment fonctionne l'Internet ?](how_the_internet_works/README.md) * [Introduction à l'interface en ligne de commande](intro_to_command_line/README.md) * [Installation de Python](python_installation/README.md) * [L'éditeur de texte](code_editor/README.md) * [Introduction à Python](python_introduction/README.md) -* [Django](django/README.md) +* [Qu'est-ce que Django?](django/README.md) * [Installation de Django](django_installation/README.md) -* [Votre premier projet Django!](django_start_project/README.md) +* [Votre premier projet Django !](django_start_project/README.md) * [Les modèles dans Django](django_models/README.md) -* [Django ORM and QuerySets](django_orm/README.md) -* [L'interface d'administration de Django](django_admin/README.md) -* [Déployer!](deploy/README.md) +* [Django admin](django_admin/README.md) +* [Déployer !](deploy/README.md) * [Les urls Django](django_urls/README.md) * [Créons nos vues Django!](django_views/README.md) * [Introduction au HTML](html/README.md) +* [Django ORM (Querysets)](django_orm/README.md) * [Données dynamiques dans les templates](dynamic_data_in_templates/README.md) * [Templates Django](django_templates/README.md) * [CSS - Rendez votre site joli](css/README.md) * [Héritage de template](template_extending/README.md) * [Finaliser votre application](extend_your_application/README.md) * [Formulaires Django](django_forms/README.md) -* [Nom de domaine](domain/README.md) -* [La suite?](whats_next/README.md) +* [La suite ?](whats_next/README.md) \ No newline at end of file diff --git a/fr/code_editor/README.md b/fr/code_editor/README.md index 08a0f46ac4d..b149081182d 100755 --- a/fr/code_editor/README.md +++ b/fr/code_editor/README.md @@ -1,33 +1,7 @@ # L'éditeur de texte -Vous allez bientôt écrire vos premières lignes de code : il vous faut tout d'abord télécharger un éditeur de texte ! +Vous allez bientôt écrire vos premières lignes de code : Il vous faut tout d'abord télécharger un éditeur de texte ! -Choisir un éditeur de texte parmi tous ceux disponibles est surtout une histoire de goûts personnels. La plupart des programmeurs Python utilisent des IDE (Environnement de développement intégré) complexes mais très puissant, comme Pycharm par exemple. Ce n'est pas forcément le meilleur choix pour débuter : ceux que nous vous recommandons sont tout aussi puissants, mais beaucoup plus simples à utiliser. +> **Note** : Vous l'avez peut-être déjà fait dans le chapitre d'installation. Si c'est le cas, passez directement au prochain chapitre! -Vous pouvez choisir l'un des éditeurs de la liste ci-dessous mais n'hésiter pas à demander à votre coach l'éditeur qu'il·elle préfère. - -## Gedit - -Gedit un éditeur libre et gratuit qui est disponible sur tous les systèmes d'exploitation. - -[Télécharger][1] - - [1]: https://wiki.gnome.org/Apps/Gedit#Download - -## Sublime Text 2 - -Sublime text est un éditeur très populaire : il est disponible gratuitement sous forme de version d'évaluation pour tous les systèmes d'exploitation. Il est facile à installer et à utiliser. - -[Télécharger][2] - - [2]: http://www.sublimetext.com/2 - -## Atom - -Atom est un éditeur très récent créé par [GitHub][3]. Disponible pour tous les systèmes d'exploitation, il est libre, gratuit et facile à installer et à utiliser. - - [3]: http://github.com/ - -[Télécharger][4] - - [4]: https://atom.io/ \ No newline at end of file +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/fr/code_editor/instructions.md b/fr/code_editor/instructions.md new file mode 100644 index 00000000000..d5649f6293b --- /dev/null +++ b/fr/code_editor/instructions.md @@ -0,0 +1,31 @@ +Choisir un éditeur de texte parmi tous ceux qui sont disponibles est surtout une histoire de goûts personnels. La plupart des programmeurs·ses Python utilisent des IDE (Environnements de développement intégrés) complexes mais très puissants, comme Pycharm par exemple. Ce n'est pas forcément le meilleur choix pour débuter : ceux que nous vous recommandons sont tout aussi puissants, mais beaucoup plus simples à utiliser. + +Vous pouvez choisir l'un des éditeurs de la liste ci-dessous, mais n'hésitez pas à demander à votre coach l'éditeur qu'il·elle préfère. + +## Gedit + +Gedit est un éditeur libre et gratuit disponible pour tout les systèmes d'exploitation. + +[Télécharger](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime text est un éditeur très populaire : il est disponible gratuitement sous forme de version d'évaluation pour tout les systèmes d'exploitation. Il est facile à installer et à utiliser. + +[Télécharger](https://www.sublimetext.com/3) + +## Atom + +Atom est un éditeur très récent créé par [GitHub](https://github.com/). Disponible pour tout les systèmes d'exploitation, il est libre, gratuit, facile à installer et à utiliser. + +[Télécharger](https://atom.io/) + +## Pourquoi installer un éditeur de texte? + +Vous vous demandez sûrement pourquoi nous vous faisons installer un éditeur spécialement créé pour écrire du code. Pourquoi ne pourrions nous pas simplement utiliser un éditeur de texte comme Word ou Notepad ? + +La première raison est que votre code doit être écrit en **texte brut**. Le problème avec les applications comme Word ou Textedit, c'est qu'elles ne produisent pas du texte brut mais du texte enrichi (avec des polices et de la mise en page), basé sur un standard comme [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La seconde raison est que les éditeurs de texte dédiés à la programmation contiennent de nombreuses fonctions très utiles. Ils peuvent colorer le texte en fonction du sens de celui-ci (coloration syntaxique) ou ajouter automatiquement un guillemet fermant à chaque fois que vous ouvrez un guillemet. + +Vous allez bientôt vous rendre compte à quel point un logiciel dédié à la programmation peut être pratique ! Prenez un peu de temps pour trouver l'éditeur qui vous convient, car il deviendra rapidement l'un de vos outils préférés :) diff --git a/fr/css/README.md b/fr/css/README.md index 14f1589fe40..31e3302fa4b 100755 --- a/fr/css/README.md +++ b/fr/css/README.md @@ -1,27 +1,27 @@ # CSS - Rendez votre site joli ! -Soyons honnête : notre blog est plutôt moche, non ? Un peu de CSS devrait nous permettre d'arranger ça ! +Soyons honnêtes : notre blog est plutôt moche, non ? Un peu de CSS devrait nous permettre d'arranger ça ! ## Qu'est-ce que le CSS ? -Les feuilles de style en cascade, ou Cascading Style Sheets (CSS), sont un langage informatique utilisé pour décrire l'apparence et le formatage d'un document écrit en langage markup (ex : HTML). Pour faire simple : des produits cosmétiques pour pages web ;). +Les feuilles de style, ou Cascading Style Sheets (CSS), sont un langage informatique utilisé pour décrire l'apparence et le formatage d'un document écrit en langage markup (ex : HTML). Pour faire simple : des produits cosmétiques pour pages web ;) -Je suppose que vous n'avez pas envie de partir de rien et de tout construire vous-même. Pour éviter cela, nous allons une nouvelle fois utiliser différentes ressources créées et mises à disposition gratuitement sur Internet par d'autres développeur·se·s. Réinventer à chaque fois la roue n'est pas fun en plus d'être absolument inutile. +Je suppose que vous n'avez pas particulièrement envie de partir de rien et de devoir tout construire vous-même. Pour éviter cela, nous allons une nouvelle fois utiliser différentes ressources créées et mises à disposition gratuitement sur Internet par d'autres développeurs·ses. Réinventer à chaque fois la roue n'est pas vraiment fun, en plus, c'est absolument inutile. ## Utilisons Bootstrap ! -Bootsrap est l'un des frameworks HTML et CSS les plus populaires. Il est utilisé pour créer de très beaux sites web : http://getbootstrap.com/ +Bootsrap est l'un des frameworks HTML et CSS les plus populaires. Il est utilisé pour créer de très beaux sites web : https://getbootstrap.com/ -Il fut codé par d'anciens programmeurs de chez Twitter et est maintenant développé par des bénévoles aux quatre coins du monde. +Il a été créé par d'anciens programmeurs·ses de chez Twitter et est maintenant développé par des bénévoles aux quatre coins du monde. ## Installer Bootstrap Pour installer Bootstrap, vous avez besoin d'ajouter ceci dans le `` de votre fichier `.html` (`blog/templates/blog/post_list.html`) : - - - - +```html + + +``` En faisant ceci, vous n'ajoutez aucun nouveau fichier à votre projet : vous reliez simplement des fichiers hébergés sur Internet à votre projet. Essayez maintenant de rafraichir votre page. Et voilà ! @@ -29,64 +29,63 @@ En faisant ceci, vous n'ajoutez aucun nouveau fichier à votre projet : vous rel [1]: images/bootstrap1.png -C'est déjà un peu mieux, n'est-ce pas ? +C'est déjà un peu mieux ! ## Les fichiers statiques dans Django -Les **fichiers statiques** (static files) font eux aussi partie des nouvelles choses que vous allez apprendre aujourd'hui. Votre CSS ainsi que vos images font partie des fichiers statiques. Ces fichiers ne sont pas dynamiques, ce qui signifie qu'ils ne dépendent pas du contexte de la requête et seront donc identiques pour chaque utilisateur. +Enfin, allons jeter un coup d'œil à ces **fichiers statiques** dont nous n'arrêtons pas de vous parler. Votre CSS et vos images sont des fichiers statiques et non dynamiques. Cela signifie que leur contenu ne dépend pas du contexte de la requête et qu'il sera donc identique pour chaque utilisateur. -Comme la CSS est un fichier statique, nous devons tout d'abord configurer les fichiers statiques dans Django. Vous n'avez besoin de faire cette étape qu'une seule fois. Commençons : +### Où ranger les fichiers statiques dans Django ? -### Configurer les fichiers statiques dans Django +Comme vous l'avez probablement remarqué lorsque nous avons exécuté la commande `collectstatic` sur le serveur, Django sait déjà où trouver les fichiers statiques pour la partie "admin". Maintenant, il ne nous reste plus qu'à ajouter les fichiers statiques liés à notre app `blog`. -Tout d'abord, nous devons créer un dossier pour y ranger nos fichiers statiques. Allez-y : créez un dossier appelé `static` à l'intérieur de votre dossier `djangogirls`. +Pour cela, nous allons créer un dossier appelé `static` à l'intérieur de notre blog app : djangogirls - ├─── static - └─── manage.py - + ├── blog + │ ├── migrations + │ └── static + └── mysite -Ouvrez le fichier `mysite/settings.py` et allez à la fin de celui-ci pour ajouter les lignes suivantes : - STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "static"), - ) - - -Maintenant, Django sait où se trouvent vos fichiers statiques. +Django est capable de détecter automatiquement tout les dossiers appelés "static" dans l'arborescence de votre app. Il sera ainsi capable d'utiliser les fichiers présents à l'intérieur de ces dossiers comme des fichiers statiques. ## Votre première CSS ! -Nous allons créer un fichier CSS afin de personnaliser notre page web. Créez un nouveau dossier appelé `css` à l'intérieur de votre dossier `static`. Ensuite, créez un nouveau fichier appelé `blog.css` à l'intérieur du dossier `css`. Vous êtes prêt·e·s ? +Nous allons créer un fichier CSS afin de personnaliser notre page web. Créez un nouveau dossier appelé `css` à l'intérieur de votre dossier `static`. Ensuite, créez un nouveau fichier appelé `blog.css` à l'intérieur du dossier `css`. Vous êtes prête ? - static - └─── css - blog.css - + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css -Maintenant, écrivons un peu de CSS : ouvrez le fichier `static/css/blog.css` dans votre éditeur de texte. -Vous n'avez peut-être pas envie de passer le reste de la journée à personnaliser vos pages web et à apprendre le CSS. De toute manière, ce n'est pas l'objectif de cet atelier ! Nous vous invitons donc, une fois rentré·e chez vous, à vous plonger dans d'autres tutoriels de CSS. Vous verrez, c'est assez simple à comprendre. Vous pouvez consulter le cours [Codeacademy HTML & CSS course][2] qui est une excellente ressource qui vous permettra d'en apprendre plus sur la personnalisation de site web à l'aide de CSS. +Et c'est parti pour un peu de CSS ! Ouvrez le fichier `static/css/blog.css` dans votre éditeur de texte. - [2]: http://www.codecademy.com/tracks/web +Nous n'allons pas trop nous attarder sur les CSS aujourd'hui. Nous vous invitons, une fois rentrée chez vous, à vous plonger dans d'autres tutoriels de CSS. Vous verrez, c'est assez simple à comprendre ! Vous pouvez par exemple consulter le cours [Codeacademy HTML & CSS course][2] qui est une excellente ressource et qui vous permettra d'en apprendre plus sur la personnalisation de site web à l'aide de CSS. -Que pourrions-nous faire rapidement ? Je sais : changer la couleur de notre entête ! Pour indiquer la couleur que nous souhaitons utiliser, nous devons utiliser un code particulier. Ces codes commencent par `#` et sont suivis de 6 lettres (A-F) et chiffres (0-9). Afin de trouver le code associé à la couleur de votre choix, vous pouvez consulter le site http://www.colorpicker.com/. Vous pouvez aussi utiliser des [couleurs prédéfinies][3], comme le `rouge` et le `vert`. + [2]: https://www.codecademy.com/tracks/web + +Que pourrions-nous faire rapidement ? Pourquoi ne pas changer la couleur de notre entête ? Pour indiquer la couleur que nous souhaitons utiliser, nous devons utiliser un code particulier. Ces codes commencent par `#` et sont suivis de 6 lettres (A-F) et chiffres (0-9). Afin de trouver le code associé à la couleur de votre choix, vous pouvez consulter le site http://www.colorpicker.com/. Vous pouvez aussi utiliser des [couleurs prédéfinies][3], comme `red` ou `green`. [3]: http://www.w3schools.com/cssref/css_colornames.asp -Ajoutez ceci dans votre fichier `static/css/blog.css` : +Ajoutez le code suivant dans votre fichier `blog/static/css/blog.css` : - h1 a { - color: #FCA205; - } - +```css +h1 a { + color: #FCA205; +} +``` `h1 a` est un sélecteur CSS. Cela signifie que nous appliquons ce style pour chaque élément `a` présent à l'intérieur d'un élément `h1` (ce qui est le cas de `

link

`). Dans notre exemple précédent, nous indiquions notre souhait de changer la couleur du texte en `#FCA205`, c'est à dire en orange. Bien évidemment, vous êtes libre de choisir n'importe quelle couleur ! Un fichier CSS permet de déterminer le style des éléments présents dans un fichier HTML. Les différents éléments sont identifiés par leur nom (`a`, `h1`, `body`), l’attribut `class` ou l’attribut `id`. Class et id sont des noms que vous choisissez vous-même. Les classes définissent des groupes d'éléments tandis que les ids désignent des éléments précis. Par exemple, l'élément suivant peut être identifié par CSS à la fois par son nom `a`, sa classe `external_link`, ou son identifiant `link_to_wiki_page` : - - +```html + +``` Nous vous conseillons d'en apprendre un peu plus sur les sélecteurs CSS sur [w3schools][4]. @@ -97,7 +96,6 @@ Afin que nos modifications fonctionnent, nous devons aussi signaler à notre tem ```html {% load staticfiles %} ``` - Hop, nous chargeons les fichiers statiques :). Pour l'ajout de code suivant, gardez en tête que le navigateur lit vos fichiers dans l'ordre dans lequel ils lui sont donnés : en le plaçant à l'endroit que nous vous indiquons, vous allez pouvoir remplacer du code provenant des fichiers Boostrap par le vôtre. Donc, entre le `` et le `` et après les liens vers les fichiers CSS de Boostrap, ajoutez ceci : @@ -116,7 +114,6 @@ Maintenant, votre fichier doit ressembler à ceci : Django Girls blog - @@ -128,15 +125,14 @@ Maintenant, votre fichier doit ressembler à ceci :

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -Ok, on sauvegarde et on rafraîchit la page ! +Ok, on sauvegarde et on rafraichit la page ! ![Figure 14.2][5] @@ -144,10 +140,11 @@ Ok, on sauvegarde et on rafraîchit la page ! Bravo ! Peut-être que nous pourrions un peu aérer notre page web en augmentant la marge du côté gauche ? Essayons pour voir ! - body { - padding-left: 15px; - } - +```css +body { + padding-left: 15px; +} +``` Ajoutez ceci à votre fichier CSS, sauvegardez-le et voyons le résultat ! @@ -157,18 +154,20 @@ Ajoutez ceci à votre fichier CSS, sauvegardez-le et voyons le résultat ! Et si nous changions aussi la police de caractères de notre entête ? Collez ceci dans la partie `` de votre fichier `blog/templates/blog/post_list.html` : - - +```html + +``` Cette ligne nous permet d'importer la police de caractères *Lobster* depuis Google Fonts (https://www.google.com/fonts). -Maintenant, ajouter la ligne `font-family: 'Lobster';` dans votre fichier CSS `static/css/blog.css`. Attention à bien la placer à l'intérieur du block déclaratif `h1 a` (c'est à dire entre les accolades `{` et `}`). Ensuite, rechargez la page. Votre code doit ressembler à ceci : +Maintenant, ajoutons `font-family: 'Lobster';` à l'intérieur du bloc déclaratif `h1 a` dans le fichier CSS `blog/static/css/blog.css`. Le bloc déclaratif est le code situé à l'intérieur des accolades `{` et `}`. N'oubliez pas ensuite de rafraichir la page. - h1 a { - color: #FCA205; - font-family: 'Lobster'; - } - +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` ![Figure 14.3][7] @@ -180,84 +179,87 @@ Comme nous l'avions mentionné précédemment, il existe une notion de classe da Allons donner des noms à certaines parties de notre code html. Ajouter la classe `page-header` à votre `div` qui contient votre entête. Votre fichier doit ressembler maintenant à ceci : - - +```html + + ``` -Maintenant, ajouter la classe `post` à votre `div` contenant votre blog post. +Maintenant, ajoutez la classe `post` à votre `div` contenant votre blog post. -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- - -Nous allons maintenant ajouter des blocs déclaratifs à différents sélecteurs. Les sélecteurs qui commencent par `.` sont reliés aux classes. Le net regorge de bons tutoriels sur CSS qui vous permettront de comprendre le code que nous allons maintenant rajouter à notre fichier. Comme nous n'avons malheureusement pas le temps d'entrer dans les détails, copiez le code suivant dans votre fichier `mysite/static/css/blog.css` : - - .page-header { - background-color: #ff9400; - margin-top: 0; - padding: 20px 20px 20px 40px; - } - - .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { - color: #ffffff; - font-size: 36pt; - text-decoration: none; - } - - .content { - margin-left: 40px; - } - - h1, h2, h3, h4 { - font-family: 'Lobster', cursive; - } - - .date { - float: right; - color: #828282; - } - - .save { - float: right; - } - - .post-form textarea, .post-form input { - width: 100%; - } - - .top-menu, .top-menu:hover, .top-menu:visited { - color: #ffffff; - float: right; - font-size: 26pt; - margin-right: 20px; - } - - .post { - margin-bottom: 70px; - } - - .post h1 a, .post h1 a:visited { - color: #000000; - } - - -Nous allons maintenant nous intéresser au code concernant les posts. Remplacer le code suivant : +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Nous allons maintenant ajouter des blocs déclaratifs à différents sélecteurs. Les sélecteurs qui commencent par `.` sont reliés aux classes. Le net regorge de bons tutoriels sur CSS qui vous permettront de comprendre le code que nous allons rajouter à notre fichier. Pour l'instant, copier-coller le code qui suit dans votre fichier `blog/static/css/blog.css` : + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +Nous allons maintenant nous intéresser au code concernant les posts. Il va falloir remplacer le code suivant : ```html {% for post in posts %}

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} -``` +``` -Ce code se trouve dans le fichier `blog/templates/blog/post_list.html` et doit être remplacé par celui-ci : +Ce code se trouve dans le fichier `blog/templates/blog/post_list.html`. Il doit être remplacé par le code suivant : ```html
@@ -269,25 +271,24 @@ Ce code se trouve dans le fichier `blog/templates/blog/post_list.html` et doit {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %}
``` - -Sauvegardez les fichiers modifiés et rafraîchissez votre site web. +Sauvegardez les fichiers modifiés et rafraichissez votre site web. ![Figure 14.4][8] [8]: images/final.png -Woohoo ! C'est pas mal, non ? Le code que nous avons collé n'est pas bien compliqué à comprendre et vous devriez pouvoir en comprendre l'essentiel rien qu'en le lisant (ce n'est pas grave si ce n'est pas le cas ! ). +Woohoo ! C'est pas mal, non ? Le code que nous avons collé n'est pas bien compliqué à comprendre et vous devriez pouvoir en saisir l'essentiel rien qu'en le lisant (ce n'est pas grave si ce n'est pas le cas ! ). N'ayez pas peur et jouez un peu avec la CSS : essayez par exemple d'en changer des morceaux. Vous avez cassé quelque chose ? Pas de problème : vous pouvez toujours annuler vos modifications ! -Voilà pour la partie CSS. Nous vous encourageons vivement à suivre le tutoriel gratuit de [Code Academy][2] : considérez ce tutoriel comme un petit travail à faire une fois rentré⋅e chez vous. Vous connaîtrez ainsi tout ce qu'il y a savoir pour rendre son site bien plus joli ! +Voilà pour la partie CSS. Nous vous encourageons vivement à suivre le tutoriel gratuit de [Code Academy][2] : considérez ce tutoriel comme un petit travail à faire une fois rentrée chez vous. Vous connaitrez ainsi tout ce qu'il y a à savoir pour rendre son site bien plus joli ! -Prêt⋅e pour le chapitre suivant ? :) +Prête pour le chapitre suivant ? :) diff --git a/fr/deploy/README.md b/fr/deploy/README.md index 4161b61897d..2d5e1a0f96b 100755 --- a/fr/deploy/README.md +++ b/fr/deploy/README.md @@ -1,237 +1,291 @@ # Déployer ! -> **Note** Le chapitre suivant peut-être parfois un peu difficile à comprendre. Accrochez-vous et allez jusqu'au bout. Le déploiement fait partie intégrale du processus de développement d'un site internet. Nous avons décidé de placer ce chapitre au milieu du tutoriel afin que votre coach puisse vous aider dans cette tâche compliquée qu'est la mise en ligne d'un site web. Ça signifie que vous serez capable de finir le tutoriel par vous-même plus tard si jamais vous êtes à court de temps à la fin de la journée. +> **Note** Le chapitre suivant peut-être un peu difficile à comprendre. Accrochez-vous et allez jusqu'au bout : le déploiement fait partie intégrale du processus de développement d'un site internet. Ce chapitre a été placé au milieu du tutoriel afin de permettre à votre coach de vous aider dans cette étape un peu compliquée qu'est la mise en ligne de votre site. Si jamais vous manquez de temps à la fin de la journée, ne vous inquiétez pas ! Une fois ce chapitre terminé, vous serez en mesure de finir le tutoriel chez vous :) -Jusqu'à présent, votre site Internet était seulement disponible sur votre ordinateur. Maintenant, vous allez apprendre à le déployer ! Déployer signifie mettre en ligne votre site pour que d'autres personnes puissent enfin voir votre app :). +Jusqu'à présent, votre site web n'était seulement disponible que sur votre ordinateur. Maintenant, vous allez apprendre à le déployer ! Déployer signifie mettre en ligne votre site pour que d'autres personnes puissent enfin voir votre app :). -Comme vous l'avez appris, un site web a besoin d'être installé sur un serveur. Il existe de nombreux fournisseurs. Nous allons utiliser celui qui possède le processus de déploiement le plus simple : [Heroku][1]. Heroku est gratuit pour les petits sites qui n'ont pas beaucoup de visiteurs, ce qui devrait vous convenir pour le moment. +Comme vous l'avez appris, un site web a besoin d'être installé sur un serveur. Il existe de très nombreux fournisseurs de serveurs sur Internet. Nous allons en utiliser un qui dispose d'un système de déploiement relativement simple : [PythonAnywhere][1]. PythonAnywhere est gratuit pour les petites applications qui n'ont pas beaucoup de visiteurs : cela correspond parfaitement à ce dont nous avons besoin pour le moment. - [1]: http://heroku.com/ + [1]: https://pythonanywhere.com/ -Nous allons suivre ce tutoriel : https://devcenter.heroku.com/articles/getting-started-with-django. Nous l'avons reproduit (et traduit ! ) ici pour que cela soit plus simple pour vous. +Nous allons aussi utiliser les services [GitHub][2], ce qui nous permettra d'héberger notre code en ligne. Il existe d'autres entreprises qui proposent des services similaires. Cependant, presque tous⋅tes les développeurs·ses possèdent aujourd'hui un compte Github et, dans quelques instants, vous aussi ! -## Le fichier `requirements.txt` + [2]: https://www.github.com -Le fichier `requirements.txt` permet de communiquer à Heroku la liste des paquets Python qui ont besoin d'être installés sur le serveur qui hébergera votre site. +Github va nous servir d'intermédiaire pour envoyer et récupérer notre code sur PythonAnywhere. -Mais avant de créer ce fichier, nous avons besoin d'installer quelques paquets sur Heroku. Reprenez votre console, vérifiez que `virtualenv` est bien activé, puis tapez ceci : +# Git - (myvenv) $ pip install dj-database-url waitress whitenoise - +Git est un "gestionnaire de version" utilisé par de nombreux·ses développeurs·ses. Ce logiciel permet de garder une trace des modifications apportées à chaque fichier afin que vous puissiez facilement revenir en arrière ou à une version spécifique. Cette fonction est similaire au "suivi des modifications" de Microsoft Word, mais en beaucoup plus puissant. -Une fois l'installation terminée, allez dans le dossier `djangogirls` et tapez cette commande : +## Installer Git - (myvenv) $ pip freeze > requirements.txt - +> **Note** Si vous avez suivi la partie "installation" du tutoriel, vous n'avez pas besoin d'installer Git à nouveau. Vous pouvez passer directement à la prochaine section et commencer à créer votre dépôt Git. -Cette commande va créer le fichier `requirements.txt` qui contiendra la liste de tous les paquets Python que vous avez installés, c'est-à-dire toutes les librairies Python que vous utilisez, comme Django par exemple :). +{% include "/deploy/install_git.md" %} -> **Note**: `pip freeze` va lister toutes les librairies Python installées dans votre virtualenv tandis que `>` va se charger de mettre cette liste dans un fichier. Essayez de lancer `pip freeze` sans `> requirements.txt` et regardez ce qui se passe ! +## Démarrer un dépôt Git -Ouvrez le fichier créé et ajoutez ceci à la fin : +Git conserve toutes les modifications apportées à un ensemble de fichiers dans un "repository" (ou "dépôt"). Nous allons devoir en créer un pour notre projet. Ouvrez votre terminal et allez dans le répertoire `djangogirls`. Ensuite, tapez les commandes suivantes : - psycopg2==2.5.3 - +> **Note** : n'oubliez pas de vérifier dans quel répertoire vous vous trouvez avant d'initialiser votre dépôt. Pour cela tapez la commande `pwd` (OSX/Linux) ou `cd` (Windows). Vous devriez vous trouver dans le dossier `djangogirls`. -Vous avez besoin de cette dernière ligne pour que votre site web fonctionne sur Heroku. + $ git init + Initialise un dépôt Git vide à l'emplacement ~/djangogirls/.git/ + $ git config --global user.name "Votre nom" + $ git config --global user.email you@exemple.com -## Procfile -Nous avons aussi besoin de créer un Procfile. Cela va permettre à Heroku de savoir quelles commandes lancer pour démarrer votre site web. Ouvrez votre éditeur de texte, créez un fichier `Procfile` dans le dossier `djangogirls` et ajoutez y la ligne suivante : +L'initialisation d'un dépôt git ne se fait qu'une fois par projet. De même, vous n'aurez plus jamais à ré-entrer votre nom d'utilisateur ou votre email. - web: waitress-serve --port=$PORT mysite.wsgi:application - +Git va surveiller et conserver les modifications concernant l'ensemble des fichiers et dossiers présents dans ce répertoire, à l'exception de certains fichiers que nous aimerions exclure. Pour cela, nous allons créer un fichier appelé `.gitignore` dans le répertoire principal du projet. Ouvrez votre éditeur et créez un nouveau fichier en copiant le contenu suivant : -Cela signifie que nous allons déployer une application `web` et que nous allons le faire en lançant la commande `waitress-serve --port=$PORT mysite.wsgi:application`. `waitress-serve` est un programme qui est une sorte de version plus puissante de la commande `runserver` de Django. +``` +*.pyc +__pycache__ +myvenv +db.sqlite3 +/static +.DS_Store +``` -N'oubliez pas de sauvegarder votre fichier. Et voilà, c'est fait ! +Enregistrez ce fichier `.gitignore` dans votre répertoire principal "djangogirls". -## Le fichier `runtime.txt` +> **Attention**: le point au début du nom du fichier est important ! Vous pouvez parfois rencontrer des difficultés à créer ce fichier. Par exemple, Mac ne vous laisse pas enregistrer un fichier qui commence par un point dans Finder. Pour contourner ce problème, utilisez la fonction "enregistrer sous" de votre éditeur : ça marche à tous les coups! -Nous avons besoin de préciser à Heroku la version de Python que nous souhaitons utiliser. Pour cela, nous avons à nouveau besoin de créer un fichier dans le dossier `djangogirls`. Prenez votre éditeur de texte et créez le fichier `runtime.txt` qui contiendra ce tout petit bout de texte : +> **Note** L'un des fichiers spécifiés dans `.gitignore` est `db.sqlite3`. Ce fichier est votre base de donnée locale, où tous vos posts de blog sont stockés. Ce fichier n'est pas ajouté à la base de données parce que votre site internet sur PythonAnywhere utilise une base de donnée différente. Cette base de donnée peut être en SQLite, comme celle créée localement sur votre ordinateur mais en général, une base de données appelée MySQL est utilisée parce qu'elle peut gérer beaucoup plus de visiteurs qu'une base de données SQLite. Dans tous les cas, ignorer votre base de donneés SQLite pour la copie sur GitHub signifie que tous les posts que vous avez créé jusqu'à maintenant vont rester sur votre machine locale et ne seront accessible que depuis cette machine. Vous allez devoir les ajouter à nouveau sur votre site internet en production. Considérez votre base de données locale comme une aire de jeu où vous pouvez essayer des choses différentes sans vous souciez de supprimer un de vos vrais post de blog. - python-3.4.2 - +Avant de taper la commande `git add` ou lorsque vous ne vous souvenez plus des changements que vous avez effectué dans votre projet, pensez à taper la commande `git status`. Cela permet surtout d'éviter les mauvaises surprises, comme l'ajout ou l'envoi d'un mauvais fichier. La commande `git status` permet d'obtenir des informations sur tous les fichiers non-suivis/modifiés/mis-à-jour, l'état de la branche, et bien plus encore. Voici ce qui se passe lorsque vous tapez cette commande : -## mysite/local_settings.py + $ git status + On branch master -Il existe une différence entre la configuration que nous utilisons localement (sur notre ordinateur) et la configuration utilisée sur notre serveur. Heroku utilise une base de données qui est différente de celle de votre ordinateur. Nous allons devoir créer un fichier de configuration différent qui ne sera utilisé que dans notre environnement local. + Initial commit -Créez le fichier `mysite/local_settings.py`. Il doit contenir la même chose que la configuration de la partie `DATABASE` de votre fichier `mysite/settings.py`. Ça doit ressembler à ceci : + Untracked files: + (use "git add ..." to include in what will be committed) - import os - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } - } - - DEBUG = True - + .gitignore + blog/ + manage.py + mysite/ -N'oubliez pas de sauvegarder votre fichier ! :) + nothing added to commit but untracked files present (use "git add" to track) -## mysite/settings.py -il va aussi falloir modifier le fichier `settings.py` de notre site web. Pour cela, ouvrez `mysite/settings.py` dans votre éditeur de texte et ajoutez les lignes suivantes à la toute fin du fichier : +Pour le moment, nous n'avons fait que regarder l'état de notre branche. Pour enregistrer nos changements, nous allons devoir taper les commandes suivantes : - import dj_database_url - DATABASES['default'] = dj_database_url.config() - - SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - - ALLOWED_HOSTS = ['*'] - - STATIC_ROOT = 'staticfiles' - - DEBUG = False - + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py -Toujours à la fin du fichier `mysite/settings.py`, copier-coller ceci : - try: - from .local_settings import * - except ImportError: - pass - +## Publier votre code sur GitHub -Si le fichier existe, cela va vous permettre d'importer l'intégralité de votre configuration locale. +Allez sur [GitHub.com][2] et inscrivez-vous gratuitement (si vous possédez déjà un compte, c'est très bien!) -Sauvegardez le fichier. +Ensuite, créez un nouveau dépôt en lui donnant le nom "my-first-blog". Pensez à laisser les options par défaut. Dans notre cas, il n'est pas nécessaire de cocher la case "initialise with a README". Vous pouvez aussi laisser l'option .gitignore vide car nous avons déjà créé ce fichier précédemment. Enfin, comme nous n'avons pas besoin d'une licence pour notre application, laissez le champ License à None. -## mysite/wsgi.py +![][3] -Ouvrez le fichier `mysite/wsgi.py` et ajoutez les lignes suivantes à la toute fin : + [3]: images/new_github_repo.png - from whitenoise.django import DjangoWhiteNoise - application = DjangoWhiteNoise(application) - +> **Note** : dans le cadre de ce tutoriel, le nom `my-first-blog` est très important. Cependant, vous êtes libre de le changer mais, attention : à chaque fois que ce nom apparaitra dans le tutoriel, vous allez devoir le substituer avec le nom que vous avez choisi. Il est probablement plus simple de garder le nom `my-first-blog` pour cette fois. -Hop, on enchaine ! +La page suivante vous donne l'URL qui va vous permettre de cloner votre dépôt. Choisissez la version « HTTPS » et copiez l'URL car nous allons rapidement en avoir besoin : -## Se créer un compte sur Heroku +![][4] -Pour continuer, vous allez devoir installer la toolbelt Heroku qui se trouve ici : https://toolbelt.heroku.com/. Vous pouvez passer cette partie si vous l'avez déjà installé avec votre coach. + [4]: images/github_get_repo_url_screenshot.png -> Lorsque vous lancez l'installation de la toolbelt d'Heroku sous Windows, n'oubliez pas de choisir "Custom Installation" (installation personnalisée) lorsque l'on vous demandera quels composants vous souhaitez installer. N'oubliez pas de cocher "Git and SSH" dans la liste des composants disponibles à l'installation. -> -> Sous Windows, vous avez aussi besoin de lancer la commande suivante afin que Git et SSH soient ajoutés au `PATH` de votre prompt : `setx PATH "%PATH%;C:\Program Files\Git\bin"`. Relancez votre console afin que les changements soient pris en compte. +Nous avons maintenant besoin de relier nos deux dépôts : celui sur notre ordinateur et celui sur GitHub. On utilise l'expression "hook" en anglais pour cette décrire cette étape. -Il vous sera nécessaire de vous créer un compte gratuit sur Heroku. Vous pouvez le faire à cette adresse : https://id.heroku.com/signup/www-home-top +Tapez les instructions suivantes dans votre console (remplacez `` avec le nom d'utilisateur de votre compte GitHub et sans les chevrons) : -Ensuite, authentifiez votre compte Heroku sur votre ordinateur en lançant la commande suivante : + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master - $ heroku login - -Si vous n'avez pas encore de clef SSH, cette commande va vous permettre d'en créer une automatiquement. Les clefs SSH sont obligatoires afin de pusher du code sur Heroku. +Entrez votre nom d'utilisateur et mot de passe Github. Vous devriez voir quelque chose comme ceci : -## Git + Username for 'https://github.com': votre-nom + Password for 'https://votre-nom@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/votre-nom/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. -Git est un logiciel de gestion de versions décentralisé utilisé par de nombreux·ses programmeurs⋅ses. C'est un logiciel qui permet de garder un historique des changements d'un ou plusieurs fichiers : cela permet d'aller rechercher une version antérieure plus tard. Heroku utilise un repository git pour gérer les fichiers de votre projet. Nous allons donc devoir nous aussi l'utiliser. -Créez un fichier `.gitignore` dans votre dossier `djangogirls` et copiez y le contenu suivant : + - myvenv - __pycache__ - staticfiles - local_settings.py - db.sqlite3 - +Votre code est maintenant sur GitHub. Allez jeter un coup d’œil ! Votre code est maintenant au même endroit que d'autres projets super cool : [Django][5], [le tutoriel Django Girls][6] et les nombreux autres projets libres qui sont hébergés sur GitHub :) -Sauvegardez ce fichier. Le point au début du nom de fichier est important ! Comme vous pouvez le voir, nous disons à Heroku d'ignorer le fichier `local_settings.py` et de ne pas le télécharger. Il ne sera disponible que sur votre ordinateur (localement). + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial -Ensuite, nous allons créer un nouveau repository git et sauvegarder nos changements. Prenez votre console et lancez les commandes suivantes : +# Mettre votre blog en ligne avec PythonAnywhere - $ git init - Initialized empty Git repository in ~/djangogirls/.git/ - $ git config user.name "Votre nom" - $ git config user.email you@example.com - +> **Note** Vous avez peut être déjà créé un compte PythonAnyWhere au cours de la phase d'installation - si c'est le cas, inutile de le refaire. -Initialiser le repository git est quelque chose qu'il est nécessaire de ne faire qu'une fois par projet. +{% include "/deploy/signup_pythonanywhere.md" %} -Enfin, sauvegardons nos changements. Une nouvelle fois, prenez votre console et lancez les commandes suivantes : +## Récupérer votre code sur PythonAnywhere - $ git add -A . - $ git commit -m "My Django Girls app" - [master (root-commit) 2943412] My Django Girls - 7 files changed, 230 insertions(+) - create mode 100644 .gitignore - create mode 100644 Procfile - create mode 100644 mysite/__init__.py - create mode 100644 mysite/settings.py - create mode 100644 mysite/urls.py - create mode 100644 mysite/wsgi.py - create mode 100644 manage.py - create mode 100644 requirements.txt - create mode 100644 runtime.txt - +Une fois enregistré sur PythonAnywhere, vous serez automatiquement redirigée sur votre écran d'accueil où se trouve la liste des consoles. Cliquez sur le lien "Bash" dans la partie "start a new console". C'est la version PythonAnywhere des consoles que vous avez sur votre ordinateur. + +> **Note** : PythonAnywhere utilise Linux. Si vous êtes sous Windows, la console sera un peu différente de celle de votre ordinateur. + +Importons notre code depuis Github vers PythonAnywhere en créant un "clone" de notre dépôt. Tapez la commande suivante dans la console de PythonAnywhere (n'oubliez pas d'utiliser votre nom d'utilisateur Github à la place de ``): + + $ git clone https://github.com//my-first-blog.git + + +Cette commande va permettre d'effectuer une copie de votre code vers PythonAnywhere. La commande `tree my-first-blog` permet d'afficher un aperçu de ce qui se trouve maintenant sur votre serveur : + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### Créer un virtualenv sur PythonAnywhere + +Tout comme sur votre ordinateur, vous allez devoir créer un environnement virtuel et installer Django sur PythonAnywhere. L'opération est identique, à une différence près pour les utilisatrices de Windows : il s'agit ici d'une console Linux. Pas de panique, c'est très simple ! Ouvrez la console Bash de PythonAnywhere et tapez les commandes suivantes : + + $ cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + + (mvenv) $ pip install django~=1.9.0 + Collecting django + [...] + Successfully installed django-1.9 + + +> **Note** : L'étape `pip install` peut prendre quelques minutes. Patience, patience ! Cependant, si cela prend plus de 5 minutes, c'est que quelque chose ne va pas. N'hésitez pas à solliciter votre coach. + + + + + +### Créer une base de données sur PythonAnywhere + +Tout comme l'environnement virtuel, la base de données n'est pas partagée entre le serveur et votre ordinateur. Cela signifie, entre autre, que vous n'aurez plus forcément les mêmes utilisateurs ni les mêmes posts sur votre ordinateur et sur PythonAnywhere. + +Pour créer une base de données sur PythonAnywhere, nous allons taper les mêmes commandes que sur notre ordinateur: d'abord `migrate`, puis `createsuperuser`: + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + +## Faire de votre blog une application web + +Maintenant, notre code est sur PythonAnywhere, notre virtualenv est prêt, les fichiers statiques sont recueillis et la base de données est initialisée. Nous sommes prêts à le publier comme une application web ! + +Retourner sur la page d'accueil de PythonAnywhere en cliquant sur le logo en haut à gauche. Ensuite, cliquez sur l'onglet **Web** et **Add a new web app**. + +Après avoir confirmé votre nom de domaine, choisissez **manual configuration** dans la boite de dialogue (NB : ne choisissez *pas* l'option "Django"). Enfin, choisissez **Python 3.4** et cliquez sur "next" pour fermer l'assistant de configuration. + +> **Note** : Faites bien attention à sélectionner l'option configuration manuelle ("Manual configuration") et non l'option "Django". N'oubliez pas une chose : vous êtes bien trop cool pour prendre l'option Django qui est fourni par défaut ;-) + +### Configurer le virtualenv + +Une fois l'assistant fermé, vous serez automatiquement conduite sur la page de configuration dédiée à votre application web. Dès que vous aurez besoin de modifier quelque chose concernant votre appli, c'est là que vous devrez aller. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png -## Trouver un nom à son application +Dans la section "Virtualenv", cliquez sur le texte en rouge qui indique "Enter the path to a virtualenv" (entrer le chemin d'accès de votre environnement virtuel), et entrez ceci : `/home//my-first-blog/myvenv/`. Cliquez sur la boite bleue avec la case à cocher pour sauvegarder le chemin d’accès. -Nous allons rendre votre blog accessible en ligne à l'adresse `[nom de votre blog].herokuapp.com`. Pour cela, il va être nécessaire de choisir un nom qui n'est pas encore pris. Ce nom n'a pas besoin d'être en lien avec l'application `blog` de Django, `mysite`, où n'importe quoi d'autre que nous avons pu créer jusqu'à présent. Vous pouvez choisir le nom que vous voulez, tant qu'il est conforme aux règles strictes définies par Heroku : pas de majuscules, pas d'accents, pas de nombres ni de tirets (`-`). +> **Note** : N'oubliez pas de mettre votre nom d'utilisateur. Ne vous inquiétez pas : si vous faites une erreur, PythonAnywhere vous le signalera. -Si vous ne savez pas quoi prendre, pourquoi ne pas chercher quelque chose en rapport avec votre nom ou votre surnom ? Une fois que vous avez choisi, lancez cette commande en remplaçant `djangogirlsblog` par le nom de votre application : +### Configurer le fichier WSGI - $ heroku create djangogirlsblog - +Django utilise le protocole "WSGI" qui est un stantard pour servir des sites web qui utilisent Python. Ce protocole est supporté par PythonAnywhere. Afin que PythonAnywhere détecte notre blog Django, nous allons éditer le fichier de configuration WSGI. -> **Note**: N'oubliez pas de remplacer `djangogirlsblog` avec le nom de votre application sur Heroku. +Dans l'onglet web, vous allez trouver une section code : cliquez sur le lien "WSGI configuration file" : votre fichier de configuration devrait s’intituler `/var/www/_pythonanywhere_com_wsgi.py`. Une fois que vous avez cliqué dessus, vous serez automatiquement redirigée dans un éditeur de texte. -Si jamais vous n'avez vraiment pas d'idées de nom, vous pouvez lancer cette commande : +Supprimer le contenu du fichier et le remplacer par ce qui suit : - $ heroku create - +```python +import os +import sys -Heroku choisira alors un nom pour vous. Ce sera probablement quelque chose de l'ordre de `enigmatic-cove-2527`). +path = '/home//my-first-blog' # use your own username here +if path not in sys.path: + sys.path.append(path) -Si jamais vous avez envie de changer le nom de votre application Heroku, vous pouvez le faire facilement et quand vous voulez en tapant cette commande (n'oubliez pas de remplacer `the-new-name` par le nouveau nom que vous avez choisi) : +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' - $ heroku apps:rename the-new-name - +from django.core.wsgi import get_wsgi_application +from django.contrib.staticfiles.handlers import StaticFilesHandler +application = StaticFilesHandler(get_wsgi_application()) +``` -> **Note**: N'oubliez pas que lorsque vous aurez changer le nom de votre application, elle ne sera plus disponible à l'ancienne adresse, mais à `[the new name].herokuapp.com`. +> **Note** : N'oubliez pas de remplacer `` par votre nom d'utilisateur +> **Note** : A la ligne 3, on s'assure que PythonAnywhere saura trouver notre application. Il est très important que ce chemin d'accès soit correct, et plus particulièrement qu'il n'y ait pas d'espaces en plus. Dans le cas contraire "ImportError" s'affichera dans le log d'erreur. -## Déployer sur Heroku ! +Le but de ce fichier est de permettre à PythonAnywhere de savoir où votre application web se situe et de connaître le nom des fichiers de configuration de Django. -Nous venons de consacrer énormément de temps à configurer et à installer des choses mais rassurez vous, vous n'avez besoin de faire tout cela qu'une seule fois ! Maintenant, nous allons enfin pouvoir passer au déploiement ! +`StaticFilesHandler` sert à gérer notre CSS. Cette étape est réalisée automatiquement en exécutant la commande `runserver`. Nous aborderons un peu plus en détails les fichiers statiques quand nous éditerons le CSS de notre site. -Lorsque vous lancez `heroku create`, Heroku est alors ajouté à la liste des repository distants. Par conséquent, nous n'avons plus qu'à faire un simple git push pour déployer notre application : +Cliquez sur **Save** puis, retournez dans l'onglet **Web**. - $ git push heroku master - +Et voilà, c'est fini ! Vous n'avez plus qu'à cliquer sur le gros bouton vert **Reload** et vous devriez voir votre application en ligne. Le lien vers votre site est situé en haut de l'onglet web de PythonAnywhere. -> **Note**: il est probable que cela produise *énormément* d'output (sortie) la première fois que vous lancez cette commande car Heroku va installer et compiler psycopg. Pour savoir si ça a marché, vous allez voir apparaitre `https://yourapplicationname.herokuapp.com/ deployed to Heroku` vers la fin de l'output. +## Conseils en cas de bug -## Consulter son application +Si vous constatez une erreur lorsque vous essayez de visiter votre site web, les **logs d'erreurs** devraient vous permettre de comprendre ce qui ne marche pas. Vous trouverez un lien vers ces fichiers dans l'onglet [Web][8] de PythonAnywhere. Regardez s’il y a des messages d’erreurs ; les plus récents seront en bas du fichier. Les bugs les plus fréquents que vous pouvez rencontrer sont les suivants: -Tout ce que vous venez de faire vous a permis de déployer votre code sur Heroku. Vous avez aussi spécifié le type de processus dans le fichier `Procfile` : rappelez vous, nous avons choisi le processus de type `web` tout à l'heure. Maintenant, nous pouvons dire à Heroku de lancer ce `processus web`. + [8]: https://www.pythonanywhere.com/web_app_setup/ -Pour cela, tapez la commande suivante : +* Oublier une étape lors du passage dans la console. Vous devriez avoir fait toutes les étapes suivantes : créer un environnement virtuel, l'activer, installer Django, lancer la commande "collectstatic" et enfin créer la base de données. - $ heroku ps:scale web=1 - +* Se tromper dans le chemin d'accès à l'environnement virtuel : si c'est le cas, vous trouverez un petit message d'erreur en rouge dans l'onglet "web", section virtualenv. -Cela dit à Heroku de lancer une seule instance de notre processus `web`. Comme l'application blog que nous avons créée est relativement simple, nous n'avons pas besoin d'énormément de ressources. Un seul processus devrait faire l'affaire. Il est possible de demander à Heroku de lancer plusieurs processus (appelés "Dynos" sur Heroku) mais cette option est payante. +* Se tromper lors de la création du fichier de configuration WSGI : pensez à vérifier si le chemin d'accès que vous avez entré est bien celui de "my-first-blog"? -Maintenant, vous pouvez aller sur votre app dans votre navigateur à l'aide de la commande `heroku open`. +* Se tromper de version de Python : votre environnement virtuel et votre application web doivent toutes les deux être sous Python 3.4. - $ heroku open - +* Il y a quelques [astuces générales de débogage sur le wiki PythonAnywhere][9]. -> **Note**: vous allez rencontrer une page d'erreur ! Pas de soucis, nous allons y venir dans un instant. + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError -Cette commande va ouvrir une url du type [https://djangogirlsblog.herokuapp.com/]() dans votre navigateur qui affichera une page d'erreur. Nous n'avons, pour l'instant, que créé l'interface d'administration de notre site. Essayez d'ajouter `admin/` à la fin de l'url ([https://djangogirlsblog.herokuapp.com/admin/]()). Cette page doit normalement fonctionner :) +Et n'oubliez pas, votre coach est là pour vous aider ! -L'erreur que vous venez de voir est liée au fait que lorsque nous avons déployé notre application sur Heroku, nous avons créé une base de données vide. Pour cela, nous avons besoin de lancer la commande ~~~ migrate~~~ comme lorsque nous avons démarré notre projet pour la première fois. Cela permettra de générer notre base de données correctement : +# Votre site est en ligne ! - $ heroku run python manage.py migrate - - $ heroku run python manage.py createsuperuser - +La page qui s'affiche devrait être la même que celle sur votre ordinateur : "Welcome to Django". Vous pouvez essayer d'accéder à l'interface d’administration en ajoutant `/admin/` à la fin de l'URL. Normalement, une page de login devrait s'afficher. Une fois connectée en utilisant votre nom d'utilisateur et votre mot de passe, vous devriez pouvoir ajouter des nouveaux posts sur le serveur. -Normalement, votre site web devrait maintenant pouvoir se charger dans votre navigateur ! Félicitations :) ! \ No newline at end of file +*Félicitations !* Le déploiement est l’une des parties les plus épineuses du développement web et il faut souvent plusieurs jours avant d'obtenir quelque chose de fonctionnel. Mais vous avez réussi sans trop d'encombres à mettre votre site en ligne : parfait <3 diff --git a/fr/deploy/images/github_get_repo_url_screenshot.png b/fr/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/fr/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/fr/deploy/images/new_github_repo.png b/fr/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/fr/deploy/images/new_github_repo.png differ diff --git a/fr/deploy/images/pythonanywhere_web_tab_virtualenv.png b/fr/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/fr/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/fr/deploy/install_git.md b/fr/deploy/install_git.md new file mode 100644 index 00000000000..2190df46aa8 --- /dev/null +++ b/fr/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows + +Vous pouvez télécharger Git sur [git-scm.com](https://git-scm.com/). Vous pouvez cliquer sur "next" à toutes les étapes, sauf pour la cinquième, "Adjusting your PATH environment" : n'oubliez pas de choisir "Run Git and associated Unix tools from the Windows command-line", situé en bas de la liste des options disponibles. Les autres choix par défaut n'ont pas besoin d'être modifiés. L'option "Checkout Windows-style, commit Unix-style line endings" est parfaite: vous n'avez rien à changer sur cette page. + +### MacOS + +Vous pouvez télécharger Git sur [git-scm.com](https://git-scm.com/). Pour le reste de l'installation, suivez simplement les instructions de l'installateur. + +### Linux + +Git est probablement déjà installé mais, si ce n'est pas le cas, voici les instructions à suivre : + + sudo apt-get install git + # ou + sudo yum install git + # ou + sudo zypper install git \ No newline at end of file diff --git a/fr/deploy/signup_pythonanywhere.md b/fr/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..3b6e7b711a2 --- /dev/null +++ b/fr/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Si vous ne l'avez pas encore fait, n'oubliez pas de vous créer un compte "Beginner" sur PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note** : Le nom d'utilisateur que vous allez choisir va déterminer l'adresse de votre blog de la manière suivante : `votrenomdutilisateur.pythonanywhere.com`. Si vous ne savez pas quoi prendre, nous vous conseillons de choisir votre surnom ou un nom proche du sujet de votre blog. \ No newline at end of file diff --git a/fr/django/README.md b/fr/django/README.md index dd1c0321caf..b11204e524e 100755 --- a/fr/django/README.md +++ b/fr/django/README.md @@ -1,27 +1,27 @@ -# Django ? +# Qu'est-ce que Django? -Django (*/ˈdʒæŋɡoʊ/ jang-goh*) est un framework web gratuit et libre écrit en Python. C'est un framework web, c'est-à-dire un ensemble de composants qui vous aide à développer des sites web plus rapidement et plus facilement. +Django (*/ˈdʒæŋɡoʊ/ jang-goh*) est un framework web gratuit et libre écrit en Python. Un framework web est un ensemble de composants qui vous aide à développer des sites web plus rapidement et plus facilement. -Quand vous construisez un site web, vous avez toujours besoin des mêmes composants de base : quelque chose pour que les utilisateurs puissent se connecter (s'inscrire, se connecter, se déconnecter), une partie administration, des formulaires, un moyen d'uploader des fichiers, etc. +Lorsque vous créez un site web, vous avez souvent besoin de la même chose : une manière de gérer l'authentification de vos utilisateurs (créer un compte, se connecter, se déconnecter), une partie dédiée à la gestion de votre site, des formulaires, une manière de mettre en ligne des fichiers, etc. -La bonne nouvelle, c'est que d'autres personnes se sont aussi rendues compte de ce problème. Elles se sont alliées avec des développeurs et ont créé différents frameworks, dont Django, pour fournir un set de composants de base qui fonctionnent et qui peuvent être utilisés lors de la création d'un site web. +La bonne nouvelle, c'est que d'autres gens se sont aussi rendus compte de ce problème et ont décidé de s'allier avec des développeurs·ses pour le résoudre. Ensemble, ces personnes ont créé différents frameworks, dont Django, pour fournir un set de composants de base qui peuvent être utilisés lors de la création d'un site web. -Les frameworks existent pour vous éviter de réinventer la roue à chaque fois. Ils vous aident aussi à mettre facilement en place tous les éléments dont vous pourriez avoir besoin avant de vous lancer dans la création de votre site. +Les frameworks existent pour vous éviter de réinventer la roue à chaque fois. Ils vous aident aussi à alléger la charge de travail liée à la création d'un site web. ## Pourquoi est-ce que vous auriez besoin d'un framework ? -Pour comprendre ce qu'est exactement Django, nous avons besoin de nous intéresser aux différents rôles des serveurs. La première chose qu'a besoin de savoir un serveur, c'est que vous aimeriez qu'il vous affiche une page web. +Pour comprendre ce à quoi peut bien servir Django, nous avons besoin de nous intéresser aux multiples rôles des serveurs. Par exemple, la première chose qu'a besoin de savoir un serveur, c'est que vous aimeriez qu'il vous affiche une page web. -Imaginez que vous ayez une boîte aux lettres (port) qui serait surveillée afin de recevoir des lettres (requêtes). C'est ce que fait un serveur. Le serveur web lit la lettre qu'il a reçue et en réponse, retourne une page web. Généralement, lorsque vous voulez envoyer quelque chose, vous avez besoin de contenu. Django est quelque chose qui va vous aider à créer ce contenu. +Imaginez une boîte aux lettres (un port) dont l'arrivée de lettres (une requête) serait surveillée. C'est le travail qu'effectue le serveur. Le serveur web lit la lettre qu'il a reçue et en réponse, retourne une page web. Généralement, lorsque vous voulez envoyer quelque chose, vous avez besoin de contenu. Django est quelque chose qui va vous aider à créer ce contenu. -## Qu'est-ce qui se passe quand quelqu'un demande un site web sur votre serveur ? +## Que se passe-t-il quand quelqu'un demande un site web à votre serveur ? -Quand une requête arrive sur un serveur web, elle est transmise à django dont le premier travail va être d'essayer de comprendre ce qui est exactement demandé. Il s'occupe tout d'abord de l'adresse de la page web et essaye de comprendre ce qu'il doit en faire. Ce travail est effectué par l' **urlresolver** de Django (l'adresse d'une page web est appelée URL, Uniform Resource Locator, ce qui nous aide à comprendre le nom *urlresolver*). Comme il n'est pas très malin, il prend une liste de modèles existants et essaye de trouver celui qui correspond à notre URL. Django lit sa liste de modèles du haut vers le bas et si jamais quelque chose correspond, il envoie la requête à la fonction associée (qui s'appelle une *vue (view)*). +Quand une requête arrive sur un serveur web, elle est transmise à Django dont le premier travail va être d'essayer de comprendre ce qui est exactement demandé. Il s'occupe tout d'abord de l'adresse de la page web et essaye de comprendre ce qu'il doit en faire. Ce travail est effectué par l' **urlresolver** de Django (l'adresse d'une page web est appelée URL, Uniform Resource Locator, ce qui nous aide à comprendre le nom *urlresolver*). Comme il n'est pas très malin, il prend une liste de modèles existants et essaye de trouver celui qui correspond à notre URL. Django lit sa liste de modèles du haut vers le bas et si jamais quelque chose correspond, il envoie la requête à la fonction associée (qui s'appelle une *vue (view)*). -Ce serait comme une postière qui descendrait la rue avec une lettre et qui vérifierait à chaque maison si le numéro de celle-ci correspond à celui inscrit sur l'enveloppe. Dès que c'est le cas, elle dépose l'enveloppe dans la boîte aux lettres correspondante. C'est de cette manière que fonctionne l'urlresolver ! +Afin d'y voir un peu plus clair, imaginez une postière transportant une lettre. Elle descend la rue et vérifie à chaque maison si le numéro de celle-ci correspond à celui de la lettre. Si jamais les deux numéros correspondent, elle met la lettre dans la boîte aux lettres de cette maison. C'est à peu près comme cela que fonctionne l'urlresolver ! -C'est dans la fonction *vue* que les choses intéressantes se passent : c'est à ce moment qu'on regarde dans la base de données à la recherche d'informations dont on a besoin. Par exemple, peut-être que l'utilisateur vient de demander de changer quelque chose dans ces données ? Ce serait comme une lettre dont le contenu serait : "Merci de changer la description de mon emploi actuel". La *vue* va tout d'abord vérifier que l'utilisateur est bien autorisé à effectuer ce changement puis elle corrigera la description de l'emploi. Enfin, elle retournera un message de type : "C'est bon, j'ai terminé ! ". La *vue* créera une réponse et c'est Django qui se chargera de la transmettre au navigateur de l'utilisateur. +C'est dans la fonction *vue* que les choses intéressantes se passent : cela nous permet de jeter un œil dans la base de données pour obtenir des informations. Par exemple, peut-être que l'utilisateur vient de demander de changer quelque chose dans ces données ? Ce serait comme une lettre dont le contenu serait : "Merci de changer la description de mon emploi actuel". La *vue* va tout d'abord vérifier que l'utilisateur est bien autorisé à effectuer ce changement puis elle corrigera la description de l'emploi. Enfin, elle retournera un message de type : "C'est bon, j'ai terminé ! ". La *vue* créera une réponse et c'est Django qui se chargera de la transmettre au navigateur de l'utilisateur. -Bien sûr, ceci n'est qu'une description très simplifiée du processus. Vous n'avez pas besoin de connaître tous les détails techniques pour le moment : cette vue d'ensemble suffira largement. +Bien sûr, ceci n'est qu'une description très simplifiée du processus. Vous n'avez pas besoin de connaitre tous les détails techniques pour le moment : cette vue d'ensemble suffira largement. -Maintenant, nous aurions la possibilité de vous assommer de détails compliqués sur comment tout cela fonctionne. À la place, nous allons plutôt commencer à construire quelque chose ! Nous vous donnerons toutes les informations importantes au fur et à mesure que vous progresserez. Ce sera plus sympa, non ? \ No newline at end of file +Maintenant, nous aurions la possibilité de vous assommer avec des détails complexes sur comment tout cela fonctionne. À la place, nous allons plutôt commencer à construire quelque chose ! Nous vous donnerons toutes les informations importantes au fur et à mesure que vous progresserez. Ce sera plus sympa, non ? diff --git a/fr/django_admin/README.md b/fr/django_admin/README.md index d94a433f0a7..3cc9b5adaa1 100755 --- a/fr/django_admin/README.md +++ b/fr/django_admin/README.md @@ -4,26 +4,22 @@ Pour ajouter, éditer et supprimer les posts que nous venons de modéliser, nous Ouvrons le fichier `blog/admin.py` et remplaçons son contenu par ceci : - from django.contrib import admin - from .models import Post - - admin.site.register(Post) - - -Comme vous pouvez le voir, nous importons le modèle « Post » que nous avons écrit dans le chapitre précédent. Afin que notre modèle soit visible dans l'interface d'administration, nous avons besoin d'enregistrer notre modèle à l'aide de `admin.site.register(Post)`. +```python +from django.contrib import admin +from .models import Post -Ok, allons voir notre modèle « Post ». N'oubliez pas de lancer le server web en tapant `python manage.py runserver` dans la console. À l'aide de votre navigateur, allez à l'adresse suivante : +admin.site.register(Post) +``` - http://127.0.0.1:8000/admin/ - +Comme vous pouvez le voir, nous importons le modèle « Post » que nous avons écrit dans le chapitre précédent. Afin que notre modèle soit visible dans l'interface d'administration, nous avons besoin d'enregistrer notre modèle à l'aide de `admin.site.register(Post)`. -Vous verrez une page de login qui ressemble à celle-ci : +Voilà, il est temps de jeter un œil à notre modèle Post. N'oubliez pas d'exécuter `python manage.py runserver` dans votre console afin de lancer le serveur web. Dans votre navigateur, entrez l'adresse http://127.0.0.1:8000/admin/. Si tout va bien, vous verrez une page comme celle-ci: ![Page de login][1] [1]: images/login_page2.png -Afin de pouvoir vous connecter, vous avez besoin de créer un *superuser ou superutilisateur*. C'est un utilisateur qui peut contrôler l'intégralité du site. Reprenez votre ligne de commande et taper `python manage.py createsuperuser` et appuyez sur entrée. Tapez votre nom d'utilisateur (en minuscules, sans espace), votre email et votre mot de passe lorsqu'on vous le demande. Ce qui apparaît dans votre console doit ressembler à ceci, au détail près que « username » et « email » doivent être ceux que vous avez entrés : +Afin de vous connecter, vous allez devoir créer un *superuser*, c'est à dire un utilisateur qui contrôlera l'intégralité du site. Retournez à votre ligne de commande : tapez `python manage.py createsuperuser` puis appuyez sur entrée. Tapez votre nom d'utilisateur (en minuscules, sans espace), votre email et votre mot de passe. Vous ne voyez pas le mot de passe que vous êtes en train de taper ? C'est tout à fait normal, ne vous inquiétez pas ! Tapez simplement votre mot de passe et appuyez sur `entrée` pour continuer. La sortie que vous allez obtenir doit ressembler à celle-ci. Notez que le nom d'utilisateur et l'adresse email doivent correspondre aux informations que vous venez d'entrer. (myvenv) ~/djangogirls$ python manage.py createsuperuser Username: admin @@ -39,14 +35,14 @@ Retournez dans votre navigateur et connectez-vous en tant que superutilisateur g [2]: images/django_admin3.png -Allez dans la partie "Post" et bidouillez un peu. Ajoutez 5 à 6 posts par exemple. N'accordez pas d'importance à leur contenu : vous pouvez tout simplement copier-coller le texte de ce tutoriel dans vos posts pour gagner du temps :). +Allez voir vos posts et expérimentez un peu avec. Ajoutez 5 ou 6 posts. Ne vous occupez pas du contenu - vous pouvez juste copier du texte de ce tutoriel pour aller plus vite :). -Ajoutez une date de publication à au moins deux ou trois posts sur tous ceux que vous venez de créer : nous en aurons besoin pour la suite. +Sur vos 5 posts, faites en sorte qu'au moins 2 ou 3 posts possèdent une date de publication. Prenez garde à ne pas en donner à tous vos posts car nous allons avoir besoin de ces deux différents cas plus tard. ![Django admin][3] [3]: images/edit_post3.png -Si vous voulez en savoir plus sur l'interface d'administration de Django, n'hésitez pas à consulter la documentation du framework : https://docs.djangoproject.com/en/1.7/ref/contrib/admin/ +Si jamais vous voulez en savoir un peu plus sur l'interface d'administration de Django, vous pouvez lire la documentation qui lui est associée : https://docs.djangoproject.com/fr/1.8/ref/contrib/admin/ -C'est probablement le bon moment de faire une pause et d'aller vous chercher un café (ou un thé) et quelque chose à grignoter : vous venez de créer votre premier modèle Django ! Vous méritez bien une petite récompense ! \ No newline at end of file +Il est probablement temps d'aller recharger vos batteries avec un café, un thé ou un truc à grignoter. Vous venez de créer votre modèle Django : vous méritez bien une petite pause ! \ No newline at end of file diff --git a/fr/django_forms/README.md b/fr/django_forms/README.md index bfb83b95ca2..db1231445d0 100755 --- a/fr/django_forms/README.md +++ b/fr/django_forms/README.md @@ -1,39 +1,40 @@ # Formulaires Django -La dernière chose que nous voulons faire sur notre site web, c'est de créer une manière sympathique d'ajouter ou éditer des blog posts. `L'interface d'administration` de Django est cool, mais elle est assez complexe à personnaliser et à rendre jolie. Les `formulaires` vont nous donner un pouvoir absolu sur notre interface : nous allons être capables de faire, à peu près, tout ce que nous pouvons imaginer ! +La dernière chose que nous voulons faire sur notre site web, c'est créer une manière sympathique d'ajouter ou d'éditer des blog posts. `L'interface d'administration` de Django est cool, mais elle est assez complexe à personnaliser et à rendre jolie. Les `formulaires` vont nous donner un pouvoir absolu sur notre interface : nous allons être capables de faire à peu près tout ce que nous pouvons imaginer ! Ce qui est pratique avec les formulaires Django, c'est que nous pouvons aussi bien en définir un à partir de rien ou créer un `ModelForm` qui va enregistrer le résultat du formulaire dans un modèle. -C'est exactement ce que nous voulons faire : nous allons créer un formulaire pour notre modèle `Post`. +C'est la seconde solution que nous allons utiliser pour créer un formulaire pour notre modèle `Post`. -Comme toutes les choses qui sont importantes dans Django, les formulaires ont leur propre fichier : `forms.py`. +Comme toutes les choses importantes dans Django, les formulaires ont leur propre fichier : `forms.py`. Nous allons devoir créer un fichier avec ce nom dans notre dossier `blog`. blog └── forms.py - -Ouvrons maintenant ce fichier et tapons le code suivant : - from django import forms - - from .models import Post - - class PostForm(forms.ModelForm): - - class Meta: - model = Post - fields = ('title', 'text',) - +Ouvrez maintenant ce fichier et tapez le code suivant : -Nous avons besoin tout d'abord d'importer les formulaires Django (`from django import forms`), puis, évidemment, nous avons besoin de notre modèle `Post` (`from .models import Post`). +```python +from django import forms -Comme vous l'avez probablement deviné, `PostForm` est le nom de notre formulaire. Nous avons besoin de préciser à Django que ce formulaire est un `ModelForm`. Nous utilisons `forms.ModelForm` pour cela. +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Nous avons besoin tout d'abord d'importer les formulaires Django (`from django import forms`), puis, évidemment, notre modèle `Post` (`from .models import Post`). + +Comme vous l'avez probablement deviné, `PostForm` est le nom de notre formulaire. Nous avons besoin de préciser à Django que ce formulaire est un `ModelForm`. Pour cela, nous utilisons `forms.ModelForm`. Ensuite, nous avons une `Meta Classe` qui nous permet de dire à Django quel modèle il doit utiliser pour créer ce formulaire (`model = Post`). -Enfin, nous précisions quels sont le⋅s champ⋅s qui doivent figurer dans notre formulaire. Dans notre cas, nous souhaitons que seul `title` et `text` apparaissent dans notre formulaire, car nous obtiendrons les autres données différemment. En effet, nous nous attendons à ce qu'`author` soit le nom de la personne connectée (en l’occurrence, vous ! ) et `created_date` soit générée automatiquement lors de la création du post (cf code que nous avons écrit). +Enfin, nous précisions quels sont le⋅s champ⋅s qui doivent figurer dans notre formulaire. Dans notre cas, nous souhaitons que seuls `title` et `text` apparaissent dans notre formulaire. Nous obtiendrons les autres données différemment : par exemple, on s'attend à ce que l'auteur (`author`) soit la personne actuellement enregistrée (c'est à dire vous !) et que la date de création `created_date` soit générée automatiquement lors de la création du post (cf code que nous avons écrit). Et voilà, c'est tout ! Tout ce qu'il nous reste à faire, c'est d'utiliser ce formulaire dans une *vue* et de l'afficher dans un template. @@ -44,9 +45,8 @@ Nous allons donc une nouvelle fois suivre le processus suivant et créer : un li C'est le moment d'ouvrir le fichier `blog/templates/blog/base.html`. Nous allons ajouter un lien dans un `div` appelé `page-header` : ```html - + ``` - Remarquez que notre nouvelle vue s'appelle `post_new`. @@ -59,13 +59,12 @@ Après avoir ajouté cette ligne, votre fichier html devrait maintenant ressembl Django Girls blog -
@@ -80,53 +79,57 @@ Après avoir ajouté cette ligne, votre fichier html devrait maintenant ressembl ``` -Normalement, après avoir rechargé la page `http://127.0.0.1:8000`, vous devriez encore tomber sur l'erreur `NoReverseMatch`. +Sauvegardez votre fichier et rafraichissez la page http://127.0.0.1:8000 : vous devez normalement tomber encore une fois sur l'erreur `NoReverseMatch` ! ## URL Ouvrez le fichier `blog/urls.py` et ajoutez cette ligne : +```python url(r'^post/new/$', views.post_new, name='post_new'), - +``` Votre fichier doit maintenant ressembler à ceci : - from django.conf.urls import patterns, include, url - from . import views - - urlpatterns = patterns('', - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - url(r'^post/new/$', views.post_new, name='post_new'), - ) - +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` -Une fois la page rechargée, vous allez voir une `AttributeError`, ce qui est normal, car nous n'avons pas encore de vue `post_new` implémentée. Allons nous occuper de ça maintenant. +Une fois la page rechargée, vous allez voir une `AttributeError`, ce qui est normal. Nous n'avons pas encore implémentée la vue `post_new`. Allons nous occuper de ça maintenant. ## La vue post_new -Ouvrons maintenant le fichier `blog/views.py` et ajoutez les lignes suivantes sous celles existantes : +Ouvrez maintenant le fichier `blog/views.py` et ajoutez les lignes suivantes avec celles du `from` qui existent déjà : - from .forms import PostForm - +```python +from .forms import PostForm +``` Puis ajoutez la *vue* : - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` Afin de pouvoir créer un nouveau formulaire `Post`, nous avons besoin d'appeler la fonction `PostForm()` et de la passer au template. Nous reviendrons modifier cette *vue* plus tard, mais pour l'instant, créons rapidement un template pour ce formulaire. ## Template -Nous avons pour cela besoin de créer un fichier `post_edit.html` dans le dossier `blog/templates/blog`. Afin que notre formulaire fonctionne, nous avons besoin de plusieurs choses : +Pour cela, nous avons besoin de créer un fichier `post_edit.html` dans le dossier `blog/templates/blog`. Afin que notre formulaire fonctionne, nous avons besoin de plusieurs choses : -* Nous avons besoin d'afficher le formulaire. Pour cela, nous n'avons qu'à utiliser `{{ form.as_p }}`. +* Nous voulons afficher le formulaire. Nous pouvons le faire à l'aide d'un simple `{% raw %}{{ form.as_p }}{% endraw %}` par exemple. * La ligne précédente va avoir besoin d'être enveloppée dans des balises HTML : `...` * Nous avons besoin d'un bouton `Save (sauvegarder)`. Nous allons le créer à l'aide d'un bouton HTML : `` -* Enfin, nous avons besoin d'ajouter `{% raw %}{% csrf_token %}{% endraw %}` juste après la balise `
`. C'est très important : c'est ce qui va permettre de sécuriser votre formulaire ! De toute manière, si vous avez oublié ce petit morceau, Django va se plaindre lors de la sauvegarde du formulaire : +* Enfin, nous devons ajouter `{% raw %}{% csrf_token %}{% endraw %}` juste après ``. C'est très important car c'est ce qui va permettre de sécuriser votre formulaire ! De toute manière, si vous avez oublié ce petit morceau, Django vous le fera remarquer lorsque vous sauvegarderez le formulaire : ![CSFR Forbidden page][1] @@ -145,9 +148,8 @@ Ok, voyons maintenant à quoi devrait ressembler le fichier `post_edit.html` :
{% endblock %} ``` - -Rafraîchissons la page ! Et voilà : le formulaire s'affiche ! +Rafraichissons la page ! Et voilà : le formulaire s'affiche ! ![Nouveau formulaire][2] @@ -155,82 +157,91 @@ Rafraîchissons la page ! Et voilà : le formulaire s'affiche ! Heu, attendez une minute... Quand vous tapez quelque chose dans `title` et `text` et que vous essayez de le sauvegarder, que se passe-t-il ? -Absolument rien ! Nous retombons sur la même page sauf qu'en plus, notre texte a disparu et aucun post ne semble avoir été créé. Est-ce que nous venons de rencontrer un bug ? +Absolument rien ! Nous retombons sur la même page sauf qu'en plus, notre texte a disparu et aucun post ne semble avoir été créé. Que s'est-il passé ? -Heureusement non ! Nous avons juste encore un peu de travail à accomplir. Retournons à notre *vue*. +La réponse est : rien ! Nous avons juste encore un peu de travail à accomplir. Retournons à notre *vue*. ## Sauvegarder le contenu du formulaire -Ouvrez à nouveau le fichier `blog/views.py`. Pour le moment, le contenu de notre vue `post_new` se limite à ceci : +Ouvrez à nouveau `blog/views.py`. Actuellement, `post_new` n'est composé que des lignes de code suivantes : - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Ainsi, lorsque nous soumettons notre formulaire, nous revenons à la même vue, mais cette fois, nous avons un peu plus de données dans `request` ou, plus précisément, dans `request.POST`. Est-ce que vous vous souvenez avoir défini la variable `method="POST"` dans le fichier HTML qui contient notre `` ? Tous les champs du formulaire se trouvent maintenant dans `request.POST`. Veillez à ne pas renommer `POST` en quoi que ce soit d'autre : la seule autre valeur autorisée pour `method` est `GET`. Malheureusement, nous n'avons pas le temps de rentrer dans les détails aujourd'hui. +Lorsque nous envoyons notre formulaire, nous revenons à la même vue. Cependant, nous avons des données dans `request`, et plus particulièrement dans `request.POST`. Prenez garde que "POST" ici n'a aucun lien avec "blog post" : le nom est lié au fait que nous envoyons des données. Rappelez-vous : nous avions défini la variable `method="POST"` dans le fichier HTML qui contient notre `` ? Tous les champs du formulaire se trouvent maintenant dans `request.POST`. Veillez à ne pas renommer `POST` en quoi que ce soit d'autre : la seule autre valeur autorisée pour `method` est `GET`. Malheureusement, nous n'avons pas le temps de rentrer dans les détails aujourd'hui. -Dans notre *vue*, nous avons donc deux situations différentes à gérer. Tout d'abord, nous avons la situation où nous accédons à la page pour la première fois et que nous voulons un formulaire vide. Ensuite, nous avons la seconde situation où nous retournons sur la *vue* et nous voulons que les champs du formulaire contiennent les informations que nous avions tapées. Pour gérer ces deux cas, nous allons utiliser une condition (`if (si)`). +Dans notre *vue*, nous avons donc deux situations différentes à gérer. Tout d'abord, nous avons la situation où nous accédons à la page pour la première fois et que nous voulons un formulaire vide. Ensuite, nous avons la seconde situation où nous retournons sur la *vue* et nous voulons que les champs du formulaire contiennent les informations que nous avions tapées. Pour gérer ces deux cas, nous allons utiliser une condition `if` (si). - if request.method == "POST": - [...] - else: - form = PostForm() - +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` -Attaquons nous à remplir ces `[...]`. Comme la `method` est `POST`, c'est que nous voulons construire notre `PostForm` avec les données de notre formulaire. Pour cela, nous devons ajouter : +Attaquons-nous à remplir ces `[...]`. Si la `method` est `POST`, c'est que nous voulons construire notre `PostForm` avec les données de notre formulaire. Pour cela, nous devons ajouter : - form = PostForm(request.POST) - +```python +form = PostForm(request.POST) +``` -Facile ! La prochaine étape est de vérifier si le contenu de notre formulaire est correct. Nous aimerions vérifier, par exemple, que les champs obligatoires sont bien remplis et qu'aucune donnée incorrecte ne soient sauvegardée. Nous allons utiliser `form.is_valid()`. +Facile ! La prochaine étape est de vérifier si le contenu de notre formulaire est correct. Nous aimerions vérifier, par exemple, que les champs obligatoires soient bien remplis et qu'aucune donnée incorrecte ne soit sauvegardée. Pour cela, nous allons utiliser `form.is_valid()`. Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le ! - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` -En gros, nous effectuons deux choses ici : nous sauvegardons le formulaire grâce à `form.save` et nous ajoutons un auteur. Rappelez vous, il n'y avait pas de champ `author` dans le `PostForm` mais nous avons obligatoirement besoin pour que le formulaire que nous avons créé soit valide. `commit=False` signifie que nous ne voulons pas encore enregistrer notre modèle `Post`. Nous voulons tout d'abord ajouter un auteur. La plupart du temps, vous utiliserez `form.save()` sans `commit=False`. Cependant, nous en avons besoin ici. `post.save()` va nous permettre de sauvegarder les changements, c'est-à-dire l'ajout d'un auteur. Et voilà, maintenant c'est sûr, un nouveau blog post sera créé ! +En gros, nous effectuons deux choses ici : nous sauvegardons le formulaire grâce à `form.save` et nous ajoutons un auteur. Rappelez-vous, il n'y avait pas de champ `author` dans le `PostForm` mais nous avons obligatoirement besoin d'un auteur pour que le formulaire que nous avons créé soit valide. `commit=False` signifie que nous ne voulons pas encore enregistrer notre modèle `Post`. Nous voulons tout d'abord ajouter un auteur. La plupart du temps, vous utiliserez `form.save()` sans `commit=False`. Cependant, nous en avons besoin ici. `post.save()` va nous permettre de sauvegarder les changements, c'est-à-dire l'ajout d'un auteur. Et voilà, maintenant c'est sûr, un nouveau blog post sera créé ! -Enfin, ce serait génial si nous pouvions tout de suite obtenir la page `post_detail` pour le blog post que nous venons de créer. Pour cela, nous avons besoin d'un dernier "import" : +Enfin, ce serait génial si nous pouvions tout de suite aller à la page `post_detail` du post de blog que nous venons de créer. Pour cela, nous avons besoin d'importer une dernière chose : - from django.shortcuts import redirect - +```python +from django.shortcuts import redirect +``` Ajoutez-le au tout début de votre page. Maintenant, nous allons ajouter la ligne qui signifie : "aller à la page `post_detail` pour le nouveau post qui vient d'être créé". - return redirect('blog.views.post_detail', pk=post.pk) - +```python +return redirect('blog.views.post_detail', pk=post.pk) +``` `blog.views.post_detail` est le nom de la vue où nous voulons aller. Rappelez-vous : une *vue* a besoin d'une variable `pk`. Afin de le passer à la vue, nous utilisons `pk=post.pk`, où `post` désigne le blog post nouvellement créé ! -Et si au lieu de parler, nous vous montrons à quoi ressemble maintenant notre *vue* ? +Et si au lieu de parler, nous vous montrions à quoi ressemble maintenant notre *vue* ? - def post_new(request): - if request.method == "POST": - form = PostForm(request.POST) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Voyons si ça marche. Allez à la page `http://127.0.0.1:8000/post/new/`. Ajoutez un `title` et du `text` et sauvegardez votre formulaire ... Et voilà ! Le nouveau post est bien créé et vous êtes redirigé vers la page `post_detail` ! +Voyons si ça marche. Allez à l'adresse http://127.0.0.1:8000/post/new/, ajoutez un `titre` et du `texte`, puis sauvegardez... Et voilà ! Le nouveau post est bien créé et vous êtes redirigé vers la page `post_detail` ! -Vous avez peut-être remarqué que nous ne nous sommes pas du tout occupé de la date de publication de nos posts ? Nous nous occuperons d'ajouter un *publish button (bouton de publication)* dans la partie **Tutoriel Django Girls : exercices supplémentaires**. +Vous avez peut-être remarqué que nous avons choisi une date de publication avant de sauvegarder le post. Nous en aurons besoin lorsque nous créerons le *publish button* (bouton publier) dans **l'un des extensions du tutoriel Django Girls** (en anglais). -Est-ce que ce n'est pas déjà génial tout ce que nous avons accompli ensemble aujourd'hui ? +Encore bravo ! ## Validation de formulaire -Maintenant, nous allons vous montrer à quel point les formulaires Django sont cools ! Un blog post a besoin de champs `title (titre)` et `text (texte)`. Comme nous n'avons pas signalé dans notre modèle `Post` que ces deux champs n'étaient pas obligatoire (à l'inverse du cas de `published_date`) Django s'attend à ce qu'ils soient remplis à chaque fois. +Maintenant, nous allons vous montrer à quel point les formulaires Django sont cools ! Un post de blog a besoin de champs `title` (titre) et `text` (texte). Dans notre modèle `Post`, nous n'avons pas signalé que ces champs n'étaient pas obligatoire (à l'inverse de `published_date`). Django s'attend donc à ce qu'ils soient remplis à chaque fois. Essayez de sauvegarder un formulaire sans mettre de `titre` ou de `texte`. Devinez ce qui va se passer ! @@ -238,9 +249,9 @@ Essayez de sauvegarder un formulaire sans mettre de `titre` ou de `texte`. Devin [3]: images/form_validation2.png -Django va s'occuper de la validation : il va regarder si tous les champs de notre formulaire sont en adéquation avec le modèle. C'est cool, non ? +Django va s'occuper de la validation : il va regarder si tous les champs de notre formulaire sont en adéquation avec notre modèle. C'est cool, non ? -> Comme nous avons récemment utilisé l'interface d'administration de Django, le système pense que nous sommes encore connectés. Cependant, il y a plusieurs cas qui peuvent amener un utilisateur à être déconnecté : fermer le navigateur, redémarrer la base de données, etc. Si jamais vous avez une erreur lors de la création de post qui fait référence au fait que vous ne pouvez pas faire cette action car vous n'êtes pas connecté, allez faire un tour dans l'interface d'administration `http://127.0.0.1:8000/admin`. Cela vous obligera forcément à vous connecter. Cependant, vous devinez bien que cette solution n'est pas bonne sur le long terme. Afin de corriger ce problème, n'hésitez pas à faire la partie **Devoir : ajouter de la sécurité à son site internet !** qui est située juste après la partie principale du tutoriel. +> Comme nous avons récemment utilisé l'interface d'administration de Django, le système pense que nous sommes encore connectés. Cependant, il y a plusieurs cas qui peuvent amener un utilisateur à être déconnecté : fermer le navigateur, redémarrer la base de données, etc. Si jamais vous obtenez des erreurs lors de la création d'un post qui disent que vous n'êtes pas connecté, retournez sur la page d'administration présente à l'adresse http://127.0.0.1:8000/admin et connectez-vous à nouveau. Cependant, vous devinez bien que cette solution n'est pas suffisante à long terme. Afin de corriger ce problème, n'hésitez pas à faire la partie **Devoir : ajouter de la sécurité à son site internet !** qui est située juste après la partie principale du tutoriel. ![Erreur de loggin][4] @@ -252,7 +263,7 @@ Maintenant, nous savons comme ajouter un nouveau formulaire. Comment faire si no Ouvrez le fichier `blog/templates/blog/post_detail.html` et ajoutez la ligne suivante : -```html +```python ``` @@ -262,58 +273,64 @@ Votre template doit ressembler à ceci : {% extends 'blog/base.html' %} {% block content %} -
- {% if post.published_date %} - {{ post.published_date }} - {% endif %} - +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

{% endblock %} ``` - Maintenant, dans `blog/urls.py`, ajoutez cette ligne : +```python url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), - +``` Nous allons réutiliser le template de `blog/templates/blog/post_edit.html`. Il ne va donc nous manquer qu'une *vue*. Ouvrons `blog/views.py` et ajoutons à la toute fin du fichier : - def post_edit(request, pk): - post = get_object_or_404(Post, pk=pk) - if request.method == "POST": - form = PostForm(request.POST, instance=post) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm(instance=post) - return render(request, 'blog/post_edit.html', {'form': form}) - - -Vous ne trouvez pas que ça ressemble presque à la vue de `post_new` ? Regardons un peu plus en détails. Tout d'abord, nous passons un paramètre `pk` supplémentaire. Ensuite, nous récupérons le modèle `Post` que nous souhaitons éditer à l'aide de `get_object_or_404(Post, pk=pk)`. Puis, lorsque nous créons un formulaire, nous faisons deux fois de ce post une `instance`. Tout d'abord lorsque nous sauvegardons le formulaire : - - form = PostForm(request.POST, instance=post) - +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Vous ne trouvez pas que ça ressemble presque à la vue de `post_new` ? Regardons un peu plus en détail. Tout d'abord, nous passons un paramètre `pk` supplémentaire. Ensuite, nous récupérons le modèle `Post` que nous souhaitons éditer à l'aide de `get_object_or_404(Post, pk=pk)`. Puis, lorsque nous créons un formulaire, nous faisons de ce post deux `instances`. Tout d'abord lorsque nous sauvegardons le formulaire : + +```python +form = PostForm(request.POST, instance=post) +``` Puis ensuite lorsque nous ouvrons le formulaire associé à ce post afin de l'éditer : - form = PostForm(instance=post) - +```python +form = PostForm(instance=post) +``` -Alors, voyons si ça marche ! Allons sur la page `post_detail`. Un bouton d'édition devrait apparaître dans le coin supérieur droit de la page : +Alors, voyons si ça marche ! Allons à la page `post_detail`. Un bouton d'édition devrait apparaitre dans le coin supérieur droit de la page : ![Bouton d'édition][5] [5]: images/edit_button2.png -Lorsque vous cliquez dessus, vous devez voir le formulaire du blog post apparaître : +Lorsque vous cliquez dessus, vous devez voir le formulaire du post de blog apparaitre : ![Éditer un formulaire][6] @@ -321,24 +338,59 @@ Lorsque vous cliquez dessus, vous devez voir le formulaire du blog post apparaî Essayez de manipuler un peu ce que vous venez de créer : ajoutez du texte, changez le titre puis sauvegardez ces changements ! -Bravo ! Votre application se complexifie et contient de plus en plus de fonctionnalité ! +Bravo ! Votre application se complexifie et contient de plus en plus de fonctionnalités ! + +Si jamais vous voulez en savoir plus sur les formulaires dans Django, n'hésitez pas à lire la documentation associée : https://docs.djangoproject.com/fr/1.8/topics/forms/ + +## Sécurité + +C’est génial de pouvoir créer de nouveaux posts juste en cliquant sur un lien ! Mais n’importe qui visitant votre site pourra mettre un nouveau post en ligne, ce qui n’est probablement pas ce que vous souhaitez. Faisons en sorte que le bouton n’apparaisse seulement qu'à vous. + +Dans `blog/templates/blog/base.html`, trouvez notre `page-header` `div` et la balise ancre que vous y avez mis plus tôt. Ça doit ressembler à ça : + +```html + +``` -Si vous souhaitez en apprendre plus sur les formulaires Django, n'hésitez pas à consulter la documentation associée : https://docs.djangoproject.com/en/1.7/topics/forms/ +On va y ajouter une autre balise `{% if %}` qui ne fera apparaitre le lien qu’aux utilisateurs⋅trices connecté⋅e⋅s dans l’administration : uniquement vous pour le moment ! Changez la balise `` comme ceci : + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Ce `{% if %}` fait en sorte de n’envoyer le lien au navigateur que si l’utilisateur⋅trice demandant la page est connecté⋅e. Ce n’est pas une protection complète, mais c’est un bon début. Nous reviendrons sur les questions de sécurité dans les extensions du tutoriel. + +Comme vous êtes probablement connectée, vous ne verrez aucune différence si vous rafraichissez la page. Mais chargez la page dans un autre navigateur ou dans une fenêtre incognito, et vous verrez que le lien n’apparait pas ! ## Encore un petit effort : déployons ! -Ce serait génial si nous pouvions aller sur notre site web hébergé sur Heroku et voir toutes ces nouvelles fonctionnalités ! Remontons nos manches et déployons encore une fois. Si vous ne vous souvenez plus de ce que fait chaque commande, consultez la fin du chapitre 15 : - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Ajout des vues qui permettent d'ajouter et éditer des blog posts directement sur le site" -... -$ git push heroku master +Nos modifications fonctionnent-elles sur PythonAnywhere ? Pour le savoir, déployons à nouveau ! + +* Tout d'abord, commitez votre nouveau code et pushez-le à nouveau sur Github +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Ajout de vues qui permettent de créer et d'éditer un post de blog sur le site." + $ git push ``` - + +* Puis, dans la console bash de [PythonAnywhere][7]: + + [7]: https://www.pythonanywhere.com/consoles/ +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +* Enfin, cliquez sur l'onglet [Web][8] et cliquez sur **Reload**. + + [8]: https://www.pythonanywhere.com/web_app_setup/ Normalement, ça devrait suffire ! Encore bravo :) diff --git a/fr/django_installation/README.md b/fr/django_installation/README.md index b9cbbee9657..c775ee7bbc4 100755 --- a/fr/django_installation/README.md +++ b/fr/django_installation/README.md @@ -1,113 +1,5 @@ # Installation de Django -> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (http://django.carrots.pl/). -> -> Ce chapitre est en partie inspiré du [tutoriel django-marcador][1] qui est sous licence Creative Commons Attribution-ShareAlike 4.0 International License. Le tutoriel django-marcador a été créé par Markus Zapke-Gründemann et al. +> **Note** Si vous avez déjà suivi les étapes d'Installation, vous n'avez rien d'autre à faire - vous pouvez aller directement au chapitre suivant ! - [1]: http://django-marcador.keimlink.de/ - -## L'environnement virtuel - -Avant d'installer Django, nous allons vous faire installer un outil extrêmement utile qui vous aidera à maintenir votre environnement de développement propre. Vous pouvez sauter cette partie, mais nous vous le déconseillons : bien préparer votre ordinateur vous épargnera de nombreux problèmes par la suite ! - -Donc, commençons par créer un **environnement de développement** (ou *virtualenv*). Cela va vous permettre, pour chaque projet, d'isoler votre installation Python/Django afin que les modifications que vous souhaitiez effectuer sur un site n'affectent pas les autres que vous seriez en train de développer à côté. Cool, non ? - -Tout ce dont vous avez besoin, c'est de trouver un dossier où vous voulez créer votre `virtualenv` ; vous pouvez choisir votre home par exemple. Sous Windows, le home ressemble à `C:\Users\Name` (où `Name` est votre login). - -Dans ce tutoriel, nous allons utiliser le nouveau dossier `djangogirls` que vous allez créer dans votre dossier home : - - mkdir djangogirls - cd djangogirls - - -Nous allons créer un virtualenv appelé `myvenv`. Pour cela, nous taperons une commande qui ressemblera à : - - python -m venv myvenv - - -### Windows - -Afin de créer un nouveau `virtualenv`, vous avez besoin d'ouvrir votre console (on vous en a parlé précédemment, est-ce que vous vous en souvenez ?) et tapez `C:\Python34\python -m venv myvenv`. Ça ressemblera à ça : - - C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv - - -`C:\Python34\python` doit être le nom du dossier où vous avez installé Python et `myvenv` doit être le nom de votre `virtualenv`. Vous pouvez choisir le nom que vous voulez, mais veillez à n'utiliser que des minuscules et à n'insérer ni espaces, ni caractères spéciaux. C'est aussi une bonne idée de choisir un nom plutôt court, car vous aller souvent l'utiliser ! - -### Linux et OS X - -Pour créer un `virtualenv` sous Linux ou OS X, tapez simplement la commande `python3 -m venv myvenv`. Ça ressemblera à ça : - - ~/djangogirls$ python3 -m venv myvenv - - -`myvenv` est le nom de votre `virtualenv`. Vous pouvez choisir le nom que vous voulez, mais veillez à n'utiliser que des minuscules et à n'insérer ni espaces, ni caractères spéciaux. C'est aussi une bonne idée de choisir un nom plutôt court, car vous aller souvent l'utiliser ! - -> **NOTE:** initialiser un environnement virtuel sous Ubuntu 14.04 de cette manière donne l'erreur suivante : -> -> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 -> -> -> Pour résoudre ce problème, utilisez plutôt la commande `virtualenv`. -> -> ~/djangogirls$ sudo apt-get install python-virtualenv -> ~/djangogirls$ virtualenv --python=python3.4 myvenv -> - -## Travailler avec virtualenv - -Les commandes listées ci-dessus permettent de créer un dossier appelé `myvenv` (ou le nom que vous avez choisi) qui contient notre environnement virtuel. Pour faire simple, c'est un dossier composé lui-même d'autres dossiers et de fichiers. Tout ce que nous avons à faire maintenant, c'est de le lancer en tapant : - - C:\Users\Name\djangogirls> myvenv\Scripts\activate - - -sous Windows, ou : - - ~/djangogirls$ source myvenv/bin/activate - - -sous Linux et OS X. - -N'oubliez pas que si vous avez choisi un autre nom pour votre `virtualenv` à la place de `myvenv`, vous devez utiliser celui-là ! - -> **NOTE :** il arrive parfois que `source` ne soit pas disponible. Dans ce cas, vous pouvez essayer ceci : -> -> ~/djangogirls$ . myvenv/bin/activate -> - -Vous saurez que votre `virtualenv` est lancé quand le prompt de votre console ressemblera à ceci : - - (myvenv) C:\Users\Name\djangogirls> - - -ou : - - (myvenv) ~/djangogirls$ - - -Remarquez le préfixe `(myvenv)` qui vient d'apparaître ! - -Quand vous travaillez dans un environnement virtuel, la commande `python` fera automatiquement référence à la bonne version de Python que vous utilisez. Vous pouvez ainsi utiliser `python` à la place de la commande `python3`. - -Ok, nous avons installé toutes les dépendances dont nous avions besoin. Nous allons enfin pouvoir installer Django ! - -## Installation de Django - -Maintenant que notre `virtualenv` est lancé, nous pouvons installer Django en utilisant `pip`. Dans la console, tapez `pip install django==1.7.1` (notez que nous utilisons un double signe égal) : `==`). - - (myvenv) ~$ pip install django==1.7.1 - Downloading/unpacking django==1.7.1 - Installing collected packages: django - Successfully installed django - Cleaning up... - - -Sous Windows : - -> Si vous obtenez une erreur en utilisant pip sous Windows, vérifiez si le chemin d'accès de votre projet ne contient pas des espaces (par exemple : `C:\Users\User Name\djangogirls`). Si c'est le cas, il vaudrait peut-être mieux changer l'emplacement de votre projet afin de ne plus avoir de chemin d'accès avec des espaces (par exemple : `C:\djangogirls`). Après l'avoir déplacé, essayez de retaper la commande précédente. - -Sous Linux : - -> Si vous obtenez une erreur lorsque vous utilisez pip sous Ubuntu 12.04, tapez la commande `python -m pip install -U --force-reinstall pip` pour réparer l'installation de pip dans votre virtualenv. - -Et voilà ! Vous êtes (enfin) prêt⋅e à créer votre première application en Django ! Pour cela, vous allez avoir besoin d'un programme sympathique pour y écrire votre code ... \ No newline at end of file +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/fr/django_installation/instructions.md b/fr/django_installation/instructions.md new file mode 100644 index 00000000000..e698429eae6 --- /dev/null +++ b/fr/django_installation/instructions.md @@ -0,0 +1,113 @@ +> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Ce chapitre est en partie inspiré du [tutoriel django-marcador](http://django-marcador.keimlink.de/) qui est sous licence Creative Commons Attribution-ShareAlike 4.0 International License. Le tutoriel django-marcador a été créé par Markus Zapke-Gründemann et al. + +## L'environnement virtuel + +Avant d'installer Django, nous allons vous faire installer un outil extrêmement utile qui vous aidera à maintenir votre environnement de développement propre. Nous vous recommandons fortement de ne pas sauter cette étape, même si elle n'est pas indispensable. En commençant avec la meilleure configuration possible vous éviterez beaucoup de problèmes par la suite ! + +Donc, commençons par créer un **environnement virtuel de programmation** (ou *virtualenv*). Chaque projet aura sa propre configuration en Python/Django grâce à virtualenv. Ce qui veut dire que si vous modifiez un site web, ça n'affectera pas les autres sites sur lesquels vous travaillez. Plutôt cool, non ? + +Tout ce dont vous avez besoin, c'est de trouver un dossier où vous voulez créer votre `virtualenv` ; vous pouvez choisir votre home par exemple. Sous Windows, le home ressemble à `C:\Utilisateurs\Nom` (où `Nom` est votre login). + +Dans ce tutoriel, nous allons utiliser un nouveau dossier `djangogirls` que vous allez créer dans votre dossier home : + + mkdir djangogirls + cd djangogirls + + +Nous allons créer un virtualenv appelé `myvenv`. Pour cela, nous taperons une commande qui ressemblera à : + + python3 -m venv myvenv + + +### Windows + +Afin de créer un nouveau `virtualenv`, vous avez besoin d'ouvrir votre console (nous en avons déjà parlé dans un chapitre précédent. Est-ce que vous vous en souvenez ?) et tapez `C:\Python34\python -m venv myvenv`. Ça ressemblera à ça : + + C:\Utilisateurs\Nom\djangogirls> C:\Python34\python -m venv myvenv + + +`C:\Python34\python` doit être le nom du dossier où vous avez installé Python et `myvenv` doit être le nom de votre `virtualenv`. Vous pouvez choisir un autre nom mais attention : il doit être en minuscules, sans espaces et sans accents ou caractères spéciaux. C'est aussi une bonne idée de choisir un nom plutôt court, car vous aller souvent l'utiliser ! + +### Linux et OS X + +Pour créer un `virtualenv` sous Linux ou OS X, tapez simplement la commande `python3 -m venv myvenv`. Ça ressemblera à ça : + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` est le nom de votre `virtualenv`. Vous pouvez choisir un autre nom, mais veillez à n'utiliser que des minuscules et à n'insérer ni espaces, ni caractères spéciaux. C'est aussi une bonne idée de choisir un nom plutôt court, car vous aller souvent l'utiliser! + +> **NOTE:** initialiser un environnement virtuel sous Ubuntu 14.04 de cette manière donne l'erreur suivante : +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Pour résoudre ce problème, utilisez plutôt la commande `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Travailler avec virtualenv + +Les commandes listées ci-dessus permettent de créer un dossier appelé `myvenv` (ou le nom que vous avez choisi) qui contient notre environnement virtuel. Pour faire simple, c'est un dossier composé lui-même d'autres dossiers et de fichiers. + +#### Windows + +Démarrez votre environnement virtuel en exécutant : + + C:\Utilisateurs\Nom\djangogirls> myvenv\Scripts\activate + + +#### Linux et OS X + +Démarrez votre environnement virtuel en exécutant : + + ~/djangogirls$ source myvenv/bin/activate + + +N'oubliez pas de remplacer `myvenv` par le nom que vous avez choisi pour votre `virtualenv` (le cas échéant) ! + +> **NOTE :** il arrive parfois que `source` ne soit pas disponible. Dans ce cas, vous pouvez essayer ceci : +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Vous saurez que votre `virtualenv` est lancé quand le prompt de votre console ressemblera à ceci : + + (myvenv) C:\Utilisateurs\Nom\djangogirls> + + +ou : + + (myvenv) ~/djangogirls$ + + +Vous remarquez que le préfixe `(myvenv)` est apparu ! + +Quand vous travaillez dans un environnement virtuel, la commande `python` fera automatiquement référence à la bonne version de Python. Vous pouvez donc utiliser `python` plutôt que `python3`. + +Ok, nous avons installé toutes les dépendances dont nous avions besoin. Nous allons enfin pouvoir installer Django ! + +## Installation de Django + +Maintenant que vous avez lancé votre `virtualenv`, vous pouvez installer Django à l'aide de `pip`. Dans votre console, tapez `pip install django~=1.9.0`. Notez bien que nous utilisons un tilde suivi du signe égal : `~=`). + + (myvenv) ~$ pip install django~=1.9.0 + Downloading/unpacking django==1.9 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +Sous Windows : + +> Si jamais vous obtenez des erreurs lorsque vous utilisez pip sous Windows, vérifiez si votre chemin d'accès contient des espaces, des accents ou des caractères spéciaux (ex : `C:\Utilisateurs\Nom d'Utilisateur\djangogirls`). Si c'est le cas, changez de dossier et essayez d'en créer un nouveau en prenant en compte le fait qu'il ne doit donc avoir ni accents, ni espaces, ni caractères spéciaux (ex : `C:\djangogirls`). Après l'avoir déplacé, essayez de retaper la commande précédente. + +Sous Linux : + +> Si vous obtenez une erreur lorsque vous utilisez pip sous Ubuntu 12.04, tapez la commande `python -m pip install -U --force-reinstall pip` pour réparer l'installation de pip dans votre virtualenv. + +Et voilà ! Vous êtes (enfin) prête pour créer votre première application Django ! diff --git a/fr/django_models/README.md b/fr/django_models/README.md index c27d63df4c8..b3c902b5f01 100755 --- a/fr/django_models/README.md +++ b/fr/django_models/README.md @@ -1,14 +1,14 @@ # Les modèles dans Django -Maintenant, ce qu'on veut, c'est un moyen de stocker les articles de notre blog. Mais, pour pouvoir faire ça, on doit tout d'abord parler d'un truc qui s'appelle les `objets`. +Maintenant, nous aimerions créer quelque chose qui permet de stocker les articles de notre blog. Mais avant de pouvoir faire ça, nous allons tout d'abord devoir vous parler d'un truc qui s'appelle les `objets`. ## Les objets -Il y a un concept en programmation qu'on appelle la `programmation orientée objets`. L'idée, c'est de modéliser les choses et de définir comment elles interagissent entre elles plutôt que de tout voir comme une séquence d'instructions. +Il existe un concept en programmation qu'on appelle la `programmation orientée objets`. L'idée, c'est de modéliser les choses et de définir comment elles interagissent entre elles plutôt que de tout voir comme une séquence d'instructions. -Du coup, c'est quoi un objet ? C'est une collection de propriétés et d'actions. Ça a l'air bizarre. Un exemple va nous permettre d'y voir plus clair. +Du coup, c'est quoi un objet ? C'est une collection de propriétés et d'actions. Ça a l'air bizarre dit comme ça. Un exemple devrait vous permettre d'y voir un peu plus clair. -Si on veut modéliser un chat, nous allons créer un objet `Chat` qui a quelques propriétés comme `couleur`, `age`, `humeur` (bonne humeur, mauvaise humeur, fatigué ;)). Il peut aussi avoir un `propriétaire` (un objet `Personne`) mais ce n'est pas obligatoire : cette propriété pourrait être vide dans le cas d'un chat sauvage. +Si on veut modéliser un chat, nous allons créer un objet `Chat` qui a quelques propriétés comme `couleur`, `age`, `humeur` (bonne humeur, mauvaise humeur, fatigué ;)). Il peut aussi avoir un `propriétaire` (un objet `Personne`), mais ce n'est pas obligatoire : cette propriété pourrait être vide dans le cas d'un chat sauvage. Ensuite, nous pouvons donner des actions au `Chat` : `ronronner`, `gratter` ou `manger`. (Dans ce dernier cas, on donne au chat un objet `NourriturePourChat`, qui peut lui aussi avoir ses propres propriétés, comme le `goût`). @@ -21,20 +21,20 @@ Ensuite, nous pouvons donner des actions au `Chat` : `ronronner`, `gratter` ou ` ronronner() gratter() nourrir(nourriture_pour_chat) - - + + NourriturePourChat -------- gout - + L'idée qu'il faut retenir, c'est que l'on décrit les choses du monde réel avec des propriétés (appelées `propriétés des objets`) et des actions (appelées `méthodes`). Du coup, comment modéliser les articles de blog ? C'est bien gentil les chats, mais ce qui nous intéresse, ça reste de faire un blog ! -Pour ça, il faut réponde à la question : qu'est-ce qu'un article de blog ? Quelles propriétés a-t-il ? +Pour ça, il faut répondre à la question : qu'est-ce qu'un article de blog ? Quelles propriétés devrait-il avoir ? -Déjà, notre blog post doit avoir du texte, comme du contenu et un titre par exemple, n'est-ce pas ? Et puis, ce serait bien de savoir qui l'a écrit. On a donc besoin d'un auteur. Enfin, on aimerait aussi savoir quand l'article a été écrit et publié. +Pour commencer, notre blog post doit avoir du texte : il a bien du contenu et un titre, n'est-ce pas ? Et puis, ce serait bien de savoir aussi qui l'a écrit. On a donc besoin d'un auteur. Enfin, on aimerait aussi savoir quand l'article a été écrit et publié. Post -------- @@ -43,13 +43,13 @@ Déjà, notre blog post doit avoir du texte, comme du contenu et un titre par ex author created_date published_date - -Quel genre d'actions peut-on faire sur un article de blog ? Un bon début serait d'avoir une `méthode` qui permet de publier le post. + +Quel genre d'actions pourrions-nous faire sur un article de blog ? Un bon début serait d'avoir une `méthode` qui permet de publier le post. On va donc avoir besoin d'une méthode `publish`. -Voilà, nous savons ce que nous voulons : nous pouvons commencer à la modéliser dans Django ! +Voilà, nous avons une idée de ce que nous avons besoin. Allons modéliser tout ça dans Django! ## Les modèles dans Django @@ -61,10 +61,10 @@ Pour vous aider à visualiser ce qu'est une base de données, pensez à un table ### Créer une application -Pour ne pas nous laisser déborder par le désordre et garder une vision claire de ce que nous faisons, nous allons créer une application séparée à l'intérieur de notre projet. Prenez l'habitude de bien tout organiser dès le début. Afin de créer une application, nous avons besoin d'exécuter la commande suivante dans notre console (prenez garde à bien être dans le dossier `djangogirls` où se trouve le fichier `manage.py`) : +Pour éviter le désordre, nous allons créer une application séparée à l'intérieur de notre projet. Prenez l'habitude de bien tout organiser dès le début. Afin de créer une application, nous avons besoin d'exécuter la commande suivante dans notre console (prenez garde à bien être dans le dossier `djangogirls` où se trouve le fichier `manage.py`) : (myvenv) ~/djangogirls$ python manage.py startapp blog - + Vous pouvez voir qu'un nouveau dossier `blog` a été créé et qu'il contient différents fichiers. Vos dossiers et fichiers liés à votre projet doivent maintenant être organisés selon cette structure : @@ -83,91 +83,95 @@ Vous pouvez voir qu'un nouveau dossier `blog` a été créé et qu'il contient d ├── models.py ├── tests.py └── views.py - -Après avoir créé une nouvelle application, vous devez dire à Django de l'utiliser. Pour faire ça, nous allons nous servir du fichier `mysite/settings.py`. Vous allez devoir trouver la section `INSTALLED_APPS` et ajouter à la fin de la liste la ligne `'blog',``)`. Après ajout, cette section doit ressembler à ceci : - INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'blog', - ) - +Après avoir créé une nouvelle application, vous devez dire à Django de l'utiliser. Pour cela, nous allons éditer le fichier `mysite/settings.py`. Trouvez la section `INSTALLED_APPS` et ajoutez `'blog',` juste avant `)`. La section doit maintenant ressembler à ceci : + +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` ### Créer un modèle de blog post -Le fichier `blog/models.py` permet de définir les objets que nous appelons des `modèles`. C'est à cet endroit que nous allons définir ce qu'est un blog post. +Le fichier `blog/models.py` permet de définir les objets que nous appelons des `modèles`. C'est à cet endroit que nous allons définir ce qu'est un blog post. Pour éviter tout problème (les caractères accentués par exemple!), nous allons garder les termes en anglais. Ouvrez le fichier `blog/models.py`, supprimez tout ce qui s'y trouve et copiez-y le morceau de code suivant : - from django.db import models - from django.utils import timezone - - class Post(models.Model): - author = models.ForeignKey('auth.User') - title = models.CharField(max_length=200) - text = models.TextField() - created_date = models.DateTimeField( - default=timezone.now) - published_date = models.DateTimeField( - blank=True, null=True) - - def publish(self): - self.published_date = timezone.now() - self.save() - - def __str__(self): - return self.title - - -> Si jamais vous avez préféré le taper à la main, vérifiez que vous avez bien utilisé deux tirets bas (`_`) autour de `str`. Ils sont assez fréquemment utilisés en Python et portent parfois le doux nom de "dunder" ("double-underscore"). - -Ce gros morceau de code a l'air effrayant ! Ne vous inquiétez pas, nous allons vous expliquer ce que signifie chacune de ces lignes ! +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Vérifiez que vous avez bien utilisé deux tirets bas (`_`) autour de `str`. C'est une convention fréquemment utilisée en Python qui porte même un petit nom en anglais : "dunder", pour "double-underscore". + +Ce gros morceau de code a l'air effrayant mais, ne vous inquiétez pas : nous allons vous expliquer ce que signifie chacune de ces lignes! Toutes les lignes qui commencent par `from` ou `import` sont des lignes qui permettent d'importer des morceaux d'autres fichiers. Concrètement, au lieu de recopier ou de copier-coller la même chose dans différents fichiers, nous pouvons tout simplement faire référence à certains morceaux d'autres fichiers à l'aide de `from ... import ...`. `class Post(models.Model):` - C'est cette ligne qui permet de définir notre modèle. C'est un `object`). * Le mot clef spécial `class` permet d'indiquer que nous sommes en train de définir un objet. -* `Post` est le nom de notre modèle. Vous pouvez lui donner un autre nom mais vous ne pouvez pas utiliser de caractères spéciaux ou accentués ainsi qu'y insérer des espaces. Le nom d'une classe commence toujours par une majuscule. +* `Post` est le nom de notre modèle. Vous pouvez lui donner un autre nom mais vous ne pouvez pas utiliser de caractères spéciaux ou accentués ni insérer des espaces. Le nom d'une classe commence toujours par une majuscule. * `models.Model` signifie que Post est un modèle Django. Comme ça, Django sait qu'il doit l'enregistrer dans la base de données. -Maintenant, nous allons pouvoir définir les propriétés dont nous parlions au début de ce chapitre : `title (titre)`, `text (texte)`, `created_date (date de création)`, `published_date (date de publication)` et `author (auteur)`. Pour cela, nous allons avoir besoin de définir le type de chaque champ (Est-ce du texte ? Un nombre ? Une date ? Une relation à un autre objet, un utilisateur par exemple ?). +Maintenant, nous allons pouvoir définir les propriétés dont nous parlions au début de ce chapitre : `title (titre)`, `text (texte)`, `created_date (date de création)`, `published_date (date de publication)` et `author (auteur)`. Pour cela, nous allons avoir besoin de définir le type de chaque champ (Est-ce que c'est du texte? Un nombre ? Une date ? Une relation à un autre objet, un utilisateur par exemple ?). * `models.CharField` - Cela nous permet de définir un champ texte avec un nombre limité de caractères. -* `models.TextField` - Ce type de champ est pour les longs textes car il ne possède pas de limite de taille. Ça ne vous paraît pas être pile ce que l'on cherche pour le contenu de nos blog posts ? +* `models.TextField` - Cela nous permet de définir un champ texte sans limite de caractères. Parfait pour le contenu d'un blog post ! * `models.DateTimeField` - Définit que le champ en question est une date ou une heure. * `models.ForeignKey` - C'est un lien vers un autre modèle. -Malheureusement, nous n'avons pas le temps de vous expliquer tous les bouts de code que nous allons manipuler dans ce tutoriel. Si vous voulez en savoir plus sur les modèles Django, n'hésitez pas à consulter la documentation officielle de Django (https://docs.djangoproject.com/en/1.7/ref/models/fields/#field-types). +Malheureusement, nous n'avons pas le temps de vous expliquer tous les bouts de code que nous allons manipuler dans ce tutoriel. Si vous voulez en savoir un peu plus sur les différents champs disponibles dans les modèles ou que vous aimeriez définir quelque chose qui n'est pas listé dans les exemples ci-dessus, n'hésitez pas à consulter la documentation de Django (https://docs.djangoproject.com/fr/1.8/ref/models/fields/#field-types). -Et sinon, c'est quoi `def publish(self):` ? Il s'agit de notre méthode `publish (publication)` dont nous parlions tout à l'heure. C'est le mot `def` qui permet de dire que c'est une fonction/méthode. `publish` est le nom de notre méthode. Vous pouvez le changer si vous le voulez. Mais, si vous le faîtes, veillez à respecter les règles suivantes : n'utilisez que des minuscules, pas de caractères spéciaux ou accentués, et remplacez les espaces par des tirets bas. Par exemple, si vous vouliez créer une méthode qui permet de calculer le prix moyen de quelque chose, vous pourriez l'appeler : `calcul_prix_moyen`). +Et sinon, c'est quoi `def publish(self):` ? Il s'agit de notre méthode `publish` dont nous parlions tout à l'heure. `def` signifie que nous créons une fonction/méthode qui porte le nom `publish`. Vous pouvez changer le nom de la méthode si vous le souhaitez. N'oubliez pas les règles de nommage et pensez à utiliser des minuscules et des tirets bas à la place des espaces. Par exemple, une méthode qui calcule le prix moyen d'un produit pourrait s'appeler `calcul_prix_moyen`. -Les méthodes `retournent` très souvent quelque chose. C'est le cas de la méthode `__str__`. Dans notre tutoriel, lorsque nous appellerons `__str__()`, nous allons obtenir du texte (**string**) dans le titre du Post. +Les méthodes renvoient (`return`) souvent quelque chose. C'est le cas de la méthode `__str__`. Dans notre tutoriel, lorsque nous appellerons la méthode `__str__()`, nous allons obtenir du texte (**string**) avec un titre de Post. -Si quelque chose ne vous paraît pas clair au sujet des modèles, n'hésitez pas à demander à votre coach ! Ça peut être très compliqué à comprendre la première fois, surtout lorsque l'on apprend les objets et les fonctions en même temps. Rassurez-vous ! Avec le temps, tout cela vous paraitra de moins en moins magique et de plus en plus évident ! +Si quelque chose ne vous parait pas clair au sujet des modèles, n'hésitez pas à demander à votre coach ! Cela peut être compliqué à comprendre la première fois, surtout lorsque l'on apprend les objets et les fonctions en même temps. Gardez espoir ! Avec le temps, tout cela vous paraitra de moins en moins magique et de plus en plus évident ! ### Créer des tables pour votre modèle dans votre base de données -La dernière étape pour cette section est d'ajouter notre nouveau modèle à notre base de données. Tout d'abord, nous allons devoir signaler à Django que nous avons fait des modifications dans notre modèle (nous venons de le créer ! ). Pour cela, tapez `python manage.py makemigrations blog`. Ça ressemblera à ça : +La dernière étape pour cette section est d'ajouter notre nouveau modèle à notre base de données. Tout d'abord, nous devons signaler à Django que nous venons de créer notre modèle. Tapez `python manage.py makemigrations blog` dans votre console. Le résultat devrait ressembler à ça : (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': 0001_initial.py: - Create model Post - -Django vient de nous préparer un fichier de migration que nous allons pouvoir appliquer dès maintenant à notre base de données. Pour cela, tapez `python manage.py migrate blog`. Normalement, vous devez voir ceci s'afficher dans votre console : + +Django vient de nous préparer un fichier de migration que nous allons pouvoir appliquer dès maintenant à notre base de données. Pour cela, tapez `python manage.py migrate blog`. Normalement, vous devrez voir ceci s'afficher dans votre console : (myvenv) ~/djangogirls$ python manage.py migrate blog Operations to perform: Apply all migrations: blog Running migrations: + Rendering model states... DONE Applying blog.0001_initial... OK - -Youpi ! Notre modèle Post est maintenant intégré à la base de données. Ce serait cool de voir à quoi il ressemble réellement ! Pour ça, il va falloir attaquer la section suivante ! Au boulot ;) \ No newline at end of file + +Youpi ! Notre modèle Post est maintenant intégré à la base de données. Ce serait cool de voir à quoi il ressemble réellement ! Pour ça, il va falloir attaquer la section suivante ! Au boulot ;)! diff --git a/fr/django_orm/README.md b/fr/django_orm/README.md index c2dade5425a..9285b2cf808 100755 --- a/fr/django_orm/README.md +++ b/fr/django_orm/README.md @@ -1,4 +1,4 @@ -# Django ORM and QuerySets +# L'ORM Django et les QuerySets Dans ce chapitre, nous allons apprendre comment Django se connecte à la base de données et comment il y enregistre des choses. On respire un grand coup et on y va ! @@ -10,16 +10,16 @@ Il est plus simple d'apprendre avec un exemple. Et si nous nous intéressions à ## Le shell Django -Ouvrez votre console et tapez cette commande : +Ouvrez la console de votre ordinateur (et non celle de PythonAnywhere) et tapez la commande suivante : (myvenv) ~/djangogirls$ python manage.py shell - + Ceci devrait maintenant s'afficher dans votre console : (InteractiveConsole) >>> - + Vous êtes maintenant dans la console interactive de Django. C'est comme celle de Python, mais avec toute la magie qu'apporte Django :). Du coup, les commandes Python sont aussi utilisables dans cette console. @@ -27,132 +27,151 @@ Vous êtes maintenant dans la console interactive de Django. C'est comme celle d Essayons tout d'abord d'afficher tous nos posts. Vous pouvez le faire à l'aide de cette commande : - >>> Post.objects.all() - Traceback (most recent call last): - File "", line 1, in - NameError: name 'Post' is not defined - +```python +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` -Ooops ! Voilà que ça nous renvoie une erreur ! Cela nous dit qu'il n'existe pas de Post. En effet, nous avons oublié de commencer par un "import" ! +Ooops ! Voilà que ça nous renvoie une erreur qui nous dit qu'il n'existe pas de Post. En effet, nous avons oublié de commencer par un "import" ! - >>> from blog.models import Post - +```python +>>> from blog.models import Post +``` Rien de compliqué : nous importons le modèle `Post` depuis notre `blog.models`. Essayons à nouveau la commande précédente : - >>> Post.objects.all() - [] - +```python +>>> Post.objects.all() +[, ] +``` -Ce double crochet signifie que notre liste est vide. Ce qui est totalement correct : nous n'avons pas encore créé de post ! Corrigeons ça de suite. +Cela nous permet d'obtenir une liste des posts que nous avons créé tout à l'heure ! Rappelez-vous : nous avions créé ces posts à l'aide de l'interface d'administration de Django. Cependant, nous aimerions maintenant créer de nouveaux posts à l'aide de Python : comment allons-nous nous y prendre ? ### Créer des objets -Voilà comment créer un objet Post dans notre base de données : +Voici comment créer un nouveau objet Post dans la base de données : - >>> Post.objects.create(author=moi, title='Exemple de titre', text='Test') - +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` -Cependant, il nous manque un petit quelque chose : `moi`. Nous avons besoin de lui passer une instance du modèle `User` en guise d'auteur (author). Comment faire ? +Cependant, il nous manque un petit quelque chose : `me`. Nous avons besoin de lui passer une instance du modèle `User` en guise d'auteur (author). Comment faire ? Tout d'abord, il nous faut importer le modèle User : - >>> from django.contrib.auth.models import User - +```python +>>> from django.contrib.auth.models import User +``` Avons-nous des utilisateurs dans notre base de données ? Voyons voir : - >>> User.objects.all() - [] - - -Nous n'avons pas d'utilisateur ! Il nous faut donc nous en créer un : - - >>> User.objects.create(username='ola') - - - -Avons-nous bien créé un utilisateur dans notre base de données ? Pour le savoir, tapons la commande suivante : - - >>> User.objects.all() - [] - +```python +>>> User.objects.all() +[] +``` -Cool ! L'utilisateur que nous avons créé dans cet exemple s'appelle Ola. Essayons maintenant d'obtenir l'instance de cet utilisateur : +C'est le superutilisateur que nous avions créé tout à l'heure ! Essayons maintenant d'obtenir une instance de l'utilisateur : - moi = User.objects.get(username='ola') - +```python +me = User.objects.get(username='ola') +``` Comme vous pouvez le voir, nous obtenons (`get`) un utilisateur (`User`) avec comme nom d'utilisateur (`username`) 'ola'. Cool ! Bien sûr, vous pouvez utiliser votre nom si vous le souhaitez. -Maintenant, nous pouvons enfin créer notre premier post : +Nous allons enfin pouvoir créer notre post : - >>> Post.objects.create(author = moi, title = 'Exemple de titre', text = 'Test') - +```python +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` Youpi ! Et si on vérifiait quand même si ça a marché ? - >>> Post.objects.all() - [] - +```python +>>> Post.objects.all() +[, , ] +``` + +Et voilà : un post de plus dans la liste ! ### Ajouter plus de posts -Amusez-vous à ajouter plusieurs posts avec ce que nous venons de voir. Ajoutez en deux ou trois puis passez à la suite. +Amusez-vous à ajouter d'autres posts pour vous entrainer un peu. Essayez d'ajouter 2-3 posts en plus puis passez à la partie suivante. ### Filtrer les objets -L'intérêt des QuerySets, c'est qu'on peut les filtrer. Disons que nous voulons trouver les posts écrits par l'utilisateur Ola. Nous allons utiliser `filter` à la place de `all` dans `Post.objects.all()`. Les parenthèses vont nous servir à préciser le⋅s condition⋅s nécessaire⋅s aux différents posts pour qu'ils puissent se retrouver dans notre QuerySet. Dans notre exemple, `author` est égal à `moi`. La manière de le dire en Django c'est : `author=moi`. Maintenant, votre bout de code doit ressembler à ceci : +L'intérêt des QuerySets, c'est que l'on peut les filtrer. Disons que nous aimerions retrouver tous les posts écrits par l'utilisateur Ola. Pour cela, nous allons utiliser `filter` à la place de `all` dans `Post.objects.all()`. Les parenthèses vont nous servir à préciser quelles sont les conditions auxquelles un post de blog doit se conformer pour être retenu par notre QuerySet. Dans notre exemple, `author` est égal à `me`. La manière de le dire en Django c'est : `author=me`. Maintenant, votre bout de code doit ressembler à ceci: - >>> Post.objects.filter(author=moi) - [, , , ] - +```python +>>> Post.objects.filter(author=me) +[, , , ] +``` -Et si nous voulions chercher les posts qui contiennent uniquement le mot "titre" dans le champs `title` ? +Et si nous voulions chercher les posts qui contiennent uniquement le mot "titre" dans le champs `title`? - >>> Post.objects.filter(title__contains='title') - [, ] - +```python +>>> Post.objects.filter(title__contains='title') +[, ] +``` > **Note** Il y a deux tirets bas (`_`) entre `title` et `contains`. L'ORM de Django utilise cette syntaxe afin de séparer les noms de champ ("title") et les opérations ou les filtres ("contains"). Si vous n'utilisez qu'un seul tiret bas, vous allez obtenir une erreur du type : "FieldError: Cannot resolve keyword title_contains". -Vous pouvez aussi obtenir une liste de tous les posts publiés. Pour cela, nous allons seulement conserver les posts qui possèdent une date de publication (`published_date`) : +Comment obtenir une liste de tous les posts publiés ? Cela se fait facilement en filtrant tous les posts qui ont une date de publication, `published_date`, dans le passé : - >>> Post.objects.filter(published_date__isnull=False) - [] - +```python +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +``` -Malheureusement, aucun de nos posts n'a été publié pour l'instant. Changeons ça ! Tout d'abord, obtenons une instance du post que nous souhaitons publier : +Malheureusement, le post que nous avons créé dans la console Python n'est pas encore publié. Allons corriger ce problème ! Dans un premier temps, nous aimerions obtenir une instance du post que nous voulons publier : - >>> post = Post.objects.get(id=1) - +```python +>>> post = Post.objects.get(title="Sample title") +``` -Ensuite, publions-le grâce à notre méthode `publish` ! +Ensuite, publions-le grâce à notre méthode `publish`! - >>> post.publish() - +```python +>>> post.publish() +``` -Réessayons d'obtenir une liste des posts publiés (pour aller plus vite, appuyez trois fois sur la flèche du haut de votre clavier et appuyer sur entrer) : +Maintenant, essayez d'obtenir à nouveau la liste des posts publiés. Pour cela, appuyez trois fois sur la flèche du haut et appuyez sur `entrée` : - >>> Post.objects.filter(published_date__isnull=False) - [] - +```python +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` ### Classer les objets -Les QuerySets vous permettent aussi de classer des listes d'objets. Essayons de les classer par date de création (champ `created_date`) : +Les QuerySets permettent aussi de trier la liste des objets. Essayons de les trier par le champ `created_date` : + +```python +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +On peut aussi inverser l'ordre de tri en ajouter `-` au début: + +```python +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Chainer les QuerySets - >>> Post.objects.order_by('created_date') - [, , , ] - +Vous pouvez aussi combiner les QuerySets and les **chainant** les unes aux autres : -Nous pouvons inverser l'ordre en mettant un `-` au début du nom de notre champ : +```python +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` - >>> Post.objects.order_by('-created_date') - [, , , ] - +C'est un outil très puissant qui va vous permettre d'écrire des requêtes complexes. -Cool ! Maintenant, vous êtes prêt⋅e à passer à la partie suivante ! Pour fermer le shell, tapez ceci : +Génial ! Vous êtes maintenant prête à passer à l'étape suivante ! Pour fermer le shell, tapez ceci: - >>> exit() - $ \ No newline at end of file +```python +>>> exit() +$ +``` diff --git a/fr/django_start_project/README.md b/fr/django_start_project/README.md index 9dd364f1d6e..d6f4a946a87 100755 --- a/fr/django_start_project/README.md +++ b/fr/django_start_project/README.md @@ -1,34 +1,34 @@ # Votre premier projet Django ! -> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (http://django.carrots.pl/). -> +> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> > Des morceaux de ce chapitre sont inspirés du [tutoriel django-marcador][1], disponible sous licence Creative Commons Attribution-ShareAlike 4.0 International. Le tutoriel django-marcador a été créé par Markus Zapke-Gründemann et al. [1]: http://django-marcador.keimlink.de/ Nous allons créer un petit blog ! -La première étape consiste à démarrer un nouveau projet Django. En gros, ça veut dire que nous allons lancer quelques scripts fournis par Django qui vont nous créer un squelette de projet Django (une poignée de fichiers qui vont nous être utiles). +La première étape consiste à démarrer un nouveau projet Django. En gros, cela veut dire que nous allons lancer quelques scripts fournis par Django qui vont créer un squelette de projet Django. Il s'agit de fichiers et de dossiers que nous utiliserons par la suite. -Il y a certains fichiers et dossiers dont les noms sur extrêmement importants pour Django. Il ne faut pas renommer les fichiers que nous sommes sur le point de créer. Ce n'est pas non plus une bonne idée de les déplacer. Django a besoin de maintenir une certaine structure pour retrouver les éléments importants. +Il existe certains fichiers et dossiers dont les noms sont extrêmement importants pour Django. Il ne faut pas renommer les fichiers que nous sommes sur le point de créer. Ce n'est pas non plus une bonne idée de les déplacer. Django a besoin de maintenir une certaine structure pour retrouver les éléments importants. -Dans une console, lancez ça (n'oubliez pas, pas besoin de taper `(myvenv) ~/djangogirls$`) : +> N'oubliez pas de tout exécuter dans votre virtualenv. Si vous ne voyez pas le préfixe `(myvenv)` dans votre console, vous avez besoin d'activer votre virtualenv. Nous vous avons expliqué comment faire ça dans le chapitre **Installation de Django**, dans la partie **Travailler avec virtualenv**. Tapez `myvenv\Scripts\activate` dans votre console Windows ou `source myvenv/bin/activate` dans celle de Mac OS ou Linux afin d'activer votre virtualenv. -> N'oubliez pas de tout lancer dans le virtualenv. Si vous ne voyez pas le préfixe `(myvenv)` dans votre console, vous avez besoin d'activer votre virtualenv. Nous vous avons expliqué comment faire ça dans le chapitre **Installation de Django**, dans la partie **Travailler avec virtualenv**. +Retournons à la création de notre premier projet. Tapez la commande suivante dans votre console MacOS ou Linux. **N'oubliez pas le point `.`à la fin** : -Lancer sous Windows : + (myvenv) ~/djangogirls$ django-admin startproject mysite . - (myvenv) ~/djangogirls$ python myvenv\Scripts\django-admin.py startproject mysite . - -ou sous Linux ou Mac OS : +Pour les utilisatrices de Windows, tapez la commande suivante. **N'oubliez pas le point `.` à la fin** : - (myvenv) ~/djangogirls$ django-admin startproject mysite . - + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . -> **Remarque** : N'oubliez pas le point (`.`) à la fin de la commande. Il est super important. -`django-admin` est un script qui créé les dossiers et fichiers nécessaires pour vous. Vous devriez maintenant avoir une structure de dossier qui ressemble à celle-ci : +> Le point `.` est très important : c'est lui qui permet de dire au script d'installer Django dans votre répertoire courant (le point `.` est une référence abrégée à celui-ci). +> +> **Note** : lorsque vous tapez les commandes précédentes dans votre console, vous ne devez recopier que la partie qui commence par `django-admin` ou `django-admin.py`. Les `(myvenv) ~/djangogirls$` et `(myvenv) C:\Users\Name\djangogirls>` du tutoriel sont là pour vous rappeler que ces commandes doivent être tapées dans votre console. + +`django-admin.py` est un script qui crée les dossiers et fichiers nécessaires pour vous. Vous devriez maintenant avoir une structure de dossier qui ressemble à celle-ci: djangogirls ├───manage.py @@ -37,72 +37,101 @@ ou sous Linux ou Mac OS : urls.py wsgi.py __init__.py - + `manage.py` est un script qui aide à gérer le site. Il permet notamment de lancer un serveur web sur notre ordinateur sans rien installer d'autre. Le fichier `settings.py` contient la configuration de votre site web. -Vous vous souvenez de l'histoire du postier qui livre des lettres ? `urls.py` contient une liste de modèles d'urls utilisés par `urlresolver`. +Vous vous souvenez de l'histoire du postier qui livre des lettres ? `urls.py` contient une liste de patterns d'urls utilisés par `urlresolver`. -Ignorons les autres fichiers pour l'instant, nous n'allons pas avoir besoin d'y toucher. Le seul truc aucun il faut faire attention est de ne pas les supprimer par accident ! +Ignorons les autres fichiers pour l'instant, nous n'allons pas avoir besoin d'y toucher. La seule chose à retenir est qu'il ne faut pas les supprimer par accident ! ## Changer la configuration Apportons quelques changements à `mysite/settings.py`. Ouvrez le fichier avec l'éditeur de code que vous avez installé tout à l'heure. -Ce serait sympa d'avoir les bonnes heures sur notre site web. Allez voir sur http://en.wikipedia.org/wiki/List_of_tz_database_time_zones et copiez le bon fuseau horaire (timezone, TZ). (par exemple, `Europe/Berlin`) +Ça serait sympa d'avoir l'heure correcte sur notre site Web. Allez sur [wikipedia timezones list][2] et copiez le fuseau horaire qui correspond le mieux à l'endroit où vous vous trouvez (TZ). (par exemple: `Europe/Paris`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +Dans settings.py, recherchez la ligne qui contient le `TIME_ZONE` et modifiez-la pour choisir votre propre fuseau horaire : + +```python +TIME_ZONE = 'Europe/Paris' +``` -Vous devriez trouver des lignes qui contiennent `USE_TZ` et `TIME_ZONE`. Modifiez-les pour qu'elles ressemblent à ça (en remplaçant `Europe/Berlin` par le bon fuseau horaire) : +En remplaçant "Europe/Paris" par la valeur appropriée - USE_TZ = False - TIME_ZONE = 'Europe/Berlin' - +Nous allons aussi devoir ajouter un chemin d'accès pour les fichiers statiques (nous en apprendrons plus sur les fichiers statiques et CSS plus tard dans le tutoriel). Allez jusqu'à la *fin* du fichier et juste en dessous de la ligne `STATIC_URL`, ajoutez-en une nouvelle avec `STATIC_ROOT` : + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` ## Configuration de la base de données -Il existe tout un tas de systèmes de gestion de bases de données qu'on pourrait utiliser pour stocker les données de votre site. On va utiliser celui par défaut, `sqlite3`. +Il existe tout un tas de systèmes de gestion de bases de données qu'il est possible d'utiliser pour stocker les données de votre site. Nous allons utiliser celui par défaut : `sqlite3`. -Il est déjà configuré dans ce morceau de votre fichier `mysite/settings.py` : +Il est déjà configuré dans cette partie de votre fichier `mysite/settings.py`: - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } - +} +``` -Pour créer la base de donnée de votre blog, il fait lancer la commande suivante dans la console : `python manage.py migrate` (on a besoin d'être dans le dossier `djangogirls` qui contient le fichier `manage.py`). Si tout se passe bien, vous devriez voir quelque chose comme ça : +Pour créer la base de donnée de notre blog, il faut lancer la commande suivante dans la console : `python manage.py migrate` (vous avez besoin d'être dans le dossier `djangogirls` qui contient le fichier `manage.py`). Si tout se passe bien, vous devriez voir quelque chose comme ça: (myvenv) ~/djangogirls$ python manage.py migrate Operations to perform: - Apply all migrations: admin, contenttypes, auth, sessions + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK Applying sessions.0001_initial... OK - -Et voilà ! Il ne plus qu'à lancer le server et voir si le site web marche ! -Pour ça, vous avez besoin d'être dans le dossier qui contient le fichier `manage.py` (le dossier `djangogirls`). Dans la console, vous pouvez lancer le serveur en tapant `python manage.py runserver` : +Et voilà ! Il ne reste plus qu'à lancer le serveur et voir si notre site web fonctionne ! + +Pour cela, vous avez besoin d'être dans le dossier qui contient le fichier `manage.py` (le dossier `djangogirls`). Dans votre console, vous pouvez lancer le serveur en tapant `python manage.py runserver`: (myvenv) ~/djangogirls$ python manage.py runserver - -Ensuite, il ne vous reste plus qu'à vérifier que le site tourne. Ouvrez votre navigateur (Firefox, Chrome, Safari, Internet Explorer, ou n'importe quel autre), et entre l'adresse : + +Si vous utilisez Windows et que vous obtenez l'erreur `UnicodeDecodeError`, tapez plutôt cette commande : + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Ensuite, il ne nous reste plus qu'à vérifier que votre site fonctionne. Pour cela, ouvrez votre navigateur (Firefox, Chrome, Safari, Internet Explorer, ou n'importe quel autre), et entrez l'adresse suivante : http://127.0.0.1:8000/ - -Le serveur web remplace la ligne de commande tant que vous ne l’arrêtez pas. Pour pouvoir taper de nouvelles commandes, vous devez soit lancer une nouvelle fenêtre de terminal (et n'oubliez pas d'y activer votre virtualenv), ou arrêter le serveur web en sélectionnant la fenêtre de terminal et où tourne le serveur et en appuyant sur CTRL+C (Contrôle et C en même temps). Sous Windows, ça sera Ctrl+Arrêt défil. -Bravo ! Vous venez de créer votre premier site web, et de le lancer avec un serveur web ! C'est génial, non ? +Tant qu'il sera lancé, le serveur web va monopoliser votre console. Pour pouvoir taper de nouvelles commandes pendant que le serveur tourne, ouvrez une nouvelle console et activez à nouveau votre virtualenv. Pour arrêter votre serveur web, retournez dans la console où il se trouve et appuyez sur CTRL+C : maintenez les boutons Control et C enfoncés en même temps. Sous Windows, vous devrez peut-être appuyer sur CTRL+Arrêt défil. + +Bravo ! Vous venez de créer votre premier site web, et de le lancer avec un serveur web ! C'est génial, non? -![Ça a marché !][2] +![Ça a marché !][3] - [2]: images/it_worked2.png + [3]: images/it_worked2.png -Prête pour la suite ? Il est temps de créer du contenu ! \ No newline at end of file +Prête pour la suite ? Il est temps de créer du contenu! diff --git a/fr/django_templates/README.md b/fr/django_templates/README.md index c71457be3cd..ebba48e71c0 100755 --- a/fr/django_templates/README.md +++ b/fr/django_templates/README.md @@ -6,18 +6,19 @@ Il est temps d'afficher des données ! Pour nous aider, Django fournit des balis En HTML, vous ne pouvez pas mettre directement du code Python car les navigateurs seraient incapables de le comprendre. Les navigateurs ne connaissent que le HTML. Nous vous avons signalé précédemment que HTML est du genre statique, alors que Python est bien plus dynamique. -Les **Balises de template Django** nous permettent de transfert des choses ressemblant à du Python dans du HTML afin de nous permettre de construire des sites web plus rapidement et facilement. Cool, non ? +Les **Balises de template Django** nous permettent de transférer des choses ressemblant à du Python dans du HTML afin de nous permettre de construire des sites web plus rapidement et facilement. Cool, non ? ## Template d'affichage de la liste des posts Dans le chapitre précédent, nous avons donné à notre template une liste de posts à l'aide de la variable `posts`. Nous allons maintenant les afficher en HTML. -Afin d'afficher une variable dans un template Django, nous utilisons des doubles accolades avec le nom de la variable à l'intérieur. Ça ressemble à ceci : +Afin d'afficher une variable dans un template Django, nous utiliserons des doubles accolades avec le nom de la variable à l'intérieur. Ça ressemble à ceci : - {{ posts }} - +```html +{{ posts }} +``` -Essayez de faire la même chose avec votre template `blog/templates/blog/post_list.html` : remplacez tout ce qui se trouve entre la seconde balise `
` avec la ligne `{{ posts }}`. Sauvegardez votre fichier et rafraîchissez votre page pour voir le résultat : +Essayez de faire la même chose avec votre template `blog/templates/blog/post_list.html`. Remplacez tout ce qui se trouve entre la seconde balise `
` jusqu'au troisième `
` avec la ligne `{{ posts }}`. Sauvegardez votre fichier et rafraichissez votre page pour voir le résultat : ![Figure 13.1][1] @@ -25,25 +26,25 @@ Essayez de faire la même chose avec votre template `blog/templates/blog/post_li Comme vous pouvez le voir, tout ce que nous avons, c'est ceci : - [, ] - +```python +[, ] +``` -Cela signifie que Django l'interprète comme une liste d'objets. Essayez de vous rappeler comment afficher des listes en Python. Si vous avez un trou de mémoire, allez voir dans le chapitre **Introduction to Python**. Vous avez trouvé ? Avec des boucles ! Dans un template Django, vous pouvez les écrire de cette façon : +Cela signifie que Django l'interprète comme une liste d'objets. Essayez de vous rappeler comment afficher des listes en Python. Si vous avez un trou de mémoire, allez voir dans le chapitre **Introduction à Python**. Vous avez trouvé ? Avec des boucles ! Dans un template Django, vous pouvez les écrire de la façon suivante : ```html {% for post in posts %} {{ post }} {% endfor %} ``` - -Essayez-la dans votre template. +Essayez ceci dans votre template. ![Figure 13.2][2] [2]: images/step2.png -Ça marche ! Cependant, nous aimerions plutôt les afficher à la manière des posts statiques, comme lorsque nous les avions créés dans le chapitre **Introduction to HTML**. Vous pouvez mixer HTML et balises de template. Notre `body` ressemble maintenant à ceci : +Ça marche ! Cependant, nous aimerions plutôt les afficher à la manière des posts statiques, comme lorsque nous les avions créés dans le chapitre **Introduction au HTML**. Vous pouvez mixer HTML et balises de template. Notre `body` ressemble maintenant à ceci : ```html
@@ -52,42 +53,54 @@ Essayez-la dans votre template. {% for post in posts %}
-

published: {{ post.published_date }}

+

publié: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -{% raw %}Tout ce qui se situe entre `{% for %}` et `{% endfor %}` va être répété pour chaque objet dans la liste. Rafraichissez votre page:{% endraw %} +{% raw %}Tout ce qui se situe entre `{% for %}` et `{% endfor %}` va être répété pour chaque objet présent dans la liste. Rafraichissez votre page :{% endraw %} ![Figure 13.3][3] [3]: images/step3.png -{% raw %}Avez-vous remarqué que nous utilisons une notation légèrement différente cette fois (`{{ post.title }}` or `{{ post.text }}`) ? Nous accédons aux données associées à chaque champ défini dans notre modèle `Post`. De même, les `|barres verticales` nous permettent de rediriger le texte des posts à travers un filtre qui convertit automatiquement les fins de lignes en paragraphes.{% endraw %} +Avez-vous remarqué que nous utilisons une notation légèrement différente cette fois (`{{ post.title }}` or `{{ post.text }}`) ? Nous accédons aux données associées à chaque champ défini dans notre modèle `Post`. De même, les barres verticales `|` nous permettent de rediriger le texte des posts à travers un filtre qui convertit automatiquement les fins de lignes en paragraphes. + +## Encore une chose ! + +Maintenant, ça serait bien de voir si votre site Web fonctionne toujours sur Internet. Nous allons essayer de le re-déployer sur PythonAnywhere. Voici un récapitulatif des étapes... -## Une dernière chose +* En premier lieu, envoyez votre code sur GitHub (push) +``` + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push +``` -Ce serait génial si nous pouvions aller sur notre site web hébergé sur Heroku et voir toutes ces nouvelles fonctionnalités ! Remontons nos manches et déployons encore une fois. Si vous ne vous souvenez plus de ce que fait chaque commande, consultez la fin du chapitre 15 : +* Ensuite, reconnectez-vous à [PythonAnywhere][4] et allez sur la "**Bash console**" (ou démarrez-en une nouvelle), et lancez les commandes suivantes : -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Utilisation de template Django à la place de HTML statique" -... -$ git push heroku master + [4]: https://www.pythonanywhere.com/consoles/ +``` + $ cd my-first-blog + $ git pull + [...] ``` - -Félicitations ! Maintenant, pourquoi ne pas essayer d'ajouter un nouveau post à l'aide de l'interface d'administration ? N'oubliez pas d'ajouter une date de publication ! Ensuite, rafraîchissez votre page et regardez si votre post apparaît. +* Finalement, allez sur l'[onglet Web][5] et cliquez sur **Reload** sur votre application web. Votre site mis-à-jour devrait être en ligne ! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Félicitations ! Maintenant, pourquoi ne pas essayer d'ajouter un nouveau post à l'aide de l'interface d'administration ? N'oubliez pas d'ajouter une date de publication ! Ensuite, rafraichissez votre page et regardez si votre post apparait. -Ça a marché ? Super ! Vous pouvez être fière de vous ! Allez faire une pause et manger quelque chose qui vous fera plaisir : vous l'avez bien mérité ! +Ça a marché ? Nous sommes super fières de vous ! Éloignez vous un peu de votre clavier maintenant : vous avez mérité de faire une pause. :) -![Figure 13.4][4] +![Figure 13.4][6] - [4]: images/donut.png + [6]: images/donut.png diff --git a/fr/django_urls/README.md b/fr/django_urls/README.md index 154dbb7168f..1d911be6ea3 100755 --- a/fr/django_urls/README.md +++ b/fr/django_urls/README.md @@ -4,29 +4,30 @@ Nous sommes sur le point de construire notre première page web : la page d'accu ## Qu'est-ce qu'une URL ? -Une URL n'est tout simplement qu'une adresse web. Vous pouvez voir une URL à chaque fois que vous visitez un site web : l'URL se trouve dans la barre d'adresse (hé oui ! `127.0.0.1:8000` est aussi une URL ! Tout comme http://djangogirls.com en est une aussi) : +Une URL est simplement une adresse web. Vous pouvez voir une URL à chaque fois que vous visitez un site web: l'URL se trouve dans la barre d'adresse (hé oui! `127.0.0.1:8000` est aussi une URL ! `https://djangogirls.org` est aussi une URL) : ![Url][1] [1]: images/url.png -Chaque page internet a besoin de sa propre URL. Cela permet à votre application de savoir ce qu'elle doit afficher à un utilisateur lorsqu'il entre une URL. Dans Django, nous utilisons quelque chose qui s'appelle `URLconf` (Configuration des URLs) : c'est un ensemble de patterns que Django va essayer de faire correspondre avec l'URL reçue afin d'afficher la vue correspondante. +Chaque page internet a besoin de sa propre URL. Cela permet à votre application de savoir ce qu'elle doit afficher à un utilisateur lorsqu'il entre une URL. Dans Django, nous utilisons un outil appelé `URLconf` (configuration des URLs) : c'est un ensemble de patterns que Django va essayer de faire correspondre avec l'URL reçue afin d'afficher la vue correspondante. -## Comment est-ce que les URLs fonctionnent dans Django ? +## Comment les URLs fonctionnent-elles dans Django ? -Ouvrons le fichier `mysite/urls.py` et regardons à quoi il ressemble : +Ouvrons le fichier `mysite/urls.py` dans notre éditeur de code et regardons à quoi il ressemble : - from django.conf.urls import patterns, include, url - from django.contrib import admin - - urlpatterns = patterns('', - # Examples: - # url(r'^$', 'mysite.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), - - url(r'^admin/', include(admin.site.urls)), - ) - +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` Comme vous pouvez le voir, Django nous a déjà préparé une partie du travail. @@ -34,67 +35,91 @@ Les lignes qui commencent par `#` permettent de commenter notre code : ces ligne Comme vous pouvez le voir, l'adresse de l'interface d'administration est déjà en place : +```python url(r'^admin/', include(admin.site.urls)), - +``` Cela signifie que pour chaque URL qui commence par `admin/`, Django affichera la *vue* correspondante. Dans cet exemple, vous pouvez constater que toutes les URLs liées à l'interface d'administration sont contenues dans une seule ligne : en plus d'être pratique, cela rend notre fichier beaucoup plus propre et lisible. ## Regex -Vous vous demandez sûrement comment Django arrive à faire correspondre les URLs aux vues correspondantes ? Bon, on respire un grand coup car ça va être un peu complexe. Django utilise des `regex`, des expressions régulières. Les regex ont beaucoup (vraiment beaucoup ! ) de règles qui permettent de créer des patterns de recherche (ou des formules magiques obscures ;)). Ce n'est pas toujours évident à comprendre, donc ne vous en préoccupez pas trop aujourd'hui : vous aurez tout le temps de revenir dessus plus tard. Aujourd'hui, nous allons seulement utiliser les formules dont nous avons besoin. +Vous vous demandez sûrement comment Django arrive à faire correspondre les URLs aux vues correspondantes ? Bon, on respire un grand coup car ça va être un peu complexe. Django utilise des `regex` ("expressions régulières"). Les regex ont beaucoup (vraiment beaucoup ! ) de règles qui permettent de donner une description de la chaîne de caractères que l'on recherche (pattern). Étant donné que les regex sont un sujet avancé, nous ne rentrerons pas en détail dans leur fonctionnement. + +Si vous avez quand-même envie de comprendre comment nous avons créé nos patterns, vous pouvez lire ce qui va suivre. Dans notre exemple, nous allons utiliser un petit sous ensemble des règles disponibles pour écrire des patterns : + + ^ -> le début du texte + $ -> la fin du texte + \d -> un chiffre + + -> indique que l'expression précédente doit se répéter au moins une fois + () -> capture une partie du pattern + -Si vous êtes curieux⋅se, voici un petit exemple, histoire de ne pas vous laisser sur votre faim ! Imaginez que vous avez un site qui possède une adresse comme celle-ci : `http://www.mysite.com/post/12345/`. `12345` serait le numéro du post à afficher. Ce serait vraiment pénible de devoir écrire une vue différente pour chaque post que nous voudrions rédiger. Du coup, Django rend les choses plus faciles et vous n'avez simplement qu'à écrire `http://www.mysite.com/post//`. Ne vous préoccupez pas du reste, Django se charge de tout ! +Tout ce qui ne fait pas partie de ces règles et qui est présent dans la description de ce que l'on cherche sera interprété de manière littérale. + +Maintenant, imaginez que vous avez un site web qui a comme adresse : `http://www.mysite.com/post/12345/`. `12345` désigne le numéro de votre post. + +Ce serait vraiment pénible de devoir écrire une vue différente pour chaque post que nous aimerions rédiger. Nous allons créer un pattern qui correspond à cette URL et qui nous permettra aussi d'extraire le numéro de post : `^post/(\d+)/$`. Décomposons-la morceau par morceau pour comprendre ce que nous faisons : + +* **^ post /** indique à Django d'attraper toutes les url qui commencent par `post/` (juste après `^`) +* **(\d+)** signifie qu'il y aura un nombre (un ou plusieurs chiffres) que nous souhaitons capturer et extraire +* **/** dit à Django que le caractère `/` doit suivre le nombre +* **$** marque la fin de l'URL, ce qui signifie que seules les chaînes de caractères se terminant par `/` correspondrons au pattern ## Votre première URL Django ! -C'est le moment de créer votre toute première URL ! Nous aimerions faire de http://127.0.0.1:8000/ la page d'accueil de notre site web où s'afficherait une liste de posts. +Bon, il est temps de créer votre première URL ! Nous voulons que "http://127.0.0.1:8000/" soit la page d’accueil de notre blog et qu'elle nous montre la liste des articles du blog. Nous aimerions aussi garder notre fichier `mysite/urls.py` propre. Pour cela, nous allons importer les URLs de notre application `blog` dans notre fichier principal `mysite/urls.py`. -On y va : supprimez les lignes commentées, c'est-à-dire celles qui commencent par `#`, et ajoutez une ligne qui va nous permettre d'importer `blog.urls` dans notre URL principale (`''`). +On y va : supprimez les lignes commentées, c'est-à-dire celles qui commencent par `#`. Ensuite, ajoutez une ligne qui va nous permettre d'importer `blog.urls` dans notre URL principale (`''`). -Votre fichier `mysite/urls.py` doit maintenant ressembler à ceci : +Votre fichier `mysite/urls.py` devrait maintenant ressembler à ceci: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` - from django.conf.urls import patterns, include, url - from django.contrib import admin - - urlpatterns = patterns('', - url(r'^admin/', include(admin.site.urls)), - url(r'', include('blog.urls')), - ) - +Django va maintenant rediriger tout ce qui arrive sur "http://127.0.0.1:8000/" vers `blog.urls` puis regardera dans ce fichier pour y trouver la suite des instructions à suivre. -Django va maintenant rediriger tout ce qui arrive sur `http://127.0.0.1:8000/` vers `blog.urls`. À partir de là, il agira en fonction des instructions que nous lui aurons données. +En Python, les expressions régulière commencent toujours par `r` au début de la chaîne de caractères. Cela permet d'indiquer à Python que ce qui va suivre inclut des caractères qu'il ne doit pas interpréter en tant que code Python mais en tant qu'expression régulière. ## blog.urls -Créez un fichier appelé `blog/urls.py`. Ajoutez ces deux lignes au début de votre nouveau fichier : +Créez un nouveau fichier vide `blog/urls.py`. OK ! Ajoutez maintenant ces deux premières lignes : - from django.conf.urls import patterns, include, url - from . import views - +```python +from django.conf.urls import url +from . import views +``` -Ici, nous ne faisons qu'importer les méthodes Django dont nous avons besoin ainsi que toutes les `vues` liées à notre application `blog`. Mais nous n'avons pas encore créé de vues ! Pas de problème : nous y viendrons dans une minute ! +Nous venons d'importer les méthodes de Django dont nous avons besoin ainsi que toutes les `vues` liées à notre application `blog`. Cependant, nous n'avons pas encore créé de vues ! Pas de problème : nous y viendrons dans une minute -Ensuite, nous pouvons ajouter notre premier pattern d'URL : +Après ça, nous pouvons ajouter notre premier pattern d'URL: - urlpatterns = patterns('', - url(r'^$', views.post_list), - ) - +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` -Comme vous pouvez le voir, nous assignons une `vue` appelée `post_list` à l'URL `^$`. Mais qu'est-ce que `^$` signifie ? C'est une formule regex magique :) Découpons-la en petits morceaux : - `^` signifie en regex "le début". C'est à partir de ce site que nous pouvons commencer à chercher les correspondances par rapport à notre pattern - `$` signifie "la fin". Ça signifie que nous arrêterons de cherchons notre pattern à cet endroit +Comme vous pouvez le voir, nous assignons une `vue` appelée `post_list` à l'URL `^$`. Décomposons cette expression régulière : `^` pour début suivie de `$` pour fin. Si nous mettons ces deux symboles ensemble, cela donne l'impression que nous sommes à la recherche d'une chaîne de caractères (string) vide. Ça tombe bien car c'est exactement ce que nous voulons ! En effet, l'URL resolver de Django ne considère pas 'http://127.0.0.1:8000/' comme faisant partie de l'URL. Ce pattern va donc indiquer à Django d'afficher la vue `views.post_list` à un utilisateur de votre site web qui se rendrait à l'adresse "http://127.0.0.1:8000/". -Si nous mettons ces deux symboles ensemble, ça donne l'impression que nous sommes à la recherche d'une chaine de caractère (string) vide ! C'est exactement ce que nous voulons ! En effet, pour l'url resolver de Django, `http://127.0.0.1:8000/` ne fait pas partie de l'URL. Ce pattern va montrer à Django que la vue `views.post_list` doit être affichée lorsqu'un utilisateur de votre site web se rend à l'adresse `http://127.0.0.1:8000/`. +La dernière partie, `name='post_list'`, est le nom de l'URL qui sera utilisée afin d'identifier la vue. Ce nom peut être le même que celui de la vue ou quelque chose de complètement différent. Plus tard dans ce tutoriel, nous allons utiliser les noms que nous avons donné à nos URLs. Il est donc important de donner un nom unique à chaque URL que nous créons. Pour vous faciliter la tâche, essayez de trouver des noms d'URLs simple à retenir. -Est-ce que cela vous paraît clair ? Ouvrons http://127.0.0.1:8000/ dans notre navigateur pour voir ce que ça donne. +Est-ce que tout fonctionne toujours ? Ouvrez votre navigateur à l'adresse http://127.0.0.1:8000/ pour vérifier. ![Erreur][2] [2]: images/error1.png -"It works" ne s'affiche plus, pourquoi donc ? Ne vous inquiétez pas, c'est tout simplement une page d'erreur et elle ne va pas vous manger ! Bien au contraire, il va nous falloir nous nourrir de ce qu'elle raconte : +"It works" a disparu ! Ne vous en faites pas : ce que vous voyez est juste une page d'erreur. N'ayez pas peur des pages d'erreur, elles sont en fait très utiles : -Vous pouvez lire le message **no attribute 'post_list'**. Est-ce que *post_list* vous rappelle quelque chose ? C'est le nom de notre vue ! Cela signifie que nous avons posé les fondations, mais que nous n'avons pas encore créé notre *vue*. Pas de problème, on y vient :) +Sur cette page, vous pouvez lire le message **no attribute 'post_list'** (il manque un attribut "post_list"). Est-ce que *post_list* vous rappelle quelque chose ? Yep, c'est le nom que nous avons donné à notre vue ! Cela signifie que nous avons posé les fondations mais, que nous n'avons pas encore créé notre *vue*. Pas de problème, on y vient :). -> Si vous voulez en savoir plus au sujet de la configuration des URLs dans Django, vous pouvez aller consulter la documentation officielle du framework : https://docs.djangoproject.com/en/1.7/topics/http/urls/ \ No newline at end of file +> Si vous voulez en savoir plus au sujet de la configuration des URLs dans Django, vous pouvez aller consulter la documentation officielle du framework : https://docs.djangoproject.com/fr/1.8/topics/http/urls/ diff --git a/fr/django_views/README.md b/fr/django_views/README.md index 22a8605ae07..ab3c357f8ef 100755 --- a/fr/django_views/README.md +++ b/fr/django_views/README.md @@ -1,8 +1,8 @@ -# Créons nos vues Django ! +# Créons nos vues Django! Il est enfin temps de se débarrasser du bug que nous avons créé dans le chapitre précédent :) -C'est dans la *vue* que nous allons ranger toute la partie "logique" de notre application. C'est elle qui va se charger d'aller chercher les informations liées à notre `modèle` que nous venons de créer et de les passer à un `template` que nous allons créer dans la section suivante. Concrètement, les vues ne sont que des méthodes Python un peu plus élaborées que ce que nous avons manipulé dans la partie **Introduction à Python**. +C'est dans la *vue* que nous allons ranger toute la partie "logique" de notre application. C'est elle qui va se charger d'aller chercher les informations liées à notre `modèle `que nous venons de créer et de les passer à un `template`. Nous allons créer ce template dans le chapitre suivant. Concrètement, les vues ne sont que des méthodes Python un peu plus élaborées que celles que nous avons manipulées dans la partie **Introduction à Python**. Les vues sont placées dans le fichier `views.py`. Nous allons créer nos *vues* dans le fichier `blog/views.py`. @@ -10,19 +10,20 @@ Les vues sont placées dans le fichier `views.py`. Nous allons créer nos *vues* Ok, allons-y ! Ouvrons ce fichier pour voir ce qu'il contient : - from django.shortcuts import render - - # Create your views here. - +```python +from django.shortcuts import render + +# Create your views here. +``` Il n'y pas encore grand chose dans ce fichier. La vue la plus simple que l'on peut créer ressemble à ceci : - def post_list(request): - - return render(request, 'blog/post_list.html', {}) - +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` -Comme vous pouvez le voir, nous avons créé une méthode (`def`) appelé `post_list` qui prend une `request (requête)` et `return (retourne)` une méthode `render` qui va permettre d'assembler tout ça selon notre template `blog/post_list.html`. +Comme vous pouvez le voir, nous avons créé une méthode (`def`) appelée `post_list` qui prend une `request (requête)` et `return (retourne)` une méthode `render` qui va permettre d'assembler tout ça selon notre template `blog/post_list.html`. Sauvegardez votre fichier et allez à l'adresse http://127.0.0.1:8000/ pour voir ce qui s'affiche maintenant. @@ -34,4 +35,4 @@ Une autre erreur ! Voyons ce qu'elle nous dit : Celle-là est plutôt simple : *TemplateDoesNotExist*. Corrigeons ça en créant un template dans la section suivante ! -> Pour en apprendre un peu plus sur les vues dans Django, consultez la documentation officielle : https://docs.djangoproject.com/en/1.7/topics/http/views/ \ No newline at end of file +> Pour en apprendre un peu plus sur les vues dans Django, consultez la documentation officielle : https://docs.djangoproject.com/fr/1.8/topics/http/views/ diff --git a/fr/domain/README.md b/fr/domain/README.md index 5d6e476a7a2..ff70deddbb7 100755 --- a/fr/domain/README.md +++ b/fr/domain/README.md @@ -6,7 +6,7 @@ C'est ce que nous allons voir dans ce chapitre : comment acheter un nom de domai ## Où enregistrer son nom de domaine ? -Un nom de domaine coûte environ 15$ par an. Vous pouvez en trouver des plus cher ou des moins cher, tout dépend de votre provider. Il existe de très nombreuses compagnies spécialisées dans l'enregistrement de nom de domaine : une simple recherche sur [Google][1] vous listera plusieurs centaines de possibilités. +Un nom de domaine coûte environ 15$ par an. Vous pouvez en trouver des plus ou moins cher : tout dépend de votre provider. Il existe de très nombreuses compagnies spécialisées dans l'enregistrement de nom de domaine : une simple recherche sur [Google][1] vous listera plusieurs centaines de possibilités. [1]: https://www.google.com/search?q=register%20domain @@ -18,7 +18,7 @@ Notre petit favori est [I want my name][2]. Ils revendiquent un "management de n Allez sur [iwantmyname][3] et tapez le nom de domaine que vous souhaiteriez enregistrer dans le champ de recherche. - [3]: http://iwantmyname.com + [3]: https://iwantmyname.com ![][4] diff --git a/fr/domain/images/1.png b/fr/domain/images/1.png deleted file mode 100644 index 97a06e28f2a..00000000000 Binary files a/fr/domain/images/1.png and /dev/null differ diff --git a/fr/domain/images/2.png b/fr/domain/images/2.png deleted file mode 100644 index 604fd5b02c8..00000000000 Binary files a/fr/domain/images/2.png and /dev/null differ diff --git a/fr/domain/images/3.png b/fr/domain/images/3.png deleted file mode 100644 index c941c0d231d..00000000000 Binary files a/fr/domain/images/3.png and /dev/null differ diff --git a/fr/domain/images/4.png b/fr/domain/images/4.png deleted file mode 100644 index dcbe145b271..00000000000 Binary files a/fr/domain/images/4.png and /dev/null differ diff --git a/fr/domain/images/5.png b/fr/domain/images/5.png deleted file mode 100644 index 778765053e5..00000000000 Binary files a/fr/domain/images/5.png and /dev/null differ diff --git a/fr/domain/images/6.png b/fr/domain/images/6.png deleted file mode 100644 index 52a0bb87c4c..00000000000 Binary files a/fr/domain/images/6.png and /dev/null differ diff --git a/fr/domain/images/images/1.png b/fr/domain/images/images/1.png deleted file mode 100644 index 97a06e28f2a..00000000000 Binary files a/fr/domain/images/images/1.png and /dev/null differ diff --git a/fr/domain/images/images/2.png b/fr/domain/images/images/2.png deleted file mode 100644 index 604fd5b02c8..00000000000 Binary files a/fr/domain/images/images/2.png and /dev/null differ diff --git a/fr/domain/images/images/3.png b/fr/domain/images/images/3.png deleted file mode 100644 index c941c0d231d..00000000000 Binary files a/fr/domain/images/images/3.png and /dev/null differ diff --git a/fr/domain/images/images/4.png b/fr/domain/images/images/4.png deleted file mode 100644 index dcbe145b271..00000000000 Binary files a/fr/domain/images/images/4.png and /dev/null differ diff --git a/fr/domain/images/images/5.png b/fr/domain/images/images/5.png deleted file mode 100644 index 778765053e5..00000000000 Binary files a/fr/domain/images/images/5.png and /dev/null differ diff --git a/fr/domain/images/images/6.png b/fr/domain/images/images/6.png deleted file mode 100644 index 52a0bb87c4c..00000000000 Binary files a/fr/domain/images/images/6.png and /dev/null differ diff --git a/fr/dynamic_data_in_templates/README.md b/fr/dynamic_data_in_templates/README.md index a18bd4ae128..79eeb8a02e4 100755 --- a/fr/dynamic_data_in_templates/README.md +++ b/fr/dynamic_data_in_templates/README.md @@ -1,4 +1,4 @@ -# Django Querysets +# Données dynamiques dans les templates Nous avons différents morceaux en place : le modèle `Post` qui est définit dans le fichier `models.py`, la vue `post_list` dans `views.py` et nous venons de créer notre template. Mais comment allons-nous faire pour faire apparaître nos posts dans notre template HTML ? Car au final, n'est-ce pas le but que nous souhaiterions atteindre ? Nous aimerions prendre du contenu, en l’occurrence notre modèle sauvegardé dans notre base de données, et réussir à joliment l'afficher dans notre template. @@ -8,17 +8,19 @@ Ok, et sinon, on fait comment ? Nous allons avoir besoin d'ouvrir le fichier `blog/views.py`. Pour l'instant, la *vue* `post_list` ressemble à ceci : - from django.shortcuts import render - - def post_list(request): - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render -Est-ce que vous vous souvenez de comment rajouter des morceaux de code écris dans d'autres fichiers ? Nous en avons parlé dans un chapitre précédent. Nous allons devoir importer notre modèle qui est défini dans le fichier `models.py`. Pour cela, nous allons ajouter la ligne `from .models import Post` de la façon suivante : +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` - from django.shortcuts import render - from .models import Post - +Est-ce que vous vous souvenez de comment rajouter des morceaux de code écrits dans d'autres fichiers ? Nous en avons parlé dans un chapitre précédent. Nous allons devoir importer notre modèle qui est défini dans le fichier `models.py`. Pour cela, nous allons ajouter la ligne `from .models import Post` de la façon suivante : + +```python +from django.shortcuts import render +from .models import Post +``` Le point après `from` signifie le *dossier courant* ou *l'application courante*. Comme `views.py` et `models.py` sont dans le même dossier, nous pouvons tout simplement utiliser `.` et le nom du fichier, sans le `.py`. Ensuite, nous importons le modèle (`Post`). @@ -28,39 +30,46 @@ Ok, et après ? Afin de pouvoir aller chercher les véritables posts de blog de Normalement, ce mot doit vous évoquer quelque chose. Nous en avons un peu parlé dans la section [Django ORM (QuerySets)][1]. - [1]: /django_orm/README.html - Maintenant, nous allons nous intéresser à une liste de blog posts qui sont publiés et classés par date de publication (`published_date`). Ça tombe bien, on a déjà fait ça dans la section sur les QuerySets ! - Post.objects.filter(published_date__isnull=False).order_by('published_date') - +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` Il ne nous reste plus qu'à mettre cette ligne de code à l'intérieur de notre fichier `blog/views.py`, dans la fonction `def post_list(request)` : - from django.shortcuts import render - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` Veuillez noter que nous créons une *variable* pour notre QuerySet : `posts`. Considérez que c'est le nom de notre QuerySet. À partir de maintenant, nous allons pouvoir faire référence à notre QuerySet en utilisant ce nom. -Il nous manque encore un petit quelque chose : passer notre QuerySet `posts` à notre template. Nous intéresserons plus particulièrement à celui-ci dans la section suivante. +Notez aussi que notre code utilise la fonction `timezone.now()` que nous allons aussi devoir importer de `timezone`. -Dans la fonction `render`, nous avons déjà un paramètre `request`, qui désigne tout ce que nous recevons d'un utilisateur par l'intermédiaire d'Internet, et un fichier template appelé `'blog/post_list.html'`. Le dernier paramètre, qui ressemble à `{}`, va nous permettre de glisser des instructions que notre template va suivre. Nous avons par exemple de lui donner des noms : nous allons rester sur `'posts'` pour le moment :). Ça va ressembler à ça : `{'posts': posts}`. Attention ! La partie située avant les `:` est entourée de guillemets simples `''`. +Il nous manque encore un petit quelque chose : passer notre QuerySet `posts` à notre template. Nous nous intéresserons plus particulièrement à celui-ci dans la section suivante. + +Dans la fonction `render`, nous avons déjà un paramètre `request`, qui désigne tout ce que nous recevons d'un utilisateur par l'intermédiaire d'Internet, et un fichier template appelé `'blog/post_list.html'`. Le dernier paramètre, qui ressemble à `{}`, va nous permettre de glisser des instructions que notre template va suivre. Nous avons besoin par exemple de lui donner des noms : nous allons rester sur `'posts'` pour le moment :). Ça va ressembler à ça : `{'posts': posts}`. La partie située avant `:` est une chaîne de caractères : vous devez donc l'entourer de guillemets `''`. Au final, notre fichier `blog/views.py` doit ressembler à ceci maintenant : - from django.shortcuts import render - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') - return render(request, 'blog/post_list.html', {'posts': posts}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` Et voilà, c'est bon ! Nous allons retourner du côté de notre template pour que notre QuerySet puisse s'afficher correctement ! -Si vous voulez en savoir plus sur les QuerySets, n'hésitez pas à consulter la documentation officielle du framework : https://docs.djangoproject.com/en/1.7/ref/models/querysets/ \ No newline at end of file +Si vous voulez en savoir plus sur les QuerySets, n'hésitez pas à consulter la documentation officielle du framework : https://docs.djangoproject.com/fr/1.8/ref/models/querysets/ + + [1]: ../django_orm/README.md diff --git a/fr/extend_your_application/README.md b/fr/extend_your_application/README.md index a6980197c24..2e7aab1531e 100755 --- a/fr/extend_your_application/README.md +++ b/fr/extend_your_application/README.md @@ -22,85 +22,82 @@ Nous allons tout d'abord ajouter un lien à l'intérieur du fichier `blog/templa {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} ``` - -{% raw %}Nous aimerions pouvoir cliquer sur le titre du post et arriver sur une page nous détaillant celui-ci. Pour cela, changeons `

{{ post.title }}

` et transformons-le en lien:{% endraw %} +{% raw %}Nous aimerions pouvoir cliquer sur le titre du post et arriver sur une page avec le contenu de celui-ci. Pour cela, changeons `

{{ post.title }}

` pour qu'il pointe vers la page de contenu du post :{% endraw %} ```html -

{{ post.title }}

+

{{ post.title }}

``` - -{% raw %}C'est le parfait moment pour expliquer le mystérieux `{% url 'blog.views.post_detail' pk=post.pk %}`. Vous vous souvenez peut-être que la notation `{% %}` nous permet d'utiliser les balises de template Django. Cette fois, nous allons utiliser des balises qui vont s'occuper de créer des URLs à notre place.{% endraw %} +{% raw %}C'est le moment parfait pour expliquer ce mystérieux `{% url 'post_detail' pk=post.pk %}`. Vous vous souvenez peut-être que la notation `{% %}` nous permet d'utiliser les balises de template Django. Cette fois, nous allons utiliser des balises qui vont s'occuper de créer des URLs à notre place !{% endraw %} `blog.views.post_detail` est le chemin d'accès vers la *vue* `post_detail` que nous aimerions créer. Attention : `blog` désigne notre application (le dossier `blog`) et `views` le fichier `views.py`. Enfin, `post_detail` est le nom de notre *vue*. -Maintenant, allons à l'adresse : - - http://127.0.0.1:8000/ - - -Nous allons rencontrer une erreur, ce qui est normal car nous n'avons ni URL ni *vue* pour `post_detail`. Ça doit ressembler à ceci : +Si nous essayons d'aller à http://127.0.0.1:8000/, nous allons rencontrez une erreur : nous n'avons pas d'URL ou de *vue* pour `post_detail`. L'erreur ressemble à ceci : ![Erreur NoReverseMatch][1] [1]: images/no_reverse_match2.png -Allons créer notre URL dans le fichier `urls.py` pour notre *vue* `post_detail`! +## Créer une URL vers le contenu d'un post -### URL: http://127.0.0.1:8000/post/1/ +Allons créer notre URL dans le fichier `urls.py` pour notre *vue* `post_detail`! -Nous voulons crer une URL pour pointer Django vers une *vue* appelée `post_detail`, ce qui nous permettra d'afficher l'intégralité d'un blog post. Ajoutez la ligne `url(r'^post/(?P[0-9]+)/$', views.post_detail),` au fichier `blog/urls.py`. Ça devrait ressembler à ceci : +Nous aimerions que le contenu de notre premier post s'affiche à cette **URL** : http://127.0.0.1:8000/post/1/ - from django.conf.urls import patterns, include, url - from . import views - - urlpatterns = patterns('', - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - ) - +Allons créer une URL dans le fichier `blog/urls.py` qui pointera Django vers une *vue* appelée `post_detail`. Cela nous permettra d'afficher l'intégralité d'un post de blog. Ajoutez la ligne `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` dans le fichier `blog/urls.py`. Votre fichier devrait maintenant ressembler à ceci : -Une nouvelle fois, ce bout de code a l'air effrayant ! Ne vous inquiétez pas, nous allons le décortiquer ensemble : - Il commence par `^`, qui désigne le "début" - `post/` signifie seulement qu'après le début, l'URL doit contenir le mot **post** et **/**. Jusque-là, tout va bien. - `(?P[0-9]+)` : ok, là, on s'accroche :). Cela signifie que Django va prendre tout ce que vous placez là et le transférer à une vue sous la forme d'une variable appelée `pk`. `[0-9]` nous dit aussi que nous ne voulons que des nombres (tout ce qui est entre 0 et 9 inclus) et non des lettres. `+` signifie qu'il faut, au minimum, un chiffre à cet endroit. Du coup, quelque chose comme `http://127.0.0.1:8000/post//` n'est pas valide tandis que `http://127.0.0.1:8000/post/1234567890/` l'est complètement ! - `/` - nous avons encore besoin d'un **/** - `$` - "la fin" ! +```python +from django.conf.urls import url +from . import views -Concrètement, cela signifie que si vous entrez `http://127.0.0.1:8000/post/5/` dans votre barre d'adresse, Django va comprendre que vous cherchez à atteindre une *vue* appelée `post_detail` et qu'il doit communiquer l'information que `pk` est égal `5` dans cette *vue*. +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` -`pk` est un raccourci pour `primary key`. Ce nom est très souvent utilisé dans les projets Django. Cependant, vous pouvez appeler cette variable comme bon vous semble, toujours dans la limite des règles suivantes : pas d'accents, pas de caractères spéciaux, des minuscules et des `_` à la place des espaces ! Par exemple, à la place de `(?P[0-9]+)`, nous pourrions utiliser la variable `post_id`, ce qui donnerait : `(?P[0-9]+)`. +`^post/(?P[0-9]+)/$` a l'air plutôt effrayant mais, ne vous inquiétez pas, décortiquons-le ensemble : +* Il commence par `^`, qui désigne le "début" +* `post/` signifie seulement qu'après le début, l'URL doit contenir le mot **post** et **/**. Jusque-là, tout va bien. +* `(?P[0-9]+)` : ok, là, on s'accroche :). Cela signifie que Django va prendre tout ce que vous placez là et le transférer à une vue sous la forme d'une variable appelée `pk`. `[0-9]` nous dit aussi que nous ne voulons que des nombres (tout ce qui est entre 0 et 9 inclus) et non des lettres. `+` signifie qu'il faut, au minimum, un chiffre à cet endroit. Du coup, quelque chose comme `http://127.0.0.1:8000/post//` n'est pas valide tandis que `http://127.0.0.1:8000/post/1234567890/` l'est complètement! +* `/` - nous avons encore besoin d'un **/** +* `$` - "la fin"! -Ok ! Rafraîchissons la page : +Concrètement, cela signifie que si vous entrez `http://127.0.0.1:8000/post/5/` dans votre barre d'adresse, Django va comprendre que vous cherchez à atteindre une *vue* appelée `post_detail` et qu'il doit communiquer l'information que `pk` est égal `5` dans cette *vue*. - http://127.0.0.1:8000/ - +`pk` est un raccourci pour `primary key`. Ce nom est très souvent utilisé dans les projets Django. Cependant, vous pouvez appeler cette variable comme bon vous semble, toujours dans la limite des règles suivantes : pas d'accents, pas de caractères spéciaux, des minuscules et des `_` à la place des espaces. Par exemple, à la place de `(?P[0-9]+)`, nous pourrions utiliser la variable `post_id`, ce qui donnerait : `(?P[0-9]+)`. -Boom ! Encore une erreur ! Mais on s'y attendait ;) +Comme nous venons d'ajouter un nouveau pattern d'URL au fichier `blog/urls.py`, rafraîchissons la page : http://127.0.0.1:8000/ Boom ! Encore une erreur ! Mais on s'y attendait ;) ![AttributeError][2] [2]: images/attribute_error2.png -Est-ce que vous vous souvenez de ce que nous devons faire ensuite ? Mais bien sûr ! Il faut ajouter une vue ! +Est-ce que vous vous souvenez de ce que nous devons faire ensuite ? Il falloir ajouter une vue ! -## La vue post_detail +## Ajouter une vue pour le contenu du post -Cette fois, nous allons donner un paramètre supplémentaire à notre *vue* : `pk`. Notre *vue* a besoin de le récupérer, n'est-ce pas ? Pour cela, nous allons définir une fonction : `def post_detail(request, pk):`. Attention : notez bien que nous utilisons le même nom que celui que nous avons spécifié dans le fichier url (`pk`). Oublier cette variable est incorrect et va générer une erreur ! +Cette fois, nous allons donner un paramètre supplémentaire à notre *vue* : `pk`. Notre *vue* va avoir besoin de le récupérer. Pour cela, nous allons définir une fonction : `def post_detail(request, pk):`. Attention : notez bien que nous utilisons le même nom que celui que nous avons spécifié dans le fichier url (`pk`). Oublier cette variable est incorrecte et va générer une erreur ! -Maintenant, nous aimerions obtenir qu'un seul blog post. Pour cela, nous allons utiliser des QuerySets qui ressemblent à ceux-ci : +Maintenant, nous n'aimerions obtenir qu'un seul blog post. Pour cela, nous allons utiliser des QuerySets qui ressemblent à ceux-ci: - Post.objects.get(pk=pk) - +```python +Post.objects.get(pk=pk) +``` -Cependant, il y a un petit problème dans cette ligne de code. Si aucun de nos `Posts` ne possèdent cette `primary key (clef primaire)` (`pk`), nous allons nous retrouver avec une super erreur bien cracra ! +Cependant, il y a un petit problème dans cette ligne de code. Si aucun de nos `Posts` ne possède cette `primary key (clef primaire)` (`pk`), nous allons nous retrouver avec une super erreur bien cracra! ![Erreur DoesNotExist][3] [3]: images/does_not_exist2.png -Dans l'idéal, nous aimerions pouvoir éviter ça ! Comme d'habitude, Django nous offre l'outil parfait pour ça : `get_object_or_404`. Dans le cas où il n'existerait pas de `Post` avec le `pk` indiqué, une page d'erreur beaucoup plus sympathique s'affichera : c'est ce qu'on appelle une `erreur 404 : page non trouvée`. +Dans l'idéal, nous aimerions pouvoir éviter ça! Comme d'habitude, Django nous offre l'outil parfait pour ça : `get_object_or_404`. Dans le cas où il n'existerait pas de `Post` avec le `pk` indiqué, une page d'erreur beaucoup plus sympathique s'affichera : c'est ce qu'on appelle une `erreur 404 : page non trouvée`. ![Page non trouvée][4] @@ -108,30 +105,29 @@ Dans l'idéal, nous aimerions pouvoir éviter ça ! Comme d'habitude, Django nou La bonne nouvelle, c'est que vous pouvez créer vous-mêmes votre page `Page non trouvée` et en faire ce que vous voulez ! Reconnaissez que ce n'est pas le plus important pour le moment donc nous allons zapper cette partie ;). -Ok, ajoutons notre *vue* à notre fichier `views.py` ! - -Ouvrons le fichier `blog/views.py` et ajoutons le code suivant : +Ok, ajoutons notre *vue* à notre fichier `views.py`! - from django.shortcuts import render, get_object_or_404 - +Ouvrons le fichier `blog/views.py` et ajoutons le code suivant: -Cette ligne est à ajouter en dessous des lignes `from` situées en début de fichier. Ensuite, à la fin de notre fichier, nous allons ajouter notre *vue* proprement dite : +```python +from django.shortcuts import render, get_object_or_404 +``` - def post_detail(request, pk): - post = get_object_or_404(Post, pk=pk) - return render(request, 'blog/post_detail.html', {'post': post}) - +Cette ligne est à ajouter en dessous des lignes `from` situées en début de fichier. Ensuite, à la fin de notre fichier, nous allons ajouter notre *vue* proprement dite: -Yep, c'est l'heure de recharger notre page : +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` - http://127.0.0.1:8000/ - +Hop, réactualisons la page http://127.0.0.1:8000/ ![Vue post_list][5] [5]: images/post_list2.png -Ok, ça a marché ! Mais que ce passe-t-il lorsque nous cliquons sur un lien dans un titre de blog post ? +C'est bon, ça a marché ! Mais que se passe-t-il lorsque nous cliquons sur un lien dans un titre de blog post ? ![Erreur TemplateDoesNotExist][6] @@ -139,6 +135,8 @@ Ok, ça a marché ! Mais que ce passe-t-il lorsque nous cliquons sur un lien dan Oh non ! Encore une erreur ! Mais cette fois, vous savez quoi faire : nous avons besoin d'un template ! +## Créer un template pour le contenu du post + Nous allons créer un fichier `post_detail.html` dans le dossier `blog/templates/blog`. Ça ressemblera à ça : @@ -147,20 +145,21 @@ Nous allons créer un fichier `post_detail.html` dans le dossier `blog/templates {% extends 'blog/base.html' %} {% block content %} -
+
{% if post.published_date %} - {{ post.published_date }} +
+ {{ post.published_date }} +
{% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

{% endblock %} ``` - -Une nouvelle fois, nous faisons hériter de `base.html`. Dans le `content` block, nous voulons que s'affiche la date de publication d'un post (si elle existe), son titre et son texte. Mais vous souhaitez peut-être quelques éclaircissements avant, non ? +Une nouvelle fois, nous faisons hériter de `base.html`. Dans le `content` block, nous voulons que s'affiche la date de publication d'un post (si elle existe), son titre et son texte. Mais vous souhaitez peut-être quelques éclaircissements avant, non? -{% raw %}`{% if ... %} ... {% endif %}` est une balise de template que nous pouvons utiliser si nous voulons vérifier quelque chose : souvenez-vous de `if ... else ..` de la section **Introduction to Python**. Dans notre exemple, nous aimerions vérifier si un post possède une date de publication (`published_date`).{% endraw %} +{% raw %}`{% if ... %} ... {% endif %}` est une balise de template que nous pouvons utiliser si nous voulons vérifier quelque chose : souvenez-vous de `if ... else ..` de la section **Introduction à Python**. Dans ce scénario, nous aimerions vérifier si la date de publication d'un post (`published_date`) n'est pas vide.{% endraw %} Ok, vous pouvez maintenant rafraîchir votre page et voir si la page `Page not found` a enfin disparu. @@ -168,22 +167,33 @@ Ok, vous pouvez maintenant rafraîchir votre page et voir si la page `Page not f [7]: images/post_detail2.png -Yay ! Ça marche ! +Yay ! Ça marche! ## Encore un petit effort : déployons ! -Ce serait génial si nous pouvions aller sur notre site web hébergé sur Heroku et voir toutes ces nouvelles fonctionnalités ! Remontons nos manches et déployons encore une fois. Si vous ne vous souvenez plus de ce que fait chaque commande, consultez la fin du chapitre 15 : - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Ajout de vues supplémentaires pour le site." -... -$ git push heroku master -``` - +Nous ferions bien de mettre à jour la version de notre site présente sur PythonAnywhere. On s'accroche et on déploie encore une fois :) + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push + + +* Puis, dans la console bash de [PythonAnywhere][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Enfin, cliquez sur l'onglet [Web][9] et cliquez sur **Reload**. + + [9]: https://www.pythonanywhere.com/web_app_setup/ Normalement, ça devrait suffire ! Encore bravo :) diff --git a/fr/extend_your_application/images/images/no_reverse_match2.png b/fr/extend_your_application/images/images/no_reverse_match2.png deleted file mode 100644 index db65a5dc70a..00000000000 Binary files a/fr/extend_your_application/images/images/no_reverse_match2.png and /dev/null differ diff --git a/fr/extend_your_application/images/no_reverse_match2.png b/fr/extend_your_application/images/no_reverse_match2.png index db65a5dc70a..306926206f8 100644 Binary files a/fr/extend_your_application/images/no_reverse_match2.png and b/fr/extend_your_application/images/no_reverse_match2.png differ diff --git a/fr/how_internet_works/images/internet_4.png b/fr/how_internet_works/images/internet_4.png deleted file mode 100644 index 05f1aed562f..00000000000 Binary files a/fr/how_internet_works/images/internet_4.png and /dev/null differ diff --git a/fr/how_internet_works/README.md b/fr/how_the_internet_works/README.md old mode 100755 new mode 100644 similarity index 63% rename from fr/how_internet_works/README.md rename to fr/how_the_internet_works/README.md index 5416bc7189c..4445c403ad0 --- a/fr/how_internet_works/README.md +++ b/fr/how_the_internet_works/README.md @@ -1,12 +1,12 @@ -# Comment marche l'Internet +# Comment fonctionne l'Internet ? > Ce chapitre est inspiré par la présentation "How the Internet works" par Jessica McKellar (http://web.mit.edu/jesstess/www/). -Vous utilisez sûrement Internet tous les jours. Mais savez-vous ce que ce passe vraiment quand vous tapez une adresse comme http://djangogirls.org dans votre navigateur et appuyez sur 'Entrée' ? +Vous utilisez sûrement Internet tous les jours. Mais savez-vous ce qu'il ce passe vraiment quand vous tapez une adresse comme https://djangogirls.org dans votre navigateur et appuyez sur `Entrée` ? Avant tout, il faut savoir qu'un site web n'est rien de plus qu'un tas de fichiers sauvegardés sur un disque dur. Exactement comme vos vidéos, vos musiques ou vos photos. Cependant, les sites web ont quelque chose d'unique : ils contiennent du code informatique appelé HTML. -Si vous n'avez pas l'habitude de la programmation, il peut être difficile de comprendre HTML au débit, mais vos navigateurs web (comme Chrome, Safari, Firefox, etc.) adorent ça. Les navigateurs web sont conçus pour comprendre ce code, pour suivre les instructions qu'il contient et présenter les fichiers de votre site web exactement comme vous voulez qu'ils soient présentés. +Si vous n'avez pas l'habitude de la programmation, il peut être difficile de comprendre HTML au début, mais vos navigateurs web (comme Chrome, Safari, Firefox, etc.) adorent ça. Les navigateurs web sont conçus pour comprendre ce code, pour suivre les instructions qu'il contient et présenter les fichiers de votre site web exactement comme vous voulez qu'ils soient présentés. Comme pour n'importe quel autre fichier, il faut stocker les fichiers HTML sur un disque dur quelque part. Pour Internet, on utilise des ordinateurs spéciaux, très puissants, appelés *serveurs*. Ils n'ont pas d'écran, de clavier ou de souris, car leur rôle est de stocker des données, et de les servir. C'est pour ça qu'on les appelle des *serveurs* -- parce qu'ils sont là pour vous *servir* des données. @@ -24,7 +24,7 @@ C'est le bazar, non ? En fait, c'est un réseau de machines connectées entre el [2]: images/internet_3.png -Fascinant, non ? Mais, il n'est évidemment pas possible de tirer un câble de chaque machine connecté à Internet vers chaque autre. Du coup, pour atteindre une machine (par exemple, celle où http://djangogirls.org est sauvegardé), on doit faire passer une requête par plein d'autres machines. +Fascinant, non ? Cependant, il n'est évidemment pas possible de tirer un câble entre chaque machine connectée à Internet. Du coup, pour atteindre une machine (par exemple, celle où https://djangogirls.org est sauvegardé), on doit faire passer une requête par plein d'autres machines. Ça ressemble ça : @@ -32,9 +32,9 @@ Fascinant, non ? Mais, il n'est évidemment pas possible de tirer un câble de c [3]: images/internet_2.png -C'est un peu comme si, quand vous tapez http://djangogirls.org, vous envoyiez une lettre que dit "Chères Django Girls, je voudrais voir le site djangogirls.org. Pouvez-vous me l'envoyer ?" +C'est un peu comme si, quand vous tapiez https://djangogirls.org, vous envoyiez une lettre qui dit "Chères Django Girls, je voudrais voir le site djangogirls.org. Pouvez-vous me l'envoyer ?" -Votre lettre part vers le bureau de post le plus proche. Ensuite, il file vers un autre, qui est plus proche de votre destinataire. Puis un autre, et encore une autre, jusqu'à sa destination. Pour Internet, c'est pareil. La seule différence, c'est que si vous envoyez plusieurs lettres (*des paquets de données*) vers le même endroit, chaque lettre peut emprunter une route différente, et voir différents bureaux de post (*routeurs*), selon la manière dont chaque bureau de poste distribue chaque lettre. +Votre lettre part vers le bureau de poste le plus proche. Ensuite, il file vers un autre, qui est plus proche de votre destinataire. Puis un autre, et encore un autre, jusqu'à sa destination. Une chose à retenir : si vous envoyez beaucoup de lettres (*data packets*) au même endroit, il se pourrait qu'elles transitent par des postes différentes (*routers*). Cela dépend de la manière dont elles sont distribuées à chaque bureau de poste. ![Figure 1.4][4] @@ -42,12 +42,11 @@ Votre lettre part vers le bureau de post le plus proche. Ensuite, il file vers u Oui oui, c'est aussi simple que ça. Vous envoyez des messages et attendez une réponse. Alors, bien sûr, le papier et le crayon sont remplacés par des octets de données, mais l'idée est la même. -À la place des adresses postales (nom de rue, ville, code postal), nous utilisons des adresses IP. Votre ordinateur commence par demander au DNS (Domaine Name System) de traduire djangogirls.org en une adresse IP. Ça marche un peu comme un de ces vieux annuaires où on peut chercher le nom d'une personne et trouver son numéro de téléphone et son adresse. +À la place des adresses postales (nom de rue, ville, code postal), nous utilisons des adresses IP. Votre ordinateur commence par demander au DNS (Domaine Name System) de traduire djangogirls.org en une adresse IP. Ça marche un peu comme un de ces vieux annuaires où l'on peut chercher le nom d'une personne et trouver son numéro de téléphone et son adresse. -Quand vous envoyez une lettre, elle a besoin de certaines choses pour transiter correctement, comme une adresse et un timbre. Vous devez aussi utiliser une langue que votre destinataire comprend. C'est la même chose pour les *paquets de données* que vous envoyez pour voir un site web : vous utilisez un protocole appelé HTTP (Hypertext Tranfer Protocol). - -Donc, au final, pour avoir un site web il faut qu'il soit sur un *serveur* (c'est une machine). Le *serveur* attend qu'on lui envoie une *requête* (une lettre qui demande au serveur d'envoyer le site web) et renvoie le site web (dans une autre lettre). +Quand vous envoyez une lettre, elle a besoin de certaines choses pour transiter correctement, comme une adresse et un timbre. Vous devez aussi utiliser une langue que votre destinataire comprend. C'est la même chose pour les paquets de données que vous envoyez pour voir un site web. Vous utilisez un protocole appelé HTTP (Hypertext Tranfer Protocol). +Donc, au final, pour avoir un site web il faut qu'il soit sur un *serveur* (c'est une machine). Lorsque le *serveur* reçoit une *requête* (dans une lettre), il envoie votre site Web (dans une autre lettre). Puisqu'on est dans un tutoriel sur Django, vous devez vous demander ce que Django fait. Quand vous envoyez une réponse, vous ne renvoyez pas toujours la même réponse à tout le monde. C'est bien mieux quand les lettres sont personnalisées, surtout quand elles s'adressent à quelqu'un qui vient de vous écrire, non ? Et bien Django vous aide à écrire les lettres personnalisées et intéressantes :). -Assez parler, il est temps de commencer à créer des trucs ! \ No newline at end of file +Assez parlé, il est temps de commencer à créer des trucs ! \ No newline at end of file diff --git a/fr/how_the_internet_works/images/internet_1.png b/fr/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/fr/how_the_internet_works/images/internet_1.png differ diff --git a/fr/how_the_internet_works/images/internet_2.png b/fr/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/fr/how_the_internet_works/images/internet_2.png differ diff --git a/fr/how_the_internet_works/images/internet_3.png b/fr/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/fr/how_the_internet_works/images/internet_3.png differ diff --git a/fr/how_the_internet_works/images/internet_4.png b/fr/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/fr/how_the_internet_works/images/internet_4.png differ diff --git a/fr/html/README.md b/fr/html/README.md index 66c2ce5a030..9b06a7f8817 100755 --- a/fr/html/README.md +++ b/fr/html/README.md @@ -4,13 +4,13 @@ Vous vous demandez sûrement ce qu'est un template. Un template est un fichier que vous pouvez réutiliser afin de présenter des informations différentes sous un seul et même format. Par exemple, vous pourriez avoir envie d'utiliser un template pour écrire une lettre : bien que son contenu varie ou qu'elle puisse être adressée à des personnes différentes, sa forme reste la même. -Le format d'un template Django est décrit grâce à un langage qui s'appelle HTML (c'est le même HTML que celui dont nous parlions dans le chapitre un, **Comment Internet marche**). +Le format d'un template Django est décrit grâce à un langage qui s'appelle HTML (c'est le même HTML que celui dont nous parlions dans le chapitre un, **Comment fonctionne l'Internet**). ## Qu'est-ce que le HTML ? HTML est un code simple qui est interprété par votre navigateur (Chrome, Firefox ou Safari) et qui permet d'afficher une page web à l'utilisateur. -HTML est l'abréviation de "HyperText Markup Language." **HyperText** signifie que s'est un type de texte qui supporte les hyperliens entre les pages. **Markup** signifie que nous avons pris un document et que nous avons balisé le code pour signifier (ici, au navigateur) comment il faut interpréter la page. Le code HTML est construit à l'aide de **balises**, chacune commençant par `<` et finissant par `>`. Ces balises permettent de structurer les **éléments**. +L'abréviation HTML signifie « HyperText Markup Language ». **HyperText** signifie que c'est un type de texte qui supporte les hyperliens entre les pages. **Markup** signifie que nous avons pris un document et que nous avons balisé le code pour signifier (ici, au navigateur) comment il faut interpréter la page. Le code HTML est construit à l'aide de **balises**, chacune commençant par `<` et finissant par `>`. Ces balises représentent des **éléments** markup. ## Votre premier template ! @@ -21,15 +21,15 @@ Les templates sont sauvegardés dans le dossier `blog/templates/blog`. Tout d'ab blog └───templates └───blog - + Vous pourriez vous demander pourquoi nous avons besoin de deux dossiers portant tous les deux le nom `blog`. Comme vous le découvrirez plus tard, c'est une simple convention de nommage qui va nous faciliter la vie quand les choses vont commencer à devenir compliquées. -Et maintenant, créez un fichier `post_list.html` (laisser le vide pour le moment) dans le dossier `templates/blog/blog`. +Et maintenant, créez un fichier `post_list.html` (laisser le vide pour le moment) dans le dossier `blog/templates/blog`. Allons regarder à quoi ressemble notre site maintenant : http://127.0.0.1:8000/ -> Si vous avez une erreur `TemplateDoesNotExists`, essayez de redémarrer votre serveur. Prenez votre ligne de commande, arrêtez votre server en appuyant simultanément sur Ctrl+C (les touches Control et C de votre clavier) et relancer le en tapant la commande `python manage.py runserver`. +> Si vous avez une erreur `TemplateDoesNotExists`, essayez de redémarrer votre serveur. Prenez votre ligne de commande et arrêtez votre serveur en appuyant simultanément sur Ctrl+C (les touches Control et C de votre clavier). Vous pouvez le relancer en tapant la commande `python manage.py runserver`. ![Figure 11.1][1] @@ -39,11 +39,12 @@ Et voilà, il n'y a plus d'erreurs ! Bravo :) Cependant, notre site ne peut rien Ajoutez ce qui suit à votre fichier template : - -

Hi there!

-

It works!

- - +```html + +

Hi there!

+

It works!

+ +``` Alors, à quoi ressemble notre site web maintenant ? Allons le découvrir : http://127.0.0.1:8000/ @@ -68,16 +69,17 @@ Nous utilisons `` pour transmettre la configuration de la page au navigate Par exemple, vous pouvez donner un titre à votre site en utilisant l'élément titre dans le `` : - - - Le blog d'Ola - - -

Salut !

-

Ça marche :)

- - - +```html + + + Le Blog d'Ola + + +

Hi there!

+

It works!

+ + +``` Sauvegardez votre fichier et actualisez la page. @@ -103,40 +105,41 @@ Et si nous en profitions pour nous amuser un peu ? Essayons de personnaliser not * `texte` permet de mettre l'accent sur une partie du texte * `texte` permet de mettre encore plus l'accent sur une partie de texte * `
` permet d'insérer un saut de ligne (vous ne pouvez rien mettre à l'intérieur d'un élément br) -* `link` permet de créer un lien +* `link` permet de créer un lien * `
  • premier item
  • second item
` permet de créer des listes, comme celle que nous sommes en train de faire ! * `
` permet de créer une section au sein de la page Voici un exemple de template utilisant plusieurs balises : - - - Django Girls blog - - - - -
-

published: 14.06.2014, 12:14

-

Mon premier post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

-
- -
-

published: 14.06.2014, 12:14

-

Mon second post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

-
- - - +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

Mon second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` Nous avons créé trois sections à l'aide de `div`. -* Le premier `div` contient le titre de notre blogpost - c'est un titre et un lien -* Les deux autres `div` contiennent nos blogposts avec leur date de publication, un titre de post `h2` qui est cliquable ainsi que deux `p`s (paragraphe) de texte : un pour la date et l'autre pour notre blogpost. +* Le premier `div` contient le titre de notre blog - c'est à la fois un titre et un lien +* Les deux autres `div` contiennent nos posts avec leur date de publication, un titre de post `h2` qui est cliquable ainsi que deux `p` (paragraphe) de texte : un pour la date et l'autre pour notre post. Ce qui nous donne : @@ -146,39 +149,61 @@ Ce qui nous donne : Yaaay ! Pour l'instant, notre template nous permet seulement d'afficher les **mêmes informations** alors que nous disions précédemment qu'il doit nous permettre d'afficher des informations **différentes** utilisant le **même format**. -Ce qu'on aimerait pouvoir maintenant, c'est afficher les posts que nous avons créés précédemment dans l'interface d'administration de Django. Et si nous nous penchions là dessus ? +Ce qu'on aimerait pouvoir maintenant, c'est afficher les posts que nous avons créés précédemment dans l'interface d'administration de Django. Penchons-nous là dessus. -## Encore une chose ! +## Une dernière chose : déployer ! -Ce serait bien de savoir si notre site web sera toujours capable de fonctionner correctement une fois sur Heroku. Essayons de le déployer à nouveau. +Ne serait-il pas génial de pouvoir voir tout ces changements en ligne ? Hop, déployons à nouveau ! -Tout d'abord, regardons quels fichiers ont été modifiés depuis notre dernier déploiement : +### Commiter et pusher votre code sur GitHub + +Tout d'abord, allons voir quels sont les fichiers qui ont changé depuis notre dernier déploiement (lancez ces commandes dans votre console locale et non celle de PythonAnywhere) : $ git status - -Maintenant, essayons de dire à `git` que nous voulons inclure les changements qui ont eu lieu dans le dossier courant : - $ git add -A . - +Assurez-vous que vous êtes bien dans le dossier `djangogirls`. Voici la commande qui permet de dire à `git` d'inclure tout les changements qui ont eu lieu dans ce dossier : + + $ git add --all . + -> **Note** `-A` (abréviation de "tout") signifie que `git` va aussi analyser si vous avez supprimé des fichiers (par défaut, il ne s'intéresse qu'aux nouveaux fichiers ou à ceux modifiés). Essayez de vous rappeler du chapitre 3 : `.` permet de désigner le dossier courant. +> **Note** `--all` (traduction de "tout") signifie que `git` va aussi analyser si vous avez supprimé des fichiers (par défaut, il ne s'intéresse qu'aux nouveaux fichiers ou à ceux modifiés). Essayez de vous rappeler du chapitre 3 : `.` permet de désigner le dossier courant. -Avant que nous puissions uploader nos fichiers, regardons ce que `git` à l'intention de faire (tous les fichiers que `git` va uploader vont apparaître en vert) : +Avant que nous puissions uploader nos fichiers, regardons ce que `git` à l'intention de faire (tous les fichiers que `git` va uploader vont apparaitre en vert) : $ git status - + On y est presque : nous devons maintenant lui dire de sauvegarder ces changements dans son historique. Nous allons y ajouter un "message de commit" qui nous permettra de décrire ce qui a été changé. Vous pouvez mettre ce que vous voulez dans un message de commit. Généralement, il est préférable de mettre quelque chose d'utile qui vous permettra de vous souvenir plus tard de ce que vous avez fait. $ git commit -m "Modification du HTML du site" - + > **Note** N'oubliez pas d'utiliser de doubles guillemets autour de votre message de commit. -Une fois que vous avez terminé, vous pouvez enfin uploader (pusher) vos modifications sur Heroku : +Une fois que nous avons fait cela, nous pouvons mettre en ligne (pusher) nos modifications sur GitHub : + + git push + + +### Puller les modifications sur PythonAnywhere et recharger son appli web + +* Allez sur la page des [consoles de PythonAnywhere][5]. Retournez dans votre **console Bash** ou ouvrez-en une nouvelle puis tapez la commande suivante : + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +Voilà ! Votre code modifié est téléchargé. Si vous voulez vérifier ce que vous venez de récupérer, vous pouvez aller jeter un coup d’œil dans l'onglet **Files** de PythonAnywhere. + +* Pour finir, n'oubliez pas de recharger votre application web : onglet [web][6] puis cliquez sur le bouton **Reload**. - git push heroku master - + [6]: https://www.pythonanywhere.com/web_app_setup/ -Normalement, ça devrait marcher ! Une fois qu'Heroku a terminé, vous pouvez utiliser votre navigateur pour aller sur la page de votre site et la rafraîchir. Normalement, vous devriez constater du changement ! \ No newline at end of file +Retournez sur votre site en cliquant sur l'adresse en haut de la page : normalement, vous devriez voir la dernière version. Si ce n'est pas le cas, ce n'est pas grave : n'hésitez pas à demander de l'aide à votre coach :) diff --git a/fr/installation/README.md b/fr/installation/README.md new file mode 100644 index 00000000000..f8bc70df9c6 --- /dev/null +++ b/fr/installation/README.md @@ -0,0 +1,49 @@ +# Si vous suivez ce tutoriel chez vous + +Si vous suivez ce tutoriel chez vous et non dans un [évènement Django Girls](https://djangogirls.org/events/), vous pouvez passer directement au chapitre [Comment fonctionne l'Internet ?](../how_the_internet_works/README.md). + +Les informations données ici sont couvertes dans le reste du tutoriel. Cette partie permet simplement de regrouper au même endroit tout ce qu'il est nécessaire d'installer avant de participer à un évènement. Les évènements Django Girls incluent une "soirée d'installation" qui permet de prendre un peu d'avance sur la journée de formation proprement dite. + +Rien ne vous empêche de tout installer maintenant si vous le souhaitez. Cependant, si vous avez envie d'apprendre des choses avant d'installer plein de trucs sur votre ordinateur : passez ce chapitre et installez ce dont vous avez besoin au fil des chapitres. + +Bonne chance ! + +# Installation + +Pendant l'atelier, vous allez apprendre à construire un blog. Afin d'être prête pour le jour J, vous devrez installer les éléments listés sur cette page. + +# Installer Python + +{% include "/python_installation/instructions.md" %} + +# Mettre en place virtualenv et installer Django + +{% include "/django_installation/instructions.md" %} + +# Installez un éditeur de code + +{% include "/code_editor/instructions.md" %} + +# Installer Git + +{% include "/deploy/install_git.md" %} + +# Créer un compte GitHub + +Allez sur [GitHub.com](https://www.github.com) et créez-vous un nouveau compte gratuitement. + +# Créer un compte PythonAnywhere + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Commencer à lire + +Félicitations, vous avez tout installé et êtes prête ! Si vous avez toujours du temps avant l'atelier, il peut être utile de commencer à lire les premiers chapitres : + + * [Comment fonctionne l'Internet ?](../how_the_internet_works/README.md) + + * [Introduction à la ligne de commande](../intro_to_command_line/README.md) + + * [Introduction à Python](../intro_to_command_line/README.md) + + * [Qu'est-ce que Django?](../django/README.md) diff --git a/fr/intro_to_command_line/README.md b/fr/intro_to_command_line/README.md index 0997b4bc12c..358d60a21c6 100755 --- a/fr/intro_to_command_line/README.md +++ b/fr/intro_to_command_line/README.md @@ -4,15 +4,17 @@ C'est un peu exaltant, non ? Dans quelques instants, vous allez écrire votre pr **Commençons par vous présenter un nouvel ami : la ligne de commande !** -Les étapes suivantes vont vous montrer comment utiliser la fenêtre noire que tous les bidouilleurs·euses utilisent. Elle est un peu effrayante à première vue, mais en fait, c'est un programme qui attend qu'on lui donne des commandes. +Les étapes suivantes vont vous montrer comment utiliser la fenêtre noire que tous les bidouilleurs·euses utilisent. Elle est un peu effrayante à première vue, mais en fait, c'est tout simplement un programme qui attend qu'on lui donne des commandes. + +> **Note :** Il existe deux mots pour parler de dossier : dossier ou répertoire. Il se peut que nous utilisions les deux dans le tutoriel mais, pas de panique : ils signifient la même chose. ## Qu'est-ce qu'une ligne de commande ? -Cette fenêtre, qu'on appelle aussi **ligne de commande** ou **interface en ligne de commande**, est une application textuelle qui permet de voir et de manipuler des fichiers sur votre ordinateur (comme l'explorateur Windows ou Finder sur Mac, mais sans interface graphique). On l'appelle parfois aussi : *cmd*, *CLI*, *prompt*, *console* ou *terminal*. +Cette fenêtre, qu'on appelle aussi **ligne de commande** ou **interface en ligne de commande**, est une application textuelle qui permet de voir et de manipuler des fichiers sur votre ordinateur. C'est un peu la même chose que l'Explorateur Windows ou Finder dans Mac, mais sans interface graphique. On l'appelle parfois aussi : *cmd*, *CLI*, *prompt*, *console* ou *terminal*. ## Ouvrir l'interface en ligne de commande -Pour commencer à expérimenter, on a d'abord besoin d'ouvrir notre interface en ligne de commande. +Pour commencer à expérimenter, nous avons d'abord besoin d'ouvrir notre interface en ligne de commande. ### Windows @@ -30,7 +32,7 @@ Vous la trouverez probablement dans Applications → Accessoires → Terminal, m Vous devriez maintenant voir une fenêtre noire ou blanche qui attend vos commandes. -Si vous être sous Max ou Linux, vous verrez probablement un `$`, comme ça : +Si vous être sous Mac ou Linux, vous verrez probablement un `$`, comme ça : $ @@ -42,7 +44,7 @@ Sur Windows, c'est un signe `>`, comme ça : Chaque commande commence par ce signe, puis un espace. Mais vous n'avez pas besoin de le taper, votre ordinateur le fait pour vous :) -> Petite remarque : il se peut que vous voyiez quelque chose comme `C:\Users\ola>` ou `Olas-MacBookAir:~ola$` avant le signe de prompt et c'est parfaitement normal. C'est juste parce que dans ce tutoriel, on tente de simplifier les choses autant que possible. +> Petite remarque : il se peut que vous voyiez quelque chose comme `C:\Users\ola>` ou `Olas-MacBookAir:~ola$` avant le signe de prompt. Pas de problème : c'est parfaitement normal. C'est juste parce que dans ce tutoriel, nous tentons de simplifier les choses autant que possible. ## Votre première commande (YAY !) @@ -56,23 +58,23 @@ ou > whoami -Et puis appuyez sur Entrée. Chez nous, ça donne ça : +Puis, appuyez sur la touche `entrée`. Voilà ce qui s'affiche chez moi : $ whoami olasitarska -Vous pouvez constater que l'ordinateur vient juste de vous montrer votre nom d'utilisateur. Pas mal, hein ? :) +Comme vous pouvez le voir, l'ordinateur vient d'afficher votre nom d'utilisateur. Sympa, non ? ;) -> Essayez de taper chaque commande sans copier-coller. Ça aide à retenir ! +> Essayez de taper chaque commande sans copier-coller. Ça aide à les retenir ! ## Les bases -Les différents systèmes d'exploitation ont des commandes légèrement différentes, donc faites attention à suivre les instructions pour votre système d'exploitation. On est parti ? +Les différents systèmes d'exploitation ont des commandes légèrement différentes, donc faites attention à suivre les instructions pour votre système d'exploitation. Allons-y ! ### Dossier courant -Ce serait pas mal de savoir où on est, non ? Voyons voir. Tapez cette commande et appuyez sur Entrée : +Ce serait pratique de savoir dans quel répertoire nous nous trouvons. Pour le savoir, tapez la commande suivante et appuyez sur `entrée` : $ pwd /Users/olasitarska @@ -86,13 +88,13 @@ Si vous êtes sous Windows : Vous verrez probablement quelque chose de similaire sur votre machine. Quand vous ouvrez une ligne de commande, vous démarrez habituellement dans le dossier personnel de votre utilisateur. -> Remarque : "pwd" veut dire "print working directory". +> Remarque : "pwd" veut dire "print working directory" (afficher le dossier courant). * * * ### Lister les fichiers et les dossiers -Du coup, y'a quoi dans ce dossier personnel ? Ce serait pas mal de le savoir. Essayons ça : +Du coup, que pouvons-nous trouver dans ce dossier personnel ? Pour le savoir, essayons ceci : $ ls Applications @@ -117,7 +119,7 @@ Windows : ### Changer le dossier courant -Et si on allait voir dans notre dossier Bureau ? +Maintenant, essayons d'aller sur notre bureau : $ cd Bureau @@ -141,35 +143,35 @@ Windows : Et voilà ! -> Pro tip : si vous tapez `cd B` puis que vous appuyez sur la touche `tab`, la ligne de commande va automatiquement compléter le reste du nom, pour vous permettre d'aller plus vite. Si plusieurs dossiers commencent par un "B", appuyez sur `tab` deux fois pour avoir une liste des options. +> Pro tip : si vous tapez `cd B` puis que vous appuyez sur la touche `tabulation`, la ligne de commande va automatiquement compléter le reste du nom. Cela va vous permettre d'aller plus vite et d'éviter des fautes de frappe. Si plusieurs dossiers commencent par un « B », appuyez sur `tabulation` deux fois pour avoir une liste des options. * * * ### Créer un dossier -Et si on créait un dossier Django Girls sur votre bureau ? Vous pouvez faire comme ça : +Que diriez-vous de créer un répertoire dédié aux exercices sur votre bureau ? Vous pouvez le faire de cette façon : - $ mkdir djangogirls + $ mkdir exercices Windows : - > mkdir djangogirls + > mkdir exercices -Cette petite commande crée un dossier nommé `djangogirls` sur votre bureau. Vous pouvez vérifier qu'il est bien là en regardant votre bureau, ou en lançant la commande `ls` ou `dir` ! Essayez donc :) +Cette petite commande crée un dossier nommé `exercices` sur votre bureau. Vous pouvez vérifier qu'il est bien là en regardant votre bureau, ou en lançant la commande `ls` ou `dir` ! Essayez donc :) -> Pro tip : Si vous voulez éviter de taper les mêmes commandes plein de fois, essayer d'appuyer sur les touches `flèche haut` et `flèche bas` pour retrouver les dernières commandes que vous avez tapé. +> Pro tip : Si vous voulez éviter de taper les mêmes commandes plein de fois, essayez d'appuyer sur les touches `flèche haut` et `flèche bas` pour retrouver les dernières commandes que vous avez tapé. * * * ### Un peu d'exercice ! -Petit défi pour vous : dans votre nouveau dossier `djangogirls`, créez un dossier appelé `test`. Pour ça, utilisez les commands `cd` et `mkdir`. +Petit défi pour vous : dans votre nouveau dossier `exercices`, créez un dossier appelé `test`. Pour ça, utilisez les commandes `cd` et `mkdir`. #### Solutions : - $ cd djangogirls + $ cd exercices $ mkdir test $ ls test @@ -177,13 +179,13 @@ Petit défi pour vous : dans votre nouveau dossier `djangogirls`, créez un doss Windows : - > cd djangogirls + > cd exercices > mkdir test > dir 05/08/2014 07:28 PM test -Félicitation ! :) +Félicitations ! :) * * * @@ -201,7 +203,8 @@ Windows : > cd .. -Faire un `cd` vers `..` permet de changer le dossier courant vers le dossier parent (c'est à dire le dossier qui contient le dossier courant). + +Grâce à `..` et la commande `cd`, vous pouvez aller directement dans le dossier parent de votre répertoire courant (c'est à dire le dossier qui contient le dossier dans lequel vous étiez). Vérifiez où vous êtes : @@ -215,20 +218,20 @@ Windows : C:\Users\olasitarska\Bureau -Maintenant, supprimons le dossier `djangogirls`. +Maintenant, il est temps de supprimer notre dossier `exercices` : > **Attention** : Supprimer des fichiers avec `del`, `rmdir` ou `rm` est irrévocable, ce qui veut dire que *les fichiers supprimés sont perdus à jamais* ! Du coup, faites très attention avec cette commande. - $ rm -r djangogirls + $ rm -r exercices Windows : - > rmdir /S djangogirls - djangogirls, Are you sure ? Y + > rmdir /S exercices + exercices, Are you sure ? Y -Et voilà. Pour être sûrs que le dossier a bien été supprimé, vérifions : +Et voilà. Pour être sure que le dossier a bien été supprimé, vérifiez : $ ls @@ -240,7 +243,7 @@ Windows : ### Sortir -C'est tout pour le moment ! Vous pouvez fermer maintenant fermer la ligne de commande. Faisons-le à la manière des bidouilleurs⋅euses. :) +C'est tout pour le moment ! Vous pouvez maintenant fermer la ligne de commande. Faisons-le à la manière des bidouilleurs⋅euses. :) $ exit @@ -266,12 +269,12 @@ Voici un résumé de quelques commandes utiles : | mkdir | mkdir | crée un nouveau dossier | **mkdir testdirectory** | | del | rm | supprime un dossier/fichier | **del c:\test\test.txt** | -Ce ne sont que quelques-unes des commandes que vous pouvez utiliser en ligne de commande, mais on aura pas besoin de plus aujourd'hui. +Ce ne sont que quelques-unes des commandes que vous pouvez utiliser dans votre ligne de commande. Cette liste est suffisante pour réaliser ce tutoriel. -Si vous êtes curieux⋅se, [ss64.com][1] contient une référence complète de toutes les commandes pour tous les systèmes d'exploitation. +Si vous êtes curieuse, [ss64.com][1] contient une référence complète de toutes les commandes pour tous les systèmes d'exploitation. [1]: http://ss64.com -## Vous êtes prêt·e·s ? +## Vous êtes prête ? Nous allons plonger dans Python ! diff --git a/fr/python_installation/README.md b/fr/python_installation/README.md index 735758407b6..47e71cbd43a 100755 --- a/fr/python_installation/README.md +++ b/fr/python_installation/README.md @@ -4,66 +4,10 @@ On est parti ! Tout d'abord, laissez-nous vous en dire un peu plus sur Python. Python est un langage de programmation très populaire qui peut être utilisé pour créer des sites web, des jeux, des logiciels scientifiques, des graphiques et bien d'autres choses encore. -Python a été créé à la fin des années 1980. Le rendre lisible par des humains, et non seulement des machines, était l'objectif principal des créateurs du langage. Par conséquent, il a l'air beaucoup plus simple à lire que d'autres langages de programmation. Ne vous fiez pas à son apparente simplicité de lecture et d'apprentissage : Python est un langage très puissant ! - +Python a été créé à la fin des années 1980. l'objectif principal des créateurs du langage était de rendre ce langage de programmation lisible aussi bien par des humains que par des machines. Par conséquent, il a l'air beaucoup plus simple à lire que d'autres langages de programmation. Cependant, ne vous fiez pas à son apparente simplicité de lecture et d'apprentissage : Python est un langage très puissant ! # Installation de Python -> Note : ce sous-chapitre est largement inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (http://django.carrots.pl/) - -Django est écrit en Python. Pour réaliser quelque chose en Django, il va nous falloir Python. Commençons par installer ce dernier ! Pour ce tutoriel, nous utilisons la version 3.4 de Python. Si vous avez une version antérieure, il va falloir la mettre à jour. - - -### Windows - -Vous pouvez télécharger Python pour Windows à partir de ce site : https://www.python.org/downloads/release/python-342/. Après avoir téléchargé le fichier ***.msi**, lancez le en double-cliquant sur son icône et suivez les instructions qui s'affichent à l'écran. Attention : il est important de se souvenir du chemin d'accès (le dossier) où vous avez installé Python. Vous en aurez besoin plus tard. - - -### Linux - -Il est très probable que Python soit déjà installé sur votre machine. Afin de vérifier qu'il est bien installé (et surtout quelle version vous avez), ouvrez une console et taper la commande suivante : - - $ python3 --version - Python 3.4.2 - -Si Python n'est pas installé ou que vous avez une version différente, vous pouvez l'installer en suivant les instructions suivantes : - - -#### Debian ou Ubuntu - -Tapez cette commande dans votre console : - - $ sudo apt-get install python3.4 - - -#### Fedora (<=21) - -Tapez cette commande dans votre console : - - $ sudo yum install python3.4 - - -#### Fedora (22+) - -Tapez cette commande dans votre console : - - $ sudo dnf install python3.4 - - -### OS X - -Vous devez aller sur le site https://www.python.org/downloads/release/python-342/ et télécharger l'installateur python : - -* Téléchargez le fichier *Mac OS X 64-bit/32-bit installer**DMG*, -* Double-cliquez pour l'ouvrir, -* Double-cliquez sur *Python.mpkg* pour lancer l'installateur. - -Vérifiez que l'installation s'est bien déroulée en ouvrant votre *Terminal* et en lançant la commande `python3` : - - $ python3 --version - Python 3.4.2 - - -* * * +> **Note** : Si vous avez suivi la partie installation du tutoriel, vous n'avez pas besoin d'installer Python à nouveau. Vous pouvez sauter cette partie et passer au chapitre suivant ! -Si vous avez des questions ou si quelque chose ne fonctionne pas et que vous ne savez pas quoi faire : demandez de l'aide à votre coach ! Il arrive quelques fois que les choses ne se déroulent pas comme prévu et il est alors préférable de demander à quelqu'un qui a plus d'expérience. \ No newline at end of file +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/fr/python_installation/images/add_python_to_windows_path.png b/fr/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/fr/python_installation/images/add_python_to_windows_path.png differ diff --git a/fr/python_installation/instructions.md b/fr/python_installation/instructions.md new file mode 100644 index 00000000000..c10c2d6b4c4 --- /dev/null +++ b/fr/python_installation/instructions.md @@ -0,0 +1,66 @@ +> Note : ce sous-chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django est écrit en Python. Pour réaliser quelque chose en Django, il va nous falloir Python. Commençons par installer ce dernier ! Pour ce tutoriel, nous utilisons la version 3.4 de Python. Si vous avez une version antérieure, il va falloir la mettre à jour. + +### Windows + +Vous pouvez télécharger Python pour Windows sur le site web https://www.python.org/downloads/release/python-343/. Après avoir téléchargé le fichier ***.msi**, lancez-le en double-cliquant sur son icône et suivez les instructions qui s'affichent à l'écran. Attention : il est important de se souvenir du chemin d'accès (le dossier) où vous avez installé Python. Vous en aurez besoin plus tard. + +Une chose à laquelle vous devez faire attention : dans le second écran de l'installateur intitulé "Customize", assurez-vous de bien dérouler l'écran jusqu'en bas et de choisir l'option "Ajouter python.exe au chemin", comme sur l'image ci dessous : + +![N'oubliez pas d'ajouter Python à votre chemin (path)](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Il est très probable que Python soit déjà installé sur votre machine. Afin de vérifier qu'il est bien installé (et surtout quelle version vous avez), ouvrez une console et tapez la commande suivante : + + $ python3 --version + Python 3.4.3 + + +Si Python n'est pas installé ou que vous avez une version différente, vous pouvez l'installer en suivant les instructions suivantes : + +#### Debian ou Ubuntu + +Tapez cette commande dans votre terminal : + + $ sudo apt-get install python3.4 + + +#### Fedora (jusqu'à la version 21) + +Tapez cette commande dans votre terminal : + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +Tapez cette commande dans votre terminal : + + $ sudo dnf install python3.4 + + +#### openSUSE + +Tapez cette commande dans votre terminal : + + $ sudo zypper install python3 + + +### OS X + +Vous devez aller sur le site https://www.python.org/downloads/release/python-343/ et télécharger l'installateur Python : + + * Téléchargez le fichier *Mac OS X 64-bit/32-bit installer*, + * Double-cliquez sur le fichier *python-3.4.3-macosx10.6.pkg* pour lancer l'installateur. + +Vérifiez que l'installation s'est bien déroulée en ouvrant votre *Terminal* et en lançant la commande `python3`: + + $ python3 --version + Python 3.4.3 + + +* * * + +Si vous avez des questions ou si quelque chose ne fonctionne pas et que vous ne savez pas quoi faire : demandez de l'aide à votre coach ! Il arrive parfois que les choses ne se déroulent pas comme prévu et il est alors préférable de demander à quelqu'un qui a plus d'expérience. diff --git a/fr/python_introduction/README.md b/fr/python_introduction/README.md index bebb676d77d..55b7401e2a8 100755 --- a/fr/python_introduction/README.md +++ b/fr/python_introduction/README.md @@ -1,6 +1,6 @@ # Introduction à Python -> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (http://django.carrots.pl/). +> Note : ce chapitre est en partie inspiré d'un autre tutoriel réalisé par les Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Allons écrire du code ! @@ -8,415 +8,471 @@ Allons écrire du code ! Pour commencer à jouer avec Python, nous avons besoin d'ouvrir une *ligne de commande* sur votre ordinateur. Normalement, vous savez déjà comment le faire -- vous l'avez appris dans le chapitre [Introduction à la ligne de commande][1]. - [1]: /intro_to_command_line/README.html + [1]: ../intro_to_command_line/README.md -Dès que vous êtes prêt⋅e, suivez les instructions suivantes. +Dès que vous êtes prête, suivez les instructions suivantes. -Nous voulons ouvrir une console Python. Il faut donc taper `python3` et appuyer sur Entrée. +Afin d'ouvrir une console Python, tapez `python` sous Windows ou `python3` sous Mac OS/Linux et appuyez sur `entrée`. - $ python3 - Python 3.4.2 (...) - Type "copyright", "credits" or "license" for more information. - >>> - +```python +$ python3 +Python 3.4.3 (...) +Type "help", "copyright", "credits" or "license" for more information. +>>> +``` ## Votre première commande Python ! -Après avoir lancé la commande Python, votre prompt s'est changé en `>>>`. Cela signifie que maintenant, les seules commandes que nous pouvons taper sont dans le langage Python. Vous n'avez pas besoin de taper `>>>` - Python fait ça pour vous. +Après avoir lancé la commande Python, votre prompt (ou invite de commandes) s'est changé en `>>>`. Cela signifie que maintenant, les seules commandes que nous pouvons taper sont dans le langage Python. Vous n'avez pas besoin de taper `>>>` - Python fait ça pour vous. -Quand vous voudrez sortir de la console Python, tapez `exit()` ou utilisez le raccourcit `Ctrl + Z` pour Windows ou `Ctrl + D` pour Mac/Linux. Après ça, vous ne verrez plus le `>>>`. +Quand vous voudrez sortir de la console Python, tapez `exit()` ou utilisez le raccourci `Ctrl + Z` pour Windows ou `Ctrl + D` pour Mac/Linux. Après ça, vous ne verrez plus le `>>>`. -Mais pour l'instant, nous ne voulons pas sortir de la console Python. Nous voulons en apprendre un peu plus à son sujet. Commençons par essayer quelque chose de simple. Par exemple, essayez de taper un peu de maths, comme `2 + 3` et appuyez sur Entrée. +Pour le moment, nous ne voulons pas quitter la console Python car nous nous aimerions mieux la connaitre. Démarrons avec quelque chose de vraiment simple. Par exemple, faisons un peu de math : tapez `2 + 3` et appuyez sur `entrée`. - >>> 2 + 3 - 5 - +```python +>>> 2 + 3 +5 +``` -Pas mal! Vous voyez comment la réponse est sortie ? Python sait faire des maths ! Vous pouvez essayer d'autres commandes comme : - `4 * 5` - `5 - 1` - `40 / 2` +Pas mal ! Vous voyez comment la réponse est sortie ? Python sait faire des maths ! Vous pouvez essayer d'autres commandes comme : - `4 * 5` - `5 - 1` - `40 / 2` Amusez-vous un peu avec ça, et revenez ici après :). -Comme vous pouvez le constater, Python est une très bonne calculette. Si vous vous demandez ce qu'il peut faire d'autre... +Comme vous pouvez le constater, Python est une très bonne calculette. Comme vous vous en doutez, il est aussi capable de faire autre chose ... ## Chaînes de caractères (Strings) -On essaye votre nom ? Tapez votre prénom entre guillemets comme ça : +Et si nous essayions avec votre nom ? Tapez votre prénom entre guillemets, comme cela : - >>> "Ola" - 'Ola' - +```python +>>> "Ola" +'Ola' +``` -Vous venez de créer votre première chaîne de caractères ! C'est une suite de caractères qui peut être traitée par un ordinateur. Une chaine de caractères doit toujours commencer et terminer par le même caractère. Ça peut être une guillement simple (`'`) ou une guillemet double (`"`). Ces guillements permettent à Python de savoir que tout ce qu'il y a à l'intérieur d'une chaîne de caractères. +Vous venez de créer votre première chaîne de caractères ! C'est une suite de caractères qui peut être traitée par un ordinateur. Une chaîne de caractères doit toujours commencer et terminer par le même caractère. Cela peut être un guillemet simple (`'`) ou un guillemet double (`"`), ça n'a pas d'importance. Cela permet à Python de savoir que tout ce qui se trouve à l'intérieur de ces guillemets est une chaîne de caractères. -On peut assembler des chaînes de caractères comme ça : +Il est possible d'assembler des chaînes de caractères comme ceci : - >>> "Salut " + "Ola" - 'Salut Ola' - +```python +>>> "Salut " + "Ola" +'Salut Ola' +``` Vous pouvez aussi multiplier une chaîne de caractères par un nombre : - >>> "Ola" * 3 - 'OlaOlaOla' - +```python +>>> "Ola" * 3 +'OlaOlaOla' +``` -Si vous avez besoin de mettre une apostrophe dans votre chaîne de caractères, vous avez deux manières. +Si vous avez besoin de mettre une apostrophe dans votre chaîne de caractères, vous avez deux possibilités. Vous pouvez utiliser des guillemets doubles : - >>> "J'aime la mousse au chocolat" - "J'aime la mousse au chocolat" - +```python +>>> "J'aime la mousse au chocolat" +"J'aime la mousse au chocolat" +``` -ou alors échapper l'apostrophe avec un antislash (``) : +ou échapper l’apostrophe avec une barre oblique inversée (un backslash, `\`) : - >>> 'J\'aime la mousse au chocolat' - "J'aime la mousse au chocolat" - +```python +>>> 'J\'aime la mousse au chocolat' +"J'aime la mousse au chocolat" +``` Pas mal, non ? Pour voir votre nom en majuscules, tapez juste : - >>> "Ola".upper() - 'OLA' - +```python +>>> "Ola".upper() +'OLA' +``` -Vous venez d'utiliser la **fonction** `upper` sur votre string ! Une fonction (comme `upper()`) est un ensemble d'instructions que Python va effectuer sur un objet donné (`"Ola"`) quand vous l'appelez. +Vous venez d'utiliser la **fonction** `upper` sur votre chaîne de caractères ! Une fonction (comme `upper()`) est un ensemble d'instructions que Python va effectuer sur un objet donné (`"Ola"`) lorsque vous l’appellerez. Si vous voulez savoir combien il y a de lettres dans votre nom, il y a une fonction pour ça ! - >>> len("Ola") - 3 - +```python +>>> len("Ola") +3 +``` -Vous vous demandez pourquoi des fois on appelle des fonctions avec un `.` après la chaîne de caractères (comme `"Ola".upper()`) et des fois on appelle d'abord la fonction et on met la chaîne de caractères après, entre parenthèses ? Et bien, dans certains cas, les fonctions appartiennent aux objets, comme `upper()`, qui ne peut être effectué que sur des chaînes de caractères. Dans ce cas, on appelle la fonction une **méthode**. D'autres fois, les fonctions n’appartiennent à rien de particulier et peuvent être utilisées sur différents types d'objets (c'est le cas de `len()`). C'est pour ça que nous passons `"Ola"` comme argument à la fonction `len`. +Vous avez peut-être remarqué que parfois, on appelle la fonction avec `.` en la plaçant après la chaîne de caractères (comme `"Ola".upper()`) alors qu'à d'autres moment, on appelle d'abord la fonction puis la chaîne de caractères entre parenthèses ? Il s'avère que dans certains cas, les fonctions appartiennent à des objets (c'est le cas de `upper()`) et qu'elles ne peuvent être appliquées qu'à des chaînes de caractères. Dans ce cas, on appelle la fonction une **méthode**. D'autres fois, les fonctions n’appartiennent à rien de particulier et peuvent être utilisées sur différents types d'objets (c'est le cas de `len()`). C'est pour ça que nous passons `"Ola"` comme argument à la fonction `len`. ### Résumé -OK, assez parlé de chaînes de caractères. Jusque-là, nous découvert : +OK, assez parlé de chaînes de caractères. Jusque-là, nous avons découvert : * **le prompt** - taper des commandes (du code) dans le prompt Python donne des réponses dans Python * **les nombres et les chaînes de caractères** - dans Python, les nombres sont utilisés pour faire des calculs, et les chaînes de caractères pour manipuler du texte -* **opérateurs** - comme + et *, ils combinent des valeurs pour en obtenir de nouvelles -* **les fonctions** - comme upper() et len(), que effectuent des actions sur les objets. +* **opérateurs** - comme + et * qui combinent des valeurs pour en obtenir de nouvelles +* **les fonctions** - comme upper() et len() qui effectuent des actions sur les objets. -Ce sont les bases de tous les langages de programmation que vous pouvez apprendre. Prêt⋅e pour quelque chose de plus compliqué ? Allons-y ! +Ce sont des bases présentes dans tous les langages de programmation que vous pouvez apprendre. Prête pour quelque chose de plus compliqué ? Allons-y ! ## Les erreurs -Essayons quelque chose de nouveau. Est-ce qu'on peut avoir la longueur d'un nombre de la même manière qu'on peut avoir la longueur de votre nom ? Tapez `len(304023)` et appuyez sur Entrée : +Essayons quelque chose de nouveau. Pouvons-nous obtenir la longueur d’un nombre de la même façon que celle de notre nom ? Tapez `len(304023)` et appuyez sur `entrée` : - >>> len(304023) - Traceback (most recent call last): - File "", line 1, in - TypeError: object of type 'int' has no len() - +```python +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` -On vient d'avoir notre première erreur ! Ça dit que les objets de type "int" (integers, ça veut dire nombre entier) n'ont pas de longueur. Qu'est-ce qu'ont peut faire, du coup ? Peut-être qu'on peut écrire notre nombre comme une chaîne de caractères. Les chaînes de caractères ont une taille, non ? +Nous venons d'obtenir notre première erreur ! Elle nous dit que les objets de type "int" (integers, ce qui signifie nombre entier) n'ont pas de longueur. Que pouvons-nous faire, du coup ? Pourquoi ne pas essayer d'écrire notre nombre comme une chaîne de caractères ? Après tout, les chaînes de caractères ont bien une taille, non ? - >>> len(str(304023)) - 6 - +```python +>>> len(str(304023)) +6 +``` -Ça a marché ! On a utilisé la fonction `str` à l'intérieur de la fonction `len`. La fonction `str()` convertit n'importe quoi en chaîne de caractères. +Ça a marché ! Nous avons utilisé la fonction `str` à l'intérieur de la fonction `len`. La fonction `str()` convertit n'importe quoi en chaîne de caractères. * La fonction `str` convertit des choses en **chaînes de caractères** * La fonction `int` convertit des choses en **entiers** -> Important : on peut convertir des nombres en texte, mais on ne peut pas toujours convertir du texte en nombres. Parce que, bon, ça vaudrait quoi `int('salut')` ? +> Important : il est possible de convertir des nombres en texte, mais il n'est pas toujours possible de convertir du texte en nombres. Parce que, bon, ça vaudrait quoi `int('salut')` ? ## Variables -Il y a un concept super important en programmation : les variables. Une variable, ce n'est jamais rien qu'un nom pour quelque chose qu'on peut utiliser plus tard. Les programmeurs⋅euses utilisent des variables pour stocker des données, rendre leur code plus lisible, et pour ne pas avoir à se rappeler de ce que sont les choses. +Il existe un concept super important en programmation : les variables. Une variable, c'est juste un nom pour quelque chose que l'on aimerait utiliser plus tard. Les programmeurs⋅euses utilisent des variables pour stocker des données, rendre leur code plus lisible, et pour ne pas avoir à se rappeler de ce que sont les choses. -Disons qu'on souhaite créer une variable appelée `name` : +Disons que nous aimerions créer une variable appelée `name` : - >>> name = "Ola" - +```python +>>> name = "Ola" +``` -Vous voyez ? C'est tout bête ! C'est simplement : name est égal à Ola. +Vous voyez ? C'est tout bête ! C'est simplement : name vaut Ola. -Vous avez peut-être remarqué que contrairement à tout à l'heure, le programme ne renvoie rien. Du coup, comment faire pour vérifier que la variable existe vraiment ? Tapez simplement `name` et appuyez sur Entrée : +Vous avez peut-être remarqué que contrairement à tout à l'heure, le programme ne renvoie rien. Du coup, comment faire pour vérifier que la variable existe vraiment ? Tapez simplement `name` et appuyez sur `entrée` : - >>> name - 'Ola' - +```python +>>> name +'Ola' +``` -Youpi ! Votre première variable :)! Vous pouvez toujours changer ce à quoi elle fait référence : +Youpi ! Votre première variable :) ! Vous pouvez toujours changer ce à quoi elle fait référence : - >>> name = "Sonja" - >>> name - 'Sonja' - +```python +>>> name = "Sonja" +>>> name +'Sonja' +``` Vous pouvez aussi l'utiliser dans des fonctions : - >>> len(name) - 5 - +```python +>>> len(name) +5 +``` Génial, non ? Et bien sûr, les variables peuvent être n'importe quoi, y compris des nombres ! Essayez ça : - >>> a = 4 - >>> b = 6 - >>> a * b - 24 - +```python +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` -Mais qu'est-ce qui se passe si on utilise le mauvais nombre ? Vous sauriez deviner ? Essayons ! +Mais que se passe-t-il si nous utilisons le mauvais nom ? Essayez de deviner ! C'est parti ! - >>> name = "Maria" - >>> names - Traceback (most recent call last): - File "", line 1, in - NameError: name 'names' is not defined - +```python +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` -Une erreur ! Comme vous pouvez le voir, Python a différents types d'erreurs, et celle-ci est une **NameError**. Python vous donne cette erreur quand vous essayez d'utiliser une variable qui n'a pas encore été définie. Si vous rencontrez cette erreur par la suite, vérifier dans votre code que vous n'avez pas fait une faute de frappe dans une variable. +Une erreur ! Comme vous pouvez le voir, Python a différents types d'erreurs, et celle-ci est une **NameError**. Python vous donne cette erreur quand vous essayez d'utiliser une variable qui n'a pas encore été définie. Si vous rencontrez cette erreur par la suite, vérifiez dans votre code que vous n'avez pas fait une faute de frappe dans une variable. -Jouez un peu avez ça, et voyez ce que vous arrivez à faire ! +Jouez un peu avec les variables et essayez de voir ce que vous pouvez faire ! ## La fonction print Essayez ça : - >>> name = 'Maria' - >>> name - 'Maria' - >>> print(name) - Maria - +```python +>>> name = 'Maria' +>>> name +'Maria' +>>> print(name) +Maria +``` -Quand vous tapez `name`, l'interpréteur Python répond avec la *représentation* de la chaîne de caractères associée à la variable "name", c'est à dire les lettres M-a-r-i-a, entourées par des guillemets simples. Quand vous dites `print(name)`, Python va "imprimer" le contenu de la variable sur l'écran, sans les guillemets, ce qui est plus joli. +Quand vous tapez `name`, l'interpréteur Python répond avec la *représentation* de la chaîne de caractères associée à la variable "name", c'est à dire les lettres M-a-r-i-a, entourées par des guillemets simples. Quand vous dites `print(name)`, Python va "imprimer" le contenu de la variable sur l'écran, sans les guillemets, ce qui est plus sympa. -Comme on le verra plus tard, `print()` est aussi utile quand on veut afficher des choses depuis l'intérieur de fonctions, ou quand on veut afficher des choses sur plusieurs lignes. +Comme nous le verrons plus tard, `print()` est aussi utile lorsque l'on veut afficher des choses depuis l'intérieur de fonctions ou des choses sur plusieurs lignes. ## Les listes -À part les chaînes de caractères et les entiers, Python a tout un tas d'autres types d'objets. On va maintenant vous présenter un type appelé **listes**. Les listes sont exactement ce que vous pensez qu'elles sont : ce sont des objets qui sont des listes d'autres objets :) +En plus des chaînes de caractères et des entiers, Python possède tout un tas d'autres types d'objets. Nous allons maintenant vous présenter un type appelé **listes**. Les listes sont exactement ce que vous pensez qu’elles sont : des objets qui sont des listes d’autres objets :) Allez-y, créez une liste : - >>> [] - [] - +```python +>>> [] +[] +``` -Oui, cette liste est vide. Pas très utile, hey ? Créons maintenant une liste de numéro de loterie. Nous ne voulons pas nous répéter tout le donc, donc mettons la dans une variable : +Oui, cette liste est vide. Pas très utile, non ? Créons maintenant une liste de numéros de loterie. Nous ne voulons pas nous répéter tout le temps, donc mettons-la dans une variable : - >>> lottery = [3, 42, 12, 19, 30, 59] - +```python +>>> lottery = [3, 42, 12, 19, 30, 59] +``` -Voilà, nous avons une liste ! Qu'est ce qu'on peut faire avec ? Voyons combien de numéros de loterie il y a dans cette liste. Une idée de la fonction pour faire ça ? On la connait déjà ! +Voilà, nous avons une liste ! Qu'est ce que nous pourrions en faire ? Commençons par voir combien de numéros de loterie il y a dans cette liste. Une idée de la fonction pour faire ça ? Vous la connaissez déjà ! - >>> len(lottery) - 6 - +```python +>>> len(lottery) +6 +``` Hé oui ! `len()` peut aussi vous donner le nombre d'objets dans une liste. Pratique, non ? Peut-être qu'on peut aussi la trier : - >>> lottery.sort() - +```python +>>> lottery.sort() +``` -Ça ne renvoie rien, ça a juste changé l'ordre dans lequel les nombres apparaissent dans la liste. Affichons-la encore pour voir ce qu'il s'est passé : +Ça ne renvoie rien : cette fonction a juste changé l'ordre dans lequel les nombres apparaissent dans la liste. Affichons-la encore pour voir ce qu'il s'est passé : - >>> print(lottery) - [3, 12, 19, 30, 42, 59] - +```python +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` -Comme vous pouvez le voir, les nombres de la liste sont maintenant triés sur plus petit au plus grand. Bravo ! +Comme vous pouvez le voir, les nombres de la liste sont maintenant triés du plus petit au plus grand. Bravo ! -Est-ce qu'on peut inverser l'ordre ? Faisons ça ! +Pouvons-nous inverser cet ordre ? Essayons! - >>> lottery.reverse() - >>> print(lottery) - [59, 42, 30, 19, 12, 3] - +```python +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` Facile, non ? Si vous voulez ajouter quelque chose à la liste, vous pouvez le faire en tapant cette commande : - >>> lottery.append(199) - >>> print(lottery) - [59, 42, 30, 19, 12, 3, 199] - +```python +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Si vous ne souhaitez afficher que le premier nombre, vous pouvez le faire en utilisant des **indices**. Un indice est un nombre qui dit où l'élément apparait dans la liste. Les programmeurs⋅euses préfèrent compter à partir de 0 : le premier objet dans notre liste a donc pour indice 0, le suivant 1 et ainsi de suite. Essayez ça : + +```python +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +Comme vous pouvez le voir, nous pouvons accéder à différents objets dans la liste en utilisant le nom de la liste suivi de l'indice de l'objet entre crochets. -Si vous voulez ne montrer que le premier nombre, vous pouvez le faire en utilisant des **indices**. Un indice est un nombre qui dit où l'élément apparait dans la liste. Les ordinateurs comptent à partir de 0, donc le premier objet de la liste est à l'indice 0, le suivant à l'indice 1, et ainsi de suite. Essayez ça : +Pour supprimer un objet de votre liste, vous aurez besoin de son **indice** ainsi que de la commande `pop()`. Essayons l'exemple suivant : supprimez le premier numéro de votre liste. - >>> print(lottery[0]) - 59 - >>> print(lottery[1]) - 42 - +```python +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` -Comme vous pouvez le voir, on peut accéder à différents objets dans la liste en utilisant le nom de la liste suivi de l'indice de l'objet entre crochets. +Ça marche à merveille ! -Pour voir, essayez d'autres indices : 6, 7, 1000, -1, -6 ou -1000. Est-ce que vous arrivez à prévoir le résultat avant de taper la commande ? Est-ce que les résultats vous paraissent logiques ? +Jouons encore un peu avec les indices ! Essayez-en des nouveaux : 6, 7, 1000, -1, -6 ou -1000. Est-ce que vous arrivez à prévoir le résultat avant de taper la commande ? Est-ce que ces résultats vous paraissent logiques ? Vous pouvez trouver une liste complète des méthodes disponibles pour les listes dans ce chapitre de la documentation de Python : https://docs.python.org/3/tutorial/datastructures.html ## Dictionnaires -Un dictionnaire est un peu comme une liste, mais on accède aux valeurs en utilisant une clef plutôt qu'un indice. Une clef peut être n'importe quelle chaîne de caractère ou n'importe quel nombre. La syntaxe pour définir un dictionnaire vide est : +Un dictionnaire est un peu comme une liste. Cependant, nous utilisons des clefs plutôt que des indices pour accéder aux valeurs. Une clef peut être n'importe quelle chaîne de caractère ou n'importe quel nombre. La syntaxe pour définir un dictionnaire vide est la suivante : - >>> {} - {} - +```python +>>> {} +{} +``` C'est comme ça que l'on crée un dictionnaire vide. Hourra ! -Maintenant, essayer d'écrire la commande suivante (et mettez vos propres informations) : +Maintenant, essayez d'écrire la commande suivante (et essayez aussi de changer le contenu) : - >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} - +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` Avec cette commande, vous venez de créer une variable nommée `participant` avec trois paires clef-valeur : -* La clef `name` pointe vers la valeur `'Ola'` (un object `chaîne de caractère`), -* `country` pointe vers `'Poland'` (une autre ` chaîne de caractères`), +* La clef `name` pointe vers la valeur `'Ola'` (un objet `chaîne de caractères`), +* `country` pointe vers `'Poland'` (une autre `chaîne de caractères`), * et `favorite_numbers` pointe vers `[7, 42, 92]` (une `liste` contenant trois nombres). Vous pouvez vérifier le contenu de chaque clef avec cette syntaxe : - >>> print(participant['name']) - Ola - +```python +>>> print(participant['name']) +Ola +``` -Vous voyez, c'est un peu comme une liste. Sauf que l'on a pas besoin de se souvenir de l'indice, juste du nom. +Vous voyez, c'est un peu comme une liste; Cependant, vous n'avez pas besoin de vous souvenir de l'indice, juste de son nom. -Qu'est ce que se passe quand on demande à Python la valeur correspondant à une clef qui n'existe pas ? Pouvez vous le deviner ? Essayons voir ! +Que se passe-t-il lorsque nous demandons à Python la valeur correspondant à une clef qui n'existe pas ? Pouvez-vous le deviner ? Essayons voir ! - >>> participant['age'] - Traceback (most recent call last): - File "", line 1, in - KeyError: 'age' - +```python +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` -Oh, une autre erreur ! Celle-ci est une **KeyError**. Python se rend utile et nous dit que la clef `'age'` n'existe pas dans le dictionnaire. +Oh, une autre erreur ! Celle-ci est une **KeyError**. Python nous donne un coup de main et nous dit que la clef `'age'` n'existe pas dans le dictionnaire. -Quand faut-il utiliser un dictionnaire ou une liste ? C'est une bonne question. Réfléchissez-y un instant avant de regarder la réponse à la ligne suivante. +Vous vous demandez peut-être quand est-ce qu'il faut utiliser un dictionnaire ou une liste ? C'est une bonne question. Réfléchissez-y un instant avant de regarder la réponse à la ligne suivante. * Vous avez besoin d'une suite ordonnée d'éléments ? Utilisez une liste. * Vous avez besoin d'associer des valeurs à des clefs, de manière à pouvoir les retrouver efficacement (par clef) par la suite ? Utilisez un dictionnaire. Comme les listes, les dictionnaires sont *mutables*, ce qui signifie qu'ils peuvent être modifiés après leur création. Vous pouvez ajouter de nouvelles paires clé/valeur au dictionnaire après sa création, comme ceci : - >>> participant['favorite_language'] = 'Python' - +```python +>>> participant['favorite_language'] = 'Python' +``` -Comme pour les listes, la fonction `len()` permet d'obtenir le nombre de paires clef-valeur du dictionnaire. Essayez, tapez la commande suivante : +Comme pour les listes, la fonction `len()` permet d'obtenir le nombre de paires clef-valeur du dictionnaire. Essayez et tapez la commande suivante : - >>> len(participant) - 4 - +```python +>>> len(participant) +4 +``` -J'espère que c'est compréhensible pour l'instant :) Prêt⋅e pour s'amuser un peu plus avec les dictionnaires ? Passez à la ligne suivante pour voir des trucs géniaux. +J'espère que c'est compréhensible pour l'instant :) Prête pour s'amuser un peu plus avec les dictionnaires ? Passez à la ligne suivante pour voir des trucs géniaux. -Vous pouvez utiliser la commande `del` pour supprimer un élément du dictionnaire. Par exemple, si vous voulez supprimer l'entrée correspondant à la clé `« favorite_numbers »`, tapez la commande suivante : +Vous pouvez utiliser la commande `pop()` pour supprimer un élément du dictionnaire. Par exemple, si vous voulez supprimer l'entrée correspondant à la clé `« favorite_numbers »`, tapez la commande suivante : - >>> del participant['favorite_numbers'] - >>> participant - {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} - +```python +>>> participant.pop('favorite_numbers') +>>> participant +{'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} +``` -Comme vous pouvez le voir dans la sortie, la paire clef-valeur correspondant à "favorite_numbers" a été supprimée. +Comme vous pouvez le voir dans votre console, la paire clef-valeur correspondant à "favorite_numbers" a été supprimée. -En outre, vous pouvez changer la valeur associée à une clef déjà créée dans le dictionnaire. Tapez : +De même, vous pouvez changer la valeur associée à une clef déjà créée dans le dictionnaire. Tapez ceci : - >>> participant['country'] = 'Germany' - >>> participant - {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} - +```python +>>> participant['country'] = 'Germany' +>>> participant +{'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} +``` -Voilà, la valeur de la clé `"country"` a été modifiée de `"Poland"` à `"Germany"`. :) Ce n'est pas cool, ça ? Yep ! Un autre truc génial d'appris ! +Voilà, la valeur de la clé `"country"` a été modifiée de `"Poland"` à `"Germany"`. :) Ce n'est pas cool ça ? Yep ! Un autre truc génial d'appris ! ### Résumé -C'est super ! Vous savez plein de trucs sur la programmation maintenant. Dans cette partie, vous avez appris : +C'est super ! Vous savez plein de choses sur la programmation maintenant. Dans cette partie, vous avez appris : -* **les erreurs** - vous savez maintenant comment lire et comprendre les erreurs qui apparaissent quand Python ne comprend pas une de vos commandes +* **les erreurs** - vous savez maintenant comment lire et comprendre les erreurs qui apparaissent quand Python ne comprend pas l'une de vos commandes * **les variables** - des noms pour les objets qui vous permettent de coder plus facilement et de rendre votre code plus lisible * **les listes** - des listes d'objets stockés dans un ordre particulier * **les dictionnaires** - des objets stockés sous forme de paires clef-valeur -Embalé⋅e pour la partie suivant ? :) +On continue ? :) ## Comparer des choses -Comparer des choses, c'est vachement important en programmation. Quelle est la chose la plus facile à comparer ? Les nombres ! Voyons voir comment ça marche : +Comparer des choses est très important en programmation. Quelle serait la chose la plus facile à comparer ? Les nombres, bien sûr ! Voyons voir comment ça marche : - >>> 5 > 2 - True - >>> 3 < 1 - False - >>> 5 > 2 * 2 - True - >>> 1 == 1 - True - +```python +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` -On a donné à Python des nombres à comparer. Comme vous pouvez voir, Python peut comparer des nombres, mais aussi des résultats de méthodes. Pas mal, non ? +Nous avons donné à Python des nombres à comparer. Comme vous pouvez le voir, Python peut comparer des nombres, mais aussi des résultats de méthodes. Pas mal, non ? -Vous vous demander pourquoi on a mis deux signes `==` côte à côte pour savoir si deux nombres sont égaux ? On utilise déjà `=` pour assigner des valeurs aux variables. Du coup, il faut toujours, oui **toujours**, mettre deux `==` si vous voulez savoir si deux choses sont égales. +Vous vous demandez probablement pourquoi nous avons mis deux signes `==` côte à côte pour savoir si deux nombres étaient égaux ? On utilise déjà `=` pour assigner des valeurs aux variables. Du coup, il faut toujours, oui **toujours**, mettre deux `==` si vous voulez savoir si deux choses sont égales. Nous pouvons aussi dire que certaines choses ne sont pas égales à d'autres Pour cela, nous utilisons le symbole `!=`, comme illustré dans l'exemple ci-dessus. Donnons encore un peu de boulot à Python : - >>> 6 >= 12 / 2 - True - >>> 3 <= 2 - False - +```python +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` `>` et `<` sont faciles, mais qu'est ce que `>=` et `<=` veulent dire ? Ils se lisent comment ça : -* x `>` u veut dire : x est plus grand que y -* x `<` y veut dire : x est plus petit que y -* x `<=` y veut dire : x est plus petit ou égal à y -* x `>=` y veut dire : x est plus grand ou égal à y +* x `>` y veut dire : x est plus grand que y +* x `<` y signifie: x est inférieure à y +* x `<=` y signifie: x est inférieur ou égal à y +* x `>=` y veut dire : x est supérieur ou égal à y Super ! Un dernier ? Essayez ça : - >>> 6 > 2 and 2 < 3 - True - >>> 3 > 2 and 2 < 1 - False - >>> 3 > 2 or 2 < 1 - True - +```python +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` -Vous pouvez donner à Python autant de nombres à comparer, et il vous donnera la réponse. Plutôt malin, non ? +Vous pouvez donner à Python autant de nombres à comparer que vous le souhaitez et il vous donnera une réponse. Plutôt malin, non ? -* **et** - si vous utilisez l'opérateur `and`, les deux comparaisons doivent être True (vraies) pour que la commande tout entier soit True -* **ou** - si vous utilisez l'opérateur `or`, il suffit qu'une des deux comparaisons soit True (vraie) pour que la commande tout entier soit True +* **and** - si vous utilisez l'opérateur `and` (et), les deux comparaisons doivent être True (vraies) pour que la commande toute entière soit True +* **or** - si vous utilisez l'opérateur `or` (ou), il suffit qu'une des deux comparaisons soit True (vraie) pour que la commande toute entière soit True Vous connaissez l'expression "on ne compare pas les choux et les carottes" ? Essayons l'équivalent en Python : - >>> 1 > 'django' - Traceback (most recent call last): - File "", line 1, in - TypeError: unorderable types: int() > str() - +```python +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: unorderable types: int() > str() +``` -Voilà, Python n'est pas capable de comparer un nombre (`int`) et une chaîne de caractères (`str`). À la place, il nous montre une **TypeError** et nous dit que les deux types ne peuvent pas être comparés. +Comme vous le voyez, Python n'est pas capable de comparer un nombre (`int`) et une chaîne de caractères (`str`). À la place, il nous montre une **TypeError** et nous dit que les deux types ne peuvent pas être comparés. ## Booléen -Au passage, vous venez de découvrir un nouveau type d'objets en Python. On l'appelle **Booléen**, et c'est probablement le type le plus simple que existe. +Au passage, vous venez de découvrir un nouveau type d'objets en Python. On l'appelle **Booléen**. C'est probablement le type le plus simple qui existe. -Il n'y a que deux objets Booléens : True et False +Il n'y a que deux objets Booléens : - True (vrai) - False (faux) -Pour que Python le comprenne, il faut toujours l'écrire True (première lettre en majuscule, les autres en minuscule). **true, TRUE, tRUE ne marchent pas -- seul True est correct.** (Et c'est aussi vrai pour False.) +Pour que Python comprenne qu'il s'agit d'un Boléen, il faut toujours l'écrire True (première lettre en majuscule, les autres en minuscule). **true, TRUE, tRUE ne marchent pas -- seul True est correct.** (Et c'est aussi vrai pour False.) -Les Booléens aussi peuvent être des variables ! Voyez : +Les Booléens aussi peuvent être des variables ! regardez : - >>> a = True - >>> a - True - +```python +>>> a = True +>>> a +True +``` Vous pouvez aussi faire ça : - >>> a = 2 > 5 - >>> a - False - +```python +>>> a = 2 > 5 +>>> a +False +``` Entrainez-vous et amusez-vous avec les Booleéns en essayant de lancer les commandes suivantes : @@ -425,268 +481,311 @@ Entrainez-vous et amusez-vous avec les Booleéns en essayant de lancer les comma * `True or 1 == 1` * `1 != 2` -Bravo ! Les Booléens sont une des fonctionnalités les plus cools en programmation, et vous venez d'apprendre comment les utiliser ! +Bravo ! Les Booléens sont l'une des fonctionnalités les plus cools en programmation et vous venez juste d'apprendre comment les utiliser ! # Sauvegardez tout ça ! -Pour l'instant, on a écrit tout notre code python directement dans l'interpréteur, ce qui nous limite à une ligne à la fois. Les programmes normaux sont sauvegardés dans des fichiers et sont exécutés par **l'interpréteur** ou le **compilateur** de notre langage de programmation. Jusque-là, c'était ligne par ligne dans **l'interpréteur**. On va avoir besoin de plus qu'une ligne de code pour la suite, alors on va avoir besoin de : +Pour l'instant, nous avons écrit tout notre code Python directement dans l'interpréteur, ce qui nous limite à une ligne à la fois. Les programmes normaux sont sauvegardés dans des fichiers et sont exécutés par **l'interpréteur** ou le **compilateur** de notre langage de programmation. Jusque-là, c'était ligne par ligne dans **l'interpréteur**. Nous allons avoir besoin de bien plus qu'une ligne de code par la suite alors, vous allez rapidement avoir besoin de : * Quitter l'interpréteur Python * Ouvrir l'éditeur de code de notre choix -* Sauvegarder du code dans un nouveau fichier python +* Sauvegarder du code dans un nouveau fichier Python * Le lancer ! -Pour quitter l'interpréteur Python que nous sommes en train d'utiliser, il suffit de taper la fonction ~ ~ ~ exit() ~ ~ ~ : +Pour quitter l'interpréteur Python que nous sommes en train d'utiliser, il suffit de taper la fonction `exit()` : + +```python +>>> exit() +$ +``` - >>> exit() - $ - +Cela vous ramènera dans la ligne de commande de votre système d'exploitation. -Ça vous ramènera dans la ligne de commande du système d'exploitation. +Tout à l'heure, dans la section [L'éditeur de texte][2], nous avons choisi un éditeur de texte. Ouvrez-le et écrivez le code suivant dans un nouveau fichier : -Tout à l'heure, dans la section [L'éditeur de texte][2], nous avons choisi un éditeur de texte. Nous avons maintenant besoin de l'ouvrir et d'écrire du code dans un nouveau fichier : + [2]: ../code_editor/README.md - [2]: code_editor/README.md +```python +print('Hello, Django girls!') +``` - print('Hello, Django girls!') - +> **Note :** Vous avez probablement constaté que votre code se pare de multiples couleurs : ça fait partie des choses qui rendent la programmation dans un éditeur de texte bien plus agréable. Votre console Python n'avait pas cette fonctionnalité : tout était donc de la même couleur. Dans votre éditeur de texte, vous devriez voir que la fonction `print` possède différentes couleurs. C'est ce qu'on appelle « la coloration syntaxique ». C'est une fonctionnalité très utile lorsque l'on programme. La couleur des choses va vous permettre de détecter des problèmes : une chaîne de caractères non fermée, une faute dans un mot (ce sera par exemple le cas dans la fonction `def` que vous verrez un peu plus bas). C'est ce genre de fonctionnalités qui font que vous aimerez rapidement programmer avec un éditeur de code :) -Alors forcément, vous avez maintenant pas mal de connaissances en python, donc n'hésitez pas à écrire du code avec ce que vous avez appris aujourd'hui. +Vous avez maintenant pas mal de connaissances en Python : n'hésitez pas à écrire du code avec ce que vous avez appris aujourd'hui ! -Sauvegardons maintenant le fichier en lui donnant un nom descriptif. On n'a qu'à l'appeler **python_intro.py** et le sauvegarder sur le bureau. On peut lui n'importe quel nom, tant qu'on s'assure que le nom de fichier se termine par **.py**, ça permet à l'ordinateur de savoir que c'est un **fichier exécutable python** et que Python peut l'exécuter. +Sauvegardons maintenant le fichier en lui donnant un nom descriptif. On n'a qu'à l'appeler **python_intro.py** et le sauvegarder sur le bureau. Vous pouvez donner le nom que vous souhaitez à ce fichier mais il est important qu'il se termine par **.py**. L'extension **.py** permet de signaler à votre système d'exploitation que ce fichier est un **fichier exécutable Python** et que Python peut le lancer. -Une fois que le fichier est sauvegardé, on peut le lancer ! En utilisant les compétences que vous avez apprises dans la section sur la ligne de commande, utilisez le terminal pour **changer le dossier courant** vers le bureau. +Une fois que le fichier est sauvegardé, vous pouvez le lancer ! En utilisant les compétences que vous avez apprises dans la section sur la ligne de commande, utilisez le terminal pour **changer le dossier courant** vers le bureau. Sur Mac, ça ressemblera à : - cd /Users//Desktop - + $ cd /Users//Desktop + Sous Linux, comme ça (il se peut que le mot Bureau soit dans une autre langue) : - cd /home//Bureau - + $ cd /home//Desktop + Et sous Windows, ce sera comme ça : - cd C:\Users\\Desktop - + > cd C:\Users\\Desktop + -Si vous êtes bloqué⋅e, n'hésitez pas à appeler à l'aide. +Si vous êtes bloquée, n'hésitez pas à appeler à l'aide. -Une fois que c'est bon, utilisez Python pour exécuter le fichier comme ça : +Maintenant, utilisez Python pour exécuter le code contenu dans votre fichier : $ python3 python_intro.py Hello, Django girls! - -Okay ! Vous venez de lancer votre premier programme python à partir d'un fichier. Vous vous sentez génial⋅e ? + +Super ! Vous venez de lancer votre premier programme python à partir d'un fichier. Cool non ? Et maintenant, passons à un autre outil essentiel de la programmation : ## If...elif...else -Quand on code, il y a plein choses qui ne doivent être exécutées que dans certaines conditions. Pour ça, Python a quelque chose qui s'appelle le l'instruction **if**. +Quand on code, il y a plein choses qui ne doivent être exécutées que dans certaines conditions. Pour cela, Python possède ce qu'on appelle l'instruction **if** (si). -Remplacer le code dans votre fichier **python_intro.py** par ça : +Remplacez le code dans votre fichier **python_intro.py** avec ceci : - if 3 > 2: - +```python +if 3 > 2: +``` -Si on sauvegardait ça et qu'on le lançait tel quel, on aurait l'erreur suivante : +Si nous sauvegardons ce fichier et que nous le lançons, nous obtiendrons l'erreur suivante : - $ python3 python_intro.py - File "python_intro.py", line 2 - ^ - SyntaxError: unexpected EOF while parsing - +```python +$ python3 python_intro.py +File "python_intro.py", line 2 + ^ +SyntaxError: unexpected EOF while parsing +``` -Python s'attend à se qu'on lui donne des instructions sur ce qu'il faut exécuter quand la condition `3 > 2` est vraie (ou plutôt, `True`). Faisons-lui afficher "Ça marche !". Remplacez le code dans **python_intro.py** par ça : +Python s'attend à ce que nous lui donnions des instructions sur ce qu'il faut exécuter lorsque la condition `3 > 2` est vraie (ou plutôt, `True`). Essayons de lui faire afficher "Ça marche !". Remplacez le code dans **python_intro.py** par ceci : - if 3 > 2: - print('Ça marche !') - +```python +if 3 > 2: + print('It works!') +``` -Vous remarquez comme on a décalé la seconde ligne de code de 4 espaces sur la gauche ? On appelle ça indenter. On a besoin de le faire pour que Python sache quel code lancer si la condition est vraie. Un seul espace suffirait, mais à peu près tous⋅tes les programmeur⋅se⋅s Python pensent que 4, c'est plus clair. Une tabulation compte aussi comme 4 espaces. +Avez-vous remarqué que nous avions décalé la ligne suivante de quatre espaces ? C'est ce que l'on appelle indenter. Nous avons besoin d'indenter pour que Python sache quel code exécuter si le résultat est vrai. Un seul espace suffirait, mais à peu près tous⋅tes les programmeurs⋅euses Python pensent que 4 espaces sont plus clairs. Une seule `tab` (tabulation) compte également comme 4 espaces. Sauvegardez le fichier et relancez le : $ python3 python_intro.py Ça marche ! - -### Et sinon ? -Dans le dernier exemple, le code était exécuté quand la condition est vraie. Mais Python a aussi des instructions `elif` et `else` : +### Et que se passe-t-il si une condition n’est pas vraie ? - if 5 > 2: - print('5 est effectivement plus grand que 2') - else: - print("5 n'est pas plus grand que 2") - +Dans les exemples précédents, le code était exécuté quand la condition était vraie. Cependant, Python possède aussi des instructions `elif` (sinon si) et `else` (sinon) : -Quand on lance ça, ça affiche : +```python +if 5 > 2: + print('5 est effectivement plus grand que 2') +else: + print("5 n'est pas plus grand que 2") +``` + +Lorsque vous exécuterez le code, ceci s'affichera : $ python3 python_intro.py 5 est effectivement plus grand que 2 - -Et si 2 était plus grand que 5, la seconde commande serait exécutée. Facile, non ? Voyons voir comment `elif` marche : - name = 'Sonja' - if name == 'Ola': - print('Hey Ola!') - elif name == 'Sonja': - print('Hey Sonja!') - else: - print('Hey anonymous!') - +Et si 2 était plus grand que 5, la seconde commande serait exécutée. Facile, non ? Voyons comment `elif` fonctionne : + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` -On l'exécute : +Exécutons le code : $ python3 python_intro.py Hey Sonja! - -Vous voyez ce qu'il s'est passé ? + +Que s'est-il passé ? `elif` vous permet d'ajouter d'autres conditions à exécuter si les précédentes échouent. + +Vous pouvez ajouter autant de `elif` que vous le souhaitez après le premier `if`. Voici un exemple : + +```python +volume = 57 +if volume < 20: + print("C'est plutôt calme.") +elif 20 <= volume < 40: + print("Une jolie musique de fond.") +elif 40 <= volume < 60: + print("Parfait, je peux entendre tous les détails du morceau.") +elif 60 <= volume < 80: + print("Parfait pour faire la fête !") +elif 80 <= volume < 100: + print("Un peu trop fort !") +else: + print("Au secours ! Mes oreilles ! :(") +``` + +Python va tester les différentes conditions puis il affichera ceci : + + $ python3 python_intro.py + Parfait, je peux entendre tous les détails du morceau. + ### Résumé Avec ces trois derniers exercices, vous avez appris : -* **comparer des choses** - en Python, vous pouvez comparer des choses avec `>`, `>=`, `==`, `<=`, `<` et avec les opérateurs `and`, `or` +* **Comment comparer des choses** - en Python, vous pouvez comparer des choses avec `>`, `>=`, `==`, `<=`, `<` et avec les opérateurs `and`, `or` * **Booléen** - un type d'objet qui n'a que deux valeurs possibles : `True` et `False` -* **Sauvegarder des fichiers** - stocker votre code dans des fichiers pour pouvoir écrire des programmes plus longs. +* **Comment sauvegarder des fichiers** - stocker votre code dans des fichiers pour pouvoir écrire des programmes plus longs. * **if...elif...else** - des instructions que vous permettent de n'exécuter du code que dans certaines conditions. Il est temps d'attaquer la dernière partie de ce chapitre ! ## Vos propres fonctions ! -Vous vous souvenez des fonctions comme `len()` que vous pouvez exécuter en Python ? Et bien, bonne nouvelle, vous allez apprendre comment écrire vos propres fonctions ! +Vous vous souvenez des fonctions comme `len()` que vous pouvez exécuter en Python ? Et bien, bonne nouvelle : vous allez apprendre à écrire vos propres fonctions! -Une fonction est un ensemble d'instructions que Python va exécuter. Chaque fonction en Python commence par le mot-clef `def`. On lui donne un nom, et elle peut avoir des paramètres. On va commencer par quelque chose de facile. Remplacer le code de **python_intro.py** avec ça : +Une fonction est un ensemble d'instructions que Python va exécuter. Chaque fonction en Python commence par le mot-clef `def`. On lui donne un nom, et elle peut avoir des paramètres. Commençons par quelque chose de facile. Remplacer le code de **python_intro.py** par ceci : - def hi(): - print('Hi there!') - print('How are you?') - - hi() - +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` Voilà, notre première fonction est prête ! -Vous vous demandez peut-être pourquoi nous avons écrit le nom de la fonction à la fin du fichier. C'est parce que Python lit le fichier et l'exécute de haut en bas. Donc pour pouvoir utiliser notre fonction, nous devons la réécrire en bas. +Vous vous demandez peut-être pourquoi nous avons écrit le nom de la fonction à la fin du fichier. C'est parce que Python lit le fichier et l'exécute du haut vers le bas. Donc pour pouvoir utiliser notre fonction, nous devons la réécrire en bas. -Lançons le pour voir ce qui se passe : +Lançons notre code pour voir ce qui se passe : $ python3 python_intro.py Hi there! How are you? - -C'était facile ! Construisons maintenant notre première fonction avec des paramètres. Dans l'exemple précédent, on avait une fonction que dit "Salut" à la personne qui la lance. Faisons pareil, mais avec un nom : - def hi(name): - +C'était facile ! Construisons maintenant notre première fonction avec des paramètres. Dans l'exemple précédent, nous avions une fonction qui disait "Hi there!" à la personne qui la lançait. Faisons une fonction identique, mais ajoutons un nom cette fois : -Comme vous le voyez, on a donné à notre fonction un paramètre appelé `name` : +```python +def hi(name): +``` - def hi(name): - if name == 'Ola': - print('Hi Ola!') - elif name == 'Sonja': - print('Hi Sonja!') - else: - print('Hi anonymous!') - - hi() - +Comme vous le voyez, nous avons donné à notre fonction un paramètre appelé `name` : -Comme vous voyez, on a dur mettre deux indentations avant la fonction `print`, parce que le `if` a besoin de savoir ce qui doit se passer quand la condition est vraie. Voyons voir comment ça marche : +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') - $ python3 python_intro.py - Traceback (most recent call last): - File "python_intro.py", line 10, in - hi() - TypeError: hi() missing 1 required positional argument: 'name' - +hi() +``` -Oups, une erreur. Heureusement, Python nous donne un message d'erreur assez utile. Il nous dit que la fonction `hi()` (celle qu'on a définie) a besoin d'un argument (qu'on a appelé `name`) et que nous avons oublier de le passer quand nous avons appelé la fonction. Corrigeons la dernière ligne du fichier : +Rappelez-vous : la fonction `print` est indentée de quatre espaces dans le bloc `if`, car elle est exécutée uniquement quand la condition est satisfaite. Voyons comment ça marche : - hi("Ola") - +```python +$ python3 python_intro.py +Traceback (most recent call last): +File "python_intro.py", line 10, in + hi() +TypeError: hi() missing 1 required positional argument: 'name' +``` -et relançons le : +Oups, une erreur. Heureusement, Python nous donne un message d'erreur assez utile. Il nous dit que la fonction `hi()` (celle que nous avons définie) a besoin d'un argument (que nous avons appelé `name`). Nous avons oublier de passer cet argument lorsque nous avons appelé notre fonction. Corrigeons la dernière ligne du fichier : + +```python +hi("Ola") +``` + +Et exécutez votre code à nouveau : $ python3 python_intro.py Hi Ola! - -Ey si on change le nom ? - hi("Sonja") - +Et que se passe-t-il quand on change de nom ? + +```python +hi("Sonja") +``` -et qu'on le lance : +Exécutez votre code à nouveau : $ python3 python_intro.py Hi Sonja! - -Et maintenant, qu'est-ce qui se passera si on met un autre nom (Ni Ola ni Sonja) ? Essayez et voyez si vous arriver à deviner. Ça devrait afficher ça : + +Maintenant, que pensez-vous qu'il se passera lorsque nous écrirons un autre nom (ni Ola, ni Sonja) ? Faites un essai et regardez si vous avez raison. Ceci devrait s'afficher : Hi anonymous! - -Super, non ? Avec ça, vous n'avez pas besoin de vous repéter quand vous voulez changer le nom de la personne à saluer. Et c'est exactement pour ça qu'on a besoin de fonctions : parce qu'on ne veut jamais avoir à répéter du code ! -Faisons maintenant quelque chose de plus malin -- il existe plus de deux noms, et ce serait un peu dur d'écrire une condition pour chacune, non ? +Super, non ? Avec ça, vous n'avez pas besoin de vous répéter lorsque vous voulez changer le nom de la personne à saluer. C'est pour cette raison que nous avons besoin de fonctions : vous ne voulez pas avoir à répéter votre code ! + +Faisons maintenant quelque chose de plus malin : comme vous le savez, il existe plus de deux prénoms. Cependant, ce serait un peu pénible de devoir écrire une condition pour chacun d'entre eux, n'est-ce pas ? - def hi(name): - print('Hi ' + name + '!') - - hi("Rachel") - +```python +def hi(name): + print('Hi ' + name + '!') -Appelons le code : +hi("Rachel") +``` + +Exécutons à nouveau notre code : $ python3 python_intro.py Hi Rachel! - -Bravo ! Vous venez d'apprendre à écrire des fonctions :) ! + +Félicitations ! Vous venez juste d’apprendre à écrire des fonctions ! :) ## Les boucles -Et voici la dernière partie. Ça a été vite, non ? :) +C’est déjà la dernière partie. C’était rapide, non ? :) -On l'a déjà dit : les programmeur⋅euse⋅s sont fénéant⋅e⋅s, et n'aiment pas se répéter. Programmer, c'est automatiser des choses : on ne veut pas avoir à saluer chaque personne par son nom manuellement, non ? C'est là que les boucles interviennent. +Les programmeurs⋅euses n'aiment pas devoir se répéter. L'essence de la programmation est d'automatiser les choses : nous aimerions pouvoir saluer automatiquement chaque personne. Pour cela, nous allons utiliser des boucles. Vous vous souvenez des listes ? Faisons une liste de Django Girls : - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] - +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` Nous voulons saluer chacune d'entre elles par son nom. Nous avons déjà la fonction `hi` pour faire ça, utilisons donc une boucle : - for name in girls: - +```python +for name in girls: +``` + +L'instruction `for` se comporte un peu comme `if`. Le code qui suit doit donc être indenté de quatre espaces. -L'instruction ~~~for~~~ se comporte un peu comme ~~~if~~~, le code qui suit doit être indenté de quatre espaces. +Voilà le code complet à mettre dans votre fichier : -Voilà le code complet à mettre dans le fichier : +```python +def hi(name): + print('Hi ' + name + '!') - def hi(name): - print('Hi ' + name + '!') - - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] - for name in girls: - hi(name) - print('Next girl') - +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` -Et quand on le lance : +Exécutez votre code : $ python3 python_intro.py Hi Rachel! @@ -699,15 +798,16 @@ Et quand on le lance : Next girl Hi You! Next girl - -Comme vous le voyez, tout ce qu'on met dans un `for` avec une indentation est repété pour chaque élément de la liste `girls`. -Vous pouvez aussi utiliser `for` sur des nombres grâce à la fonction `range` : +Comme vous le voyez, tout ce que nous avons mis dans un `for` avec une indentation est répété pour chaque élément de la liste `girls`. - for i in range(1, 6): - print(i) - +Vous pouvez aussi utiliser `for` sur des nombres grâce à la fonction `range`: + +```python +for i in range(1, 6): + print(i) +``` Ce qui affiche : @@ -716,17 +816,17 @@ Ce qui affiche : 3 4 5 - -`range` est une fonction qui crée une liste de nombres qui se suivent (c'est vous qui donnez l'intervale via les paramètres). -Remarquez que le second de ces nombres n'est pas inclus dans la liste que Python nous donne (ce qui signifie que `range(1, 6)` compte de 1 à 5, mais n'inclue pas 6). +`range` est une fonction qui crée une liste de nombres qui se suivent (c'est vous qui définissez l’intervalle à l'aide de paramètres). + +Vous pouvez remarquer que le second de ces nombres n'est pas inclus dans la liste que Python nous donne (ce qui signifie que `range(1, 6)` compte de 1 à 5, mais n'inclut pas 6). C'est lié au fait que "range" est à moitié ouvert. Cela signifie qu'il inclut la première valeur mais pas la dernière. ## Résumé -Et voilà ! **Vous roxez du poney !** Ça n'était pas si facile que ça, vous pouvez être fière de vous. En tout cas, nous, on est fiers de vous pour être arrivée jusque ici ! +Et voilà ! **Vous êtes géniale !** Ce chapitre était un peu compliqué et vous devriez être fière de vous ! En tout cas, nous sommes super fières de vous ! -Allez donc vous chercher un cupcake avant de passer au chapitre suivant :) +N'hésitez pas à prendre une pause : étirez-vous, marchez un peu ou reposez-vous les yeux. Une fois que vous avez un peu rechargé vos batteries, vous pouvez attaquer le chapitre suivant :) ![Cupcake][3] diff --git a/fr/template_extending/README.md b/fr/template_extending/README.md index a20114f1563..8670e4bd472 100755 --- a/fr/template_extending/README.md +++ b/fr/template_extending/README.md @@ -2,22 +2,22 @@ Django vous réserve encore bien des surprises : une assez géniale est **l'héritage de template**. Qu'est ce que ça signifie ? C'est une fonctionnalité qui vous permet de réutiliser certains morceaux de HTML dans différentes pages de votre site web. -Concrètement, cela permet de vous éviter de vous répéter dans chaque fichier lorsque vous voulez utiliser la même information ou mise en page. Ainsi, lorsque vous voudrez changer quelque chose, vous n'aurez à le faire que dans un seul template! +Concrètement, cela permet d'éviter de vous répéter dans chaque fichier lorsque vous voulez utiliser la même information ou mise en page. Ainsi, lorsque vous voudrez changer quelque chose, vous n'aurez à le faire qu'une seule fois! ## Créer un template de base Un template de base est le template le plus simple que vous pouvez faire hériter à chaque page de votre site web. -Créons le fichier `base.html` dans le dossier `blog/templates/blog/`: +Créons le fichier `base.html` dans le dossier `blog/templates/blog/` : blog └───templates └───blog base.html post_list.html - -Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le fichier `post_list.html`. Ça devrait ressembler à ça: + +Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le fichier `post_list.html`. Ça devrait ressembler à ça : ```html {% load staticfiles %} @@ -26,7 +26,6 @@ Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le Django Girls blog - @@ -44,7 +43,7 @@ Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %}
@@ -53,9 +52,8 @@ Ensuite, ouvrez ce fichier `base.html` et collez-y tout ce qui se trouve dans le ``` - -Puis, dans le fichier `base.html`, remplacer tout ce qui se trouve dans `` (de `` à ``) par ceci: +Puis, dans le fichier `base.html`, remplacez tout ce qui se trouve dans `` (de `` à ``) par ceci : ```html @@ -72,16 +70,14 @@ Puis, dans le fichier `base.html`, remplacer tout ce qui se trouve dans ``
``` - -{% raw %}Nous venons concrètement de remplacer tout ce qui se trouve entre `{% for post in posts %}{% endfor %}` par:{% endraw %} +Nous venons concrètement de remplacer tout ce qui se trouve entre `{% for post in posts %}{% endfor %}` par : ```html {% block content %} {% endblock %} ``` - Qu'est-ce que cela signifie ? Vous venez simplement de créer un `block` : c'est une balise de template qui vous permet d'insérer le HTML de ce block dans d'autres templates qui héritent de `base.html`. Nous vous expliquerons comment faire dans un instant. Maintenant, sauvegardez votre fichier puis ouvrez à nouveau `blog/templates/blog/post_list.html`. Supprimez tout ce qui n'est pas dans body. Supprimez aussi ``. Votre fichier doit maintenant ressembler à ça : @@ -93,20 +89,18 @@ Maintenant, sauvegardez votre fichier puis ouvrez à nouveau `blog/templates/blo {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -Maintenant, ajoutez cette ligne au début du fichier: +Maintenant, ajoutez cette ligne au début du fichier : ```html {% extends 'blog/base.html' %} ``` - -Vous venez de permettre à `post_list.html` d'hériter du template de `base.html`. Une dernière chose à faire: déplacez tout le contenu du fichier dans la partie située entre `{% block content %}` et `{% endblock content %}`. Attention à ne pas déplacer la ligne que vous venons juste d'insérer. Votre fichier doit maintenant ressembler à ceci: +{% raw %}Cela signifie que nous sommes en train d'étendre le modèle du template `base.html` dans `post_list.html`. Une dernière chose à faire : déplacez tout le contenu du fichier dans la partie située entre `{% block content %}` et `{% endblock content %}`. Attention à ne pas déplacer la ligne que nous venons juste d'insérer. Comme ceci :{% endraw %} ```html {% extends 'blog/base.html' %} @@ -118,13 +112,12 @@ Vous venez de permettre à `post_list.html` d'hériter du template de `base.html {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} ``` - Et voilà ! Vérifiez que votre site fonctionne toujours correctement :) -> Si jamais vous rencontrez une erreur de type `TemplateDoesNotExists` qui signale que le fichier `blog/base.html` n'existe pas et que `runserver` tourne dans votre console, tuez le (en appuyant sur les touches Ctrl+C en même temps) et relancez votre server à l'aide de la commande `python manage.py runserver`. +> Si jamais vous rencontrez une erreur de type `TemplateDoesNotExists` qui signale que le fichier `blog/base.html` n'existe pas et que `runserver` tourne dans votre console, tuez-le (en appuyant sur les touches Ctrl+C en même temps) et relancez votre server à l'aide de la commande `python manage.py runserver`. diff --git a/fr/whats_next/README.md b/fr/whats_next/README.md index 77c6a3a36f3..fe4f7f90a6b 100755 --- a/fr/whats_next/README.md +++ b/fr/whats_next/README.md @@ -1,6 +1,6 @@ -# La suite ? +# La suite? -Un immense bravo à vous ! **Vous êtes totalement géniale**. Nous sommes fièr·e·s de vous ! < 3 +Un immense bravo à vous ! **Vous êtes totalement géniale**. Nous sommes fière de vous ! < 3 ### Que faire maintenant ? @@ -8,10 +8,10 @@ Faites une pause et détendez-vous. Vous venez d'accomplir quelque chose de vrai Après ça, vous pouvez : -* Suivez Django Girls sur [Facebook][1] ou [Twitter][2] pour être tenu·e au courant +* Suivez Django Girls sur [Facebook][1] ou [Twitter][2] pour être tenue au courant [1]: http://facebook.com/djangogirls - [2]: http://twitter.com/djangogirls + [2]: https://twitter.com/djangogirls ### À la recherche de ressources supplémentaires ? @@ -19,8 +19,7 @@ Jetez un coup d’œil à notre autre livre, [Django Girls Tutorial: Extensions] [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ -Vous pouvez aussi essayer les ressources suivantes. Elles sont toutes recommandables! - +Ensuite, vous pouvez essayer les ressources listées ci-dessous. Elles sont toutes recommandables ! - [Django's official tutorial][4] - [New Coder tutorials][5] - [Code Academy Python course][6] @@ -28,13 +27,13 @@ Vous pouvez aussi essayer les ressources suivantes. Elles sont toutes recommanda - [Django Carrots tutorial][8] - [Learn Python The Hard Way book][9] - [Getting Started With Django video lessons][10] -- [Two Scoops of Django: Best Practices for Django book][11] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] - [4]: https://docs.djangoproject.com/en/1.7/intro/tutorial01/ + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ [5]: http://newcoder.io/tutorials/ - [6]: http://www.codecademy.com/en/tracks/python - [7]: http://www.codecademy.com/tracks/web - [8]: http://django.carrots.pl/en/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ [9]: http://learnpythonthehardway.org/book/ [10]: http://gettingstartedwithdjango.com/ - [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6 + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/hu/GLOSSARY.md b/hu/GLOSSARY.md new file mode 100644 index 00000000000..0b906ac1f3c --- /dev/null +++ b/hu/GLOSSARY.md @@ -0,0 +1,3 @@ +# kódszerkesztő + +A kódszerkesztő egy alkalmazás, amely segítségével elmentheted a kódodat, így később vissza tudsz térni hozzá. A [Kódszerkesztő fejezetből](./code_editor/README.md) tudhatod meg, hogyan juthatsz hozzá \ No newline at end of file diff --git a/hu/README.md b/hu/README.md new file mode 100644 index 00000000000..747acf69ced --- /dev/null +++ b/hu/README.md @@ -0,0 +1,51 @@ +# Django Girls Tutorial + +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Ez az anyag Creative Commons Attribution-ShareAlike 4.0 International License jogvédelme alatt áll. A licenc megtekintéséhez látogass el ide: https://creativecommons.org/licenses/by-sa/4.0/ + +## Fordítás +A tutorial magyar fordítását egy csapat lelkes önkéntes készítette el: Czapári Dóri, Hanna Kollo, Erő Julcsi, Bónis Balázs, Kádár Szilvi, Szelle Erika, Téglássy Anna, Szabó Adrienn, Nádudvari György. Köszönjük nekik! <3 + +## Bevezetés + +Érezted már úgy hogy a világ egyre inkább a technológiáról szól, és te valahogy kimaradsz belőle? Gondolkoztál már azon, hogyan kell egy weblapot létrehozni, de soha nem volt elég erőd elkezdeni? Érezted úgy, hogy a szoftveres világ túl bonyolult ahhoz, hogy egyáltalán megpróbálj valamit létrehozni benne magadtól? + +Nos, jó hírünk van számodra! A programozás egyáltalán nem olyan nehéz, mint amilyennek tűnik, és mi megmutatjuk, hogy mennyire jó móka tud lenni. + +Ez a tutorial nem fog téged egy csapásra programozóvá változtatni. Ha profi akarsz lenni benne, hónapokat vagy akár éveket kell eltöltened tanulással és gyakorlással. De meg szeretnénk mutatni, hogy a programozás, illetve a weblapkészítés nem annyira bonyolult, mint amilyennek tűnik. Megpróbáljuk minél jobban elmagyarázni a különböző részleteket, hogy ne tűnjön annyira ijesztőnek a technológia. + +Reméljük, veled is annyira megszerettetjük a számítógépek világát, mint amennyire mi szeretjük! + +## Mit fogsz a tutorial alatt megtanulni? + +A tutorial befejezésével lesz egy egyszerű, működő webes alkalmazásod: a saját blogod. Megmutatjuk, hogyan kell a netre feltölteni, hogy mások is lássák az eredményt! + +Körülbelül így fog kinézni: + +![Figure 0.1][2] + + [2]: images/application.png + +> Ha egyedül dolgozol a tutorialon és nincs melletted coach, aki segíthetne, ha bármi probléma felmerül, használd a chatet, amit neked tartunk fenn: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Megkértük a segítőinket és korábbi résztvevőket, hogy legyenek fent, ahogy idejük engedi, és segítsenek másoknak a tutorialban. Kérdezz tőlük bátran! + +Oké, [kezdjük az elejénél...][3] + + [3]: ./how_the_internet_works/README.md + +## A tutorialról és a közreműködésről + +Ezt a tutorialt a [DjangoGirls][4] tartja fenn. Ha bármilyen hibát találsz benne, vagy frissíteni szeretnéd, kérlek kövesd a [közreműködési útmutatót][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Szeretnél segíteni lefordítani a tutorialt más nyelvekre? + +A fordításokat jelenleg a crowdin.com platformon végezzük: + +https://crowdin.com/project/django-girls-tutorial + +Ha a te nyelved nem szerepel a crowdin listán, kérlek [hozz létre egy új issue-t][6], amely megjelöli a nyelvet, hogy hozzáadhassuk. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new \ No newline at end of file diff --git a/hu/SUMMARY.md b/hu/SUMMARY.md new file mode 100644 index 00000000000..32bf04596b8 --- /dev/null +++ b/hu/SUMMARY.md @@ -0,0 +1,26 @@ +# Összefoglaló + +* [Bevezetés](README.md) +* [Installáció](installation/README.md) +* [Hogy működik az Internet?](how_the_internet_works/README.md) +* [Bevezetés a parancssor használatába](intro_to_command_line/README.md) +* [A Python telepítése](python_installation/README.md) +* [Kódszerkesztő (editor)](code_editor/README.md) +* [Bevezetés a Pythonba](python_introduction/README.md) +* [Mi a Django?](django/README.md) +* [Django telepítés](django_installation/README.md) +* [Az első Django projekted!](django_start_project/README.md) +* [Django modellek](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Deploy!](deploy/README.md) +* [Django url-ek](django_urls/README.md) +* [Django views - itt az ideje alkotni!](django_views/README.md) +* [Bevezetés a HTML-be](html/README.md) +* [Django ORM és QuerySet-ek](django_orm/README.md) +* [Dinamikus adatok a template-ben](dynamic_data_in_templates/README.md) +* [Django sablonok (template)](django_templates/README.md) +* [CSS - Tegyük széppé!](css/README.md) +* [Template-kiegészítés](template_extending/README.md) +* [Egészítsd ki az applikációdat](extend_your_application/README.md) +* [Django űrlapok](django_forms/README.md) +* [Következő lépések](whats_next/README.md) diff --git a/hu/code_editor/README.md b/hu/code_editor/README.md new file mode 100644 index 00000000000..dd6521f1a3b --- /dev/null +++ b/hu/code_editor/README.md @@ -0,0 +1,7 @@ +# Kódszerkesztő (editor) + +Nemsokára megírod a kód első sorát, itt az ideje letölteni egy kódszerkesztőt! + +> **Megjegyzés:** Lehet, hogy ezt már megtetted a Telepítés fejezet olvasása során - ha igen, ugorj előre a következő fejezetre! + +{% include "/code_editor/instructions.md" %} diff --git a/hu/code_editor/instructions.md b/hu/code_editor/instructions.md new file mode 100644 index 00000000000..01c41e862f6 --- /dev/null +++ b/hu/code_editor/instructions.md @@ -0,0 +1,31 @@ +Sokféle kódszerkesztő program létezik, és valójában ízlés kérdése, hogy ki melyiket választja. A legtöbb Python programozó bonyolult fejlesztői környezetet (IDE - Integrated Development Environment) használ, mint például a PyCharm. Egy kezdőnek viszont nem ezek a legmegfelelőbbek. A programok, amiket mi ajánlunk, hasonlóan hatékonyak, de használatuk sokkal egyszerűbb. + +Mi az alábbiakat javasoljuk, de nyugodtan kérj segítséget a coach-odtól, ő is könnyen tud tanácsot adni ez ügyben. + +## Gedit + +A Gedit egy open-source (nyílt forráskódú), ingyenes kódszerkesztő, az összes jelenlegi operációs rendszeren elérhető. + +[Letöltés](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +A Sublime Text egy nagyon népszerű editor, ingyenes próbaidővel. Könnyű telepíteni és használni, és minden operációs rendszeren elérhető. + +[Letöltés](https://www.sublimetext.com/3) + +## Atom + +Az Atom egy teljesen új kódszerkesztő, amelyet a [GitHub](https://github.com/) hozott létre. Ingyenes, nyílt forráskódú, könnyen telepíthető és könnyen használható. Elérhető Windows-on, OSX-en és Linuxon. + +[Letöltés](https://atom.io/) + +## Miért telepítünk kódszerkesztőt? + +Most talán azon gondolkozol, miért telepítünk speciális kódszerkesztőt, ahelyett, hogy a Word vagy a Notepad alkalmazást használnánk. + +Az első ok az, hogy a kódot **egyszerű szövegként** kell szerkeszteni. Az általános (nem programozóknak szánt) szövegszerkesztőkkel, mint a Word és a Textedit, az a probléma, hogy nem egyszerű szöveges fájlt állítanak elő, hanem formázott dokumentumot (például [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format) formátumban), amelyben számít például a betűtípus, formázás, stb. + +A másodsorban ezek a programozáshoz tervezett szövegszerkesztők kifejezetten kódszerkesztésre szakosodtak, ami azt jelenti hogy különböző funkciókkal segítik a munkát, mint például a programkód részeinek, szavainak kiemelése annak jelentése alapján, vagy az automatikus kiegészítés. + +Ezt mind látni fogjuk a későbbiekben. Hamarosan úgy fogsz gondolni a jó öreg megbízható kódszerkesztődre, mint az egyik kedvenc eszközödre :) \ No newline at end of file diff --git a/hu/css/README.md b/hu/css/README.md new file mode 100644 index 00000000000..e2f0722c829 --- /dev/null +++ b/hu/css/README.md @@ -0,0 +1,295 @@ +# CSS - csinosítsd ki! + +Egyelőre nem túl szép a blogunk, igaz? Itt az ideje, hogy kicsinosítsd! Erre a CSS-t fogjuk használni. + +## Mi a CSS? + +A CSS (Cascading Style Sheets) egy nyelv, amit a HTML-ben megírt weboldalak kinézetének leírására használunk. Vagyis mintha kisminkelnéd a weboldaladat ;). + +De nem akarjuk megint az alapoktól kezdeni, igaz? Itt is olyasmit fogunk felhasználni, amit más programozók már létrehoztak, és szabadon elérhetővé tettek az Interneten. Minek találnánk fel újra a spanyolviaszt? + +## Használjunk Bootstrapet! + +A Bootstrap az egyik legnépszerűbb HTML és CSS keretrendszer, amivel szép weboldalakat készíthetünk: https://getbootstrap.com/ + +Eredetileg a Twitternél dolgozó programozók készítették, de most önkéntesek fejlesztik szerte a világon. + +## Bootstrap telepítés + +Hogy telepítsd a Bootstrapet, add hozzá a következő a sorokat a `` részhez a `.html` fájlodban (`blog/templates/blog/post_list.html`): + +```html + + +``` + +Ezzel nem adsz hozzá új fájlokat a projektedhez, csak az Interneten létező fájlokra hivatkozol. Nyisd meg újra a weboldaladat, és frissítsd! Itt is van! + +![14.1 ábra][1] + + [1]: images/bootstrap1.png + +Már sokkal jobban néz ki! + +## Statikus fájlok a Django-ban + +Most nézzük meg kicsit közelebbről ezeket a "**statikus fájl**"-nak nevezett dolgokat. A CSS-ed és az összes képfájl statikus fájlnak számít -- ilyen minden, ami nem dinamikus, vagyis aminek a tartalma nem függ a kontextustól (magyarul a weboldal aktuális állapotától), és ezért minden felhasználó számára ugyanaz. + +### Hová pakoljuk a statikus fájlokat? + +Amikor -- kicsit korábban -- a `collectstatic` parancsot futtattuk a szerveren, Django már tudta, hol találja a statikus fájlokat a beépíttett "admin" alkalmazáshoz. Most csak annyit kell tennünk, hogy a saját, `blog` alkalmazásunkhoz hozzáadunk néhány statikus fájlt. + +Ehhez pedig létre kell hozunk egy "`static`" nevű könyvtárat a blog applikáción belül: + + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite + + +A Django automatikusan megtalál minden "static" nevű mappát az alkalmazásaid könyvtárain belül, és képes lesz használni azok tartalmát statikus fájlokként. + +## Az első CSS fájlod! + +Írjunk egy CSS fájlt, hogy hozzáadd a saját stílusodat a weboldaladhoz. Hozz létre egy `css` nevű könyvtárat a `static` könyvtárban! Majd hozz létre egy új fájlt `blog.css` néven a `css` könyvtárban. Kész vagy? + + djangogirls + └─── blog + └─── statikus + └─── css + └─── blog.css + + +Itt az ideje, hogy a CSS fájlunkba írjunk is valamit! Nyisd meg a `blog/static/css/blog.css` fájlt a kódszerkesztődben. + +Most nem fogunk túlságosan belemélyedni a CSS-be, mert nem bonyolult, és magadtól is meg tudod majd tanulni a workshop után. Szerintünk a [Codeacademy][2] HTML & CSS kurzusából mindent megtanulhatsz arról, hogyan teheted széppé a weboldalaidat CSS segítségével. + + [2]: https://www.codecademy.com/tracks/web + +De azért egy pár dolgot megmutatunk. Például megváltoztathatnánk a header színét? Hogy a számítógépek megértsék a színeket, speciális kódokat használnak. `#` jellel kezdődnek, majd 6 betű (A-F) és szám (0-9) következik. Színkódokat például itt találhatsz: http://www.colorpicker.com/. [Előre meghatározott színeket][3] is használhatsz, mint a `red` vagy a `green`. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +A `blog/static/css/blog.css` fájlba írd bele a következő kódot: + +```css +h1 a { + color: #FCA205; +} +``` + +A `h1 a` egy CSS szelektor. Ez azt jelenti, hogy alkalmazzuk a stílusunkat minden olyan `a` elemre, ami egy `h1` elemen belül van (például, mikor valami ilyesmi van a kódban: `

link

`). Ebben az esetben azt mondjuk, hogy változtasd meg a kiválasztott elem színét `#FCA205`-re, ami narancssárgát jelent. Természetesen nyugodtan használd a saját színedet itt! + +A CSS fájlban mondjuk meg, hogy nézzenek ki a HTML fájl elemei. Az egyes elemek beazonosíthatók az elemek nevei alapján (pl. `a`, `h1`, `body`), és a `class` vagy az `id` attribútumaik alapján. A class és az id olyan nevek, amelyeket te adhatsz meg az elemeknek. A class attribútum elemek egy csoportjára vonatkozik, míg az id-val kifejezetetten egy elemet tudunk beazonosítani. A következő tag például beazonosítható akár az "`a`" tag névvel, az `external_link` class-szal vagy a `link_to_wiki_page` id-val: + +```html + +``` + +Olvass utána a [CSS szelektorokról a w3schools oldalán][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Mindezek után közölnünk kell a HTML fájlunkkal is, hogy hozzáadtunk pár CSS-t. Nyisd meg a `blog/templates/blog/post_list.html` fájlt és add a következő sort a fájl legelejére: + +```html +{% load staticfiles %} +``` + +Itt csak betöltünk pár statikus fájlt :). Ezután a `` és a `` tagek közé, a Bootstrap CSS fájlok linkjei után (a böngésző olyan sorrendben olvassa az egyes fájlokat, amilyenben követik egymást, tehát a mi fájlunkban lévő kód lehet, hogy felülír pár kódot a Bootstrap fájlban), a következő sort add: + +```html + +``` + +Most megmondtuk a template-ünknek, hol találja a CSS fájlokat. + +Így kellene kinéznie a fájlodnak: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + + +Oké, mentsd el a fájlt és frissítsd be az oldalt! + +![14.2 ábra][5] + + [5]: images/color2.png + +Szép munka! Lehet, hogy jó lenne adni egy kis "teret" a weboldalunknak és növelni a bal oldali margót. Próbáljuk meg! + +```css +body { + padding-left: 15px; +} +``` + +Írd hozzá a CSS fájlodhoz, mentsd el és lássuk, működik-e! + +![14.3 ábra][6] + + [6]: images/margin2.png + +Lehet, hogy testre szabhatnánk a betű stílusát a header-ünkben. A következő sort másold bele a ``-be a `blog/templates/blog/post_list.html` fájlon belül: + +```html + +``` + +Ez a sor beimportál egy *Lobster* nevű betűtípust a Google Fonts-ból (https://www.google.com/fonts). + +Most add hozzá a `font-family: 'Lobster';` sort a `blog/static/css/blog.css` fájlodban, a `h1 a` stílusát meghatározó blokkhoz (ez a `{` kapcsos zárójel `}` közötti kód) és frissítsd az oldalt: + +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` + +![14.3 ábra][7] + + [7]: images/font.png + +Szuper! + +Ahogy fentebb említettük, a CSS-ben van egy "class" nevű fogalom, ami alapvetően azt teszi lehetővé, hogy elnevezd a HTML kódod egy részét és alkalmazz rajta egy stílust, csak ezen a részen, ami így nem befolyásolja a többit. Nagyon hasznos tud lenni, például amikor van két dived, amelyek nagyon különböző dolgokat csinálnak (akár a header-ed vagy a post-od), tehát nem akarod, hogy ugyanúgy nézzenek ki. + +Menj végig és nevezd el egy részét a HTML kódodnak. Adj egy `page-header` nevű class-t a `div`-edhez, amelyik a header-t tartalmazza, akárcsak így: + +```html + +``` + +És most adj egy `post` class-t a `div`-hez, ami a blog postokat tartalmazza. + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Most pedig adjunk stílusblokkokat a különböző szelektorokhoz. A `.` -tal kezdődő szelektorok classokra utalnak. Rengeteg szuper tutorial és magyarázat található a weben a CSS-ről, ami segít megérteni a következő kódot. Most csak másold ki és illeszd be a `blog/static/css/blog.css` fájlodba: + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +Ezután jelöld ki a HTML kódot, ami a post-okat jeleníti meg egy class="post" attribútummal. Cseréld le ezt: + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +a `blog/templates/blog/post_list.html` fájlban ezzel: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Mentsd el a fájlokat és frissítsd az oldalad. + +![14.4 ábra][8] + + [8]: images/final.png + +Nahát! Fantaszikus nem? A kódot, amit beillesztettünk, nem túl nehéz megérteni és a nagyja már csak átolvasva is érthető kell, hogy legyen. + +Ne félj kicsit megbuherálni ezt a CSS-t és megváltoztatni pár dolgot. Ha valamit elrontasz, ne aggódj, vissza tudod csinálni! + +Mindenesetre melegen ajánljuk ezt az ingyenes online [Codeacademy HTML & CSS kurzust][2], mint workshop utáni házi feladatot, hogy mindent tudj arról, hogyan tudod csinosabbá varázsolni a weboldaladat CSS-sel. + +Készen állsz a következő fejezetre?! :) \ No newline at end of file diff --git a/hu/css/images/bootstrap1.png b/hu/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/hu/css/images/bootstrap1.png differ diff --git a/hu/css/images/color2.png b/hu/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/hu/css/images/color2.png differ diff --git a/hu/css/images/final.png b/hu/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/hu/css/images/final.png differ diff --git a/hu/css/images/font.png b/hu/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/hu/css/images/font.png differ diff --git a/hu/css/images/margin2.png b/hu/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/hu/css/images/margin2.png differ diff --git a/hu/deploy/README.md b/hu/deploy/README.md new file mode 100644 index 00000000000..47848ff0bee --- /dev/null +++ b/hu/deploy/README.md @@ -0,0 +1,314 @@ +# Deploy! + +> **Megjegyzés** A következő fejezet néhol kissé bonyolult lehet. Tarts ki és vedd át az egész fejezetet; ugyanis most a webfejlesztés egy nagyon fontos része következik - az ún. deployment. Ez a fejezet a tutorial közepén található, így majd a mentorod is tud segíteni a trükkösebb részeknél, miközben a honlapodat online is elérhetővé teszed. Magát a tutorialt később egyedül is befejezheted, ha esetleg kifutnál az időből. + +Ezidáig a honlapod csak a saját számítógépeden volt elérhető - most tanuljuk meg, hogyan tegyük mások számára is elérhetővé! Ez az ún. deploying - az a tevékenység, amely során az alkalmazásodat közzé teszed az interneten, hogy mások is láthassák és használhassák azt :). + +Ahogyan azt már tudod, a honlapot egy szerveren kell elhelyezni. Több szerver szolgáltató is elérhető az interneten. Mi egy olyat fogunk használni, amit viszonylag egyszerű kezelni: [PythonAnywhere][1]. A PythonAnywhere ingyenes olyan kisebb alkalmazások számára, amelyeknek nincs sok látogatójuk, tehát a mi esetünkben ez pont megfelelő lesz. + + [1]: https://pythonanywhere.com/ + +A másik külső szolgáltatás, amit igénybe fogunk venni a [GitHub][2], ami egy ún. code hosting service (forráskód tárolására és megosztására alkalmas online tárhely). Vannak más hozzá hasonló szolgáltatók is, de szinte minden programozó ezt használja manapság, és nemsokára te is közéjük tartozhatsz! + + [2]: https://www.github.com + +A GitHubról fogjuk a forráskódunkat áthelyezni a PythonAnywhere-be, és fordítva. + +# Git + +A Git egy "version control system" (VCS, magyarul verziókezelő rendszer), amit sok programozó használ. Ez a szoftver nyomon követ minden változást a fájlokban, így a későbbiekben is visszatérhetünk egy bizonyos régebbi verzióhoz. Valamelyest hasonlít a "változások nyomon követése" funkcióhoz a Microsoft Wordben, de ez jóval hatékonyabb. + +## Git telepítése + +> **Megjegyzés** Ha már követted a korábbi telepítési utasításokat, ezt a pontot átugorhatod és kezdheted kialakítani a saját Git csomagtáradat! + +{% include "/deploy/install_git.md" %} + +## Készítsünk Git repository-t + +A Git nyomon követi a változásokat az adott fájlokban egy ún. csomagtárban (repository vagy röviden "repo"). Nyissunk egy új repo-t a projektünknek. Nyisd fel a konzolt és futtasd le a következő parancsokat, a `djangogirls` mappában: + +> **Megjegyzés** Az alábbi parancsokkal ellenőrizheted a munkamappát (working directory, az éppen megnyitott mappa): `pwd` (OSX/Linux) vagy `cd` (Windows) mielőtt létrehoznád a repositoryt. A `djangogirls` mappában kell lenned. + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +A git csomagtár inicializálása olyasvalami, amit minden projekt esetében csak egyszer kell véghezvinni (így majd nem kell újra és újra megadni a felhasználónevet ill. jelszót). + +A Git ezután nyomon követ minden változást a fájlokban és mappákban ezen a mappán belül. De vannak bizonyos fájlok, amiket nem szeretnénk figyelembe venni. Ezt úgy tehetjük meg, hogy létrehozunk egy fájlt `.gitignore` névvel a gyökérkönyvtárban. Nyisd meg a szövegszerkesztőt és hozz létre egy új fájlt, amibe az alábbi sorok kerülnek: + + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store + + +Majd mentsd le `.gitignore` néven a "djangogirls" legfelsőbb mappájában. + +> **Megjegyzés** Nagyon fontos, hogy a fájl neve ponttal kezdődjön! Ha bármi gond adódna a fájl létrehozásánál (pl. Mac számítógépeken a Finder alapvetően nem engedi, hogy a fájlnév ponttal kezdődjön), akkor használd a "Save as" lehetőséget. + +Jó ötlet a `git status` parancs használata még a `git add` előtt, valamint ezen kívül még bármikor, ha tudni szeretnéd, hogy mi változott. Ez majd segít elkerülni olyan szituációkat, mint például rossz fájlok hozzáadása ill. feltöltése a csomagtárba. A `git status` parancs információt szolgáltat minden nem követett (not tracked) / megváltozott (modified) /feltöltésre felkészített fájlról (staged files) stb. A kimenet ehhez hasonló lesz: + + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) + + +Végül mentsük le a változtatásokat. A konzolban futtasd le a következő parancsokat: + + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Forráskód feltöltése a GitHubra + +A böngészőben keresd fel a [GitHub.com][2] honlapot és regisztrálj be egy új "free user" fiókba. (Ha már beregisztráltál, ezt a pontot kihagyhatod) + +Ezután hozz létre egy új csomagtárat ("repót"), amit nevezz "my-first-blog"-nak. Hagyd az "initialise with a README" mezőt jelöletlenül, a .gitignore lehetőséget hagyd üresen (ezt manuálisan tettük), a "License" résznél maradjon a "None" opció. + +![][3] + + [3]: images/new_github_repo.png + +> **Megjegyzés** A `my-first-blog` név fontos -- választhattál volna más nevet is, de gyakran előfordul majd a későbbiekben is a parancsokban. Valószínűleg egyszerűbb lesz számodra is, ha a `my-first-blog` nevet használod. + +A következő oldalon látni fogod a repód url-jét (repo's clone url). Válaszd a "HTTPS" verziót, másold ki - mindjárt bemásoljuk a terminálba: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Most összekötjük a Git csomagtárat a számítógépeden a másik csomagtárral a GitHubon. + +A konzolba írd be a következőt (helyettesítsd a `` a saját felhasználóneveddel, amivel a GitHubon regisztráltál, de a kacsacsőrök nélkül): + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Add meg a GitHub felhasználónevedet és jelszódat, valami hasonlót kell hogy láss: + + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +A forráskódod most már fent van a GitHubon. Menj és nézd meg! Láthatod hogy jó társasága van - [Django][5], a [Django Girls Tutorial][6], és sok más szuper nyílt forráskódú szoftver forráskódja szintén a GitHubon található :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Tegyük fel a blogot a PythonAnywhere-re + +> **Megjegyzés** Valószínűleg már létrehoztál egy PythonAnywhere fiókot korábban a telepítés során - ha így van, ezt nem kell újból megtenned. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Forráskód letöltése a PythonAnywhere-be + +Amikor bejelentkezel a PythonAnywhere-be, egyből a dashboard-on, vagy "Consoles" oldalon találod magad. Válaszd a "Bash" konzol indítása opciót -- ez a PythonAnywhere konzolja, ugyanolyan, mint a parancssor a gépeden. + +> **Megjegyzés** A PythonAnywhere Linux rendszeren alapszik, tehát ha Windows-ot használsz, a konzol egy kissé máshogy fog kinézni a te számítógépeden. + +Töltsük be a forráskódodat a GitHubról a PythonAnywhere-be egy "clone" létrehozásával. Írd be az alábbiakat a konzolba a PythonAnywhere-ben (ne felejtsd, hogy a `` helyébe a saját, GitHubon használt felhasználónevedet helyettesítsd be): + + $ git clone https://github.com//my-first-blog.git + + +Ez majd betölti a forráskódod másolatát a PythonAnywhere-be. Ellenőrizheted, ha beírod a konzolba, hogy `tree my-first-blog`: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### Virtuális környezet létrehozása a PythonAnywhere-en + +Ugyanúgy, ahogy a saját gépeden csináltad, a PythonAnywhere-en is létrehozhatsz virtualenvet. Írd be a Bash konzolba: + +``` +$ cd my-first-blog + +$ virtualenv --python=python3.4 myvenv +Running virtualenv with interpreter /usr/bin/python3.4 +[...] +Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(mvenv) $ pip install django whitenoise +Collecting django +[...] +Successfully installed django-1.8.2 whitenoise-2.0 +``` + + +> **Megjegyzés** A `pip install` lépés eltarthat pár percig. Légy türelmes! De ha több mint 5 percig tart, akkor valószínűleg valami nincs rendben. Kérdezd meg a coachodat! + + + +### Statikus fájlok összegyűjtése. + +Kíváncsi vagy, mi ez a "whitenoise" nevű dolog? Egy eszköz az úgynevezett "statikus fájlok" kiszolgálására. A statikus fájlok olyan fájlok, amelyek nem változnak meg rendszeresen, vagy nem futtatnak programkódot - mint például a HTML vagy a CSS fájlok. A szervereken ezek másképp működnek, mint a saját gépünkön, ezért szükségünk van egy olyan eszközre, mint a "whitenoise", hogy kiszolgáljuk őket. + +A statikus fájlokról többet is tanulsz majd a tutorial során, amikor a CSS-t fogod szerkeszteni a honlapodhoz. + +Egyelőre csak egy `collectstatic` parancsot kell lefuttatnod a szerveren. Ez megmondja a Django-nak, hogy gyűjtse össze a szerveren az összes statikus fájlt, amire szüksége lesz. Ezek most többnyire olyan fájlok, amik az adminfelület kinézetét adják. + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +Írd be, hogy "yes", és el is tűnik! Te is imádod, ha kiírathatsz a gépeddel egy csomó érthetetlen szöveget? Én mindig fura hangokat adok ki ilyenkor, nagyon jól illik hozzá. Brp, brp, brp... + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### Adatbázis létrehozása PythonAnywhere-en + +Van még valami, ami máshogy működik a saját gépeden és a szerveren: különböző szervert használnak. Így a felhasználói fiókok és a blogposztok különbözőek lehetnek a szerveren és a gépeden. + +A szerveren ugyanúgy tudod létrehozni az adatbázist, mint a saját gépeden, a `migrate` és `createsuperuser` parancsokkal: + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + +## Tegyük közzé a blogot a weben! + +Most már fent van a kódod a PythonAnywhere-en, kész a virtuális környezet, össze vannak gyűjtve a statikus fájlok, és az adatbázist is elkészítetted. Készen állsz, hogy webes alkalmazást csinálj belőle! + +Menj vissza a PythonAnywhere dashboardra (a logóra kattintva megteheted), majd kattints a **Web** tabra. Végül nyomd meg a **Add a new web app** gombot. + +Miután leokéztad a domainnevedet, válaszd a **manual configuration**-t (kézi konfiguráció - vigyázz, *ne* a "Django" opciót válaszd!) a párbeszédablakban. Aztán válaszd ki a **Python 3.4**-et, majd nyomd meg a Nextet. + +> **Megjegyzés** Fontos, hogy a "Manual configuration" lehetőséget válaszd, ne a "Django"-t. Túl menők vagyunk a PythonAnywhere-es Django setuphoz:) + +### Virtuális környezet beállítása + +Most a PythonAnywhere config oldalára kerülsz, ahol különböző dolgokat állíthatsz be az appeddel kapcsolatban. Ha bármit meg szeretnél változtatni később, ide kell visszajönnöd. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +A "Virtualenv" részben kattints rá a piros szövegre: "Enter the path to a virtualenv", majd írd be: `/home//my-first-blog/myvenv/`. Kattints a kék dobozra a pipajellel, hogy elmentsd a path-t, mielőtt továbblépsz. + +> **Megjegyzés** Helyettesítsd be a saját felhasználóneved. Ha elrontasz valamit, a PythonAnywhere figyelmeztetni fog. + +### A WSGI fájl konfigurálása + +A Django a "WSGI protokollt" használja. Ez egy szabvány, ami a Python segítségével kiszolgált weboldalakra érvényes. A PythonAnywhere is támogatja ezt. Ahhoz, hogy a PythonAnywhere felismerje a Django blogunkat, egy WSGI konfigurációs fájlt kell szerkesztenünk. + +Kattints a "WSGI configuration file" linkre (a "Code" szekcióban az oldal tetejénél -- olyasmi neve lesz, hogy `/var/www/_pythonanywhere_com_wsgi.py`). Egy kódszerkesztőbe fogsz jutni. + +Törölj ki mindent, és cseréld ki valami ilyesmire: + +```python +import os +import sys + +path = '/home//my-first-blog' # itt a saját felhasználónevedet használd! +if path not in sys.path: + sys.path.append(path) + +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Megjegyzés** Ne felejtsd el a saját felhasználóneveddel helyettesíteni a ``-et! + +Ennek a fájlnak az a dolga, hogy megmondja a PythonAnywhere-nek, hol lakik a webes alkalmazásunk, és mi annak a fájlnak a neve, ahol a Django beállításai vannak. Ezenkívül a "whitenoise"-t is beállítja, ami a statikus fájlok kiszolgálásában segít. + +Nyomd meg a **Save** (Mentés) gombot, majd menj vissza a **Web** fülre. + +Kész is vagyunk! Nyomd meg a nagy zöld **Reload** gombot, és máris meg fogod tudni nézni az alkalmazásodat. Az oldal tetején fogsz találni hozzá egy linket. + +## Tippek debuggoláshoz + +Ha hibát látsz, amikor megpróbálod meglátogatni az oldaladat, az első hely, ahol információt kaphatsz a debuggoláshoz, az **error log**. Ehhez a PythonAnywhere [Web tab][8]-ján találod meg a linket. Nézd meg, hogy van-e benne bármilyen hibaüzenet; a legfrissebbek lesznek alul. Gyakran előforduló problémák: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* Kihagytad valamelyik lépést a konzolban: a virtualenv létrehozását, aktiválását, a Django installálását a virtualenvben, a collectstatic lefuttatását, az adatbázis migrálását. + +* Valamit elrontottál a virtualenv path-ban a Web fülön -- általában egy piros hibaüzenet jelzi, ha valami gond van. + +* Valamit elrontottál a WSGI konfigurációs fájlban -- jól írtad be a my-first-blog könyvtárhoz vezető elérési útvonalat? + +* Ugyanazt a Python verziót választottad a virtualenved számára, mint az alkalmazásodhoz? Mindkettőnek a 3.4-esnek kell lennie. + +* A [PythonAnywhere wikiben is találsz néhány általános hibakeresési tippet][9]. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +És ne feledd, a coachod azért van, hogy segítsen! + +# Él a weboldalad! + +A honlapod alapértelmezett oldala a "Welcome to Django", ugyanúgy, mint a saját gépeden. Add hozzá az `/admin/`-t az URL végéhez, és az adminfelületre kerülsz. Jelentkezz be a felhasználóneveddel és a jelszavaddal, és látni fogod, hogy itt is tudsz új Postokat létrehozni. + +Megérdemelsz egy *HATALMAS* vállveregetést! A szerver deployment a webfejlesztés legbonyolultabb részei közé tartozik, és a fejlesztők gyakran napokat töltenek azzal, hogy mindent működésre bírjanak. De neked most komolyan van egy működő weboldalad, az Interneten, és nem is tartott sokáig megcsinálni! diff --git a/hu/deploy/images/github_get_repo_url_screenshot.png b/hu/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/hu/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/hu/deploy/images/new_github_repo.png b/hu/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/hu/deploy/images/new_github_repo.png differ diff --git a/hu/deploy/images/pythonanywhere_web_tab_virtualenv.png b/hu/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/hu/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/hu/deploy/install_git.md b/hu/deploy/install_git.md new file mode 100644 index 00000000000..77b9051fa9a --- /dev/null +++ b/hu/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows + +A Gitet innen töltheted le: [git-scm.com](https://git-scm.com/). Telepítése: csak kattints a "next" gombra egészen addig, amíg el nem érsz az ötödik lépésig - "Adjusting your PATH environment" címmel - itt válaszd ki a "Run Git and associated Unix tools from the Windows command-line" lehetőséget (keresd alul). Ezen kívül a többi maradhat az alapbeállításon. Checkout Windows-style, commit Unix-style line endings - ezek is maradhatnak így. + +### MacOS + +Töltsd le a Git-tet az alábbi linken: [git-scm.com](https://git-scm.com/), majd kövesd az utasításokat. + +### Linux + +Ha még nincs telepítve, elérhető a a package manager-en keresztül, szóval próbáld meg az alábbiakat: + + sudo apt-get install git + # vagy + sudo yum install git + # vagy + sudo zypper install git diff --git a/hu/deploy/signup_pythonanywhere.md b/hu/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..283a3a92986 --- /dev/null +++ b/hu/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Most itt az ideje, hogy létrehozz magadnak egy ingyenes, "Kezdő" ("Beginner") fiókot a PythonAnywhere oldalon. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Megjegyzés:** A blogod címe, vagyis URL-je `felhasználónév.pythonanywhere.com` lesz, vagyis érdemes a regisztrációkor felhasználónévnek vagy a saját becenevedet választani, vagy a blogod témájához kapcsolódó nevet. \ No newline at end of file diff --git a/hu/django/README.md b/hu/django/README.md new file mode 100644 index 00000000000..4daf57a971a --- /dev/null +++ b/hu/django/README.md @@ -0,0 +1,27 @@ +# Mi a Django? + +A Django egy webes alkalmazások készítésére használható, Pythonban írt, ingyenes, nyílt forráskódú keretrendszer (framework). A webes keretrendszerek különböző építőelemek gyűjteményei, segítségükkel könnyebben és gyorsabban tudunk weboldalakat fejleszteni. + +Amikor weboldalt készítesz, mindig hasonló elemekre lesz szükséged: meg kell oldanod a felhasználók azonosítását (regisztráció, be- és kijelentkezés), kell egy felület a honlap kezeléséhez, formok (kérdőívek), kell valami megoldás a fájlok feltöltésére, stb. + +Szerencsére mások már régen észrevették, hogy a webfejlesztők mindig hasonló problémákkal szembesülnek egy új oldal készítésekor, ezért közösen kifejlesztettek különböző keretrendszereket (ezek egyike a Django). Ezek a frameworkok használatra kész komponenseket tartalmaznak. + +A keretrendszerek megakadályozzák, hogy újra és újra fel kelljen találnod a spanyolviaszt, és sok időt megspórolnak a weboldalkészítésben. + +## Miért van szükséged keretrendszerre? + +Hogy megértsd, pontosan mire jó a Django, fontos, hogy jobban megismerd a szervereket. Az első dolog, amit egy szervernek tudnia kell az az, hogyha szeretnéd, hogy kiszolgáljon neked egy weboldalt. + +Képzelj el egy postaládát (port), amit folyamatosan figyelnek, hogy vannak-e beérkezett levelek (requestek). Ezt csinálja egy webszerver. A webszerver elolvassa a levelet, és választ (response) küld, amiben egy weboldal van. Azonban amikor küldeni szeretnél valamit, szükséged van tartalomra. A Django ennek a tartalomnak a megalkotásában segít. + +## Mi történik, amikor valaki lekérdez egy honlapot a szerveredtől? + +Amikor beérkezik egy kérés (request) a szerverre, a Django kapja meg, ami megpróbálja kitalálni, hogy pontosan mire irányul a kérés. Először a weboldal címét nézi meg, és megpróbál rájönni, hogy mit kell tenni. Ezt a részt a Django **urlresolver** része végzi (emlékezz vissza, hogy a weboldalak címét URL-nek - Uniform Resource Locatornak - hívják, vagyis az *urlresolver* névnek - kb. url-fordító - van értelme). Ez a dolog nem túl okos - csak fog egy csomó mintát (pattern), és megpróbálja hozzájuk illeszteni az URL-t. A Django felülről lefelé vizsgálja meg a mintákat, és ha az URL valamelyikkel megegyezik, továbbadja a requestet a megfelelő function-nek (függvénynek), amit *view*-nak hívunk). + +Képzelj el egy postást egy levéllel. Ahogy halad az utcán, minden házszámot megnéz, és összehasonlítja a levélen lévővel. Ha megegyezik, bedobja a levelet a postaládába. Így működik az urlresolver! + +A *view*, vagyis "nézet" rész az, ahol az érdekes dolgok történnek: itt nézhetünk bele adatbázisokba, hogy megkeressünk valamilyen információt. Talán a felhasználó meg szeretne változtatni valamilyen adatot? Mint egy levél, ami azt írja: "Kérlek, változtasd meg a munkám leírását." A *view* megnézi, hogy jogosult vagy-e erre a módosításra, aztán megváltoztatja a munka leírását, és visszaküld egy üzenetet: "Kész!". Aztán a *view* létrehoz egy választ, amit a Django elküld a felhasználó böngészőjének. + +Természetesen ez a leírást egy kicsit leegyszerűsítettünk, de még nem kell, hogy minden technikai részletet tudj. Elég, ha van egy általános elképzelésed. + +Most ahelyett, hogy túlságosan belemennénk a részletekbe, egyszerűen csak elkezdünk létrehozni valamit a Djangóval, és menet közben fogjuk megtanulni a fontos részeket! \ No newline at end of file diff --git a/hu/django_admin/README.md b/hu/django_admin/README.md new file mode 100644 index 00000000000..41fcb46710d --- /dev/null +++ b/hu/django_admin/README.md @@ -0,0 +1,48 @@ +# Django admin + +Az előbb elkészítettük a bejegyzések modelljeit. Ahhoz, hogy létrehozhassuk, szerkeszthessük és törölhessük őket, a Django admint fogjuk használni. + +Nyisd meg a `blog/admin.py` fájlt, és cseréld ki a benne lévő kódot erre: + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Amint láthatod, importáljuk az előző fejezet végén definiált Post modellt, vagyis elérhetővé tesszük ebben a fájlban is. Hogy a modell látszódjon az admin oldalon, regisztrálnunk kell a `admin.site.register(Post)` sorral. + +Most nézzük meg, hogy néz ki a Post modell. Ne felejtsd el futtatni a `python manage.py runserver` parancsot a konzolban, hogy elindítsd a webszervert. Írd be a böngészőben a http://127.0.0.1:8000/admin/ címet. Egy ilyen login oldalt fogsz látni: + +![Login page][1] + + [1]: images/login_page2.png + +A bejelentkezéshez létre kell hoznod egy *superuser*-t - egy olyan felhasználót, akinek mindenhez van hozzáférése az oldalon. Menj vissza a parancssorba, és írd be a `python manage.py createsuperuser` parancsot, majd nyomj entert. A következő lépésekben meg kell adnod egy felhasználónevet (ne használj nagybetűket és szóközt), emailcímet és jelszót. Ne ijedj meg, ha nem látod a jelszót, amikor begépeled - ennek így kell lennie. Csak írd be, és nyomj `enter`t a folytatáshoz. Az outputnak így kell kinéznie (természetesen a felhasználónév és az email az lesz, amit te adtál meg): + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Térj vissza a böngészőbe. Jelentkezz be a superuser adataival, amit az előbb adtál meg; ha minden jól megy, a Django admin dashboardra jutsz. + +![Django admin][2] + + [2]: images/django_admin3.png + +Nyisd meg a Posts részt, és kísérletezz vele egy kicsit. Hozz létre 5-6 blogposztot. Ne törődj a tartalommal - nyugodtan másolj be valami szöveget ebből a tutorialból, hogy időt spórolj :). + +Állíts be legalább két-három posztnak (de ne mindegyiknek!) egy publish date-et (megjelenési dátumot). Később jól fog jönni. + +![Django admin][3] + + [3]: images/edit_post3.png + +Ha szeretnél többet megtudni a Django adminról, a Django dokumentációban tudsz olvasni róla: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +Itt az ideje, hogy kávézz vagy teázz egyet, vagy egyél valamit, hogy új erőre kapj. Elkészítetted az első Django modelledet - megérdemelsz egy kis lazítást! \ No newline at end of file diff --git a/hu/django_admin/images/django_admin3.png b/hu/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/hu/django_admin/images/django_admin3.png differ diff --git a/hu/django_admin/images/edit_post3.png b/hu/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/hu/django_admin/images/edit_post3.png differ diff --git a/hu/django_admin/images/login_page2.png b/hu/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/hu/django_admin/images/login_page2.png differ diff --git a/hu/django_forms/README.md b/hu/django_forms/README.md new file mode 100644 index 00000000000..6a83a7af970 --- /dev/null +++ b/hu/django_forms/README.md @@ -0,0 +1,396 @@ +# Django űrlapok + +Utolsó lépésként azt fogjuk megcsinálni, hogy a blogposztokat ne csak az admin oldalon hozhassuk létre és szerkeszthessük. A Django `admin` menő, de elég nehéz személyre szabni, és nem is túl szép. A `form`ok (űrlapok) segítségével viszont majdnem mindent meg tudunk csinálni a felületünkön, amit csak szeretnénk! + +A Django formokban az a jó, hogy ha akarjuk, teljesen az alapoktól is megírhatjuk őket, de `ModelForm`-ot is létrehozhatunk, ami az űrlap eredményét a modellbe menti el. + +Pontosan ezt szeretnénk: egy űrlapot a `Post` modellünkhöz. + +Mint minden fontos résznek a Django-ban, a formoknak is megvan a maguk helye: a `forms.py` fájl. + +Hozz létre egy új fájlt ezzel a névvel a `blog` könyvtárban. + + blog + └── forms.py + + +Rendben, most nyisd meg, és írd bele a következő kódot: + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Először importálnunk kell a Django formjait (`from django import forms`), és persze a `Post` modellünket is (`from .models import Post`). + +Valószínűleg már sejted, hogy a `PostForm` az űrlapunk neve lesz. Meg kell mondanunk a Django-nak, hogy ez a form egy `ModelForm` (hogy egy kis Django varázslat kerüljön bele) - ezért a `forms.ModelForm` felelős. + +Aztán a `class Meta` következik, itt mondjuk meg a Django-nak, hogy melyik modellt kell használnia az űrlap elkészítéséhez (`model = Post`). + +Legvégül megadhatjuk, hogy melyik mezők kerüljenek bele az űrlapba. Mi csak a `title` (cím) és a `text` (szöveg) mezőket szeretnénk megjeleníteni - az `author` (szerző) az a felhasználó lesz, aki éppen be van jelentkezve (te magad!), és a `created_date`-et (létrehozás dátumát) automatikusan állítja be a Django, amikor elmented a posztot, emlékszel? + +Ennyi az egész! Most már csak az van hátra, hogy használjuk az űrlapot egy *view*-ban, és megjelenítsük egy template-ben. + +Tehát még egyszer: egy link az oldalhoz, egy URL, egy view és egy template. + +## Link az oldalhoz, ahol az űrlap van + +Itt az ideje, hogy megnyisd a `blog/templates/blog/base.html` fájlt. Itt hozzáadunk egy linket a `page-header` nevű `div`hez: + +```html + +``` + +Figyelem: az új nézetünket `post_new`-nak fogjuk hívni. + +Miután hozzáadtad ezt a sort, így fog kinézni a html fájlod: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Ha elmented, és frissíted a http://127.0.0.1:8000 oldalt, az ismerős `NoReverseMatch` hibát kell látnod, igaz? + +## URL + +Nyisd meg a `blog/urls.py` fájlt, és add hozzá ezt a sort: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + +Így fog kinézni a teljes kód: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +Ha frissíted az oldalt, egy `AttributeError`t fogsz látni, hiszen még nincs implementálva a `post_new` nevű view. Készítsük el most rögtön. + +## post_new nézet + +Nyisd meg a `blog/views.py` fájlt, és add hozzá a következő sorokat: + +```python +from .forms import PostForm +``` + +és a *view*t: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Ahhoz, hogy egy új `Post` űrlapot kapjunk, meg kell hívnunk a `PostForm()`-ot, és továbbadni a template-nek. Még visszatérünk erre a *view*-ra, de előbb gyorsan készítsük egy sablont a formnak. + +## Template + +Létre kell hoznunk egy `post_edit.html` nevű fájlt a `blog/templates/blog` könyvtárban. Ahhoz, hogy működjön az űrlapunk, szükségünk van pár dologra: + +* meg kell jelenítenünk az űrlapot. Ezt egyszerűen megtehetjük a `{% raw %}{{ form.as_p }}{% endraw %}` kóddal. +* az előző sort be kell csomagolnunk egy HTML form tagbe: `
...
` +* szükségünk van egy `Save` (Mentés) gombra. Ezt egy HTML gombbal tudjuk létrehozni: `` +* és végül, a nyitó `
` tag után hozzá kell adnunk ezt: `{% raw %}{% csrf_token %}{% endraw %}`. Ez nagyon fontos, mert ettől lesznek biztonságosak az űrlapjaid! A Django panaszkodni fog, ha úgy próbálod elmenteni a formot, hogy kifelejtetted ezt a részt: + +![CSFR tiltott oldal][1] + + [1]: images/csrf2.png + +Rendben, nézzük, hogy néz ki a HTML kód a `post_edit.html`-ben: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Itt az ideje, hogy frissítsd az oldalt! Juhú! Ott van az űrlapod! + +![Új űrlap][2] + + [2]: images/new_form2.png + +De várjunk csak egy percet! Ha begépelsz valamit a `title` és a `text` mezőbe, és megpróbálod elmenteni - mi történik? + +Semmi! Megint ugyanazon az oldalon vagyunk, és a szöveg eltűnt... és nem jött létre új bejegyzés. Mi romlott el? + +A válasz: semmi. Csak még egy kicsit dolgoznunk kell a *view*-n. + +## Űrlap mentése + +Nyisd meg újra a `blog/views.py` fájlt. Most mindössze ennyi van a `post_new` nézetben: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Amikor beküldünk egy űrlapot, ugyanabba a nézetbe kerülünk vissza, de ilyenkor a `request`ben több adat van, mint korábban, egész pontosan a `request.POST`-ban (ennek az elnevezésnek nincs köze a blogban lévő "poszt"-hoz, ez annyit jelent, hogy éppen adatokat "posztolunk", vagyis küldünk). Emlékszel, hogy a HTML fájlban a `
` definíciójában szerepelt a `method="POST"` változó? Most az űrlap minden mezője bekerült a `request.POST`-ba. Semmiképp se nevezd át a `POST` (a `method` másik érvényes értéke a `GET` lenne, de most nincs idő elmagyarázni a különbséget). + +Tehát a *view*-ban két különböző esetet kell kezelnünk. Az első: amikor először kerülünk az oldalra, és egy üres űrlapot szeretnénk látni. A második: amikor visszajutunk a *view*-ba, azokkal az adatokkal, amiket épp az előbb gépeltünk be a formba. Ehhez egy feltételt kell hozzáadnunk (az `if`-et fogjuk használni). + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Itt az ideje, hogy kitöltsük a `[...]` részeket. Ha a `method` `POST`, akkor egy `PostForm`-ot szeretnénk létrehozni az űrlapban beküldött adatokból, igaz? Ezt így tehetjük meg: + +```python +form = PostForm(request.POST) +``` + +Nem nehéz! A következő, hogy ellenőrizzük, helyes-e az űrlap (minden kötelező mező ki lett-e töltve, és nem készülünk-e helytelen adatokat elmenteni). Ezt csinálja a `form.is_valid()`. + +Megnézzük, hogy érvényes-e a form, és ha igen, elmenthetjük! + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Itt lényegében két dolog történik: elmentjük az űrlapot a `form.save` paranccsal, és hozzáadunk egy szerzőt (mivel nem volt `author` mező a `PostForm`-ban, viszont ez a mező kötelező!). A `commit=False` azt jelenti, hogy még nem mentjük el a `Post` modellt - előbb még hozzá akarunk adni egy szerzőt. Az idő nagy részében a `commit=False` nélkül fogod használni a `form.save()`-et, de most szükségünk van erre a részre. A `post.save()` megőrzi a változtatásokat (szerző hozzáadása), és létrehoz egy új blogposztot! + +Végül tök jó lenne, ha egyből a frissen elkészült bejegyzés `post_detail` oldalára jutnánk nem? Ehhez egy újabb importra van szükségünk: + +```python +from django.shortcuts import redirect +``` + +Ezt írd a fájlod elejére. És most megmondhatjuk a Django-nak: menj az új blogposzt `post_detail` oldalára. + +```python +return redirect('blog.views.post_detail', pk=post.pk) +``` + +A `blog.views.post_detail` a nézet neve, ahova most menni akarunk. Emlékszel, hogy ez a *view* egy `pk` változót kér? Ahhoz, hogy ezt megkapja, a `pk=post.pk` részt használjuk, ahol a `post` az új blogposztunkat jelenti! + +Rendben, elég sokat beszéltünk, de most már látni szeretnéd, hogy néz ki a teljes *view*, igaz? + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Nézzük meg, hogy működik-e. Menj a http://127.0.0.1:8000/post/new/ oldalra, adj hozzá egy `title`-t és egy `text`-et, mentsd el... és voilà! Az új poszt bekerült az adatbázisba, és át lettél irányítva a `post_detail` oldalra! + +Talán észrevetted, hogy a poszt elmentése előtt beállítjuk a közzététel dátumát. Később, a **Django Girls Tutorial: Extensions** részben egy *publish* gombot is készítünk. + +Ez nagyszerű! + +## Form validáció + +Most megmutatjuk, mennyire menők a Django űrlapok. Egy blogposztnak kell, hogy legyen `title` és `text` mezője. A `Post` modellben nem jelentettük ki külön, hogy ezek a mezők nem kötelezőek (ellentétben a `published_date` mezővel), ezért a Django elvárja, hogy ki legyenek töltve. + +Próbáld meg elmenteni az űrlapot `title` vagy `text` nélkül. Találd ki, mi fog történni! + +![Form validáció][3] + + [3]: images/form_validation2.png + +A Django gondoskodik az összes mező ellenőrzéséről. Hát nem fantasztikus? + +> Mivel nemrég használtuk a Django admin felületét, a rendszer most azt hiszi, hogy be vagyunk jelentkezve. Néhány esetben előfordul, hogy a rendszer kijelentkeztet minket (pl. ha bezárod a böngészőt vagy újraindítod az adatbázist). Ha azt veszed észre, hogy a hibaüzenetek arra utalnak, hogy nincs bejelentkezett felhasználó, menj az admin oldalra -http://127.0.0.1:8000/admin - és jelentkezz be újra. Ez ideiglenesen megoldja a problémát. Van egy hosszútávú megoldás is a **Házi feladat: tedd biztonságosabbá a weboldalad!** fejezetben a tutorial fő része után. + +![Bejelentkezési hiba][4] + + [4]: images/post_create_error.png + +## Űrlapok szerkesztése + +Most már tudod, hogyan tudsz új formot hozzáadni. De mi van, ha egy létező űrlapot szeretnél módosítani? Az eddigiekhez nagyon hasonlóan fog működni. Gyorsan készítsük néhány fontos dolgot (ha nem értesz valamit, kérdezd meg a coachodat, vagy nézz bele az előző fejezetekbe, hiszen ezeket a lépéseket már mind megcsináltad egyszer). + +Nyisd meg a `blog/templates/blog/post_detail.html` fájlt, és add hozzá ezt a sort: + +```python + +``` + +Így fog kinézni a template: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +A `blog/urls.py`-ban pedig erre a sorra lesz szükségünk: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Itt újrahasznosíthatjuk a `blog/templates/blog/post_edit.html` sablont, szóval már csak egy *view* van hátra. + +Nyisd meg a `blog/views.py`-t, és add hozzá ezt a fájl végén: + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Majdnem pont úgy néz ki, mint a `post_new` view, nem igaz? De nem teljesen. Először is átadunk egy extra `pk` paramétert az url-ekből. Aztán a `Post` modellt a `get_object_or_404(Post, pk=pk)` sorral kapjuk meg, és végül, amikor létrehozzuk a formot, ezt a posztot adjunk át `instance`-ként, amikor elmentjük: + +```python +form = PostForm(request.POST, instance=post) +``` + +és akkor is, amikor megnyitjuk az űrlapot, hogy szerkeszthessük a posztot: + +```python +form = PostForm(instance=post) +``` + +Oké, most teszteljük le, hogy működik-e! Menj a `post_detail` oldalra. Kell lennie egy szerkesztés gombnak a jobb felső sarokban: + +![Szerkesztés gomb][5] + + [5]: images/edit_button2.png + +Ha rákattintasz, megkapod az űrlapot a blogposzttal: + +![Űrlapok szerkesztése][6] + + [6]: images/edit_form2.png + +Változtasd meg a címet vagy a szöveget, és mentsd el! + +Gratulálunk! Az alkalmazásod egyre és egyre jobb! + +Ha szeretnél többet tudni a Django formokról, olvass róluk a dokumentációban: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## Biztonság + +Nagyon jó, hogy az új blogposztok írásához csak egy linkre kell kattintani! Viszont most bárki létre tud hozni egy új bejegyzést, aki meglátogatja az oldaladat, és valószínűleg ezt nem szeretnéd. Csináljuk meg, hogy a gombot csak te lásd, és mások ne. + +A `blog/templates/blog/base.html`-ben keresd meg a `page-header` `div`et, és az anchor taget, amit korábban írtál bele. Így néz ki: + +```html + +``` + +Írunk még egy `{% if %}` taget, ami arra lesz jó, hogy csak azoknak az usereknek mutassa a linket, akik be vannak jelentkezve az adminba. Most ez csak te vagy! Változtasd meg a `` taget, hogy így nézzen ki: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Az `{% if %}` miatt a link csak akkor küldődik át a böngészőbe, ha a felhasználó, aki lekérte az oldalt, be van jelentkezve. Ez nem akadályozza meg teljesen az új posztok létrehozását, de kezdésnek jó. A kiegészítő leckékben többet is tanulhatsz a biztonságról. + +Mivel valószínűleg be vagy jelentkezve, semmi változást nem fogsz látni, ha frissítesz. Viszont ha megnyitod az oldalt egy másik böngészőben, vagy egy inkognitóablakban, látni fogod, hogy a link nincs ott! + +## Még egy dolog: itt az ideje egy újabb deploynak! + +Nézzük meg, hogy működik-e ez az egész a PythonAnywhere-en. Itt az ideje egy újabb deploynak! + +* Először is commitold az új kódodat, és pushold GitHubra +``` +$ git status +$ git add --all . +$ git status +$ git commit -m "Added views to create/edit blog post inside the site." +$ git push +``` + +* Aztán írd be ezt a [PythonAnywhere Bash konzol][7]ba: + + [7]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Végül menj a [Web tab][8]-ra, és nyomj **Reload**ot. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +Ennyi az egész. Gratulálunk :) diff --git a/hu/django_forms/images/csrf2.png b/hu/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/hu/django_forms/images/csrf2.png differ diff --git a/hu/django_forms/images/drafts.png b/hu/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/hu/django_forms/images/drafts.png differ diff --git a/hu/django_forms/images/edit_button2.png b/hu/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/hu/django_forms/images/edit_button2.png differ diff --git a/hu/django_forms/images/edit_form2.png b/hu/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/hu/django_forms/images/edit_form2.png differ diff --git a/hu/django_forms/images/form_validation2.png b/hu/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/hu/django_forms/images/form_validation2.png differ diff --git a/hu/django_forms/images/new_form2.png b/hu/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/hu/django_forms/images/new_form2.png differ diff --git a/hu/django_forms/images/post_create_error.png b/hu/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/hu/django_forms/images/post_create_error.png differ diff --git a/hu/django_installation/README.md b/hu/django_installation/README.md new file mode 100644 index 00000000000..e1f8f731196 --- /dev/null +++ b/hu/django_installation/README.md @@ -0,0 +1,5 @@ +# Django telepítés + +> **Megjegyzés** Ha elvégezted a legelső, Installáció című fejezetet, már túlvagy ezen - ugorj a következő fejezetre! + +{% include "/django_installation/instructions.md" %} diff --git a/hu/django_installation/instructions.md b/hu/django_installation/instructions.md new file mode 100644 index 00000000000..139c8f2100c --- /dev/null +++ b/hu/django_installation/instructions.md @@ -0,0 +1,113 @@ +> Ennek a fejezetnek egy része a Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) tutorialjain alapul. +> +> A fejezet részben a [django-marcador tutorial](http://django-marcador.keimlink.de/)-on alapszik, ami a Creative Commons Attribution-ShareAlike 4.0 International License jogvédelem alatt áll. A django-marcador tutorial jogvédelem alatt áll, Markus Zapke-Gründemann et al által. + +## Virtuális környezet + +Mielőtt feltelepítjük a Django-t, egy rettentő hasznos eszközt fogunk installálni, ami segít, hogy a kódolói környezetedet rendben tartsa a számítógépeden. Át lehet ugrani ezt a lépést, de nem ajánlott. Ha a lehető legjobb kiindulási helyzetből kezded a kódolást, sok bosszúságot megspórolhatsz magadnak a jövőben! + +Tehát először is hozzunk létre egy **virtuális környezetet** (virtual environment), amit *virtualenv*-nek is hívunk. A virtualenv projektenként különíti el a Python/Django környezetet. Ez azt jelenti, hogy ha megváltoztatsz valamit egy weboldalon, az nem lesz hatással a többi weboldalra, amit párhuzamosan fejlesztesz. Jó, igaz? + +Csak annyit kell tenned, hogy kiválasztasz egy könyvtárat, ahova a `virtualenv`et szeretnéd telepíteni, például a home könyvtárat. Windowson ez így nézhet ki: `C:\Users\Name` (ahol a `Name` a felhasználód neve). + +Ehhez a tutorialhoz egy új, `djangogirls` nevű mappát fogunk használni a home könyvtáradon belül: + + mkdir djangogirls + cd djangogirls + + +Most pedig létrehozunk egy `myvenv` nevű virtuális környezetet. A kód általánosan így néz ki: + + python3 -m venv myvenv + + +### Windows + +Ahhoz, hogy létrehozz egy új `virtualenv`-et, meg kell nyitni a konzolt (pár fejezettel ezelőtt tanultál róla - emlékszel?) és a ezt a parancsot kell lefuttatnod: `C:\Python34\python -m venv myvenv`. Ez fog történni: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + +itt a `C:\Python34\python` azt a könyvtárat jelenti, ahova korábban a Pythont telepítetted, és a `myvenv` a `virtualenv`-ed neve. Bármi más nevet is használhatsz, de maradj a kisbetűs szavaknál, és ne használj szóközt, ékezeteket, vagy más speciális karaktereket. Jó ötlet rövid nevet adni - sokszor be kell majd gépelned! + +### Linus és OS X + +A `virtualenv` létrehozása Linux és OS X környezetben is csak annyiból áll, hogy a `python3 -m venv myvenv` parancsot futtatod. Így fog kinézni: + + ~/djangogirls$ python3 -m venv myvenv + + +A `myvenv` a`virtualenv`-ed neve. Más nevet is használhatsz, de maradj a kisbetűs szavaknál, és ne használj szóközt, ékezeteket, vagy más speciális karaktereket. Jó ötlet rövid nevet adni - sokszor be kell majd gépelned! + +> **MEGJEGYZÉS:** A virtuális környezetet létrehozó parancs Ubuntu 14.04 alatt ezt a hibát adja: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Hogy ezt elkerüld, használd a `virtualenv` parancsot. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Hogyan dolgozhatsz virtuális környezetben + +A fenti parancs létrehozott egy `myvenv` nevű (vagy bármi más név, amit választottál) könyvtárat, ami a virtuális környezetünket tartalmazza (ez tulajdonképpen csak egy csomó könyvtár és fájl). + +#### Windows + +Így indíthatod el a virtuális környezetet: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +#### Linus és OS X + +Így indíthatod el a virtuális környezetet: + + ~/djangogirls$ source myvenv/bin/activate + + +Fontos, hogy `myvenv` helyett azt a neved írd be, amit a `virtualenv`-ednek választottál! + +> **MEGJEGYZÉS:** néha a `source` nem elérhető. Ebben az esetben próbáld meg ezt: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Onnan tudod, hogy a `virtualenv` elindult, hogy a konzolodban a prompt így néz ki: + + (myvenv) C:\Users\Name\djangogirls> + + +vagy: + + (myvenv) ~/djangogirls$ + + +Figyeld meg, hogy megjelent a `(myvenv)` előtag! + +Ha virtuális környezetben dolgozol, a `python` parancs mindig a megfelelő Python verzióra fog mutatni, tehát nyugodtan használhatod a `python`-t `python3` helyett. + +Oké, most már minden feltétel teljesült. Végre installálhatjuk a Django-t! + +## A Django telepítése + +Most, hogy elindítottad a `virtualenv`-et, a `pip` segítségével tudod telepíteni a Django-t. Futtasd ezt a parancsot a konzolban: `pip install django==1.8` (figyelj oda, hogy dupla egyenlőségjelet használj: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +Windowson + +> Ha hibát kapsz, amikor a pip-et hívod Windowson, nézd meg, hogy tartalmaz-e a projekted elérési útvonala szóközt, ékezetet, vagy speciális karaktereket (pl. `C:\Users\User Name\djangogirls`). Ha igen, helyezd át az egészet egy olyan helyre, ahol nincsenek szóközök, ékezetek vagy speciális karakterek (javaslat: `C:\djangogirls`). Miután áthelyezted, próbáld meg újra lefuttatni az előző parancsot. + +Linuxon + +> Ha Ubuntu 12.04 alatt hibát kapsz, amikor a pip-et próbálod hívni, futtasd a `python -m pip install -U --force-reinstall pip` parancsot, hogy megjavítsd a virtualenv-ben a pip feltelepített verzióját. + +Ennyi! Most pedig (végre) létrehozhatod a Django alkalmazásodat! diff --git a/hu/django_models/README.md b/hu/django_models/README.md new file mode 100644 index 00000000000..b80121951bf --- /dev/null +++ b/hu/django_models/README.md @@ -0,0 +1,172 @@ +# Django modellek + +Most valami olyasmire van szükségünk, ami eltárolja az összes blogbejegyzést. De ahhoz, hogy létre tudjunk hozni ilyesmit, előbb egy kicsit beszélnünk kell az `objektumokról`. + +## Objektumok + +Létezik egy `objektumorientált programozás` nevű fogalom a programozáson belül. Ennek az az alapötlete, hogy ahelyett, hogy mindent utasítások unalmas sorozataként írnánk le, modellezhetjük is a dolgokat, és definiálhatjuk, hogyan lépnek kapcsolatba egymással. + +Tehát mi az az objektum? Tulajdonságok és tevékenységek gyűjteménye. Furán hangozhat, de mindjárt mutatunk egy példát. + +Ha egy macskát szeretnék modellezni, létrehozunk egy `Cat` (macska) objektumot, aminek van néhány tulajdonsága: `color` (szín), `age` (életkor), `mood` (kedv -például jó, rossz, álmos ;)), és `owner` (tulajdonos - aki egy `Person` (személy) objektum, és talán, ha kóbor macskáról van szó, ez a tulajdonság üres). + +Aztán a `Cat`-hez tartozik néhány tevékenység: `purr` (dorombolás), `scratch` (karmolás), vagy `feed` (evés - ahol a macskának adunk egy kis macskaeledelt, vagyis `CatFood`-ot, ami egy külön objektum, saját tulajdonságokkal, mint például `taste` (íz)). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + +Tehát az egésznek az az alapötlete, hogy a valós dolgokat kódban tulajdonságokkal (vagyis `object property`-kkel) és tevékenységekkel (vagyis `method`-okkal) írjuk le. + +Hogyan modellezzük a blogposztokat? Egy blogot szeretnénk fejleszteni, ugye? + +Erre a kérdésre keressük a választ: Mi egy blogposzt? Milyen tulajdonságai vannak? + +Nos, a bejegyzésünknek biztos van szövege, és címe, igaz? Azt is jó lenne tudni, hogy ki írta - vagyis szükségünk van egy szerzőre is. Végül tudni szeretnénk, mikor lett megírva és közzétéve a poszt. + + Post + -------- + title + text + author + created_date + published_date + + +Milyen dolgokat lehet csinálni egy blogbejegyzéssel? Jó lenne, ha lenne valamiféle `method`, ami közzéteszi a posztot, nem? + +Tehát szükségünk van egy `publish` methodra. + +Most, hogy tudjuk, mit szeretnénk elérni, kezdjük el modellezni Django-ban! + +## Django modell + +Most, hogy tudjuk, mik az objektumok, már el tudjuk készíteni a blogposzt Django modelljét. + +A Django-ban a modellek speciális objektumok - az `adatbázisban` vannak elmentve. Az adatbázis tulajdonképpen adatok gyűjteménye. Ez az a hely, ahol adatokat tárolhatsz a felhasználókról, a blogposztokról, stb. Mi egy SQLite adatbázist fogunk használni az adataink tárolásához. Ez az alapértelmezett Django adatbázis adapter -- ez egyelőre elég is lesz nekünk. + +Az adatbázisban lévő modellt úgy képzeld el, mint egy táblázatot (pl. az Excelben), ahol oszlopok (mezők) és sorok (adatok) vannak. + +### Készítsünk egy alkalmazást! + +Hogy minden szép rendben maradjon, most a projekten belül egy külön alkalmazást hozunk létre. Jó, ha már az elejétől fogva rendezetten tartjuk a dolgokat. Ahhoz, hogy létrehozzuk az alkalmazást, ezt a parancsot kell futtatnunk a parancssorban (a `djangogirls` könyvtárban, ahol a `manage.py` fájl van): + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +Azt fogod látni, hogy egy új `blog` könyvtár keletkezett, és már most van benne néhány fájl. Így kell kinézniük a könyvtáraknak és fájloknak a projekten belül: + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +Miután létrejött az alkalmazás, meg kell mondanunk a Django-nak, hogy használja is azt. A `mysite/settings.py` tehetjük meg. Keresd meg az `INSTALLED_APPS` részt, és adj hozzá egy sort a `)` fölött, amiben ez áll: `'blog'`. Így kell kinéznie ennek a résznek: + +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` + +### Hozzuk létre a blogposzt modelljét + +A `Model` nevű objektumokat a `blog/models.py` fájlban definiáljuk - tehát itt fogjuk definiálni a blogposztunkat is. + +Nyisd meg a `blog/models.py`-t, törölj ki mindent, és ezt a kódot írd bele: + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Jól figyelj, hogy mindenképp két underscore (alulvonás) karaktert (`_`) használj a `str` mindkét oldalán. Ez a jelölés gyakran előfordul a Pythonban, és néha "dunder"-nek hívjuk (a "double underscore" - dupla alulvonás rövidítése). + +Ijesztőnek tűnik? Ne aggódj, mindjárt elmagyarázzuk, hogy mit jelentenek ezek a sorok. + +Azok a sorok, amik úgy kezdődnek, hogy `from` vagy `import`, más fájlokban lévő dolgokat adnak hozzá a fájlunkhoz. Ahelyett, hogy minden fájlba átmásolnánk ugyanazokat a dolgokat, beemelhetünk néhány dolgot a `from ... import ...` segítségével.. + +`class Post(models.Model):` - ez a sor definiálja a modellünket (ami egy `objektum`). + +* a `class` egy speciális kulcsszó, ami azt mutatja meg, hogy éppen egy objektumot definiálunk. +* a `Post` a modellünk neve. Más nevet is adhatnál neki (de kerüld el a speciális karaktereket - pl ékezetes karakterek - és a szóközt). Az osztályok (classok) nevét mindig nagybetűvel kezdjük. +* a `models.Model` azt jelenti, hogy a Post egy Django Model, így a Django tudni fogja, hogy el kell menteni az adatbázisba. + +Most pedig azokat a tulajdonságokat definiáljuk, amikről korábban beszéltünk:`title` (cím), `text` (szöveg), `created_date` (létrehozás dátuma), `published_date` (közzététel dátuma) és `author` (szerző). Ahhoz, hogy ezt megtehessük, mindegyik mezőnek meg kell határoznunk a típusát (Szöveg lesz benne? Egy szám? Dátum? Egy másik objektumhoz fog tartozni, például egy User-hez (felhasználó)?). + +* `models.CharField` - így definiálsz olyan szövegmezőt, ami meghatározott számú karaktert tartalmazhat. +* `models.TextField` - ez hosszú szövegekhez van, korlátozás nélkül. Pont jó egy blogbejegyzéshez, igaz? +* `models.DateTimeField` - ez dátumot és időt tartalmaz. +* `models.ForeignKey` - ez egy másik modellel való kapcsolatot jelent. + +Most nem magyarázzuk el nagyon részletesen a kódot, mert túl sok idő lenne. Ha szeretnél többet tudni a Model mezőkről, és hogy milyen más dolgokat lehet definiálni bennünk, olvashatsz róla a Django dokumentációban (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +És mi a helyzet a `def publish(self):` résszel? Ez pontosan az a `publish` (közzététel) method, amiről korábban beszéltünk. A `def` azt jelenti, hogy ez egy függvény (function) / method, és a `publish` ennek a methodnak a neve. Ha szeretnéd, megváltoztathatod a metódus nevét. Az a szabály, hogy csak kisbetűket használunk, és szóköz helyett underscore-t (alulvonás). Például egy olyan method neve, ami az átlagárat számolja ki, ez lehetne: `calculate_average_price`. + +A methodok gyakran `return`-ölnek (visszaadnak) valamit. Erre van is egy példa a `__str__` methodban. Ebben az esetben amikor meghívjuk a `__str__()`-t, egy szöveget kapunk vissza (**string**), ami a Post címe. + +Ha valami még nem teljesen világos a modellekkel kapcsolatban, nyugodtan kérdezd meg a coachodat! Tudjuk, hogy bonyolult, főleg, ha egyszerre tanulsz az objektumokról és a függvényekről. De reméljük, már sokkal kevésbé tűnik varázslatnak az egész! + +### Készíts táblákat a modelleknek az adatbázisodban + +Az utolsó lépés, hogy hozzáadjuk az új modellünket az adatbázishoz. Először valahogy tudatnunk kell a Django-val, hogy változtattunk a modellünkön (vagyis most alkottuk meg!). Gépeld be, hogy `python manage.py makemigrations blog`. Ez fog történni: + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +A Django létrehozott nekünk egy migrációs fájlt, amit most futtatni fogunk az adatbázison. Írd be, hogy `python manage.py migrate blog`, és ezt az outputot kell kapnod: + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK + + +Hurrá! Bekerült az adatbázisba a Post modellünk! Jó lenne látni is, nem igaz? A következő fejezetben kiderül, hogy néz ki! \ No newline at end of file diff --git a/hu/django_orm/README.md b/hu/django_orm/README.md new file mode 100644 index 00000000000..7e09e6db212 --- /dev/null +++ b/hu/django_orm/README.md @@ -0,0 +1,158 @@ +# Django ORM és QuerySet-ek + +Ebben a fejezetben megtanulod, hogy hogyan kapcsolódik az adatbázishoz a Django, és hogyan tárol benne adatokat. Ugorjunk fejest! + +## Mi a QuerySet? + +A QuerySet lényegében egy lista, amely egy bizonyos Model objektumait tartalmazza. A QuerySetek segítségével tudsz adatot kinyerni az adatbázisból, szűrheted és sorba rendezheted. + +A legkönnyebb, ha példákon keresztül tanulod meg. Próbáljuk csak ki! + +## Django shell + +Nyisd meg a lokális konzolodat (nem a PythonAnywhere-ét), és gépeld be ezt a parancsot: + + (myvenv) ~/djangogirls$ python manage.py shell + + +Ezt fogod látni: + + (InteractiveConsole) + >>> + + +Most a Django interaktív konzoljában vagy. Olyasmi, mint a Python prompt, csak egy kis extra Django varázslattal :) Természetesen itt is használhatod az összes Python parancsot. + +### Az összes objektum + +Először is próbáljuk meg az összes posztot megjeleníteni. A következő paranccsal tudod megtenni: + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +Hoppá, egy hiba! Azt mondja, hogy nincs olyan, hogy Post. Igaza van -- elfelejtettük importálni! + + >>> from blog.models import Post + + +Ez egyszerű: importáljuk a `Post` modellt a `blog.models`-ből. Próbáljuk meg újra megjeleníteni a Post-okat: + + >>> Post.objects.all() + [, ] + + +Egy lista a posztokból, amiket korábban megírtál! Ezeket még a Django admin felületén hoztad létre. Viszont ugyanezt meg tudod tenni a Python segítségével is. De vajon hogyan? + +### Objektum létrehozása + +Így hozhatsz létre egy új Post objektumot az adatbázisodban: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +De az egyik összetevő hiányzik: a `me`. Az `User` (felhasználó) modell egy instance-át kell megadnunk author-ként (szerző). Hogy tudjuk ezt megcsinálni? + +Először importáljuk az User modellt: + + >>> from django.contrib.auth.models import User + + +Milyen felhasználók vannak az adatbázisban? Próbáld meg ezt: + + >>> User.objects.all() + [] + + +Ez a superuser, amit korábban hoztál létre! Most vegyük ennek a felhasználónak egy instance-ét: + + me = User.objects.get(username='ola') + + +Ahogy láthatod, most hozzájutottunk (`get`) egy `User`-hez, `username`-mel (felhasználónév), ami 'ola'-val egyenlő. Szuper! Természetesen itt a saját felhasználónevedet kell beírnod. + +Most pedig végre létrehozhatjuk a posztot: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Hurrá! Meg akarod nézni, hogy működött-e? + + >>> Post.objects.all() + [, , ] + + +Ott is van, egy újabb poszt a listában! + +### Hozz létre még néhány posztot + +A móka kedvéért hozz létre még 2-3 posztot, hogy lásd, hogyan működik. Ha ez megvan, továbbléphetsz a következő részre. + +### Objektumok filterezése + +A QuerySet-ek egyik nagy előnye, hogy filterezhetjük (szűrhetjük) őket. Mondjuk le szeretnénk kérdezni az összes posztot, amit az ola User írt. Itt a `filter`-t fogjuk használni az `all` helyett a `Post.objects.all()`-ban. A zárójelek között megadhatjuk, hogy milyen feltétel(ek)nek kell teljesülnie ahhoz, hogy egy blogposzt bekerülhessen a querysetünkbe. Ebben az esetben az `author` (szerző) egyenlő `me`-vel (én). Ezt a Django-ban így írjuk le: `author=me`. Most így néz ki a kódunk: + + >>> Post.objects.filter(author=me) + [, , , ] + + + +És ha össze szeretnénk gyűjteni minden olyan posztot, aminek a `title` (cím) mezőjében szerepel a 'title' szó? + + >>> Post.objects.filter(title__contains='title') + [, ] + + +> **Note** A `title` és a `contains` (vagyis 'tartalmaz') között két underscore karakter (`_`) van. A Django ORM ezt a szintaxist használja arra, hogy elkülönítse a mezők neveit ("title") a műveletektől vagy filterektől ("contains"). Ha csak egy underscore-t használt, egy ilyen hibát fogsz kapni: "FieldError: Cannot resolve keyword title_contains" (kb "Mezőhiba: a title_contains kulcsszó nem található"). + +Megkaphatod az összes közzétett poszt listáját is. Ezt úgy tudod megtenni, hogy az összes poszt között szűrsz azokra, amiknél be van állítva múltbéli `published_date` (vagyis közzététel dátuma): + + >>> from django.utils import timezone + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + +Sajnos az a poszt, amit a Python konzolban hoztunk létre, még nem lett közzétéve. De ezen könnyen változtathatunk! Először is, hozzá kell férnünk a poszt instance-éhez, amit közzé szeretnénk tenni: + + >>> post = Post.objects.get(title="Sample title") + + +Aztán közzétesszük a `publish` methoddal! + + >>> post.publish() + + +Most próbáld meg újra lekérdezni a közzétett posztok listáját (nyomd meg háromszor a felfelé nyilat, és nyomj `enter`t): + + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + + +### Objektumok sorbarendezése + +A QuerySetek segítségével sorba is rendezheted az objektumok listáját. Először próbáljuk meg a létrehozás dátuma (`created_date` mező) alapján rendezni őket: + + >>> Post.objects.order_by('created_date') + [, , , ] + + +Meg is fordíthatjuk a sorrendet, ha az elejére egy `-` jelet teszünk: + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +### QuerySetek összefűzése + +A QuerySeteket kombinálhatod is, ha összefűződ őket (**chaining**): + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +Ez egy nagyon hatékony módszer, és a segítségével bonyolult query-ket írhatsz. + +Remek! Most már készen állsz a következő részre! Hogy kilépj a shellből, gépeld be ezt: + + >>> exit() + $ \ No newline at end of file diff --git a/hu/django_start_project/README.md b/hu/django_start_project/README.md new file mode 100644 index 00000000000..400c3af15dd --- /dev/null +++ b/hu/django_start_project/README.md @@ -0,0 +1,137 @@ +# Az első Django projekted! + +> Ez a fejezet részben a Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) tutorial-jain alapszik. +> +> A fejezet néhány része a [django-marcador tutorial][1] alapján készült, ami a Creative Commons Attribution-ShareAlike 4.0 International License alatt áll. A django-marcador tutorial jogait, Markus Zapke-Gründemann és társai birtokolják. + + [1]: http://django-marcador.keimlink.de/ + +Most egy egyszerű blogot fogunk készíteni! + +Az első lépés, hogy indítsunk egy új Django projektet. Ez annyit jelent, hogy lefuttatunk néhány scriptet, amit a Django tartalmaz, ezzel létrehozzuk a projekt vázát. Ez tulajdonképpen néhány mappa és fájl, amit majd később fogunk használni. + +Néhány fájl és könyvtár neve nagyon fontos a Django-ban. A fájlokat, amiket most hozunk létre, ne nevezd át! Az áthelyezésük sem egy jó ötlet. Fontos, hogy megtartsunk egy bizonyos szerkezetet, ami segít a Django-nak, hogy megtalálja a fontos dolgokat. + +> Figyelem: mindent a virtualenv-ben futtass. Ha nem látod a `(myvenv)` előtagot a konzolodban, aktiválnod kell a virtuális környezetedet. Ezt a **Django telepítés** fejezetben írtuk le, a **Virtuális környezetben való fejlesztés** résznél. Windows környezetben a `myvenv\Scripts\activate` parancssal, Mac OS / Linux alatt a `source myvenv/bin/activate` paranccsal tudod megtenni. + +Ha Mac OS-t vagy Linuxot használsz, a következő parancsot kell futtatnod; **ne felejtsd el kitenni a pontot `.` a végén**: + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +Ha Windowst használsz: **ne felejtsd el kitenni a pontot `.` a végén**: + + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> A pont `.` nagyon fontos, mert ez mondja meg a scriptnek, hogy abba a könyvtárba telepítse a Django-t, ahol éppen vagy (a pont `.` egy rövidítése ennek). +> +> **Megjegyzés** Amikor begépeled a fenti parancsokat, csak azokat a részeket írd be, amik úgy kezdődnek, hogy `django-admin` vagy `django-admin.py`. A `(myvenv) ~/djangogirls$` és `(myvenv) C:\Users\Name\djangogirls>` csak példák a parancssorodra, amely azt várja, hogy parancsokat gépelj be neki. + +A `django-admin.py` egy script, ami könyvtárakat és fájlokat hoz létre neked. Most ilyen könyvtárszerkezetednek kell lennie: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +A `manage.py` egy script, ami az oldal menedzselésében segít. Segítségével elindíthatsz egy webszervert a saját gépeden, anélkül, hogy bármit kellene installálnod, és más dolgokra is jó. + +A `settings.py` tartalmazza a weboldalat konfigurációját (beállításait),. + +Emlékszel, mit olvastál a postásról, aki azt próbálja kitalálni, hova vigye a levelet? Az `urls.py` fájl tartalmazza a mintákat, amiket az `urlresolver` használ.. + +Most ne foglalkozzunk a többi fájllal, mert azokat nem fogjuk módosítani. Az egyetlen dolog, amit ne felejts el, hogy ne töröld ki őket véletlenül! + +## A beállítások megváltoztatása + +Változtassunk meg néhány dolgot a `mysite/settings.py` fájlban. Nyisd meg a fájlt a kódszerkesztővel, amit korábban telepítettél! + +Jó lenne, ha a weboldalunk a mi időzónánk szerinti időt mutatná. Nézd meg a [wikipedia időzóna listát][2], és másold ki az időzónádat (TZ, time zone). (például `Europe/Budapest` ) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +Keresd meg a settings.py azt a sort, ami így keződik: `TIME_ZONE`, és írd át, hogy a saját időzónádat használja: + +```python + TIME_ZONE = 'Europe/Budapest' +``` + +Az "Europe/Budapest"-et változtasd meg kedved szerint. + +Szükségünk lesz még arra, hogy megadjuk a statikus fájlokhoz vezető elérési útvonalat (később mindent megtudhatsz a statikus fájlokról és a CSS-ről). Menj a fájl *végére*, és a `STATIC_URL` bejegyzés alatt adj hozzá egy következő bejegyzést `STATIC_ROOT` névvel: + +```python + STATIC_URL = '/static/' + STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## Adatbázis létrehozása + +Sok különféle adatbázis-szoftver létezik, ami adatokat tud tárolni a weboldalakhoz. Mi az alapértelmezettet fogjuk használni, az `sqlite3`-ot. + +Ez már be van állítva a `mysite/settings.py` fájlodban: + +```python + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } +``` + +Hogy létrehozz egy adatbázist a blogodhoz, futtasd le a következő parancsot a konzolban: `python manage.py migrate` (fontos, hogy a `djangogirls` könyvtárban legyél, ami tartalmazza a `djangogirls` fájlt). Ha minden jól megy, valami ilyesmit kell látnod: + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK + + +Készen is vagyunk! Itt az ideje, hogy elindítsd a webszervert, és meglásd, hogy működik-e. + +Ehhez abban a könyvtárban kell lenned, ahol a `manage.py` fájl van (a `djangogirls` könyvtárban). A konzolban a következő paranccsal tudod elindítani a szervert: `python manage.py runserver`. + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Ha Windowst használsz, és `UnicodeDecodeError` hibaüzenetet kapsz, ezt a parancsot használd: + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Most nincs más dolgod, mint ellenőrizni, hogy fut-e a weboldalad. Nyisd meg a böngésződet (Firefox, Chrome, Safari, Internet Explorer, vagy bármi más, amit használsz), és írd be a következő címet: + + http://127.0.0.1:8000/ + + +A webszerver átvette az irányítást a parancssorod fölött, egészen addig, amíg le nem állítod. Hogy újabb parancsokat írhass be, amíg fut a szerver, új terminálablakot kell nyitnod, és újraaktiválni a virtuális környezetedet. Hogy leállítsd a szervert, lépj vissza az ablakba, ahol fut, és nyomd meg a CTRL + C (Control és C billentyű egyszerre) billentyűkombinációt. (Windowson lehet, hogy a Ctrl+Break fog működni). + +Gratulálunk! Létrehoztad az első weboldaladat, és futtatad is egy webszerver segítségével! Hát nem fantasztikus? + +![It worked!][3] + + [3]: images/it_worked2.png + +Készen állsz a következő lépésre? Itt az ideje, hogy létrehozzunk némi tartalmat! diff --git a/hu/django_start_project/images/it_worked2.png b/hu/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/hu/django_start_project/images/it_worked2.png differ diff --git a/hu/django_templates/README.md b/hu/django_templates/README.md new file mode 100644 index 00000000000..ad8d0bb7f39 --- /dev/null +++ b/hu/django_templates/README.md @@ -0,0 +1,106 @@ +# Django sablonok (template) + +Itt az idő, hogy megjelenítsünk pár adatot! Ehhez Django felkínál nekünk pár beépített **template tag**-et számunkra. + +## Mik a template tag-ek? + +Mint látod, a HTML-ben nem tudsz Python kódot írni, mivel a böngészők nem értik, csak a HTML-t. Fontos tudni, hogy a HTML inkább statikus, míg Python inkább dinamikus. + +A **Django template tag-ek** lehetővé teszik, hogy Python-szerű dolgokat írjunk a HTML-be, ezáltal gyorsabban és könnyebben tudsz dinamikus weboldalt készíteni. Éljen! + +## Template a bejegyzések listájához + +Az előző fejezetben hozzáadtuk a template-hez a bejegyzéseink listáját a `post` változóban. Most meg fogjuk ezt jeleníteni a HTML-ben. + +Ahhoz, hogy kiírjunk egy változót a Django template-ben, dupla kapcsos zárójelet használunk, benne a változó nevével, mint itt: + +```html +{{ posts }} +``` + +Próbáld ki a `blog/templates/blog/post_list.html` template-ben. Cserélj ki mindent a második `
` -től a harmadikig a következővel: `{{ posts }}`. Mentsd el a fájlt és frissítsd az oldalt, hogy lásd az eredményt: + +![13.1 ábra][1] + + [1]: images/step1.png + +Ahogy látod, ez minden, amink van: + + [, ] + + +Ez azt jelenti, hogy a Django objektumok listájaként értelmezi. Emlékszel a **Bevezetés a Python-ba** című fejezetből, hogy hogyan jelenítünk meg listákat? Igen, for loop-okkal! Egy Django template-ben ezt így tudod megtenni: + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Próbáld ki a template-edben. + +![13.2 ábra][2] + + [2]: images/step2.png + +És működik! De azt akarjuk, hogy úgy jelenjen meg, mint a statikus bejegyzések, amit korábban készítettünk el a **Bevezetés a HTML-be** című fejezetben. A HTML-t és a template tageket használhatod együtt. A `body` így fog kinézni: + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %} Minden, amit a `{% for %}` és `{% endfor %}` közé írsz, a lista minden egyes elemére meg fog ismétlődni. Frissítsd az oldalt:{% endraw %} + +![13.3 ábra][3] + + [3]: images/step3.png + +Észrevetted, hogy most egy kicsit más megjelölést használtunk: `{{ post.title }}`? Az adatokat a `Post` modelben meghatározott mezők szerint érjük el. Emellett `|linebreaksbr` kíséri a szöveget, ezáltal egy filteren keresztül új bekezdéssé alakítja az új sorokat. + +## Még valami + +Jó lenne látni, hogy a weblapod még mindig működik az Interneten, nem igaz? Telepítsük újra a PythonAnywhere-en. Itt a lépések összefoglalója... + +* Először tedd fel a kódot a Github-ra +``` +$ git status +[...] +$ git add --all . +$ git status +[...] +$ git commit -m "Modified templates to display posts from database." +[...] +$ git push +``` + +* Ezután a [PythonAnywhere][4]-en menj a **Bash console**-ba (vagy indíts újat), és futtasd le: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd my-first-blog +$ git pull +[...] +``` + +* Végül, a [Web][5] menüpontban klikkelj a **Reload**-ra. A frissítések ott vannak! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Gratulálunk! Folytatásképp hozz létre új bejegyzéseket a Django adminban (ne felejts el published_date-t hozzáadni), majd frissítsd az oldalt, hogy lásd, megjelentek-e. + +Olyan, mint a varázslat? Büszkék vagyunk Rád! Hagy ott egy kicsit a gépet, megérdemelsz egy kis szünetet. :) + +![13.4 ábra][6] + + [6]: images/donut.png \ No newline at end of file diff --git a/hu/django_templates/images/donut.png b/hu/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/hu/django_templates/images/donut.png differ diff --git a/hu/django_templates/images/step1.png b/hu/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/hu/django_templates/images/step1.png differ diff --git a/hu/django_templates/images/step2.png b/hu/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/hu/django_templates/images/step2.png differ diff --git a/hu/django_templates/images/step3.png b/hu/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/hu/django_templates/images/step3.png differ diff --git a/hu/django_urls/README.md b/hu/django_urls/README.md new file mode 100644 index 00000000000..61db2cdefd6 --- /dev/null +++ b/hu/django_urls/README.md @@ -0,0 +1,125 @@ +# Django url-ek + +Mindjárt elkészíted az első weblapodat: a blogod honlapját! De előbb tanuljunk egy kicsit a Django url-ekről. + +## Mi az URL? + +Az URL egyszerűen csak egy webes cím. Minden alkalommal látsz URL-eket, amikor meglátogatsz egy weboldalt - a böngésződ címsorában találodm meg (igen! a `127.0.0.1:8000` egy URL! És a `https://djangogirls.org` is egy URL): + +![Url][1] + + [1]: images/url.png + +Az interneten minden oldalnak szüksége van egy saját URL-re. Innen tudja az alkalmazásod, hogy mit mutasson a felhasználónak, aki megnyitott egy URL-t. A Django-ban egy `URLconf` nevű dolgot használunk (URL configuration, vagyis URL beállítások). Az URLConf egy csomó minta, amit a Django megpróbál összehasonlítani az URL-lel, amit kapott, és ez alapján találja meg a helyes view-t. + +## Hogy működnek az URL-ek a Django-ban? + +Nyisd meg a `mysite/urls.py` fájlt a kódszerkesztőben, és nézd meg: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` + +Amint láthatod, a Django már előre iderakott nekünk pár dolgot. + +Azok a sorok, amik így kezdődnek: `#`, kommentek - ez azt jelenti, hogy ezeket a sorokat a Python nem futtatja le. Hasznos, igaz? + +Az admin URL, amit az előző fejezetben már meglátogattál, már itt van: + +```python + url(r'^admin/', include(admin.site.urls)), +``` + +Ez azt jelenti, hogy minden URL-nél, ami `admin/`-nal kezdődik, a Django meg fogja találni a hozzátartozó *view*-t. Ebben az esetben sok admin URL-t hozzáadunk, hogy ne kelljen az egészet ebbe a kis fájlba tömni - így olvashatóbb és letisztultabb. + +## Regex + +Kíváncsi vagy, hogyan párosítja össze a Django az URL-eket és a view-kat? Na, ez a rész trükkös. A Django `regex`-et használ (a "regular expressions", vagyis reguláris kifejezések rövidítése). A regexnek nagyon (nagyon!) sok szabálya van arra, hogy hogyan épít fel egy keresési mintázatot. Mivel a regex egy magasabb szintű téma, most nem megyünk bele a részletekbe. + +Ha szeretnéd megérteni, hogy hogyan hoztuk létre a mintákat, itt egy példa - csak néhány szabályra van szükségünk, hogy felépítsük a mintát, amit keresünk, például: + + ^ a szöveg eleje + $ a szöveg vége + \d számjegy + + ez azt jelzi, hogy az előző elem egynél többször ismétlődik + () ez a minta egy részét fogja össze + + +A Django minden mást, ami az url definícióban van, szó szerint fog értelmezni. + +Képzeld el, hogy van egy weboldalad ezzel a címmel: `http://www.mysite.com/post/12345/`, ahol a `12345/` a bejegyzésed száma. + +Minden egyes poszt számához új view-t írni nagyon idegesítő lenne. A reguláris kifejezésekkel létrehozhatunk egy mintát, ami megtalálja az URL-t, és kiszedi belőle a számot: `^post/(\d+)/$`. Nézzük meg lépésről lépésre, hogy mi történik itt: + +* A **^post/** azt mondja meg a Django-nak, hogy minden olyan url-t találjon meg, ami `post/`-tal kezdődik (rögtön ezután: `^`) +* A **(\d+)** azt jelenti, hogy ezután egy szám fog következni (egy vagy több számjegyű), és ezt a számot ki szeretnénk olvasni az URL-ből +* A **/** azt mondja meg a Django-nak, hogy utána még egy `/` karakternek kell következnie +* A **$** az URL végét jelzi, vagyis csak azok a stringeket fogja megfeleltetni a mintának, amik így végződnek: `/` + +## Az első Django URL-ed! + +Itt az ideje, hogy létrehozzuk az első URL-t! Azt szeretnénk, ha a 'http://127.0.0.1:8000/' lenne a blog kezdőoldala, és itt egy listát láthatnánk a blogbejegyzésekből. + +Fontos, hogy tisztán tartsuk a `mysite/urls.py` fájlt, ezért a `blog` alkalmazásból fogjuk importálni az url-eket. + +Töröld ki a kikommentelt soroket (azokat, amik `#` jellel kezdődnek), és adj hozzá egy sort, ami importálja a `blog.urls` a fő url-be (`''`). + +A `mysite/urls.py` fájlod most így néz ki: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + +Mostantól a Django mindent, ami a 'http://127.0.0.1:8000/'-re jön, átirányít a `blog.urls`-re, és ott fogja keresni a további tennivalókat. + +Amikor Pythonban írunk reguláris kifejezéseket, a stringek előtt mindig egy `r` áll. Ez egy hasznos tipp a Pythonnak, hogy a string tartalmazhat speciális karaktereket, de ezek a reguláris kifejezés alkotóelemei, és nem magának a Pythonnak szólnak. + +## blog.urls + +Hozz létre egy új, üres fájlt `blog/urls.py` néven. Nagyszerű! Most írd be az első két sort: + +```python +from django.conf.urls import url +from . import views +``` + +Itt csak annyi történik, hogy importáljuk a Django methodjait és az összes `view`nkat a `blog` alkalmazásból (még egyet sem írtunk meg, de mindjárt ezzel is foglalkozunk!) + +Ezután megírhatjuk az első URL mintát: + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +Amint láthatod, itt egy `post_list` nevű `view`t rendeltünk hozzá a `^$` URL-hez. Ez a regex a `^` karaktert (string kezdete) és az utána következő `$` karaktert (string vége) fogja keresni - vagyis csak az üres string felel meg neki. Ez így helyes, mert a Django URL resolverében a 'http://127.0.0.1:8000/' nem számít az URL részének. Ez a minta mondja meg a Django-nak, hogy ha valaki a 'http://127.0.0.1:8000/' címen lép be a weboldaladra, a `views.post_list` a helyes lépés. + +Az utolsó rész, `name='post_list'` az URL neve, amit a view azonosítására használunk. Ez lehet ugyanaz, mint a view neve, de lehet teljesen más is. A projekt későbbi részeiben ezeket az elnevezett URL-eket fogjuk használni, ezért fontos, hogy az app minden URL-jének nevet adjunk. Törekedj arra, hogy egyedi és könnyen megjegyezhető neveket adj. + +Minden világos? Nyisd meg a http://127.0.0.1:8000/ URL-t a böngésződben, hogy lásd az eredményt. + +![Hiba][2] + + [2]: images/error1.png + +Már nincs ott az "It works", igaz? Ne aggódj, ez csak egy hibaoldal, semmi félelmetes nincs benne! Tulajdonképpen nagyon is hasznos az ilyesmi: + +Azt olvashatod, hogy **no attribute 'post_list'**, vagyis "nincs post_list nevű attribútum". Eszedbe jut valami a *post_list*-ről? Így neveztük el a view-t! Ez azt jelenti, hogy minden a megfelelő helyen van, csak még nem hoztuk létre a *view*-t. Ne aggódj, mindjárt eljutunk odáig. + +> Ha többet szeretnél megtudni a Django URLconf-ról, nézz bele a hivatalos dokumentációba: https://docs.djangoproject.com/en/1.8/topics/http/urls/ \ No newline at end of file diff --git a/hu/django_urls/images/error1.png b/hu/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/hu/django_urls/images/error1.png differ diff --git a/hu/django_urls/images/url.png b/hu/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/hu/django_urls/images/url.png differ diff --git a/hu/django_views/README.md b/hu/django_views/README.md new file mode 100644 index 00000000000..9dabfe619b2 --- /dev/null +++ b/hu/django_views/README.md @@ -0,0 +1,38 @@ +# Django views - itt az ideje alkotni! + +Eljött az idő, hogy megszabaduljunk a hibától, amit az előző fejezetben szereztünk :) + +A *nézet (view)* az a rész, ahova az applikációnk "logikáját" írjuk. Szükség lesz a nemrég elkészült `model`-ben megadott adatokra, amit majd továbbít a `template`-nek. A template-et majd a következő fejezetben hozzuk létre. A nézetek ugyanolyan Python metódusok, mint amiket a **Bevezetés a Python-ba** című fejezetben csináltunk, csak egy kicsit bonyolultabbak. + +A nézetek a `views.py` fájlban találhatók. A *view-kat* a `blog/views.py` fájlba fogjuk írni. + +## blog/views.py + +Ok, nyissuk ki ezt a fájlt és nézzük, mi van benne: + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Egyelőre nem túl sok minden. A legegyszerűbb *view* így néz ki. + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Mint látod, létrehoztunk egy `post_list` elnevezésű metódust (`def`), ami vesz egy `request`-et és `return`-öl (visszaad) egy `render` metódust, ami összeállítja a `blog/post_list.html` template-et. + +Mentsd el a fájlt, menj a http://127.0.0.1:8000/ címre és lássuk, mink van. + +Újabb hiba! Olvasd el, mi a helyzet: + +![Hiba][1] + + [1]: images/error.png + +Ez egyszerű: *TemplateDoesNotExist*. Javítsuk ki ezt a hibát, és hozzunk létre egy template-et a következő fejezetben! + +> Tanulj meg többet a Django nézetekről a hivatalos dokumentációból: https://docs.djangoproject.com/en/1.8/topics/http/views/ \ No newline at end of file diff --git a/hu/django_views/images/error.png b/hu/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/hu/django_views/images/error.png differ diff --git a/hu/domain/README.md b/hu/domain/README.md new file mode 100644 index 00000000000..4357ae76e5f --- /dev/null +++ b/hu/domain/README.md @@ -0,0 +1,71 @@ +# Domain + +Heroku gave you a domain, but it's long, hard to remember, and ugly. It'd be awesome to have a domain name that is short and easy to remember, right? + +In this chapter we will teach you how to buy a domain and direct it to Heroku! + +## Hol tudsz domaint regisztrálni? + +A typical domain costs around $15 a year. There are cheaper and more expensive options, depending on the provider. There are a lot of companies that you can buy a domain from: a simple [google search][1] will give hundreds of options. + + [1]: https://www.google.com/search?q=register%20domain + +Our favourite one is [I want my name][2]. They advertise as "painless domain management" and it really is painless. + + [2]: https://iwantmyname.com/ + +## How to register domain in IWantMyName? + +Go to [iwantmyname][3] and type a domain you want to have in the search box. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +You should now see a list of all available domains with the term you put in the search box. As you can see, a smiley face indicates that the domain is available for you to buy, and a sad face that it is already taken. + +![][5] + + [5]: images/2.png + +We've decided to buy `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Go to checkout. You should now sign up for iwantmyname if you don't have an account yet. After that, provide your credit card info and buy a domain! + +After that, click `Domains` in the menu and choose your newly purchased domain. Then locate and click on the `manage DNS records` link: + +![][7] + + [7]: images/4.png + +Now you need to locate this form: + +![][8] + + [8]: images/5.png + +And fill it in with the following details: - Hostname: www - Type: CNAME - Value: your domain from Heroku (for example djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Click the Add button and Save changes at the bottom. + +It can take up to a couple of hours for your domain to start working, so be patient! + +## A domain beállítása Herokun + +You also need to tell Heroku that you want to use your custom domain. + +Go to the [Heroku Dashboard][10], login to your Heroku account and choose your app. Then go into app Settings and add your domain in the `Domains` section and save your changes. + + [10]: https://dashboard.heroku.com/apps + +That's it! \ No newline at end of file diff --git a/hu/dynamic_data_in_templates/README.md b/hu/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..b4c81dc739c --- /dev/null +++ b/hu/dynamic_data_in_templates/README.md @@ -0,0 +1,74 @@ +# Dinamikus adatok a template-ben + +Az összetevőink különböző helyeken vannak: a `Post` modellt a `models.py`-ban definiáltuk, a `post_list` a `views.py`-ban van, és létrehoztunk egy sablont is. De mégis hogyan fogjuk megjeleníteni a bejegyzést a HTML sablonban? Mert pontosan ez az, amit szeretnénk: fogjuk a tartalmat (az adatbázisban elmentett modelleket) és szépen megjelenítjük a sablonunkban. + +Pont ez az, amit a *nézetek (views)* csinálnak: összekötik a modelleket a sablonokkal. A `post_list` *view*-ba kell berakni a modelleket, amiket meg akarunk jeleníteni, és továbbítani a sablonba. Tehát a *nézet*ben eldöntjük, hogy mi fog megjelenni a sablonban. + +OK, hogyan fogjuk ezt megvalósítani? + +Meg kell nyitni a `blog/views.py` fájlt. Eddig így nézett ki a `post_list` *view*: + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Emlékszel, amikor azt magyaráztuk, hogyan tudsz korábban megírt kódot beletenni más fájlokba? Most itt az alkalom, hogy beletegyük a modelt, amit a `models.py`-ba írtunk. A `from .models import Post` sort a következőképpen adjuk hozzá: + +```python +from django.shortcuts import render +from .models import Post +``` + +A pont a `from` után az *aktuális könyvtárt*, vagy az *aktuális applikációt* jelenti. Mivel a `views.py` és a `models.py` ugyanabban a könyvtárban vannak, elég annyit használnunk, hogy `.` és a fájl nevét (`.py` nélkül). Ezután importáljuk a model nevét.). + +De mi jön ezután? Ahhoz, hogy megkapjuk az aktuális blog bejegyzést a `Post` modelből, szükségünk lesz valamire, amit `QuerySet`-nek hívnak. + +## QuerySet + +Már ismerős lehet, hogy hogyan működik a QuerySet. A [Django ORM (QuerySets)][1] fejezetben már beszéltünk róla. + + [1]: ../django_orm/README.md + +Most azok a bejegyzések érdekelnek minket, amik publikálva vannak és a `published_date` szerint vannak sorba rendezve. Ezt már megtettük a QuerySets fejezetben! + + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +Most ezt a kódrészletet rakjuk a `blog/views.py` fájlba, hozzáadva a `def post_list(request)` function-hoz: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + +Figyeld meg, hogy létrehozunk egy *változót* a QuerySethez: `posts`. Vedd úgy, hogy ez a QuerySet neve. Innentől kezdve erre a névre hivatkozva használjuk. + +Szintén fontos, hogy a kód a `timezone.now()` function-t tartalmazza, ehhez importálnunk kell a `timezone`-t. + +Az utolsó hiányzó rész, hogy továbbítsuk a `posts`-ot a sablonba (ezt a következő fejezetben kifejtjük). + +A `render` function-ban már van egy `request` paraméterünk (vagyis minden, ami a felhasználótól érkezik az interneten keresztül) és egy template file `'blog/post_list.html'`. Az utolsó paraméter, ami így néz ki: `{}`, egy olyan összetevő, amiben megadhatjuk azokat a dolgokat, amiket használni fogunk a template-ben. El kell neveznünk őket (egyelőre ragaszkodunk a `'posts'`-hoz :)). Így kell kinéznie: `{'posts': posts}`. Ne felejtsd el, hogy a `:` előtti rész egy string, ezt idézőjelbe kell tenned `''`. + +Végül a `blog/views.py` fájlnak így kell kinéznie: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +És megvan! Itt az idő visszatérni a template-hez és megjeleníteni ezt a QuerySet-et! + +Ha utána szeretnél olvasni a QuerySet-nek, itt megteheted: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ \ No newline at end of file diff --git a/hu/extend_your_application/README.md b/hu/extend_your_application/README.md new file mode 100644 index 00000000000..0ec2859cc32 --- /dev/null +++ b/hu/extend_your_application/README.md @@ -0,0 +1,192 @@ +# Egészítsd ki az applikációdat + +Most már teljesítettük az összes szükséges lépést a website-unk létrehozásához: tudjuk hogyan írjunk egy modelt, url-t, view-t és template-et. Azt is tudjuk, hogy hogyan csinosítsuk ki az oldalunkat. + +Itt az idő gyakorolni! + +Az első dolog, amire szükségünk van, nyilván egy oldal, ami megjelenít egy bejegyzést, ugye? + +Már van egy `Post` modellünk, úgyhogy nem kell hozzáadnunk semmit a `models.py`-hoz. + +## Template link a bejegyzés részleteihez + +Kezdjük azzal, hogy hozzáadunk egy linket a `blog/templates/blog/post_list.html` fájlhoz. Eddig így kell kinéznie: + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + + +{% raw %}Szükségünk van egy linkre a bejegyzések címei és a bejegyzések részletes oldala között. Cseréljük ki a `

{{ post.title }}

` sort úgy, hogy a bejegyzés részletes oldalára vezet: {% endraw %} + +```html +

{{ post.title }}

+``` + +{% raw %}Itt az ideje elmagyarázni a rejtélyes `{% url 'post_detail' pk=post.pk %}` részt. Ahogy gyaníthattad, a `{% %}` jelölés azt jelenti, hogy Django template tag-eket használunk. Ezúttal egy olyat, ami létrehoz egy URL-t nekünk!{% endraw %} + +A `blog.views.post_detail` egy elérési út a `post_detail` *view*-hez, amit létre akarunk hozni. Jegyezd meg: `blog` az applikációnk neve (a `blog` könyvtár), `views` a `views.py` nevéből van, és az utolsó rész - `post_detail` - a *nézet* neve. + +Most amikor a http://127.0.0.1:8000/ címre megyünk, lesz egy hibaüzenetünk (ahogy vártuk is, mivel nincsen sem URL, sem *view* a `post_detail`-hez). Így fog kinézni: + +![NoReverseMatch hiba][1] + + [1]: images/no_reverse_match2.png + +## URL a bejegyzés részleteihez + +Hozzunk létre egy URL-t a `urls.py`-ban a `post_detail` *view*-hoz! + +Az első bejegyzésünk részleteit a kövekező **URL** címen akarjuk megjeleníteni: http://127.0.0.1:8000/post/1/ + +Hozzunk létre egy URL-t a `blog/urls.py` fájlban, ami egy `post_detail` nevű *view*-ra mutat -- ez majd egy egész blogbejegyzést jelenít meg. Add hozzá a `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` sort a `blog/urls.py` fájlhoz. Így kell kinéznie a fájlnak: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + +Ez a rész `^post/(?P[0-9]+)/$` elég ijesztően néz ki, de ne aggódj,elmagyarázzuk: - `^`-vel kezdődik -- "eleje" - `post/` azt jelenti, hogy az eleje után az URL-nek tartalmaznia kell ezt: **post** és **/**. Eddig jó. - `(?P[0-9]+)` - ez a rész trükkösebb. Ez azt jelenti, a Django fogja, amit ideraksz, és átirányítja egy nézethez egy `pk` nevű változóként. `[0-9]` azt közli, hogy ez csak egy számjegy lehet, betű nem (tehát minden 0 és 9 között). `+` azt jelenti, hogy egy vagy több számjegynek kell lennie. Tehát `http://127.0.0.1:8000/post//` nem érvényes, de `http://127.0.0.1:8000/post/1234567890/` teljesen jó! - `/` - kell még egy **/** - `$` - "vége"! + +Ez azt jelenti, hogy ha beírod a `http://127.0.0.1:8000/post/5/` címet a böngésződbe, akkor a Django megérti, hogy egy `post_detail` nevű 1>nézetet keresel, és közvetíti az információt, hogy a `pk` `5-tel` egyenlő annál a *nézetnél*. + +`pk` a `primary key` rövid változata. Ezt a kifejezést gyakran használják Django projektekben. De úgy nevezed el a változódat, ahogy akarod (ne feledd: kisbetűkkel és szóköz helyett `_` karakterrel!). Például `(?P[0-9]+)` esetén használhatunk `post_id` változót, amivel így nézne ki: `(?P[0-9]+)`. + +Ok, hozzáadtunk egy új URL-t a `blog/urls.py`-hoz! Frissítsük az oldalt: http://127.0.0.1:8000/ Boom! Már megint egy újabb hiba! Várható volt! + +![AttributeError][2] + + [2]: images/attribute_error2.png + +Emlékszel, mi a következő lépés? Hát persze: hozzáadni egy új nézetet! + +## Nézet a bejegyzés részleteihez + +Ezúttal adunk a *nézetünknek* egy extra paramétert: `pk`. A *nézetünknek* ezt meg kell kapnia, igaz? Úgyhogy a function-t úgy fogjuk meghatározni, hogy `def post_detail(request, pk):`. Jegyezd meg, hogy pontosan ugyanazt a nevet kell használnunk, amit az url-ben jelöltünk meg (`pk`). A változó kihagyása helytelen, és hibát fog eredményezni! + +Most egyetlen egy blogbejegyzést akarunk szerezni. Ehhez egy ilyen queryset-et használhatunk: + + Post.objects.get(pk=pk) + + +De ennél a kódnál van egy kis gond. Ha nincsen `Post` az adott `primary key`-vel (`pk`), akkor egy nagyon csúnya hibát kapunk! + +![DoesNotExist hiba][3] + + [3]: images/does_not_exist2.png + +Mi ezt nem akarjuk! De, természetesen a Django-nak van valamije, ami ezt megoldja nekünk: `get_object_or_404`. Abban az esetben, ha nincsen `Post` az adott `pk`-val, akkor egy sokkal szebb oldalt ad ki (`Page Not Found 404` oldalt). + +![Az oldal nem található][4] + + [4]: images/404_2.png + +A jó hír az, hogy elkészítheted a saját `Page not found` oldaladat, és olyan szépre alakíthatod, amilyenre akarod. De ez nem olyan fontos egyelőre, úgyhogy átugorhatjuk. + +Oké, itt az idő, hogy hozzáadjuk a *view*-t a `views.py` fájlunkhoz! + +Nyisd meg a `blog/views.py` fájlt és add hozzá a következő kódot: + + from django.shortcuts import render, get_object_or_404 + + +A többi `from` sor mellé. És a fájl alján hozzáadjuk a *view*-t: + + def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) + + +Igen. Ideje frissíteni az oldalt: http://127.0.0.1:8000/ + +![Post list nézet][5] + + [5]: images/post_list2.png + +Sikerült! De mi történik, ha ráklikkelsz egy linkre a blog bejegyzés címében? + +![TemplateDoesNotExist hiba][6] + + [6]: images/template_does_not_exist2.png + +Jaj ne! Egy másik hiba! De már tudjuk, hogyan kezeljük, igaz? Létre kell hoznunk egy template-et! + +## Template a bejegyzés részleteihez + +Létrehozunk egy fájlt a `blog/templates/blog` könyvtárban, és elnevezzük: `post_detail.html`. + +Ez fog történni: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Itt megint a `base.html`-t bővítjük ki. A `content` blokkban meg szeretnénk jeleníteni a bejegyzés címét, szövegét és a megjelenési idejét (published_date) - ha van. De pár fontos dolgot tisztáznunk kell még, igaz? + +{% raw %}`{% if ... %} ... {% endif %}` egy template tag, amit akkor használni, amikor ellenőrizni akarunk valamit (emlékszel az `if ... else ..` részre a **Bevezetés a Python-ba** fejezetnél?). Ebben az esetben azt akarjuk leellenőrizni, hogy a bejegyzés `published_date` eleme nem üres.{% endraw %} + +Ok, most már frissíthetjük az oldalunkat és kiderül, hogy a `Page not found` eltűnt. + +![Post részletei oldal][7] + + [7]: images/post_detail2.png + +Juppi! Működik! + +## Még egy dolog: itt az ideje egy újabb deploynak! + +Jó lenne ellenőrizni, hogy még mindig működik-e a weboldalad a PythonAnywhere-en, igaz? Próbáld meg újra deployolni. + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push + + +* Aztán írd be ezt a [PythonAnywhere Bash konzol][8]ba: + + [8]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Végül menj a [Web tab][9]-ra, és nyomj **Reload**ot. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +Ennyi az egész. Gratulálunk :) diff --git a/hu/extend_your_application/images/404_2.png b/hu/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/hu/extend_your_application/images/404_2.png differ diff --git a/hu/extend_your_application/images/attribute_error2.png b/hu/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/hu/extend_your_application/images/attribute_error2.png differ diff --git a/hu/extend_your_application/images/does_not_exist2.png b/hu/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/hu/extend_your_application/images/does_not_exist2.png differ diff --git a/hu/extend_your_application/images/no_reverse_match2.png b/hu/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/hu/extend_your_application/images/no_reverse_match2.png differ diff --git a/hu/extend_your_application/images/post_detail2.png b/hu/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/hu/extend_your_application/images/post_detail2.png differ diff --git a/hu/extend_your_application/images/post_list2.png b/hu/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/hu/extend_your_application/images/post_list2.png differ diff --git a/hu/extend_your_application/images/template_does_not_exist2.png b/hu/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/hu/extend_your_application/images/template_does_not_exist2.png differ diff --git a/hu/how_the_internet_works/README.md b/hu/how_the_internet_works/README.md new file mode 100644 index 00000000000..770f08d8e23 --- /dev/null +++ b/hu/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# Hogy működik az Internet? + +> Ez a fejezet Jessica McKellar "Hogy működik az Internet" (How the Internet works) című előadásán alapul (http://web.mit.edu/jesstess/www/). + +Biztosan minden nap internetezel. Tudod, igazából mi történik, mikor beírod a böngésződben, hogy https://djangogirls.org, és `enter`t nyomsz? + +Az első dolog, amit fontos megérteni, hogy egy weboldal nem más, mint egy csomó fájl egy merevlemezre mentve. Olyanok, mint a filmjeid, a zenéid, vagy a képeid. De van valami, ami a weboldalakat egyedivé teszi: a HTML nevű számítógépes kód. + +Ha nem igazán ismered a programozást, akkor nehéz lehet megértened először a HTML-t, de ne aggódj a böngésződ (Chrome, Safari, Firefox, stb.) imádja. A webböngészőket úgy tervezték, hogy megértsék ezt a kódot, kövessék azt, ami abban van, és megjelenítsenek mindent pont úgy, ahogy szeretnéd. + +Mint minden fájlt, a HTML-t is merevlemezen kell tárolni. Az Internethez speciális, erős számítógépeket használunk, a *szervereket*. Ezekhez a gépekhez nem tartozik képernyő, egér vagy billentyűzet, mert a fő feladatuk az adatok tárolása és szolgáltatása. Ezért hívjuk őket *szervernek*, vagyis kiszolgálónak -- ők *szolgálják ki* neked az adatokat. + +Rendben, de hogy néz ki az Internet? + +Rajzoltunk neked egy képet! Így néz ki: + +![1.1 ábra][1] + + [1]: images/internet_1.png + +Elég zavaros, igaz? Valójában ez egymáshoz kapcsolódó gépek (az előbb emlegetett *szerverek*) hálózata. Több százezer gép! Rengeteg kilométernyi kábel körös-körül a világon! Nézd meg Submarine Cable Map weboldalt (http://submarinecablemap.com), és látni fogod milyen bonyolult a net. Itt egy kép az oldalról: + +![1.2 ábra][2] + + [2]: images/internet_3.png + +Lenyűgöző, igaz? Persze az képtelenség, hogy minden gép össze legyen kötve egymással, ami az Internethez csatlakozik. Ezért hogy elérhessünk egy gépet (például azt, ahol a https://djangogirls.org van elmentve), a kérésünket egy csomó különböző gépen át kell juttatni. + +Így néz ki: + +![1.3 ábra][3] + + [3]: images/internet_2.png + +Képzeld el úgy, hogy amikor beírod a https://djangogirls.org címet, egy levelet írsz: "Kedves Django Girls, szeretném megnézni a djangogirls.org oldalt. Kérlek, küldd el nekem!" + +Először a leveled a hozzád legközelebbi postára megy. Ezután továbbhalad egy olyan postára, ami már kicsit közelebb van a címzettedhez, és így tovább, míg el nem jut a céljához. Az egyetlen egyedi dolog, hogy ha több levelet (*adatcsomagot*) küldesz ugyanarra a helyre, azok valószínűleg teljesen már postákon (*routers*) mennek keresztül. Ez csak attól függ hogyan osztják el az egyes irodákban. + +![1.4 ábra][4] + + [4]: images/internet_4.png + +Ennyire egyszerű! Elküldöd a levelet, és várod a választ. Persze papír és toll helyett adatok byte-jait küldöd, de az ötlet ugyanaz! + +Utcanév, házszám, város és irányítószám helyett IP-címeket használunk. A számítógéped először megkéri a DNS-t (Domain Name System, tartománynévrendszer), hogy fordítsa le a djangogirls.org-ot egy IP címre. Körülbelül úgy működik, mint amikor a régi telefonkönyvekből kikerested valakinek a telefonszámát, és a címét. + +Amikor levelet küldesz, bizonyos dolgokra szükség van, hogy jó helyre szállítsák őket: kell lennie rajta címnek, bélyegnek, stb. Ráadásul olyan nyelven kell írnod, amit a címzett megért. Ugyanez vonatkozik az *adatcsomagokra*, amiket azért küldesz, mert meg szeretnél nézni egy weboldalt. A HTTP (Hypertext Transfer Protocol) protokollt használjuk erre. + +Szóval, amikor van egy weboldalad, akkor szükséged van egy *szerverre* (gép), ahol az oldal lakik. Amikor a *szerver* kap egy beérkező *kérést* (egy levélben), akkor egy válaszban visszaküldi a weboldaladat (egy másik levélben). + +Mivel ez egy Django útmutató, felmerülhet benned a kérdés, hogy a Django ebben a folyamatban milyen szerepet tölt be. Amikor küldesz egy választ, nem mindig pont ugyanazt küldöd mindenkinek. Sokkal jobb, ha a levelek személyesek, főleg, ha annak az embernek szólnak, akinek válaszolsz, nem igaz? A Django segít, hogy személyes és érdekes leveleket írhass :). + +De elég a beszédből, munkára fel! \ No newline at end of file diff --git a/hu/how_the_internet_works/images/internet_1.png b/hu/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/hu/how_the_internet_works/images/internet_1.png differ diff --git a/hu/how_the_internet_works/images/internet_2.png b/hu/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/hu/how_the_internet_works/images/internet_2.png differ diff --git a/hu/how_the_internet_works/images/internet_3.png b/hu/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/hu/how_the_internet_works/images/internet_3.png differ diff --git a/hu/how_the_internet_works/images/internet_4.png b/hu/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/hu/how_the_internet_works/images/internet_4.png differ diff --git a/hu/html/README.md b/hu/html/README.md new file mode 100644 index 00000000000..1eb19bbdda4 --- /dev/null +++ b/hu/html/README.md @@ -0,0 +1,209 @@ +# Bevezetés a HTML-be + +Mi az a template, kérdezhetnéd? + +A template egy fájl, amit újrahasznosíthatunk, hogy különböző információkat jeleníthessünk meg egységes formában - például, egy template-et használhatsz egy levél megírásakor, ahol ugyan a levelek tartalma eltérhet, és a címzettek is különbözőek lehetnek, de a formájuk azonos. + +A Django template formátumát egy nyelvvel írjuk le, amit HTML-nek hívunk (ez az a HTML, amit a **Hogy működik az Internet?** fejezetben már említettünk). + +## Mi a HTML? + +A HTML egy egyszerű kód, amit a böngésződ értelmez (pl.: Chrome, Firefox, vagy Safari), hogy weboldalakat jelenítsen meg a felhasználóknak. + +A HTML a "HyperText Markup Language" rövidítése. A **HyperText** egy olyan szöveg, amely támogatja a hiperhivatkozásokat oldalak között. A **Markup** azt jelenti, hogy egy dokumentumot kód segítségével jelölésekkel látunk el, hogy leírjuk (ebben az esetben a böngészőnek) hogyan értelmezhető a weboldal. A HTML kód **tagekből** épül fel, amelyek mindegyike `<` jellel kezdődik, és `>` jellel végződik. Ezek a tagek reprezentálják a jelölő **elemeket**. + +## Az első template-ed! + +Egy template elkészítése azt jelenti, hogy létrehozunk egy template fájlt. Minden dolog egy fájl, igaz? Valószínűleg már te is észrevetted ezt. + +A template-eket a `blog/templates/blog` mappába mentjük. Először hozd létre a `templates` könyvtárat a blog mappában. Ezután hozz létre egy `blog` mappát a templates mappádban: + + blog + └───templates + └───blog + + +(Meglepő lehet, hogy miért van szükség két `blog` nevű mappára - később majd rájössz, hogy ez egy hasznos elnevezési konvenció, ami megkönnyíti az életedet, amikor a dolgok bonyolulttá válnak.) + +Ezután hozd létre a `post_list.html` fájlt (egyelőre hagyd üresen) a `blog/templates/blog` mappában. + +Nézd meg, hogy néz ki most a weboldal: http://127.0.0.1:8000/ + +> Ha továbbra is a `TemplateDoesNotExists` hibát kapod, akkor próbáld újraindítani a szervert. Menj a parancssorba, állítsd meg a szervert a Ctrl+C megnyomásával (a Control és C gombot egyszerre nyomd meg), és indítsd el újra a `python manage.py runserver` paranccsal. + +![11.1 ábra][1] + + [1]: images/step1.png + +Nincs több hiba! Ügyes vagy :) Azonban a weboldalad csak egy üres oldalt jelenít meg, mivel a template is üres, amit készítettél. Ezt ki kell javítanunk. + +Add hozzá az alábbi sorokat a template fájlodhoz: + +```html + +

Hi there!

+

It works!

+ +``` + +Szóval, hogy néz ki most a weboldalad? Kattints és nézd meg: http://127.0.0.1:8000/ + +![11.2 ábra][2] + + [2]: images/step3.png + +Működik! Szép munka :) + +* A legalapvetőbb tag a ``, amely minden weboldal elejére kerül, míg a `` a végén szerepel. Láthatod, hogy a weboldal tartalma a kezdő `` tag, és a záró `` tag közé kerül +* A `

` tag a bekezdés (paragrafus) elem; `

` zárja a bekezdéseket + +## Head és body + +Minden HTML oldalt két elemre osztunk: **head** és **body**. + +* A **head** elem információkat tartalmaz a dokumentumról, amit nem jelenítünk meg a képernyőn. + +* A **body** elem tartalmaz minden mást, ami a weboldalon jelenik meg. + +A `` elemet használjuk arra, hogy az oldal konfigurációs beállításait megadjuk a böngészőnek, és a `` elemet arra, hogy leírjuk mi jelenjen meg az oldalon. + +Például a weboldal title elemét rakhatjuk a ``-be: + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Mentsd el a fájlt, és frissítsd az oldalt. + +![11.3 ábra][3] + + [3]: images/step4.png + +Észrevetted, hogyan ismerte fel a böngésző, hogy az "Ola's blog" az oldal címe? Értelmezte a `Ola's blog` kódot, és a szöveget a böngésző cím mezőjébe rakta (ezt fogja használja könyvjelzőnek is, és így tovább). + +Valószínűleg azt is észrevetted, hogy minden nyitó taghez tartozik egy *záró tag* egy `/` jellel, és ezek az elemek *egymásba ágyazhatóak* (azaz nem lehet bezárni egy adott taget mindaddig, míg a benne levők nincsenek lezárva). + +Ez éppen olyan mintha különböző dolgokat tennénk dobozokba. Van egy nagy dobozod, a ``; ebben benne van a ``, és ez egy újabb kisebb dobozt tartalmaz: `

`. + +Követned kell a *záró* tagekre, és az *egymásba ágyazható* elemekre vonatkozó szabályokat - ha nem teszed, a böngésző nem tudja majd értelmezni a kódodat megfelelően, és az oldalad hibásan jelenik majd meg. + +## Változtasd meg a template-edet + +Most szórakozásképpen próbáld módosítani a template-edet! Itt van néhány hasznos tag ehhez: + +* `

A heading

` - a legfontosabb címedhez +* `

A sub-heading

` cím a következő szintre +* `

A sub-sub-heading

` ... és így tovább, egészen `
`-ig +* `text` dőlt szöveghez +* `text` a szöveg kiemeléséhez +* `
` új sor kezdéséhez (nem mindenhová rakhatsz br-t) +* `link` létrehoz egy linket +* `
  • first item
  • second item
` létrehoz egy listát, akárcsak ezt itt! +* `
` az oldal szakaszainak megadásához + +Itt a példa egy teljes template-re: + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` + +Három `div` elemet hoztunk létre. + +* Az első `div` tartalmazza a blogunk címét - ez egy cím, és egy link +* A másik két `div` elem a blog posztjainkat tárolja a publikálás dátumával - egy `h2` van benne a poszt címével, ami kattintható, emellett `p` bekezdések a dátumnak, és a szövegnek. + +Ennek kell megjelenni: + +![11.4 ábra][4] + + [4]: images/step6.png + +Yaaay! A template eddig pontosan **ugyanazt az infót** jeleníti meg - viszont korábban arról volt szó, hogy egy template-tel **különböző** információkat jeleníthetünk meg **azonos formában**. + +Amit igazából szeretnénk, hogy igazi posztokat jelenítünk meg, amiket a Django adminon adunk hozzá - nemsokára ezt is megnézzük. + +## Még egy dolog: deploy! + +Jó lenne lenne látni ezt az egészet élesben az interneten, ugye? Csináljunk egy újabb PythonAnywhere deploy-t: + +### Commit, és push a Github-ra + +Először nézzük meg, hogy milyen fájlok változtak a legutóbbi deploy óta (futtasd az alábbi parancsot a gépeden, ne PythonAnywhere-en): + + $ git status + + +A `djangogirls` mappában kell lenned, és a `git`-tel add hozzá az összes változtatást a könyvtáradon belül: + + $ git add --all . + + +> **Megjegytés** `-A` (az "all" rövidítése) azt jelenti, hogy a `git` felismeri, ha fájlokat törölsz (alapból csak az új, és módosított fájlokat ismeri fel). Korábban már volt róla szó (a 3. fejezetben), hogy a `.` az aktuális mappát jelenti. + +Mielőtt továbbmegyünk ellenőrizzük, hogy a `git` mit szeretne feltölteni (zölddel jelennek meg azok a fájlok, amiket a `git` fel akar tölteni): + + $ git status + + +Már majdnem készen is vagyunk, de előtte el kell mentenünk a változtatásokat az előzményekbe. Egy "commit message"-et adunk meg, ahol leírjuk, hogy mit változtattunk. Akármit beírhatsz, de később hasznos lehet, ha valami olyat adsz meg, ami segít beazonosítani, hogy mit csináltál. + + $ git commit -m "Changed the HTML for the site." + + +> **Megjegyzés** Győződj meg róla, hogy idézőjelet használsz a commit üzenetnél. + +Miután ezzel megvagy, töltsd fel (push) a változtatásaidat Github-ra: + + $ git push + + +### Pullold az új kódot PythonAnywhere-re, és frissítsd az oldalt + +* Nyisd meg a [PythonAnywhere konzol oldalát][5] és menj a **Bash console**-odra (vagy indíts egy újat). Aztán futtasd ezt: + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +A fájljaid már itt is vannak. Ha le akarod csekkolni, akkor menj át a **Files tab**-ra és nézd meg a kódodat PythonAnywhere-en. + +* Végül, kattints át a [Web tab][6]-ra, és nyomj egy **Reload**-ot a web alkalmazásodra. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +A frissítéseid kint vannak! Frissítsd az weboldalt a böngésződben, és a változtatások már látni fogod :) \ No newline at end of file diff --git a/hu/html/images/step1.png b/hu/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/hu/html/images/step1.png differ diff --git a/hu/html/images/step3.png b/hu/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/hu/html/images/step3.png differ diff --git a/hu/html/images/step4.png b/hu/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/hu/html/images/step4.png differ diff --git a/hu/html/images/step6.png b/hu/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/hu/html/images/step6.png differ diff --git a/hu/images/application.png b/hu/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/hu/images/application.png differ diff --git a/hu/installation/README.md b/hu/installation/README.md new file mode 100644 index 00000000000..a3802d348ce --- /dev/null +++ b/hu/installation/README.md @@ -0,0 +1,49 @@ +# Ha otthon csinálod a tutorialt + +Ha otthon csinálod a tutorialt, nem valamelyik [Django Girls eseményen](https://djangogirls.org/events/), át is ugorhatod ezt a fejezetet, és folytathatod a [Hogy működik az Internet?](../how_the_internet_works/README.md) fejezettel. + +Ez az oldal csak egy helyre gyűjti az installációk leírását, amikkel később úgyis találkozni fogsz a tutorial során. A Django Girls workshopok előtt mindig van egy installációs esemény, amikor mindent telepítünk, hogy a workshopon már ne kelljen ezzel bajlódni, ezért hasznos nekünk, hogy mindent megtalálunk egy helyen. + +Ha te is hasznosnak találod, nyugodtan elvégezheted ezt a fejezetet. De ha inkább fejest szeretnél ugrani a tanulásba, mielőtt egy csomó mindent telepítenél a gépedre, nyugodtan ugord át a fejezetet! Később úgyis elmagyarázzuk az összes telepítést. + +Sok szerencsét! + +# Installáció + +A workshopon egy blogot fogsz elkészíteni. Ehhez el kell végezned néhány telepítési feladatot, hogy a workshop napján már egyből elkezdhess kódolni. + +# A Python telepítése + +{% include "/python_installation/instructions.md" %} + +# Virtuális környezet létrehozása és a Django telepítése + +{% include "/django_installation/instructions.md" %} + +# Kódszerkesztő telepítése + +{% include "/code_editor/instructions.md" %} + +# A Git telepítése + +{% include "/deploy/install_git.md" %} + +# GitHub fiók létrehozása + +Menj a [GitHub.com](https://www.github.com) oldalra, és hozz létre egy új, ingyenes felhasználói fiókot. + +# PythonAnywhere felhasználó létrehozása + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Kezdheted az olvasást + +Gratulálunk, készen állsz a tutorialra! Ha van egy kis időd a workshop előtt, hasznos lehet, ha elolvasod az első néhány fejezetet: + + * [Hogy működik az Internet](../how_the_internet_works/README.md) + + * [Bevezetés a parancsssor használatába](../intro_to_command_line/README.md) + + * [Bevezetés a Pythonba](../python_introduction/README.md) + + * [Mi a Django?](../django/README.md) diff --git a/hu/intro_to_command_line/README.md b/hu/intro_to_command_line/README.md new file mode 100644 index 00000000000..1599cd88f51 --- /dev/null +++ b/hu/intro_to_command_line/README.md @@ -0,0 +1,279 @@ +# Bevezetés a parancssor használatába + +Ez nagyon izgalmas, igaz?! Pár percen belül megírod az első kódsorodat :) + +**Hadd mutassuk be neked az első új barátodat: a parancssort!** + +A következő lépésekben megmutatjuk neked, hogyan használd azt a fekete ablakot úgy, ahogy az összes hacker használja. Első ránézésre kissé ijesztőnek tűnhet, de valójában csak egy egyszerű parancsot vár tőled. + +> **Megjegyzés** A könyvben felváltva használjuk a 'könyvtár' és 'mappa' ('directory' és 'folder') szavakat, de ezek pont ugyanazt jelentik. + +## Mi az a parancssor? + +A **parancssor** (command line, vagy **command-line interface**) nevű ablak egy szöveges alapú alkalmazás, amit arra használhatsz, hogy fájlokat tekinthess meg, szerkeszthess, és különböző műveleteket végezhess rajtuk. Olyasmi, mint a Windows Explorer, vagy Mac gépeken a Finder, de a grafikus felület nélkül. Egyéb megnevezések a parancssorra: *konzol*, *terminál*, *cmd*, *CLI*, *prompt*. + +## A parancssor megnyitása + +Hogy belevághass a kísérletezésbe, először meg kell nyitnod a parancssort. + +### Windows + +Start menu → All Programs → Accessories → Command Prompt. + +### Mac OS X + +Applications → Utilities → Terminal. + +### Linux + +Valószínűleg itt találod meg: Applications → Accessories → Terminal, de ez a rendszeredtől függ. Ha nincs ott, csak keress rá a Google-n :) + +## Parancssor + +Egy fehér vagy fekete ablakot kell látnod, ami csak a te parancsaidra vár. + +Ha Mac-ed vagy Linux-od van, valószínűleg egy `$`-t kell látnod: + + $ + + +A Windows-on ez egy `>` jel: + + > + + +Minden sornak ezzel a jellel és az azt követő space-el kell kezdődnie, de ezt nem neked kell begépelned. A számítógéped megteszi helyetted :) + +> Csak egy gyors megjegyzés: így is kinézhet a parancssorod: `C:\Users\ola>` vagy `Olas-MacBook-Air:~ ola$`, és ez teljesen jó így. Ebben az útmutatóban csak próbáljuk a lehető leginkább leegyszerűsíteni. + +## Az első parancsod (YAY!) + +Kezdjük valami egyszerűvel. Gépeld be ezt a parancsot: + + $ whoami + + +vagy + + > whoami + + +Majd nyomj `enter`t. Ezt az eredményt kapod: + + $ whoami + olasitarska + + +Amint láthatod, a számítógéped az előbb kiírta a felhasználónevedet. Jó, mi?:) + +> Próbálj meg minden parancsot begépelni, ahelyett, hogy innen másolnád ki. Így többet fogsz megjegyezni! + +## Az alapok + +Minden operációs rendszer parancssora kissé különböző prancsokat igényel, ezért kérlek győzödj meg arról, hogy a te operációs rendszerednek megfelelő utasításokat követed. Próbáljuk ki, rendben? + +### A jelenlegi mappa + +Jó lenne tudni, hogy most hol vagyunk, nem? Nézzük. Írd be ezt a parancsot, és nyomj `enter`t: + + $ pwd + /Users/olasitarska + + +Ha Windows-od van: + + > cd + C:\Users\olasitarska + + +Valószínűleg valami hasonlót fogsz látni a gépeden. Amikor megnyitod a parancssort, általában a felhasználó 'home' könyvtárába kerülsz. + +> Megjegyzés: a 'pwd' jelentése: 'print working directory'. + +* * * + +### Fájlok és könyvtárak kilistázása + +És mi van benne? Szuper lenne kideríteni. Nézzük meg: + + $ ls + Applications + Desktop + Downloads + Music + ... + + +Windows: + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### Jelenlegi mappa megváltoztatása + +Most pedig lépjünk be a Desktop (vagy Asztal) mappába: + + $ cd Desktop + + +Windows: + + > cd Desktop + + +Nézzük meg, hogy tényleg megváltozott-e: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Itt is van! + +> PRO tipp: ha begépeled a `cd D`-t (vagy ha magyarul használod az operációs rendszeredet, és 'Asztal'-nak hívják a könyvtáradat, a `cd A`-t) és ezután megnyomod a <0>tab-ot, a parancssor automatikusan kiegészíti a nevet, lehetővé téve számodra a gyorsabb navigálást. Amennyiben több mappa is kezdődik ugyanazzal a betűvel, nyomd meg kétszer a `tab`-ot, hogy kilistázza a több opciót. + +* * * + +### Könyvtár létrehozása + +Mit szólnál, ha létrehoznánk egy gyakorló (practice) könyvtárat az asztalon? Így tudod megtenni: + + $ mkdir practice + + +Windows: + + > mkdir practice + + +Ez a parancs létre fog hozni egy `practice` nevű mappát az asztalodon. Ha megnézed az asztalt, meggyőződhetsz róla, hogy tényleg ott van-e, de a `ls` vagy `dir` paranccsal is megteheted! Próbáld ki :) + +> PRO tipp: Ha nem szeretnéd újra és újra ugyanazt a parancsot begépelni, próbáld meg a `felfele` és `lefele nyilakkal` behívni a legutóbb futtatott parancsokat. + +* * * + +### Feladat! + +Egy kis kihívás: hozz létre egy `test` nevű mappát a frissen elkészített `practice` könyvtáradban. Használd a `cd` és `mkdir` parancsokat. + +#### Megoldás: + + $ cd practice + $ mkdir test + $ ls + test + + +Windows: + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + +Gratulálunk! :) + +* * * + +### Takarítás + +Nem szeretnénk káoszt hagyni magunk után, szóval töröljünk le mindent, amit eddig csináltunk. + +Először vissza kell mennünk az Asztal-ra: + + $ cd .. + + +Windows: + + > cd .. + + +Ha a `cd` parancsot `..`-tal használod, a jelenlegi könyvtárból a parent (szülő) könyvtárba jutsz (ez az a mappa, ami tartalmazza azt a mappát, ahol éppen vagy). + +Ellenőrizzük le, hogy hol vagyunk: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Most pedig itt az ideje, hogy kitöröljük a `practice` könyvtárat: + +> **Figyelem**: A fájlok törlése a `del`, `rmdir`, vagy a `rm` parancsokkal visszafordíthatatlan, tehát a *törölt fájlok örökre eltűnnek*! Legyél nagyon óvatos ezzel a paranccsal. + + $ rm -r practice + + +Windows: + + > rmdir /S practice + practice, Are you sure ? Y + + +Kész! Ellenőrizzük le, hogy tényleg megtörtént-e: + + $ ls + + +Windows: + + > dir + + +### Kilépés + +Ennyi volt! Most már biztonságosan kiléphetsz a parancssorból. Csináljuk hacker módra, jó?:) + + $ exit + + +Windows: + + > exit + + +Szuper, nem? :) + +## Összefoglaló + +Egy kis összefoglalás néhány hasznos parancsról: + +| Parancs (Windows) | Parancs (Mac OS/Linux) | Leírás | Példa | +| ----------------- | ---------------------- | ----------------------------- | ------------------------------------------------- | +| exit | exit | az ablak bezárása | **exit** | +| cd | cd | könyvtár megváltoztatása | **cd test** | +| dir | ls | könyvtárak/fájlok kilistázása | **dir** | +| copy | cp | fájl másolása | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | fájl mozgatása | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | új könyvtár létrehozása | **mkdir testdirectory** | +| del | rm | könyvtár/fájl törlése | **del c:\test\test.txt** | + +Ez csak néhány parancs, azok közül, amiket a parancssorban futtathatsz, de ma nem lesz szükséged ennél többre. + +Ha kíváncsi vagy, a [ss64.com][1] oldalon megtalálod az összes parancsot bármelyik operációs rendszerre. + + [1]: http://ss64.com + +## Kész vagy? + +Merüljünk el a Python-ban! \ No newline at end of file diff --git a/hu/python_installation/README.md b/hu/python_installation/README.md new file mode 100644 index 00000000000..8dc956f79b9 --- /dev/null +++ b/hu/python_installation/README.md @@ -0,0 +1,13 @@ +# Kezdjünk ismerkedni a Pythonnal + +Végre itt vagyunk! + +Először is hadd mondjuk el, hogy mi is a Python. A Python egy nagyon népszerű programnyelv, amit weboldalkészítéshez, játékokhoz, tudományos szoftverekhez, grafikához és még csomó minden másra használnak. + +A Pythont a 80-as évek végén alkották meg, és a fő cél az volt, hogy ne csak gépek, hanem emberek számára is olvasható legyen. Ezért néz ki sokkal egyszerűbbnek, mint más programnyelvek. Ez könnyebbé teszi a tanulást, de ne aggódj, a Python igencsak erőteljes nyelv! + +# A Python telepítése + +> **Megjegyzés** Ha már elvégezted az Installáció fejezetet, nem kell újra megtenned - ugorj a következő fejezetre! + +{% include "/python_installation/instructions.md" %} diff --git a/hu/python_installation/images/add_python_to_windows_path.png b/hu/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/hu/python_installation/images/add_python_to_windows_path.png differ diff --git a/hu/python_installation/instructions.md b/hu/python_installation/instructions.md new file mode 100644 index 00000000000..fca0e75ca0a --- /dev/null +++ b/hu/python_installation/instructions.md @@ -0,0 +1,65 @@ +> Ez a fejezet a Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) tutorialján alapszik + +A Django Python nyelven íródott. Ahhoz, hogy bármit létrehozhassunk a Django-ban, szükségünk van a Pythonra is. Kezdjük a telepítésével! Azt szeretnénk, hogy a Python 3.4-es verziója legyen telepítve -- ha ennél korábbi verzióval rendelkezel, akkor frissítened kell. + +### Windows + +A Python-t az alábbi weboldalról tudod letölteni: https://www.python.org/downloads/release/python-343/. Az ***.msi** fájlt a letöltés után futtasd (dupla kattintás), és kövesd az utasításokat. Fontos, hogy emlékezz a path-ra (könyvtárra), ahova letöltötted. Később szükséged lesz rá! + +Egy fontos dolog, amire figyelj oda: a telepítővarázsló második képernyőjén ("Customize") görgess lejjebb, és válaszd ki az "Add python.exe to the Path" opciót, ahogy itt láthatod: + +![Ne felejtsd el hozzáadni a Pythont a Path-hoz](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Nagyon valószínű, hogy a Python már telepítve van a gépedre. Ahhoz, hogy ezt leellenőrizd (illetve hogy megnézd, melyik verzió van a gépeden), nyisd meg a konzolt és írd be az alábbi parancsot: + + $ python3 --version + Python 3.4.3 + + +Ha még nincs Pythonod, vagy másik verziót szeretnél telepíteni, így teheted meg: + +#### Debian vagy Ubuntu + +Írd be az alábbi parancsot a konzolba: + + $ sudo apt-get install python3.4 + + +#### Fedora (21-es verzióig) + +Írd be az alábbi programot a konzolba: + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +Írd be az alábbi programot a konzolba: + + $ sudo dnf install python3.4 + + +#### openSUSE + +Írd be az alábbi programot a konzolba: + + $ sudo zypper install python3 + +### OS X + +Menj a https://www.python.org/downloads/release/python-343/ oldalra, és töltsd le a Python installert: + + * Töltsd le a *Mac OS X 64-bit/32-bit installer* fájlt, + * Kattints duplán a *python-3.4.3-macosx10.6.pkg*-re, hogy futtasd a telepítőt. + +Bizonyosodj meg arról, hogy sikeres volt a telepítés! Nyisd meg a *Terminált* és futtasd le a `python3` parancsot: + + $ python3 --version + Python 3.4.3 + + +* * * + +Ha kétségeid vannak, vagy valami elromlott, és nem tudod, mit csinálj - csak kérdezd meg a coachodat! Néha a dolgok nem mennek teljesen simán, és jobb megkérdezni valakit, akinek több tapasztalata van a témában. diff --git a/hu/python_introduction/README.md b/hu/python_introduction/README.md new file mode 100644 index 00000000000..89c62479ebd --- /dev/null +++ b/hu/python_introduction/README.md @@ -0,0 +1,788 @@ +# Bevezetés a Pythonba + +> Ez a fejezet részben a Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) tutorialjain alapszik. + +Írjunk egy kis kódot! + +## A Python parancssor + +Hogy elkezdhess a Pythonnal ismerkedni, szükséged lesz a *parancssorra*. Már tudod, hogyan kell -- megtanultad a [ Bevezetés a parancssor használatába][1] fejezetben. + + [1]: ../intro_to_command_line/README.md + +Ha kész vagy, kövesd az alábbi utasításokat. + +Egy Python konzolt szeretnénk megnyitni. Gépeld be a `python` parancsot Windowson, vagy a `python3` parancsot, ha Mac vagy Linux van a gépeden, és nyomj `enter`t. + + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Az első Python parancsod! + +Miután futtattad a Python parancsot, a parancssor megváltozott: `>>>`. Ez azt jelenti, hogy mostantól csak a Python nyelv parancsait használhatjuk. Nem kell beírnod ezt: `>>>` - a Python megcsinálja helyetted. + +Ha bármikor szeretnél kilépni a Python konzolból, csak gépeld be, hogy `exit()`, vagy használd a `Ctrl + Z` billentyűkombinációt Windos-ra, vagy a `Ctrl + D`-t Mac-re/Linux-ra. Ezután már nem fogod látni a `>>>` jelet. + +Most épp nem szeretnénk kilépni a Python konzolból. Inkább többet szeretnénk tanulni róla. Kezdjünk valami nagyon egyszerűvel. Például kezdjünk valami matekkel, mint pl. `2 + 3` majd `enter`. + + >>> 2 + 3 + 5 + + +Szuper! Láttad, ahogy előugrott a válasz? A Python tud matekozni! Kipróbálhatsz más parancsokat is, mint például: - `4 * 5` - `5 - 1` - `40 / 2` + +Szórakozz egy kicsit ezzel aztán gyere vissza ide :). + +Amint látod, a Python jó számológép. Ha kíváncsi vagy, mire jó még... + +## Stringek + +Mi a helyzet a neveddel? Gépeld be a neved időzéjelbe téve: + + >>> "Ola" + 'Ola' + + +Épp most hoztad létre az első stringedet! Ez egy karakter-sorozat amit a számítógép fel tud dolgozni. A string kezdetét és végét ugyanazzal a karakterrel jelöljük. Ez lehet szimpla (`'`) vagy dupla (`"`) idézőjel (nincs különbség!) Az idézőjelek mondják meg a Pythonnak, hogy ami köztük van, az egy string. + +A stringeket össze is lehet fűzni. Próbáld ki ezt: + + >>> "Hi there " + "Ola" + 'Hi there Ola' + + +Sokszorosítani is lehet őket: + + >>> "Ola" * 3 + 'OlaOlaOla' + + +Ha aposztrófot szeretnél a stringedbe tenni, kétféleképpen teheted meg. + +Idézőjel segítségével: + + >>> "Runnin' down the hill" + "Runnin' down the hill" + + +vagy pedig escape karakterrel (``) az aposztróf előtt: + + >>> 'Runnin\' down the hill' + "Runnin' down the hill" + + +Jó, mi? Ha nagybetűkkel szeretnéd látni a neved, csak gépeld be ezt: + + >>> "Ola".upper() + 'OLA' + + +Épp most használtad az `upper` **functiont** (függvényt) a stringeden! A függvény, (mint például az `upper()`), egy utasítássorozat, amit a Python végrehajt egy adott objektumon (`"Ola"`), amikor a függvényt meghívod. + +Ha szeretnéd tudni, hogy hány betűből áll a neved, arra is van függvény! + + >>> len("Ola") + 3 + + +Érdekel, miért van az, hogy néha a függvényeket úgy hívjuk meg, hogy a string után egy `.` jön, majd a függvény neve (mint például `"Ola".upper()`), máskor pedig előbb a függvény neve jön, aztán a string a zárójelben? Nos, ez azért van mert néha a függvények objektumokhoz tartoznak, mint az `upper()`, amit csak azokon az objektumokon hívhatunk meg. Ebben az esetben a függvényt **metódusnak** (method) nevezzük. Máskor a függvény nem tartozik egy bizonyos típusú objektumhoz, hanem többféle típusú objektumon is meg lehet hívni, mint például a `len()`. Ezért volt az hogy az `"Ola"`-t paraméterként adtuk át a `len` függvénynek. + +### Összefoglaló + +Oké, elég a stringekből. Tehát ezidáig a következőkről tanultál: + +* **a parancssor** - ha parancsokat (kódot) írunk be a Python parancssorba, a Python végrehajtja azokat +* **számok és stringek** - a Pythonban a számokat matematikai műveletekhez, a stringeket szöveg objektumokhoz használjuk +* **operátorok** - mint a + és a *, két értékből egy újat hoznak létre +* **függvények** - mint az upper() és a len(), objektumokon hajtanak végre műveleteket. + +Ezek volnának az alapjai minden programozási nyelvnek. Készen állsz valami bonyolultabbra? Rajta! + +## Hibák + +Nézzünk valami újat. Vajon megkaphatjuk-e egy szám hosszát ugyanúgy, mint a nevünk hosszát? Írd be, hogy `len(304023)`, majd üss `enter`-t: + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +Megkaptuk az első hibánkat! Azt mondja, az "int" típusú (integerek, egész számok) objektumoknak nincs hosszuk. Most akkor mit tehetünk? Talán leírhatjuk a számunkat stringként? A stringeknek van hosszuk, nem? + + >>> len(str(304023)) + 6 + + +Működött! Használtuk a `str` függvényt a `len` függvény belsejében. A `str()` függvény stringgé alakít egy tetszőleges típusú objektumot. + +* A `str` függvény **stringgé** alakítja a dolgokat +* Az `int` függvény **integerré** alakítja a dolgokat + +> Fontos: számokat (integereket) stringgé bármikor alakíthatunk, de stringet számmá nem feltétlenül - mégis mi lenne az `int('hello')` eredménye? + +## Változók + +A programozásban nagyon fontos a változó fogalma. A változó egy név egy objektumra, amit majd később újra felhasználhatunk. A programozók arra használják a változókat, hogy adatokat tároljanak velük, hogy a kódjukat olvashatóbbá tegyék, és hogy ne kelljen megjegyezniük mindenről, hogy micsoda. + +Tegyük fel, hogy létrehoztál egy változót, aminek a neve `name`: + + >>> name = "Ola" + + +Látod? Egyszerű! Csak ennyi: name egyenlő Ola. + +Amint láthatod, a program nem adott vissza semmilyen eredményt, az eddigiekkel ellentétben. Honnan tudjuk így, hogy a változó létrejött? Egyszerűen írd be, hogy `name`, majd üss `enter`-t: + + >>> name + 'Ola' + + +Juppííí! Az első változód :)! És bármikor megváltoztathatod, hogy mit tartalmaz: + + >>> name = "Sonja" + >>> name + 'Sonja' + + +És függvényekben is használhatod: + + >>> len(name) + 5 + + +Szuper, ugye? Természetesen a változók bármilyen értéket felvehetnek, például szám-értékeket is. Próbáld ki: + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +De mi van akkor, ha rossz nevet használunk? Kitalálod? Próbáljuk ki! + + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + + +Egy hiba! Amint látod a Pythonban különböző típusú hibák vannak, ezt például úgy hívják hogy **NameError**. A Python ezt a hibát dobja, ha olyan változóra hivatkozol, ami nem volt még létrehozva. Ha majd találkozol ezzel a hibával, mindig ellenőrizd a kódod, hogy nem írtál-e el egy nevet. + +Játssz egy kicsit a változókkal, hogy lásd, mi mindenre vagy képes velük! + +## A print függvény + +Próbáld ki ezt: + + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + + +Amikor beírod, hogy `name`, a Python interpreter a "name" változó szöveges *reprezentációjával* tér vissza, ami a M-a-r-i-a betűkből áll, idézőjelek között. Amikor azt írod: `print(name)`, a Python "kinyomtatja" a változó tartalmát a képernyőre, idézőjelek nélkül, ami sokkal elegánsabb. + +Amint majd látni fogjuk, a `print()` hasznos lesz függvények belsejében is, vagy amikor több sorba szeretnénk nyomtatni. + +## Listák + +A stringek és az integerek mellett a Python még sok más típusú objektumot ismer. Most megmutatunk egy újat, amit úgy hívnak: **lista**. A lista olyan, amilyennek elképzeled: egy objektum, ami más objektumok listája :) + +Hozzunk létre egy listát: + + >>> [] + [] + + +Igen, ez egy üres lista. Nem túl hasznos, ugye? Most hozzunk létre egy listát a lottószámokkal. Nem akarjuk folyton ismételni magunkat, úgyhogy egyenesen egy változóba tesszük: + + >>> lottery = [3, 42, 12, 19, 30, 59] + + +Igen, van egy listánk! Mit lehet vele csinálni? Nézzük meg, hány lottószám van a listában. Van tipped, melyik függvényt fogjuk erre használni? Biztos tudod! + + >>> len(lottery) + 6 + + +Igen! A `len()` megadja, hogy hány objektum van a listában. Hasnzos, ugye? Most akkor rendezzük sorba a listát: + + >>> lottery.sort() + + +Ez nem ad vissza semmit, csak megváltoztatta a számok sorrendjét a listában. Írassuk ki a listát, hogy lássuk, mi történt: + + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + + +Amint látod, a számok a listában most növekvő sorrendben vannak. Gratula! + +Esetleg szeretnéd fordított sorrendbe rendezni? Csináljuk meg! + + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + + +Könnyű, ugye? Ha hozzá akarsz adni valamit a listához, a következő paranccsal teheted: + + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + + +Ha például csak az első számot akarod látni, arra használhatod az **indexelést**. Az index egy szám ami megmondja, hányadikként fordul elő egy elem a listában. A programozók szeretik 0-tól kezdeni a számolást, ezért a lista első eleme a 0-dik indexű helyen van, a következő az 1-nél és így tovább. Próbáld ki ezt: + + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + + +Amint látod, a listában előforduló különböző objektumokat elérhetjük a lista nevének, illetve az objektum indexének megjelölésével, ahol az indexet szögletes zárójelbe írjuk. + +Ahhoz, hogy valamit kitöröljünk a listából, szükségünk van az **index** fogalmára, amint azt az előbb tanultuk, valamint a `pop()` parancsra. Nézzünk egy példát hogy megerősítsük az eddig tanultakat; ki fogjuk törölni az első elemet a listánkból. + + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + + +Működik, mint a varázslat! + +Szórakozásból próbálj elérni különböző indexű elemeket: 6, 7, 1000, -1, -6 vagy -1000. Meg tudod-e mondani az eredményt előre? Értelmes-e az eredmény? + +Ebben a Python dokumentációban megtalálod a listákra értelmezett összes metódust: https://docs.python.org/3/tutorial/datastructures.html + +## Szótárak + +A szótár hasonló a listához, de a szótár elemeit nem indexekkel hanem kulcsokkal (key) érjük el. A kulcs lehet bármilyen string vagy szám. Az üres szótár létrehozására szolgáló utasítás a következő: + + >>> {} + {} + + +Épp most definiáltál egy üres szótárat. Hurrá! + +Most pedig próbáld ki a következő parancsot (és próbáld meg használni a saját adataidat): + + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + + +Ezzel a paranccsal létrehoztál egy szótár-változót aminek a neve `participant`, és ami tartalmaz három kulcs-érték (key-value) párt: + +* A `name` kulcs az `'Ola'` értékre mutat (ami egy `string` típusú objektum), +* `country` a `'Poland'`-ra mutat (szintén `string` típusú), +* és `favorite_numbers` a `[7, 42, 92]` objektumra mutat (ami egy `lista` benne három elemmel). + +Lekérdezheted az egyes kulcsokhoz tartozó értékeket a következő szintaxist használva: + + >>> print(participant['name']) + Ola + + +Látod, nagyon hasonlít a listákhoz. Csak épp nem kell indexeket megjegyezned - csupán neveket. + +Vajon mi történik, ha olyan kulcshoz tartozó értéket kérdezünk le a Pythontól, ami nem létezik? Nézzük meg! + + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + + +Jéé, egy újabb hiba! Ezúttal **KeyError**. A Python segítőkész, és megmondja, hogy az `'age'` kulcsnál nem található érték a szótárban. + +Mikor használjunk szótárakat és mikor listákat? Nos, ez egy érdekes kérdés. Gondolkozz el egy kicsit, és próbáld meg magadtól kitalálni, mielőtt elolvasod az alábbi választ. + +* Csak elemek rendezett sorozatára van szükséged? Használj listát. +* Kulcs és érték párokra van szükséged, amiket majd le tudsz kérdezni hatékonyan (kulcs alapján)? Használj szótárat. + +A szótárak, ugyanúgy mint a listák, *módosíthatók*, ami azt jelenti, hogy az objektumot meg lehet változtatni létrehozás után. Hozzá lehet adni egy kulcs-érték párt a szótárhoz a létrehozása után, pl: + + >>> participant['favorite_language'] = 'Python' + + +Ugyanúgy, mint a listáknál, a `len()` metódus visszaadja a szótár hosszát, azaz a kulcs-érték párok számát. Rajta, próbáld ki a következő parancsot: + + >>> len(participant) + 4 + + +Remélem most már világos :) Készen állsz az újabb mókára a szótárakkal? Ugorj a következő sorhoz, és láss lenyűgöző dolgokat. + +Használd a `pop()` parancsot, hogy kitörölj egy elemet a szótárból. Mondjuk ki akarod törölni a `'favorite_numbers'` kulcsnál található elemet. Csak írd be a következőt: + + >>> participant.pop('favorite_numbers') + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + + +Amint azt a kimenetből látod, a 'favorite_numbers' kulcshoz tartozó elem eltűnt a szótárból. + +Az előbbihez hasonlóan, meg is tudod változtatni egy kulcsnál a hozzá tartozó értéket a szótárban. Írd ezt: + + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + + +Amint látod, a `'country'` kulcsnál levő érték megváltozott `'Poland'`-ról `'Germany'`-ra. :) Izgalmas, ugye? Hurrá! Most ismét tanultál egy nagyszerű dolgot. + +### Összefoglaló + +Nagyszerű! Most már tudsz egy csomó mindent a programozásról. Ebben az utolsó részben a következőkről tanultál: + +* **hibák** - tudod, hogyan olvasd és értsd meg a hibákat, amiket a Python ad, amikor nem tudja értelmezni a parancsodat +* **változók** - nevek az objektumokhoz, hogy a kód könnyebben írható és könnyebben olvasható legyen +* **listák** - lista meghatározott sorrendben lévő objektumokból +* **szótárak** - objektumok, amiket kulcs-érték párokként tárolunk + +Felkészültél a következő részre? :) + +## Dolgok összehasonlítása + +A számítástechnikában nagyon fontos, hogy össze tudjunk hasonlítani dolgokat. Mik a legegyszerűbb dolgok, amiket össze tudunk hasonlítani? Hát a számok. Nézzük meg ez hogy működik: + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + + +Adtunk a Pythonnak néhány számot, hogy összehasonlítsa azokat. Amint látod, a Python nem csak számokat, de műveleti eredményeket is össze tud hasonlítani. Jó, ugye? + +Azon gondolkozol, miért kellett két egyenlőség jelet `==` tenni, amikor azt néztük, hogy két szám egyenlő-e? Az egyetlen `=` jelet arra használjuk, hogy a változóknak értéket adjunk. Mindig, de **mindig** két `==` jelet kell használni ha két dolog egyenlőségét akarod tesztelni. Azt is ki tudjuk fejezni, hogy két dolog nem egyenlő. Erre a `!=` szimbólumot használjuk, amint az alábbi példában is. + +Adj a Pythonnak két új parancsot: + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +A `>` és a `<` egyszerűek, de vajon a `>=` és a `<=` mit jelentenek? Ezeket úgy kell olvasni, hogy: + +* x `>` y azt jelenti: x nagyobb, mint y +* x `<` y azt jelenti: x kisebb, mint y +* x `<=` y azt jelenti: x kisebb vagy egyenlő y-nal +* x `>=` y azt jelenti: x nagyobb vagy egyenlő y-nal + +Nagyszerű! Szeretnél még egy példát? Próbáld ki ezt: + + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + + +Annyi összehasonlítást kombinálhatsz össze, amennyit csak akarsz, és a Python kiszámolja az eredményt. Okos, ugye? + +* **and** (azaz: és) - amikor az `and` operátort használod, a kifejezés mindkét oldalán igaz értéknek kell állnia ahhoz, hogy az eredmény igaz legyen +* **or** (azaz: vagy) - amikor az `or` operátort használod, elég csak az egyik oldalon igaz értéknek állnia ahhoz, hogy az eredmény igaz legyen + +Hallottad már azt a kifejezést hogy "almákat narancsokkal összehasonlítani"? Nézzük meg ennek a python-beli megfelelőjét: + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +Láthatod, hogy ugyanúgy, mint a kifejezéseknél, a Python nem tudja összehasonlítani a számot (`int`) a stringgel (`str`). Ehelyett **TypeError** típusú hibát dob, azaz megmondja, hogy két különböző típust nem lehet egymással összehasonlítani. + +## Boolean (Logikai) + +Véletlenül épp megismerkedtél egy újabb Python típussal. Úgy hívják: **Boolean** -- és valószínűleg ez a legegyszerűbb típus ami létezik. + +Egy Boolean objektum két lehetséges értéket vehet fel: - Igaz - Hamis + +De ahhoz, hogy a Python megértse, pontosan így kell írni: 'True' (az első betű nagybetű, a többi kisbetű). **true, TRUE, tRUE mind nem jók -- csak az True helyes.** (És ugyanígy a 'False' esetében) + +A Booleanok is lehetnek változók! Nézd: + + >>> a = True + >>> a + True + + +Sőt, ezt is írhatod: + + >>> a = 2 > 5 + >>> a + False + + +Gyakorold egy kicsit és játssz a Booleanokkal, pl próbáld ki a következő parancsokat: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Gratulálunk! A Booleanok a programozás egyik legmenőbb elemei, és te épp megtanultad használni őket! + +# Mentsd el! + +Egész mostanig a python interpreterbe írkáltuk a parancsokat, ami arra korlátoz minket hogy, egyszerre csak egy sort írjunk. A gyakorlatban a programokat fájlba mentjük, és utána futtatjuk a programnyelv **interpreter**-e vagy **compiler**-e révén. Mi mindeddig a Python **interpreter**-ével futtatuk a programjainkat, soronként. A következő feladatokhoz többsoros programokra is szükségünk lesz, úgyhogy gyorsan: + +* Lépjünk ki a Python interpreterből +* Nyissunk meg egy kódszerkesztőt +* Mensünk el benne valami kódot egy python fájlba +* És futtassuk! + +Ahhoz hogy kilépjünk a Python interpreterből, egyszerűen írjuk be, hogy ~~~ exit()~~~: + + >>> exit() + $ + + +Ezzel visszatértünk a parancssorba. + +Egy előző részben már kiválasztottuk a kedvenc [kódszerkesztő][2]nket. Most nyissuk meg az editort és az új üres fájlba írjuk bele: + + [2]: ../code_editor/README.md + +```python + print('Hello, Django girls!') +``` + +> **Megj.** Vegyük észre a kód editorok legnagyszerűbb tulajdonságát: a színeket! A Python konzolban minden egyszínű volt, most a `print` függvény más színű, mint a string. Ezt úgy hívják: "syntax highlighting" (szintaxis-kiemelés), és kódoláshoz nagyon hasznos. A kód színe mindenféle utalásokat hordoz magában, pl. egy lezáratlan string vagy egy elírás egy kulcsszó nevében (pl. a `def` a függvényeknél, amint látni fogjuk mindjárt). Ez az egyik oka annak, hogy kódszerkesztőt használuk :) + +Mostanra már tapasztalt Python programozó lettél, úgyhogy írj valami kódot, amit ma tanultál. + +Most mentsük el a fájlt, és adjunk neki valami jellemző nevet. Nevezzünk **python_intro.py**-nak, és mentsük el a desktopra. Bárhogy nevezhetjük a fájlt, de a kiterjesztés fontos, hogy **.py** legyen. A **.py** kiterjesztés megmondja az operációs rendszerünknek, hogy **python futtatható programfájl**-lal van dolga. + +Most hogy a fájl el van mentve, itt az ideje, hogy lefuttassuk. Felhaszálva a tudásodat a parancssoros részből, navigálj a terminálban a desktopra a **könyvtárváltás** parancs segítségével. + +Mac-en a parancs valahogy így néz ki: + + $ cd /Users//Desktop + + +Linuxon így (A "Desktop" lehet, hogy le van fordítva a te nyelvedre): + + $ cd /home//Desktop + + +És Windowson így néz ki: + + > cd C:\Users\\Desktop + + +Ha megakadtál volna, kérj nyugodtan segítséget. + +Most pedig futtasd le a Python kódot, így: + + $ python3 python_intro.py + Hello, Django girls! + + +Rendben! Épp lefuttattad az első Python programodat fájlból. Jó érzés, ugye? + +Most akkor továbbmehetünk egy újabb kulcsfontosságú programozási elemre: + +## If...elif...else + +Sokszor előfordul a programozásban, hogy egyes kódrészleteknek csak akkor kell lefutniuk, ha bizonyos feltételek teljesülnek. Ezért vannak a Pythonban az **if statement**ek (if állítások). + +Cseréld ki a **python_intro.py** fájlban lévő kódot erre: + +```python + if 3 > 2: +``` + +Ha ezt elmented és lefuttatod, ezt a hibaüzenetet fogod látni: + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +A Python arra számít, hogy további utasításokat kap arra az esetre, ha a `3 > 2` teljesül, vagyis `True` lesz. Vegyük rá a Pythont, hogy kiírja: "It works!" ("Működik!"). Változtasd meg erre a **python_intro.py** fájlban lévő kódot: + +```python + if 3 > 2: + print('It works!') +``` + +Megfigyelted, hogy a következő sort 4 szóközzel indentáltuk? Erre azért van szükség, hogy a Python tudja, melyik kódrészletet kell lefuttatnia, ha a feltétel teljesül. Egy szóközt is használhatnál, de szinte az összes Python programozó 4 szóközt használ, hogy rendezetten nézzen ki a kód. Egy `tab` is 4 szóköznek számít. + +Mentsd el, és futtasd le még egyszer: + + $ python3 python_intro.py + It works! + + +### Mi történik, ha egy feltétel nem teljesül (vagyis nem True)? + +A korábbi példákban a kód csak akkor futott le, ha a feltétel teljesült. De a Pythonnak van `elif` és `else` statementje is: + +```python + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') +``` + +Ha ezt lefuttatod, a következőt kapod: + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +Ha a 2 nagyobb lenne, mint az 5, a második parancs futott volna le. Egyszerű, igaz? Nézzük, hogy működik az `elif`: + +```python + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') +``` + +lefuttatva: + + $ python3 python_intro.py + Hey Sonja! + + +Látod, mi történt itt? Az `elif` arra jó, hogy plusz feltételeket írhass a kódodba, ami akkor fut le, ha a korábbi feltételek nem teljesülnek. + +Az első `if` statement után annyi `elif` állítást írhatsz, amennyit csak akarsz. Például: + +```python + volume = 57 + if volume < 20: + print("It's kinda quiet.") + elif 20 <= volume < 40: + print("It's nice for background music") + elif 40 <= volume < 60: + print("Perfect, I can hear all the details") + elif 60 <= volume < 80: + print("Nice for parties") + elif 80 <= volume < 100: + print("A bit loud!") + else: + print("My ears are hurting!:(")! :(") +``` + +A Python sorban mindegyik feltételt megnézi, és kiírja: + + $ python3 python_intro.py + Perfect, I can hear all the details + + +### Összefoglaló + +Az előző három feladatban ezekről tanultál: + +* **dolgok összehasonlítása** - Pythonban a `>`, `>=`, `==`, `<=`, `<` jelekkel, és az `and`, `or` operátorokkal hasonlíthatsz össze dolgokat +* **Boolean** - egy olyan fajta objektum, ami csak két értéket vehet fel: `True` vagy `False` +* **Fájlok elmentése** - a kódot fájlokban is tárolhatod, így hosszabb programokat is lefuttathatsz. +* **if...elif...else** - állítások, amik arra jók, hogy a kód csak bizonyos feltételek teljesülése esetén fusson le. + +Elérkeztünk a fejezet utolsó részéhez! + +## A saját függvényeidhez! + +Emlékszel például a `len()` fügvényre, amit lefuttathatsz Pythonban? Jó hírünk van - most megtanulod, hogyan írhatsz saját függvényeket! + +A függvény utasítások sorozata, amit a Python lefuttat. Minden Python függvény a `def` kulcsszóval kezdődik, van neve, és lehetnek paraméterei. Kezdjük egy könnyűvel. Cseréld ki a **python_intro.py** kódját erre: + +```python + def hi(): + print('Hi there!') + print('How are you?') + + hi() +``` + +Oké, kész is az első függvény! + +Talán elgondolkodtál, miért írtuk a függvény nevét a fájl aljára. Erre azért van szükség, mert a Python felülről lefelé olvassa be és futtatja le a fájlt. Tehát ahhoz, hogy használni tudjuk a függvényünket, újra le kell írnunk a fájl alján. + +Futtassuk le, és nézzük meg, mi történik: + + $ python3 python_intro.py + Hi there! + How are you? + + +Ez könnyű volt! Most írjuk meg az első olyan függvényt, aminek vannak paraméterei. Az előző példát fogjuk használni - egy függvény, ami köszön annak, aki futtatja, de most nevet is adunk hozzá: + +```python + def hi(name): +``` + +Ahogy láthattad, a függvény most kapott egy paramétert, amit `name`-nek hívunk: + +```python + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() +``` + +Fontos: a `print` függvény 4 szóközzel van indentálva az `if` statementen belül. Erre azért van szükség, hogy ez a függvény a feltétel teljesülése esetén fusson le. Nézzük, hogy működik: + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' + + +Hoppá, egy hiba. Szerencsére a Python elég hasznos hibaüzeneteket ad nekünk. Azt mondja, a `hi()` függvénynek (vagyis annak, amit az előbb definiáltunk) egy kötelező paramétere van (amit `name`-nek hívnak), és ezt elfelejtettük beadni, amikor meghívtuk a függvényt. Javítsuk ki a fájl alján: + +```python + hi("Ola") +``` + +És futtassuk le újra: + + $ python3 python_intro.py + Hi Ola! + + +És ha megváltoztatjuk a nevet? + +```python + hi("Sonja") +``` + +Futtasd le: + + $ python3 python_intro.py + Hi Sonja! + + +Mit gondolsz, mi fog történni, ha egy harmadik nevet írsz be? Próbáld ki, és nézd meg, jól gondoltad-e. Ezt kell kapnod: + + Hi anonymous! + + +Ez fantasztikus, nem? Így nem kell állandóan ismételned magad, ha meg szeretnéd változtatni az ember nevét, akinek a függvény köszön. Pont emiatt van szükségünk függvényekre - soha ne ismételd meg a kódodat! + +Most csináljunk valami okosabbat - több mint két név van a világon, és nehéz lenne mindegyikhez egy külön feltételt írni, nem? + +```python + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") +``` + +Most hívjuk meg a kódot: + + $ python3 python_intro.py + Hi Rachel! + + +Gratulálunk! Megtanultad, hogy kell függvényeket írni :) + +## Ciklusok (loopok) + +Ez már tényleg az utolsó rész. Gyors volt, nem igaz? :) + +A programozók nem szeretik ismételni magukat. A programozás arról szól, hogy dolgokat automatizáljunk, így nem kell minden alkalommal kézzel beírni mindenkinek a nevét, akit üdvözölni akarunk. Ilyenkor jönnek jól a ciklusok. + +Még emlékszel a listákra? Írjunk egy listát lányokból: + +```python + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +Mindegyiküket üdvözölni szeretnénk. Ehhez már megvan a `hi` függvényünk, tegyük bele egy loopba: + +```python + for name in girls: +``` + +A ~~~for~~~ statement hasonlóan működik, mint az ~~~if~~~statement; mindkettő alatt 4 szóközzel kell indentálni a következő sort. + +Itt a teljes kód, ami a fájlban lesz: + +```python + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('Next girl') +``` + +És amikor futtatjuk: + + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl + + +Amint láthattad, minden, amit indentálva a `for` statementbe tettél, megismétlődik a `girls` lista minden elemével. + +A `for`-t számokon is használhatod, a `range` függvénnyel: + + for i in range(1, 6): + print(i) + + +Ezt kapjuk: + + 1 + 2 + 3 + 4 + 5 + + +A `range` függvény létrehoz egy egymás után következő számokból álló listát (ezeket a számokat te adod meg paraméterként). + +Figyeld meg, hogy a két szám közül a második már nincs benne a listában, amit a Python visszaad (vagyis a `range(1, 6)` 1-től 5-ig számol, de nem tartalmazza a 6-ot). Ez azért van, mert a "range" félig nyitott, ez pedig azt jelenti, hogy az első értéket tartalmazza, de az utolsót már nem. + +## Összefoglaló + +Meg is vagyunk. **Szuper vagy!** Ez egy nehéz fejezet volt, büszke lehetsz magadra. Mi nagyon büszkék vagyunk rád, amiért idáig eljutottál! + +Most talán tarthatnál egy kis szünetet - nyújtózkodj, sétálj egy kicsit, pihentesd a szemeidet - mielőtt továbbmennénk a következő fejezetre. :) + +![Cupcake][3] + + [3]: images/cupcake.png diff --git a/hu/python_introduction/images/cupcake.png b/hu/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/hu/python_introduction/images/cupcake.png differ diff --git a/hu/template_extending/README.md b/hu/template_extending/README.md new file mode 100644 index 00000000000..a2a3c37ff39 --- /dev/null +++ b/hu/template_extending/README.md @@ -0,0 +1,122 @@ +# Template-kiegészítés + +Egy másik szuper dolog, amit a Django tud, a **template extending**, vagyis template-kiegészítés. Mit jelent ez? Azt, hogy a HTML-ed egyes részeit több oldalon is fel tudod használni az alkalmazásodban. + +Így nem kell megismételned magad minden fájlban, ha ugyanazt az információt szeretnéd felhasználni, vagy ugyanolyan layout-ot tervezel. És ha meg szeretnél változtatni valamit, nem kell minden sablonban külön megtenned, csak egyszer! + +## Hozd létre az alap template-et + +A base (alap) template a legegyszerűbb sablon, amit az alkalmazásod összes oldalán kiegészítesz. + +Hozz létre egy `base.html` fájlt a `blog/templates/blog/`-ban: + + blog + └───templates + └───blog + base.html + post_list.html + + +Majd nyisd meg, és másolj át mindent a `post_list.html`-ből a `base.html`-be, így: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Aztán a `base.html`-ben cseréld ki az egész ``-t (mindent a `` és a `` között) erre: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +Lényegében a `{% for post in posts %}{% endfor %}` részt kicseréltük erre: + +```html +{% block content %} +{% endblock %} +``` + +Ez mit is jelent? Létrehoztál egy `block`-ot. Ez egy olyan template tag, amely segítségével HTML-t illeszthetsz be a blokkba más template-ekben, ezzel kiegészítve a `base.html`-t. Máris megmutatjuk, hogy működik. + +Most mentsd el, és nyisd meg újra a `blog/templates/blog/post_list.html`-t. Törölj ki mindent a body-n kívül, és a `` részt is, hogy így nézzen ki a fájl: + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +És most add hozzá ezt a sort a fájl elejéhez: + + {% extends 'blog/base.html' %} + + +{% raw %}Ez azt jelenti, hogy most a `base.html` template-et egészítjük ki a `post_list.html`-ben. Már csak egy dolog van hátra: az előző sor kivételével rakj mindent `{% block content %}` és `{% endblock content %}` közé. Így:{% endraw %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +Ez az! Nézd meg, hogy még mindig működik-e a weboldalad :) + +> Ha `TemplateDoesNotExists` (a template nem létezik) hibát kapsz, ami azt mondja, nincs `blog/base.html` fájlod, és fut a `runserver` a konzolban, próbáld meg leállítani (Ctrl+C-vel, vagyis egyszerre nyomd meg a Control és a C billentyűt) és indítsd el újra a `python manage.py runserver` paranccsal. \ No newline at end of file diff --git a/hu/whats_next/README.md b/hu/whats_next/README.md new file mode 100644 index 00000000000..aaade19d5df --- /dev/null +++ b/hu/whats_next/README.md @@ -0,0 +1,40 @@ +# Következő lépések + +Gratulálj magadnak! **Szuper vagy**. Nagyon büszkék vagyunk rád! <3 + +### És most? + +Tarts egy kis szünetet, és pihenj. Valami egészen hatalmas dolgot csináltál. + +Aztán majd ne felejtsd el: + +* Követni a Django Girlst [Facebook][1]on vagy [Twitter][2]en, hogy mindenről értesülj + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Tudunk-e ajánlani bármilyen tananyagot? + +Igen! Először is nézd meg a másik könyvünket, a [Django Girls Tutorial: Extensions][3]-t. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Később megpróbálkozhatsz a lenti listában lévő anyagokkal is. Ezeket mind nagyon ajánljuk! + +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/it/GLOSSARY.md b/it/GLOSSARY.md new file mode 100644 index 00000000000..5ebfa17670a --- /dev/null +++ b/it/GLOSSARY.md @@ -0,0 +1,3 @@ +# editor di codice + +L'editor di codice è un'applicazione che ti permette di salvare il tuo codice e di potervi tornare in seguito. Puoi capire come procurartene uno nel [capitolo Editor di codice](./code_editor/README.md) \ No newline at end of file diff --git a/it/README.md b/it/README.md new file mode 100644 index 00000000000..40e85c34b2e --- /dev/null +++ b/it/README.md @@ -0,0 +1,48 @@ +# Il tutorial di Django Girls + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Questo lavoro è sotto la licenza internazionale di Creative Commons Attribution-ShareAlike 4.0. Per vedere una copia di questa licenza, visita https://creativecommons.org/licenses/by-sa/4.0/ + +## Introduzione + +Hai mai sentito che il mondo sta diventando sempre più tecnologico e sei in qualche modo rimasto indietro? ti sei mai chiesta come creare un sito web ma non hai mai avuto abbastanza motivazione per iniziare? Hai mai pensato che il mondo del software è troppo complicato per te persino per provare a fare qualcosa per conto tuo? + +Beh, abbiamo buone notizie per te! La programmazione non è così complicata come sembra e vogliamo dimostrati quanto può essere divertente. + +Il tutorial non ti trasformerà magicamente in un programmatore. Se vuoi diventare bravo/a, ci vorranno mesi o addirittura anni di apprendimento e pratica. Ma ti vogliamo dimostrare che la programmazione o creare siti web non è complicato come sembra. Proveremo a spiegarti diversi argomenti come meglio possiamo, in modo che non ti senta più intimidito/a dalla tecnologia. + +Speriamo di essere in grado di farti amare la tecnologia come lo facciamo noi! + +## Cosa imparerai durante questo tutorial? + +Una volta che avrai terminato il tutorial, avrai a disposizione una semplice applicazione web: il tuo blog personale. Ti mostreremo come metterlo in linea, in modo che gli altri possano vedere il tuo lavoro! + +Assomiglierà (più o meno) a questo: + +![Figure 0.1][2] + + [2]: images/application.png + +> Se lavori da solo/a al tutorial e non hai un'insegnante che ti possa aiutare nel caso avessi qualche problema, abbiamo una chat per te: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Abbiamo chiesto ai nostri insegnanti e partecipanti precedenti di esserci di volta in volta ed aiutare gli altri con il tutorial! Non aver paura di fare domande! + +OK, [cominciamo dall'inizio...][3] + + [3]: ./how_the_internet_works/README.md + +## Informazioni e contribuzioni + +Questo tutorial è mantenuto da [DjangoGirls][4]. Se trovi errori o se vuoi aggiornare questo tutorial, [segui le linee guida per i collaboratori][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Vorresti aiutarci a tradurre il tutorial in un altra lingua? + +Attualmente, le traduzioni vengono mantenute sulla piattaforma crowdin.com in: + +https://crowdin.com/project/django-girls-tutorial + +Se la tua lingua non è elencata su crowding, per favore [apri una nuova istanza][6] con la tua lingua in modo che possiamo aggiungerla. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new \ No newline at end of file diff --git a/it/SUMMARY.md b/it/SUMMARY.md new file mode 100644 index 00000000000..694b07fd6b9 --- /dev/null +++ b/it/SUMMARY.md @@ -0,0 +1,26 @@ +# Indice + +* [Introduzione](README.md) +* [Installazione](installation/README.md) +* [Come funziona Internet](how_the_internet_works/README.md) +* [Introduzione al command line](intro_to_command_line/README.md) +* [Installazione di Python](python_installation/README.md) +* [Code Editor](code_editor/README.md) +* [Introduzione a Python](python_introduction/README.md) +* [Che cos'è Django?](django/README.md) +* [Installazione di Django](django_installation/README.md) +* [Il tuo primo progetto Django!](django_start_project/README.md) +* [I modelli di Django](django_models/README.md) +* [L'admin di Django](django_admin/README.md) +* [Deploy!](deploy/README.md) +* [Django URL](django_urls/README.md) +* [Le views di Django - è arrivata l'ora di creare!](django_views/README.md) +* [Introduzione all'HTML](html/README.md) +* [ORM di Django (Querysets)](django_orm/README.md) +* [I dati dinamici in templates](dynamic_data_in_templates/README.md) +* [I templates di Django](django_templates/README.md) +* [CSS - dagli un bell'aspetto](css/README.md) +* [Estendere il template](template_extending/README.md) +* [Estendi la tua applicazione](extend_your_application/README.md) +* [Form Django](django_forms/README.md) +* [Quali sono le prospettive?](whats_next/README.md) \ No newline at end of file diff --git a/it/code_editor/README.md b/it/code_editor/README.md new file mode 100644 index 00000000000..8261e76f6cb --- /dev/null +++ b/it/code_editor/README.md @@ -0,0 +1,7 @@ +# Code Editor + +Stai per scrivere la tua prima riga di codice, per cui è il momento di scaricare il tuo editor! + +> **Nota** Potresti aver già affrontato questo passaggio nel capitolo Installazione - se è così, puoi saltare direttamente al prossimo capitolo! + +{% include "/code_editor/instructions.md" %} diff --git a/it/code_editor/instructions.md b/it/code_editor/instructions.md new file mode 100644 index 00000000000..bd6ab5614c2 --- /dev/null +++ b/it/code_editor/instructions.md @@ -0,0 +1,31 @@ +Sono disponibili diversi editor e la scelta di uno piuttosto che un altro dipende principalmente dal gusto personale. La maggior parte dei programmatori Python usa complessi ma estremamente potenti IDE (ambienti di sviluppo integrati), come PyCharm. Tuttavia, dal momento che sei ancora agli inizi non è l'editor più appropriato; quelli che ti suggeriremo noi sono ugualmente potenti ma molto più semplici da utilizzare. + +I nostri suggerimenti sono riportati qui di seguito, ma sentiti libero/a di chiedere al tuo coach quali sono le sue preferenze in materia di editor, in questo modo sarà più semplice per il tuo coach aiutarti. + +## Gedit + +Gedit è un editor open-source e gratuito, disponibile per tutti i sistemi operativi. + +[Scaricalo qui](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text è uno tra gli editor più utilizzati. Ha un periodo di prova gratuito. È molto facile da installare e da utilizzare ed è disponibile per tutti i sistemi operativi. + +[Scaricalo qui](https://www.sublimetext.com/3) + +## Atom + +Atom è un nuovo editor di codice creato da [GitHub](https://github.com/). È gratuito, open-source, facile da installare e da usare. È disponibile per Windows, OSX e Linux. + +[Scaricalo qui](https://atom.io/) + +## Perché installiamo un editor di codice? + +Forse ti stai chiedendo per quale motivo installiamo questo editor di codice invece di usare un applicazione come Word or Blocco Note. + +Il primo motivo è che il codice deve essere **testo semplice**, e il problema con programmi come Word e Textedit è che in realtà non producono testo semplice. Producono testo RTF (con caratteri e formattazione), utilizzando formati personalizzati come [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +La seconda ragione è che i code editor sono specializzati per programmare, perciò hanno molte funzionalità utili, ad esempio diversi colori per evidenziare frammenti di codice con diversi significati, o l'inserimento automatico del secondo paio di virgolette. + +Vedremo tutto ciò più tardi. Il tuo fidato code editor sarà presto uno dei tuoi strumenti preferiti :) \ No newline at end of file diff --git a/it/css/README.md b/it/css/README.md new file mode 100644 index 00000000000..b7b87505dd2 --- /dev/null +++ b/it/css/README.md @@ -0,0 +1,294 @@ +# CSS - dagli un bel aspetto! + +Il nostro blog sembra ancora un pochino brutto, vero? È arrivato il momento di abbellirlo! Per fare ciò useremo CSS. + +## Che cos'è CSS? + +Cascading Style Sheets (CSS) è un linguaggio usato per descrivere l'aspetto e la formattazione di un sito scritto in un linguaggio di markup (come HTML). Vedilo come il trucco del nostro sito ;). + +Ma non vogliamo ricominciare da capo, giusto? Ancora una volta useremo qualcosa preparato da altri programmatori disponibile su Internet gratuitamente per tutti. Si sa, re-inventare la ruota non è molto divertente. + +## Usiamo Bootstrap! + +Bootstrap è uno dei più popolari framework HTML e CSS per costruire bellissimi siti internet: https://getbootstrap.com/ + +È stato scritto da programmatori che lavoravano per Twitter ed è ora sviluppato da volontari da ogni parte del mondo. + +## Installa Bootstrap + +Per installare Bootstrap, avrai bisogno di aggiungere questo nel tag `` del tuo file `.html` (`blog/templates/blog/post_list.html`): + +```html + + +``` + +Le due linee sopra riportate non aggiungono nessun file al tuo progetto. Stanno solo reindirizzando ad alcuni files the esistono in internet. Ma non ti preoccupare troppo, vai avanti e apri la tua pagina web e ricarica la pagina. Eccolo qui! + +![Figura 14.1][1] + + [1]: images/bootstrap1.png + +Sembra già più carino! + +## File statici in Django + +Infine, daremo uno sguardo più approfondito a quelli che abbiamo chiamato **file statici**. I file statici sono tutti i tuoi CSS e le immagini -- file che non sono dinamici, il loro contenuto non dipende dal contesto della richiesta e sarà lo stesso per ogni utente. + +### Dove mettere i file statici in Django + +Come hai visto quando abbiamo eseguito `collectstatic` sul server, Django sa già dove trovare i file statici per l'app built-in "admin". Ora dobbiamo solo aggiungere alcuni file statici per la nostra app, `blog`. + +Lo facciamo creando una cartella denominata `static` all'interno dela nostra app blog: + + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite + + +Django troverà automaticamente tutte le cartelle chiamate "static" dentro le cartelle delle tua app, e sarà in grado di utilizzare il loro contenuto come file statici. + +## Il tuo primo file CSS! + +Ora, creiamo un file CSS, per poter aggiungere il tuo stile personale al tuo sito. Crea una nuova cartella dal nome `css` all'interno della tua cartella `static`. Poi, crea un nuovo file all'interno della tua cartella `css` e chiamalo `blog.css`. Fatto? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +È giunto il momento di scrivere un po' di CSS! Apri il file `static/css/blog.css` nel tuo editor di codice. + +Non ci dilungheremo troppo sul come personalizzare e imparare CSS in questo momento, dal momento che è abbastanza facile e puoi impararlo da solo/a alla fine di questo workshop. Ti raccomandiamo caldamente di seguire questo corso [Codeacademy HTML & CSS course][2] per imparare tutto quello che serve sapere per poter rendere più bello un sito internet con CSS. + + [2]: https://www.codecademy.com/tracks/web + +Facciamo comunque un esempio. Perchè non cambiare il colore del nostro header? Per decifrare i colori, i computer usano dei codici speciali. Questi codici cominciano con `#` a cui fanno seguito 6 caratteri, sia lettere (A-F) che numeri (0-9). Puoi trovare vari esempi di codici colore qui: http://www.colorpicker.com/. Puoi anche usare [colori predefiniti][3] come ad esempio `red` e `green`. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +Aggiungi il seguente codice nel tuo file `static/css/blog.css`: + +```css +h1 a { +    color: #FCA205; +} +``` + +`h1 a` è un esempio di selettore CSS. Questo significa che stiamo cercando di cambiare lo stile su tutti gli elementi `a` all'interno di un elemento `h1` (in questo caso, abbiamo una linea di codice così strutturata: `

link

`). In questo caso, stiamo cercando di cambiare il colore con `#FCA205`, che corrisponde all'arancione. Ovviamente puoi mettere il codice di qualsiasi altro colore tu preferisca! + +In un file CSS definiamo lo stile degli elementi presenti nel file HTML. Gli elementi in questione vengono identificati con il nome (ad esempio `a`, `h1`, `body`) oppure con l'attributo `class` o l'attributo `id`. Class e id sono i nomi che assegni agli elementi. Le classi definiscono gruppi di elementi mentre gli id indicano uno specifico elemento. Ad esempio, il seguente elemento può essere identificato nel CSS utilizzando il nome del tag `a`, la classe `external_link` oppure l'id ` link_to_wiki_page`: + +```html + +``` + +Per saperne di più puoi leggere [CSS Selectors in w3schools][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Infine, dobbiamo anche far sapere al nostro template in HTML che abbiamo effettivamente aggiunto un po' di CSS. Apri il file `blog/templates/blog/post_list.html` e aggiungi la seguente riga di testo: + +```html +{% load staticfiles %} +``` + +Per ora stiamo solamente caricando tutti i nostri static files :). Aggiungi questa riga di testo tra `` e ``, subito dopo il link al file CSS di Bootstrap (il browser legge i file nell'ordine in cui sono dati, per cui il codice nei nostri files può sovrascrivere il codice presente nei files di Bootstrap): + +```html + +``` + +Stiamo dicendo al nostro template dove trovare i nostri file CSS. + +Il tuo file dovrebbe avere questo aspetto: + +```html +{% load staticfiles %} + +     +        Django Girls blog +         +         +         +     +     +         + +        {% for post in posts %} +            
+                

published: {{ post.published_date }}

+                

{{ post.title }}

+                

{{ post.text|linebreaksbr }}

+            
+        {% endfor %} +     + +``` + +OK, salviamo il file e ricarichiamo la pagina web! + +![Figura 14.2][5] + + [5]: images/color2.png + +Ben fatto! Adesso potremmo dare un po' più d'aria alla nostra pagina web e aumentare il margine nella parte sinistra. Proviamo! + +```css +body { +    padding-left: 15px; +} +``` + +Aggiungi questo al tuo CSS, salva il file e guarda il risultato! + +![Figura 14.3][6] + + [6]: images/margin2.png + +Potremmo anche personalizzare lo stile calligrafico nel nostro header. Incolla quanto segue all'interno del tag `` che si trova nel file `blog/templates/blog/post_list.html`: + +```html + +``` + +Questa riga consente di importare un font chiamato *Lobster* da Google Fonts (https://www.google.com/fonts). + +Ora aggiungi `font-family: 'Lobster';` nel file CSS `static/css/blog.css` all'interno del blocco `h1 a` (il codice tra le due parentesi graffe, `{` e `}`) e ricarica la pagina: + +```css +h1 a { +    color: #FCA205; +    font-family: 'Lobster'; +} +``` + +![Figura 14.3][7] + + [7]: images/font.png + +Grandioso! + +Come già accennato, il CSS utilizza il concetto di 'classe' che in pratica ti permette di assegnare uno specifico nome ad una parte del tuo documento HTML e di applicare uno stile solo a questa parte senza cambiare il resto. È di grande aiuto quando hai due div che hanno funzioni differenti (ad esempio uno è un header e l'altro un post), e non vuoi che appaiano uguali. + +Prova a dare dei nomi ad alcune parti dell'HTML. Aggiungi una classe chiamta `page-header` al tuo `div` che contiene l'intestazione così: + +```html + +``` + +E ora aggiungi una classe `post` al tuo `div` che contiene un articolo del blog. + +```html +
+    

published: {{ post.published_date }}

+    

{{ post.title }}

+    

{{ post.text|linebreaksbr }}

+
+``` + +Ora aggiungiamo dei blocchi di codice ai nostri nuovi selettori. I selettori che iniziano con `.` indicano una classe. Online ci sono molti tutorial e spiegazioni sul CSS che possono aiutarti a comprendere il codice che stiamo per scrivere. Per ora, copia e incolla quanto segue nel tuo file `mysite/static/css/blog.css`: + +```css +.page-header { +    background-color: #ff9400; +    margin-top: 0; +    padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { +    color: #ffffff; +    font-size: 36pt; +    text-decoration: none; +} + +.content { +    margin-left: 40px; +} + +h1, h2, h3, h4 { +    font-family: 'Lobster', cursive; +} + +.date { +    float: right; +    color: #828282; +} + +.save { +    float: right; +} + +.post-form textarea, .post-form input { +    width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { +    color: #ffffff; +    float: right; +    font-size: 26pt; +    margin-right: 20px; +} + +.post { +    margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { +    color: #000000; +} +``` + +Ora aggiungi all'esterno del codice HTML riguardante i posts all'interno del blog alcuni elementi con definizione di classi. Sostituisci questo: + +```html +{% for post in posts %} +    
+        

published: {{ post.published_date }}

+        

{{ post.title }}

+        

{{ post.text|linebreaksbr }}

+    
+{% endfor %} +``` + +nel file `blog/templates/blog/post_list.html` con quanto segue: + +```html +
+    
+        
+            {% for post in posts %} +                
+                    
+                        {{ post.published_date }} +                    
+                    

{{ post.title }}

+                    

{{ post.text|linebreaksbr }}

+                
+            {% endfor %} +        
+    
+
+``` + +Salva entrambi i file e ricarica la pagina web. + +![Figura 14.4][8] + + [8]: images/final.png + +Woohoo! È fantastico, vero? Il codice che abbiamo appena inserito non è poi così difficile da comprendere, dovresti riuscire a capirne la maggior parte semplicemente leggendolo. + +Non farti spaventare, sperimenta con i CSS e prova a cambiare alcune cose. Se rompi qualcosa, non ti preoccupare, puoi sempre farlo tornare come era prima! + +Compito per casa post-workshop: ti consigliamo caldamente di seguire [il corso su HTML & CSS di Codeacademy][2]. Così potrai imparare tutto ciò di cui hai bisogno per rendere i tuoi siti web più belli sfruttando il CSS. + +Pronta per il prossimo capitolo?! :) \ No newline at end of file diff --git a/it/css/images/bootstrap1.png b/it/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/it/css/images/bootstrap1.png differ diff --git a/it/css/images/color2.png b/it/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/it/css/images/color2.png differ diff --git a/it/css/images/final.png b/it/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/it/css/images/final.png differ diff --git a/it/css/images/font.png b/it/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/it/css/images/font.png differ diff --git a/it/css/images/margin2.png b/it/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/it/css/images/margin2.png differ diff --git a/it/deploy/README.md b/it/deploy/README.md new file mode 100644 index 00000000000..7108b23f80e --- /dev/null +++ b/it/deploy/README.md @@ -0,0 +1,313 @@ +# Deploy! + +> **Nota** Il seguente capitolo è abbastanza difficile da capire fino in fondo. Non mollare e cerca di portarlo a termine; deployment (termine abbastanza complicato da tradurre, ma indica tutto ciò che tu rendi LIVE, accessibile sul web e non più solo dal tuo computer) è una parte importante nel processo di costruzione di un sito web. Questo capitolo è inserito a metà del tutorial per far sì che il tuo tutor possa aiutarti con il processo leggermente più complesso di messa online del sito. Questo significa che puoi ancora finire il tutorial da sola se sei a corto di tempo. + +Fino ad ora il tuo sito è accessibile solo dal tuo computer, ma ora imparerai come metterlo online! Deploying è il processo di pubblicazione online del tuo progetto in modo tale che sia visibile anche da altre persone :). + +Come hai già visto, un sito internet ha sede in un server. Ci sono tantissimi server providers disponibili su internet. Noi ne useremo uno che ha un processo di deployment relativamente semplice: [PythonAnywere][1]. Questo provider è gratuito per piccole applicazioni che non hanno troppi visitatori. Sarà quindi perfetto per te al momento. + + [1]: https://pythonanywhere.com/ + +L'altro servizio esterno che useremo è [GitHub][2], che è un servizio di hosting di codice. Ne esistono altri, ma di questi tempi quasi tutti i programmatori hanno un account GitHub e ora lo avrai anche tu! + + [2]: https://www.github.com + +Useremo GitHub come trampolino di lancio per importare ed esportare il nostro codice su PythonAnywhere. + +# Git + +Git è un "sistema di controllo versione" utilizzato da un sacco di programmatori. Questo software può tracciare le modifiche nel corso del tempo ad i file, in questo modo puoi ripristinare successivamente una specifica versione. Un pò come l'opzione "traccia modifiche" in Microsoft Word, ma molto più potente. + +## Installare Git + +> **Nota** Se hai già fatto la procedura di installazione, non devi farlo di nuovo - si può passare alla sezione successiva e iniziare a creare il tuo repository Git. + +{% include "/deploy/install_git.md" %} + +## Inizializzare un repository Git + +Git tiene traccia delle modifiche a un particolare insieme di file in quello che è chiamato repository di codice (o "repo" in breve). Iniziamone uno per il nostro progetto. Apri la console ed esegui questi comandi nella directory `djangogirls`: + +> **Nota** controlla la directory su cui stai lavorando adesso con il comando `pwd`(OSX/Linux) oppure `cd`(Windows) prima di iniziare il repository. Dovresti essere nella cartella `djangogirls`. + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Dobbiamo inizializzare il repository git solo una volta per ogni progetto (e non dovrai più reinserire il nome utente e l'email). + +Git memorizzerà le modifiche a tutti i file e le cartelle in questa directory, ma ci sono alcuni file che vogliamo ignorare. Si fa creando un file chiamato `.gitignore` nella directory di base. Apri il tuo editor e crea un nuovo file con questo contenuto: + + *.pyc + __pycache__ + myvenv + db.sqlite3 + /static + .DS_Store + + +E salvalo come `.gitignore` all'interno della cartella "djangogirls". + +> **Nota** Il punto all'inizio del nome del file è importante! Se hai difficoltà nel crearlo (ad esempio, ai Mac non piace quando crei file che iniziano con un punto tramite il Finder), allora usa la funzionalità "Salva con nome" nel tuo editor, è a prova di bomba. + +È una buona idea usare il comando `git status` prima di `git add` oppure ogni volta che non sei sicuro di cosa sia cambiato. Questo aiuterà ad evitare eventuali brutte sorprese, come file sbagliati che vengono aggiunti o a cui viene fatto il commit. Il comando `git status` restituisce informazioni riguardanti qualsiasi file non tracciato/modificato/in staging, lo stato del branch e molto altro. L'output dovrebbe essere simile a: + + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) + + +E finalmente salviamo le nostre modifiche. vai alla tua console ed esegui questi comandi: + + $ git add --all . + $ git commit -m "La mia app Django Girls, primo commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Pubblichiamo il nostro codice su GitHub + +Vai su [GitHub.com][2] e registrati per ottenere un nuovo account gratuito. (Se l'hai già fatto nella preparazione di laboratorio, è fantastico!) + +Quindi, crea un nuovo repository, dandogli il nome "my-first-blog". Lascia deselezionata la casella di controllo "initialise with a README", lascia l'opzione di .gitignore vuota (lo abbiamo fatto manualmente) e License su None. + +![][3] + + [3]: images/new_github_repo.png + +> **Nota** Il nome `my-first-blog` è importante -- potresti scegliere qualcos'altro, ma si ripeterà un sacco di volte nelle istruzioni qui sotto, e dovrai sostituirlo ogni volta. Probabilmente è più facile mantenere il nome `my-first-blog`. + +Nella schermata successiva, ti verrà mostrato l'URL per clonare il tuo repo: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Ora abbiamo bisogno di collegare il repository Git sul tuo computer a quello su GitHub. + +Digita quanto segue sulla tua console (Sostituisci `` con il nome utente che hai inserito quando hai creato il account GitHub, ma senza le parentesi angolari): + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Inserisci il tuo username e la tua password di GitHub. Dovresti vedere qualcosa di simile: + + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Adesso Il tuo codice è su GitHub. Ora controlla! Scoprirai che è in bella compagnia - [Django][5], il [Django Girls Tutorial][6] e molti altri grandi progetti open source software usano GitHub per ospitare il loro codice :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Configurare il nostro blog su PythonAnywhere + +> **Nota** Potresti aver già creato un account di PythonAnywhere precedentemente, durante i passaggi di installazione - se è così, non c'è bisogno di farlo nuovamente. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Scaricare il nostro codice su PythonAnywhere + +Quando ti sarai registrata su PythonAnywhere, verrai portata alla tua dashboard o alla pagina «Console». Scegli l'opzione per iniziare una console "Bash" -- quella è la versione PythonAnywhere di una console, proprio come quella sul tuo computer. + +> **Nota** PythonAnywhere è basato su Linux, quindi se sei su Windows, la console apparirà un po' diversa da quella sul tuo computer. + +Scarichiamo il nostro codice da GitHub e su PythonAnywhere creando un "clone" del nostro repo. Digita quanto segue nella console su PythonAnywhere ( non dimenticare di usare il tuo nome utente di GitHub al posto di ``): + + $ git clone https://github.com//my-first-blog.git + + +Questo scaricherà una copia del tuo codice su PythonAnywhere. Dai un'occhiata digitando `tree my-first-blog`: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### Creare un virtualenv su PythonAnywhere + +Proprio come hai fatto sul tuo computer, puoi creare un virtualenv su PythonAnywhere. Nella console di Bash, digita: + + cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + (mvenv) $ pip install django==1.8 whitenoise==2.0 + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 + + +> **Nota** Il passaggio `pip install` può richiedere un paio di minuti. Sii paziente! Ma se richiede più di 5 minuti, c'è qualcosa di sbagliato. Chiedi al tuo coach. + + + +### Raccogliere file statici. + +Ti stavi chiedendo cos'è quel "whitenoise"? È uno strumento per fornire i cosiddetti "file statici". I file statici sono i file che di solito non cambiano o non eseguono codice di programmazione, come i file HTML o CSS. Funzionano in modo diverso sui server e abbiamo bisogno di uno strumento come "whitenoise" per fornirli. + +Scopriremo un po' di più sui file statici più tardi nell'esercitazione, quando modificheremo il CSS per il nostro sito. + +Per ora abbiamo solo bisogno di eseguire un comando supplementare chiamato `collectstatic`, sul server. Dice a Django di raccogliere tutti i file statici di cui ha bisogno sul server. Al momento questi sono per lo più file che fanno apparire carino il sito di amministrazione. + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +Digita "yes" e si parte! Non ti piace far stampare al computer pagine e pagine di testo incomprensibile? Faccio sempre piccoli versi per accompagnarlo. Brp, brp brp... + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### Creare il database su PythonAnywhere + +Ecco un'altra differenza tra il tuo computer ed il server: usa un database diverso. Quindi gli account utente ed i post possono essere diversi sul server rispetto a come appaiono sul tuo computer. + +Possiamo inizializzare il database sul server proprio come abbiamo fatto sul tuo computer, con `migrate` e `createsuperuser`: + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + +## Pubblicare il nostro blog come una web app + +Ora il nostro codice è su PythonAnywhere, il nostro virutualenv è pronto, i file statici sono stati raccolti, ed il database è stato inizializzato. Siamo pronti a pubblicarlo come una web app! + +Torna alla dashboard di PythonAnywhere cliccando sul suo logo, e clicca sulla scheda **Web**. Infine, premi **Add a new web app**. + +Dopo aver confermato il nome del dominio, scegli **manual configuration** (NB *non* l'opzione "Django") nella finestra di dialogo. Successivamente, scegli **Python 3.4** e clicca su Avanti per completare la procedura guidata. + +> **Nota** assicurati di aver scelto l'opzione "Manual configuration", non l'opzione "Django". Siamo troppo cool per l'installazione di Django di PythonAnywhere di default;-) + +### Impostare il virtualenv + +Verrai portato alla schermata di configurazione PythonAnywhere per tua webapp, che è dove dovrai andare ogni volta che desideri apportare modifiche all'applicazione sul server. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +Nella sezione "Virtualenv", clicca sul testo rosso che dice "Enter the path to a virtualenv" ed immetti: `/home//my-first-blog/myvenv/`. Clicca sul riquadro blu con il segno di spunta per salvare il percorso prima di andare avanti. + +> **Note** Sostituisci il tuo nome utente come appropriato. se commetti un errore, PythonAnywhere ti avvertirà. + +### Configurare il file WSGI + +Django funziona usando il "protocollo WSGI", uno standard per fornire siti Web utilizzando Python, che PythonAnywhere supporta. Il modo in cui configuriamo PythonAnywhere per riconoscere il nostro blog in Django è modificando un file di configurazione WSGI. + +Clicca sul link "WSGI configuration file" (nella sezione "Code" nella parte superiore della pagina -- avrà un nome tipo `/var/www/ _pythonanywhere_com_wsgi.py`), e accederai ad un editor. + +Elimina tutti i contenuti e sostituiscili con qualcosa di simile: + +```python +import os +import sys + +path = '/home//my-first-blog' # usa il tuo username qui +if path not in sys.path: +    sys.path.append(path) + +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Nota** non dimenticare di mettere il tuo nome utente dove dice `` + +Il compito di questo file è dire a PythonAnywhere dove si trova la nostra web app e qual è il nome del file che contiene le impostazioni Django. Inolte, configura lo strumento di file statici "whitenoise". + +Clicca **Save** e poi torna alla scheda **Web**. + +Abbiamo finito! Premi il grande pulsante verde **Reload** e potrai vedere la tua applicazione. Troverai un link nella parte superiore della pagina. + +## Suggerimenti per il debug + +Se vedi un errore quando provi a visitare il tuo sito, il primo posto dove cercare qualche info per il debugging è nel tuo **error log**. Troverai un link nella [ scheda Web][8] di PythonAnywhere. Vedi se ci sono messaggi di errore lì; i più recenti sono alla fine. I problemi comuni includono: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* Dimenticare uno dei passi che abbiamo fatto nella console: creare il virtualenv, attivarlo, installarci Django, eseguire collecstatic, inizializzazione del database. + +* Commettere un errore nel percorso del virtualenv sulla scheda Web -- di solito c'è un piccolo messaggio di errore in rosso, se c'è un problema. + +* Commettere un errore nel file di configurazione WSGI -- il percorso che hai trovato per tua cartella my-first-blog è corretto? + +* Hai adottato la stessa versione di Python per il tuo virtualenv come hai fatto per la tua app web? entrambe dovrebbero essere 3.4. + +* Ci sono alcuni [consigli generali per il debugging sulla wiki di PythonAnywhere][9]. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +E ricorda, il tuo coach è qui per aiutarti! + +# Sei live! + +La pagina predefinita per il tuo sito dovrebbe dire "Welcome to Django", esattamente come sul tuo Pc locale. Prova ad aggiungere `/admin/` alla fine della URL, e verrai portata al sito di amministrazione. Accedi con il tuo username e password, e vedrai che puoi aggiungere nuovi Post sul server. + +Dà a te stessa un' *ENORME* pacca sulla schiena! Il deploy dei server è tra le parti più complicate dello sviluppo web e di solito le persone ci impiegano svariati giorni prima di farli funzionare. Ma hai pubblicato il tuo sito su Internet senza sforzo! diff --git a/it/deploy/images/github_get_repo_url_screenshot.png b/it/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/it/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/it/deploy/images/new_github_repo.png b/it/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/it/deploy/images/new_github_repo.png differ diff --git a/it/deploy/images/pythonanywhere_web_tab_virtualenv.png b/it/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/it/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/it/deploy/install_git.md b/it/deploy/install_git.md new file mode 100644 index 00000000000..dac44912b60 --- /dev/null +++ b/it/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows + +È possibile scaricare Git da [git-scm.com](https://git-scm.com/). Puoi saltare tutti i passaggi tranne uno. Nel quinto passaggio, dal titolo "Regolazione della variabile PATH di sistema", scegli "Esegui Git e gli strumenti Unix associati dalla riga di comando di Windows" (l'opzione in basso). A parte questo, i valori predefiniti vanno bene. 'Checkout Windows-style' e 'commit Unix-style line endings' vanno bene. + +### MacOS + +Scarica Git da [git-scm.com](https://git-scm.com/) e segui le istruzioni. + +### Linux + +Se non è già installato, git dovrebbe essere disponibile tramite il gestore di pacchetti, prova a cercare: + + sudo apt-get install git + # oppure + sudo yum install git + # oppure + sudo zypper install git diff --git a/it/deploy/signup_pythonanywhere.md b/it/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..d70701156de --- /dev/null +++ b/it/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Ora è il momento di registrarsi per un account gratuito "Beginner" su PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Nota** Quando scegli il tuo nome utente, tieni conto che l'URL del tuo blog diventerà `iltuousername.pythonanywhere.com`, quindi scegli il tuo nickname oppure un nome ispirato a ciò su cui si basa il tuo blog. \ No newline at end of file diff --git a/it/django/README.md b/it/django/README.md new file mode 100644 index 00000000000..5bcc3f74e2e --- /dev/null +++ b/it/django/README.md @@ -0,0 +1,27 @@ +# Che cos'è Django? + +Django (*/ˈdʒæŋɡoʊ/ jang-goh*) è un framework per applicazioni web gratuito e open source, scritto in Python. Un web framework è un insieme di componenti che ti aiuta a sviluppare siti web più velocemente e facilmente. + +Quando si costruisce un sito web, si ha sempre bisogno di un insieme di componenti simili: un sistema per gestire l'autenticazione dell'utente (registrazione, accesso, logout), un pannello di amministrazione per il tuo sito web, un sistema per caricare i file, ecc. + +Fortunatamente, alcune persone diverso tempo fa si sono rese conto che gli sviluppatori web incontrano problemi simili ogni volta che costruiscono un sito internet. Per questo motivo si sono uniti e hanno costruito dei framework (di cui Django fa parte) che offrono componenti già pronti per l'uso. + +I frameworks esistono per evitare che tu debba reinventare la ruota e ti semplificano il lavoro quando crei un nuovo sito. + +## Perché ho bisogno di un framework? + +Per capire Django, abbiamo bisogno di dare un'occhiata più da vicino ai server. La prima cosa che il server deve sapere è che vuoi che ti fornisca una pagina web. + +Immagina una cassetta delle lettere che monitora tutte le lettere in entrata (richieste). Questo è ciò che fa un web server. Il web server legge le lettere, e invia una risposta con una pagina web. Ma quando vuoi inviare qualcosa, hai bisogno di avere qualche contenuto. E Django è ciò che ti aiuta a creare questo contenuto. + +## Cosa succede quando qualcuno richiede un sito Web dal tuo server? + +Quando una richiesta arriva al web server, viene passata a Django che prova a capire che cosa é stato veramente richiesto. Django prende l'indirizzo della pagina web e cerca di capire cosa deve fare. Questa parte viene svolta da Django **urlresolver** (nota che l'indirizzo di una pagina web si chiama URL - Uniform Resource Locator -per cui il nome *urlresolver* acquista significato). Non é molto intelligente -ha bisogno di una serie di schemi e in seguito prova a far corrispondere l'URL. Django controlla questi modelli o schemi da cima a fondo e se qualcosa corrisponde a quel punto Django passa la richiesta alla funzione associata (che si chiama *view*). + +Immagina un postino con una lettera. Sta camminando per la strada e controlla ogni numero civico mettendolo a confronto con quello sulla lettera. Se corrisponde, mette lì la lettera. Questo è il modo in cui l'urlresolver funziona! + +Nella funzione *view* avvengono tutte le cose più interessanti: possiamo consultare un database alla ricerca di qualche informazione. Forse l'utente ha richiesto di cambiare qualcosa all'interno dei suoi dati? È come una lettera che dice "Per favore cambia la descrizione del mio lavoro". La *view* può controllare se sei autorizzata a farlo, poi aggiorna la descrizione del lavoro per te e manda un messaggio: "Fatto!". In seguito, la *view* genera una risposta e Django la può inviare al browser dell'utente. + +Naturalmente, la descrizione qui sopra é molto semplificata, ma per il momento non hai bisogno di sapere nel dettaglio tutti gli aspetti tecnici. Avere il senso generale per il momento è abbastanza. + +Per cui invece di perderci troppo nei dettagli, creeremo semplicemente qualcosa usando Django e apprenderemo i concetti fondamentali lungo la strada! \ No newline at end of file diff --git a/it/django_admin/README.md b/it/django_admin/README.md new file mode 100644 index 00000000000..de3fcc57f64 --- /dev/null +++ b/it/django_admin/README.md @@ -0,0 +1,47 @@ +# Django admin + +Per aggiungere, modificare e cancellare i post che abbiamo appena strutturato useremo Django admin. + +Apri il file `blog/admin.py` e sostituisci il suo contenuto con: + + from django.contrib import admin + from .models import Post + + admin.site.register(Post) + + +Come puoi vedere, stiamo importando (include) il modello di Post che abbiamo definito nel capitolo precedente. Per far si che il nostro modello sia visibile nella pagina di admin, dobbiamo registrare questo modello con `admin.site.register(Post)`. + +OK, è tempo di guardare il nostro modello Post. Ricorda di eseguire `python manage.py runserver` nella console per avviare il web server. Vai nel browser e scrivi l'indirizzo http://127.0.0.1:8000/admin/ Vedrai una pagina di login come questa: + +![Login page][1] + + [1]: images/login_page2.png + +Per accedere, devi creare un *superuser* - un utente che ha il controllo su tutto nel sito. Torna alla command-line e digita `python manage.py createsuperuser`, e premi invio. Quando richiesto, digita il tuo username (minuscole, senza spazi), indirizzo e-mail e password. Non ti preoccupare se non riesci a vedere la password che stai digitando - è così che dovrebbe essere. Basta digitarlo e premere `invio` per continuare. L'output dovrebbe essere così (dove il nome utente e l'email dovrebbero essere i tuoi): + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Torna nel tuo browser e fai il log in con le credenziali di superuser che hai scelto, dovresti vedere la dashboard d'amministrazione di Django. + +![L'admin di Django][2] + + [2]: images/django_admin3.png + +Vai su Post ed sperimenta un po'. Aggiungi cinque o sei post. Non preoccuparti del contenuto - puoi semplicemente fare il copia-incolla di parti di testo da questo tutorial per risparmiare tempo :). + +Assicurati che almeno due o tre post (ma non tutti) abbiano la data in cui sono stati pubblicati. Ti sarà utile più tardi. + +![L'admin di Django][3] + + [3]: images/edit_post3.png + +Se vuoi sapere di più riguardo l'admin di Django, dovresti dare un'occhiata alla documentazione di Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +Questo è un buon momento per andare a prendere un caffè (o tè) o qualcosa da mangiare per riprendere le forze. Hai creato il tuo primo modello Django - ti meriti una piccola pausa! \ No newline at end of file diff --git a/it/django_admin/images/django_admin3.png b/it/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/it/django_admin/images/django_admin3.png differ diff --git a/it/django_admin/images/edit_post3.png b/it/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/it/django_admin/images/edit_post3.png differ diff --git a/it/django_admin/images/login_page2.png b/it/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/it/django_admin/images/login_page2.png differ diff --git a/it/django_forms/README.md b/it/django_forms/README.md new file mode 100644 index 00000000000..c3b4a73ee65 --- /dev/null +++ b/it/django_forms/README.md @@ -0,0 +1,398 @@ +# I form di Django + +Infine vogliamo creare un bel modo per poter aggiungere e cambiare in nostri blog posts. Django `admin` è bello, ma è alquanto difficile da personalizzare e rendere carino. Con i `forms` avremo il potere assoluto sull'aspetto della nostra pagina web-possiamo fare praticamente qualsiasi cosa vogliamo! + +La bella cosa dei Django forms è che possiamo sia inventare un nuovo form da zero che creare un `ModelForm` che salverà il risultato del form sul nostro modello. + +Questo è esattamente quello che stiamo per fare: stiamo per creare un form per il nostro modello dei `Post`. + +Come ogni parte importante di Django, i forms hanno il proprio file: `forms.py`. + +Dobbiamo creare un file con questo nome all'interno della cartella `blog`. + + blog + └── forms.py + + +OK, apriamo questo file e inseriamo: + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Dobbiamo importare prima di tutto i Django Forms (`from django import forms`) e, ovviamente, il nostro `Post` model (`from .models import Post`). + +`PostForm`, come probabilmente hai intuito, è il nome del nostro form. Dobbiamo ora dire a Django che questa form é una `ModelForm` (così Django farà qualche magia per noi)- `forms.ModelForm` è il comando per farlo. + +Successivamente, abbiamo `class Meta`, con cui diciamo a Django quale model utilizzare per creare questo form (`model = Post`). + +Finalmente possiamo indicare uno o più campi che il nostro form deve avere. In questo caso vogliamo che solamente `title` e `text` siano visibili -`author` è la persona attualmente connessa (tu!) e `created_date` dovrebbe generarsi da sola ogni volta che creiamo un post (cioè nel nostro programma), giusto? + +E questo è tutto! Tutto quello che dobbiamo fare ora é usare il form nella nostra *view* e visualizzarlo nel template. + +Ricapitolando, creeremo: link che punti alla pagina, una URL, una view e un model. + +## Link ad una pagina usando il form + +È tempo di aprire `blog/templates/blog/base.html`. Aggiungeremo un link nel `div` chiamato `page-header`: + +```html + +``` + +Nota che vogliamo chiamare la nostra nuova view `post_new`. + +Dopo aver aggiunto quanto detto, il tuo file html dovrebbe essere simile a questo: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Dopo aver salvato e aggiornato la pagina http://127.0.0.1:8000 vedrai ovviamente un errore familiare `NoReverseMatch`, giusto? + +## URL + +Apri il file `blog/urls.py` e aggiungi: + +```python +    url(r'^post/new/$', views.post_new, name='post_new'), +``` + +Il risultato finale sarà: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +Dopo aver aggiornato il sito, vedremo un `AttributeError` dal momento che non abbiamo ancora creato `post_new`. Aggiungiamolo adesso. + +## post_new view + +Apri il file `blog/views.py` e aggiungi quanto segue con il resto delle importazioni `from`: + +```python +from .forms import PostForm +``` + +e la nostra *view*: + +```python +def post_new(request): +    form = PostForm() +    return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Per creare un nuovo `Post` form, dobbiamo chiamare il metodo `PostForm()` e passarlo nel nostro template. Torneremo poi sulla *view*, ma per ora creiamo un veloce template per il nostro form. + +## Template + +All'interno della cartella `blog/templates/blog` dobbiamo creare il file `post_edit.html`. Per far si che il nostro form funzioni abbiamo bisogno di diverse cose: + +* dobbiamo rendere il form visibile. Per farlo possiamo usare semplicemente `{% raw %}{{ form.as_p }}{% endraw %}`. +* le righe scritte sopra hanno bisogno di 'essere avvolte' da un HTML tag: `...` +* ci serve un `Save` pulsante. Possiamo fare ciò con HTML button: `` +* infine, subito dopo l'apertura del tag `
`, dobbiamo aggiungere `{% raw %}{% csrf_token %}{% endraw %}`. Questo passaggio è molto importante dal momento che rende il nostro form sicuro! Django si lamenterà se ti dimentichi di inserire questa parte e provi comunque a salvare ciò che è contenuto nel form: + +![CSFR Forbidden page][1] + + [1]: images/csrf2.png + +OK, il tuo HTML `post_edit.html` dovrebbe apparire così: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +    

New post

+    {% csrf_token %} +        {{ form.as_p }} +         +    
+{% endblock %} +``` + +Ora aggiorna la pagina! Yeah! Puoi ora visualizzare il tuo form! + +![New form][2] + + [2]: images/new_form2.png + +Ma, aspetta un momento! Se provi a scrivere qualcosa in `title` e `text` e cerchi di salvare ciò che hai scritto, che cosa succede? + +Niente! Siamo di nuovo sulla stessa pagina di prima e il nostro testo é sparito...e non compare nessun nuovo post. Che cosa abbiamo sbagliato? + +La risposta è: nulla. Dobbiamo solo fare un po' di lavoro in più nella nostra *view*. + +## Salvare il form + +Apri `blog/views.py` di nuovo. Attualmente tutto ciò che abbiamo nella view `post_new` é: + +```python +def post_new(request): +    form = PostForm() +    return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Quando inviamo il form, veniamo riportati alla stessa view, ma questa volta abbiamo più dati in `request`, in particolare in `request.POST` (il nome non ha nulla a che vedere con un blog "post", bensì con l'inglese "posting", ovvero inviare, in questo caso dati). Ti ricordi che nel nostro file HTML il nostro `
` aveva la variabile `method="POST"`? Per cui ora, tutto quello che l'utente ha inserito nel form è disponibile in `method="POST"`. Non è necessario rinominare `POST` in nessuna altra maniera (l'unico altro valore valido per `method` è `GET`, ma al momento non abbiamo abbastanza tempo per spiegare la differenza). + +Per cui nella nostra *view* abbiamo due diverse situazioni da gestire. Prima: quando accediamo alla pagina per la prima volta e vogliamo un form che sia vuoto. Seconda: quando torniamo alla *view* con tutti i dati appena inseriti nel form. Per cui dobbiamo aggiungere una condizione(useremo `if`). + +```python +if request.method == "POST": +    [...] +else: +    form = PostForm() +``` + +È ora di completare i puntini `[...]`. Se il `method` è `POST` allora vogliamo costruire il nostro `PostForm` con i dati appena inseriti dall'utente, giusto? Raggiungeremo questo risultato con: + +```python +form = PostForm(request.POST) +``` + +Facile! Come prossima cosa dobbiamo controllare se il form è corretto (per cui che tutti i campi necessari siano stati impostati e che non ci siano valori sbagliati). Possiamo fare questo con `form.is_valid()`. + +Se il form viene ritenuto valido verrà salvato! + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +In pratica, ci sono due cose da fare: salviamo il form con `form.save` e aggiungiamo un autore (dal momento che non c'era nessun campo autore `author` nel form `PostForm` e questo campo non può essere lasciato bianco!). `commit=False` significa che non vogliamo salvare `Post` model per il momento-vogliamo prima assicurarci di aggiungere un autore. Per la maggior parte del tempo userai `form.save()`, senza `commit=False`, ma in questo caso abbiamo bisogno di questa extra specificazione. `post.save()` salverà le modifiche (aggiunta di autore) e il nuovo post del tuo blog è stato finalmente creato! + +Infine, non sarebbe fantastico se potessimo immediatamente essere indirizzati alla pagina `post_detail` del nuovo blog post appena creato? Per fare ciò dobbiamo importare: + +```python +from django.shortcuts import redirect +``` + +Aggiungilo all'inizio del file. E ora possiamo dire: vai alla pagina `post_detail` per il post appena creato. + +```python +return redirect('blog.views.post_detail', pk=post.pk) +``` + +`blog.views.post_detail` é il nome della view che vogliamo visitare. Ti ricordi che questa *view* ha bisogno della variabile `pk`? Per passarla alla nostre views utilizziamo `pk=post.pk`, dove `post` è il post appena creato! + +Ok, abbiamo parlato abbastanza ora e forse sei curioso/a di vedere l'aspetto della nostra *view*, giusto? + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Vediamo se funziona. Vai sulla pagina http://127.0.0.1:8000/post/new/, aggiungi un `title` e un `text`, salvalo... e voilà! Il tuo nuovo post è stato aggiunto e noi siamo stati reindirizzati automaticamente alla pagina `post_detail` ! + +Forse avrai notato che stiamo impostando una data di pubblicazione prima di salvare il post. Più tardi introdurremo l'uso del *publish button* in **Django Girls Tutorial: Extensions**. + +Fantastico! + +## Validazione del Form + +E adesso ti dimostreremo quanto siano belli i form di Django. Sappiamo che un post ha bisogno di `title` e `text`. Nel nostro `Post` model non abbiamo detto (al contrario di quello che abbiamo fatto per `published_date`) che questi campi non sono obbligatori, per cui Django si aspetta che vengano impostati. + +Prova a salvare il form senza `title` e `text`. Indovina che cosa accade! + +![Validazione del form][3] + + [3]: images/form_validation2.png + +Django si sta prendendo cura di controllare che tutti i campi nel nostro form siano corretti. Non è fantastico? + +> Dato che poco fa stavamo usando l'interfaccia di Django admin, Django pensa che siamo ancora connessi. Ci sono alcune situazioni che potrebbero portarci a fare un log out(chiudere il browser, riavviare il DB etc.). Se ti trovi nella situazione di avere errori, quando crei un post, relativi alla mancanza di un utente, vai alla admin page `http://127.0.0.1:8000/admin` ed effettua il log in di nuovo. Questo risolverà temporaneamente il problema. C'è una correzione permanente che ti aspetta nella sezione degli esercizi extra alla fine del tutorial principale **Compiti: aggiungi sicurezza al tuo sito web!**. + +![Logged in error][4] + + [4]: images/post_create_error.png + +## Modifica il form + +Ora sappiamo come aggiungere un form. Ma cosa succede se ne vogliamo cambiare uno esistente? È un processo abbastanza simile a quelli che abbiamo appena fatto. Creiamo alcune cose importanti rapidamente (se non capisci qualcosa, chiedi aiuto al tuo coach o guarda i capitoli precedenti, dal momento che abbiamo coperto tutti questi passaggi precedentemente). + +Apri `blog/templates/blog/post_detail.html` e aggiungi: + +```python + +``` + +per cui il tuo template sarà così: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +In `blog/urls.py` aggiugi: + +```python +    url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Riutilizzeremo il model `blog/templates/blog/post_edit.html`, quindi l'ultima cosa che manca è una *view*. + +Apriamo `blog/views.py` e aggiungiamo alla fine del file: + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Questo sembra quasi esattamente la view `post_new`, giusto? Ma non del tutto. Prima cosa: si passa un parametro supplementare `pk` dall'URL. Dopo di che: prendiamo il modello ` Post` che vogliamo modificare con `get_object_or_404(Post, pk=pk)` e in seguito, quando creeremo un form, passeremo questo post come `instance`, sia quando salviamo il form: + +```python +form = PostForm(request.POST, instance=post) +``` + +e quando abbiamo appena aperto un form con questo post da modificare: + +```python +form = PostForm(instance=post) +``` + +Ok, testiamo se funziona! Andiamo alla pagina `post_detail`. Dovrebbe esserci un pulsante modifica nell'angolo superiore destro: + +![Pulsante modifica][5] + + [5]: images/edit_button2.png + +Quando ci clicchi, vedrai il modulo con i nostri post del blog: + +![Modifica il form][6] + + [6]: images/edit_form2.png + +Sentiti libero di cambiare il titolo o il testo e salva le modifiche! + +Complimenti! La tua application è sempre più completa! + +Se ti servono altre informazioni sui forms di Django dovresti leggere la documentazione: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## Sicurezza + +Riuscire a creare nuovi post semplicemente cliccando su un link è bellissimo! Ma, al momento, chiunque visiti il tuo sito potrebbe pubblicare un nuovo post nel tuo blog e probabilmente non vuoi che ciò accada. Facciamo in modo che questo tasto sia visibile solo per te e non per altri. + +Vai al tuo `blog/templates/blog/base.html` e trova il `page-header` `div` con il tag di tipo anchor che hai messo prima. Dovrebbe apparire così: + +```html + +``` + +Vogliamo aggiungere qui un altro tag del tipo `{% if %}` che farà comparire il link solo per gli utenti connessi come admin. Per ora, solo tu! Cambia il tag `` in modo che risulti così: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Grazie a questo `{% if %}`, il link verrà inviato al browser solo se l'utente che prova ad accedere alla pagina è connesso come admin. Con questa condizione non ci siamo protetti del tutto dalla creazione di nuovi post, ma abbiamo fatto un buon passo avanti. Nelle lezioni estensione ci occuperemo di più della sicurezza. + +Ora, dato che probabilmente sei connessa/o, se aggiorni la pagina non troverai alcuna differenza. Ma prova a ricaricare la pagina in un altro browser o in una finestra di navigazione in incognito e vedrai che il link non c'è! + +## Ultima cosa: ora di fare il deploy! + +Vediamo se funziona su PythonAnywhere. È l'ora di un altro deploy! + +* Innanzitutto, fai un commit del tuo nuovo codice e fai il push per caricarlo su Github + +``` +$ git status +$ git add --all . +$ git status +$ git commit -m "Added views to create/edit blog post inside the site." +$ git push +``` + +* Poi, in una [console PythonAnywhere Bash][7]: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* Infine, vai sulla [Web tab][8] e premi **Reload**. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +Fatto! Congratulazioni :) diff --git a/it/django_forms/images/csrf2.png b/it/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/it/django_forms/images/csrf2.png differ diff --git a/it/django_forms/images/drafts.png b/it/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/it/django_forms/images/drafts.png differ diff --git a/it/django_forms/images/edit_button2.png b/it/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/it/django_forms/images/edit_button2.png differ diff --git a/it/django_forms/images/edit_form2.png b/it/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/it/django_forms/images/edit_form2.png differ diff --git a/it/django_forms/images/form_validation2.png b/it/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/it/django_forms/images/form_validation2.png differ diff --git a/it/django_forms/images/new_form2.png b/it/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/it/django_forms/images/new_form2.png differ diff --git a/it/django_forms/images/post_create_error.png b/it/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/it/django_forms/images/post_create_error.png differ diff --git a/it/django_installation/README.md b/it/django_installation/README.md new file mode 100644 index 00000000000..15f3758fbdd --- /dev/null +++ b/it/django_installation/README.md @@ -0,0 +1,5 @@ +# Installazione di Django + +> **Nota** Se hai già eseguito i passaggi per l'Installazione, allora hai già fatto quanto serve e puoi andare direttamente al prossimo capitolo! + +{% include "/django_installation/instructions.md" %} diff --git a/it/django_installation/instructions.md b/it/django_installation/instructions.md new file mode 100644 index 00000000000..931be14224b --- /dev/null +++ b/it/django_installation/instructions.md @@ -0,0 +1,114 @@ +> Una parte di questo capitolo si basa sui tutorial delle Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Una parte di questo capitolo di basa sul [django-marcador tutorial](http://django-marcador.keimlink.de/) sotto licenza Creative Commons Attribution-ShareAlike 4.0 International License. Il tutorial di django-marcador è protetto da copyright di Markus Zapke-Gründemann et al. + +## Ambiente virtuale + +Prima di installare Django, ti vogliamo far installare uno strumento estremamente utile per tenere in ordine l'ambiente in cui programmerai sul tuo computer. Potresti saltare questo passaggio, ma è caldamente consigliato soffermarsi. Se inizi con la migliore configurazione possibile, ti risparmierai un sacco di problemi per il futuro! + +Per cui, creiamo ora un **ambiente virtuale** (chiamato anche un *virtualenv*). Virtualenv isolerà la tua configurazione di Python/Django in base ai diversi progetti. Questo significa che qualunque modifica farai su un sito non avrà alcun effetto su tutti gli altri che stai sviluppando. Chiaro ora? + +Tutto quello che devi fare è trovare una cartella in cui vuoi creare il `virtualenv`; la tua home directory, ad esempio. Su Windows potrebbe essere `C:\Users\Name` (dove `Name` è il nome del tuo login). + +Per questo tutorial useremo una nuova directory `djangogirls` dalla tua home directory: + + mkdir djangogirls + cd djangogirls + + +Ora creeremo un virtualenv dal nome `myvenv`. Questo è il formato del comando generale: + + python3 -m venv myvenv + + +### Windows + +Per creare un nuovo `virtualenv` è necessario aprire la console (ti abbiamo spiegato come fare nei capitoli precedenti, ricordi?) ed esegui `C:\Python34\python -m venv myvenv`. Il risultato somiglierà a questo: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + +dove `C:\Python34\python` è la directory in cui precedentemente hai installato Python e `myvenv` è il nome del tuo `virtualenv`. Puoi utilizzare qualsiasi altro nome, ma attieniti a utilizzare le minuscole, a non usare spazi, accenti o caratteri speciali. È meglio usare un nome breve dal momento che dovrai digitarlo spesso! + +### Linux e OS X + +Creare un `virtualenv` su Linux e OS X è semplice, basta digitare: `python3 -m venv myvenv`. Il risultato sarà simile a questo: + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` è il nome del tuo `virtualenv`. Puoi usare qualsiasi altro nome, ma utilizza solo minuscole e niente spazi. Sarebbe meglio se il nome fosse corto perchè lo dovrai digitare molte volte! + +> **NOTA:** Avviare il virtualenv su Ubuntu 14.04 in questa maniera al momento darà il seguente errore: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Per aggirare il problema utilizza, invece del precedente, il comando `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Lavorare con virtualenv + +Il comando sopra specificato, creerà una cartella dal nome `myvenv` (o col nome che hai scelto) che contiene il tuo virtual environment (ovvero un mucchio di files e cartelle). + +#### Windows + +Avvia il tuo virtualenv digitando: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + + +#### Linux e OS X + +Avvia il tuo virtualenv digitando: + + ~/djangogirls$ source myvenv/bin/activate + + +Ricordati di sostituire `myvenv` con il nome `virtualenv` che hai scelto! + +> **Nota:** a volte il comando `source` potrebbe non essere disponibile. In quel caso prova ad usare questo: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Saprai con certezza che hai avviato `virtualenv` quando vedrai che il prompt dei comandi nella console si presenta così: + + (myvenv) C:\Users\Name\djangogirls> + + +oppure: + + (myvenv) ~/djangogirls$ + + +Fai caso al prefisso `(myvenv)`! + +Quando si lavora all'interno di un ambiente virtuale, `python` farà automaticamente riferimento alla versione corretta da utilizzare. Per cui puoi digitare `python` invece `python3`. + +OK, abbiamo tutte le dipendenze importanti pronte. Finalmente possiamo installare Django! + +## Installare Django + +Ora che hai iniziato ad utilizzare il tuo `virtualenv`, puoi installare Django usando `pip`. Nella console, esegui `pip install django==1.8` (nota che usiamo un doppio simbolo di uguale: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +Su Windows + +> Se ottieni un errore quando chiami pip sulla piattaforma Windows controlla se il pathname del tuo progetto contiene spazi, accenti o caratteri speciali (i.e. `C:\Users\User Name\djangogirls`). Se è così ti conviene spostarlo in un altro path senza spazi, accenti o caratteri speciali (il suggerimento è: `C:\djangogirls`). Dopo averlo spostato, prova ad eseguire di nuovo il comando di cui sopra. + +su Linux + +> Se ottieni un errore quando esegui il comando pip su Ubuntu 12.04, prova ad eseguire `python -m pip install -U --force-reinstall pip` per risolvere il problema. + +Questo è tutto! Sei (finalmente) pronto/a a creare un'applicazione Django! diff --git a/it/django_models/README.md b/it/django_models/README.md new file mode 100644 index 00000000000..9c826a11556 --- /dev/null +++ b/it/django_models/README.md @@ -0,0 +1,172 @@ +# Modelli Django + +Vogliamo creare un qualcosa che raccoglierà tutti i post del nostro blog. Per farlo, però, dobbiamo prima introdurre i cosiddetti `oggetti`. + +## Oggetti + +Esiste un concetto nella programmazione chiamato `programmazione orientata agli oggetti`. L'idea è che invece di scrivere tutto come una noiosa sequenza di istruzioni di programmazione, possiamo modellare le cose e definire come esse interagiscono fra di loro. + +Quindi cos'è un oggetto? È un insieme di proprietà ed azioni. Suona strano, ma ti faremo un esempio. + +Se vogliamo modellare un gatto creeremo un oggetto `Gatto` che ha qualche proprietà, i.e. `colore`, `età`, `umore` (i.e. bravo, cattivo, sonnolento ;)), `padrone` (che è un oggetto `Persona` oppure, nel caso di un gatto randagio, questa proprietà è vuota). + +E poi il `Gatto` ha alcune azioni: `fusa`, `graffiare` oppure `alimentare` (nella quale daremo al gatto un po' di `Cibo per gatti`, che potrebbe essere un oggetto diverso con delle proprietà, i.e. `gusto`). + + Gatto + -------- + colore + età + umore + padrone + fare le fusa() + graffiare() + alimentare(cat_food) + + +Quindi in pratica l'idea è quella di descrivere cose vere in codice con delle proprietà (chiamate `proprietà di oggetti`) e azioni (chiamate `metodi`). + +Quindi come faremo a modellare i post del blog? vogliamo costruire un blog, giusto? + +Dobbiamo rispondere alla domanda: cos'è un post? Quali proprietà dovrebbe avere? + +Beh, sicuramente il nostro post ha bisogno di qualche testo con il suo contenuto ed un titolo, vero? Sarebbe bello sapere chi l'ha scritto - quindi abbiamo bisogno di un autore. Infine, vogliamo sapere quando il post è stato creato e pubblicato. + + Post + -------- + titolo + testo + autore + data_creazione + data_pubblicazione + + +Che tipo di cose si potrebbero fare con un post? Sarebbe bello avere qualche `metodo` che pubblica il post, vero? + +Quindi avremo bisogno di un metodo `pubblicare`. + +Dal momento che sappiamo già cosa vogliamo ottenere, iniziamo a modellarlo in Django! + +## Modello Django + +Sapendo cos'è un oggetto, possiamo creare un modello Django per il nostro post. + +Un modello in Django è uno speciale tipo di oggetto - è salvato nel `database`. Un database è un insieme di dati. È un posto in cui archivierai informazioni sui tuoi utenti, sui tuoi post, ecc. Useremo un database SQLite per archiviare i nostri dati. Questo è l'adattatore Django di database predefinito -- ci basterà per adesso. + +Puoi pensare ad un modello nel database come ad un foglio elettronico con colonne (campi) e righe (dati). + +### Creazione di un'applicazione + +Per mantenere tutto ordinato, creeremo un'applicazione diversa all'interno del nostro progetto. È molto bello avere tutto organizzato fin dall'inizio. Per creare un'applicazione abbiamo bisogno di eseguire il seguente comando nella console (dalla cartella `djangogirls` dove si trova il file `manage.py`): + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +Noterai che si è creata una nuova cartella `blog` e che ora contiene alcuni file. Le nostre cartelle ed i nostri file nel nostro progetto si dovrebbero vedere così: + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +Dopo aver creato un'applicazione dobbiamo dire a Django che dovrebbe utilizzarla. Lo facciamo nel file `mysite/settings.py`. Dobbiamo trovare `INSTALLED_APPS` ed aggiungere una riga che contenga `'blog',` appena sopra`)`. Quindi il prodotto finale dovrebbe assomigliare a questo: + +```python +INSTALLED_APPS = ( +    'django.contrib.admin', +    'django.contrib.auth', +    'django.contrib.contenttypes', +    'django.contrib.sessions', +    'django.contrib.messages', +    'django.contrib.staticfiles', +    'blog', +) +``` + +### Creazione di un modello blog post + +Nel file `blog/models.py` definiamo tutti gli oggetti chiamati `Models` - Questo è il posto dove definiremo il nostro blog post. + +Apriamo `blog/models.py`, cancella tutto quello che è lì e scrivi un codice come questo: + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Ricontrolla se stai utilizzando due caratteri di sottolineatura (`_`) su ciascun lato di `str`. Questa convenzione viene utilizzata spesso in Python e a volte li chiamiamo anche "dunder" (abbreviazione di "doppio carattere di sottolineatura"). + +Sembra spaventoso, vero? ma non ti preoccupare, ti spiegheremo cosa significano queste righe! + +Tutte le righe che iniziano con `from` oppure con `import` sono righe che aggiungono alcuni pezzi da altri file. Quindi invece di copiare e incollare le stesse cose in ogni file, possiamo includere alcune parti con `from ... import ...`. + +`class Post(models.Model):` - questa riga definisce il nostro modello (è un `oggetto`). + +* `class` è una parola chiave speciale che indica che stiamo definendo un oggetto. +* `Post` è il nome del nostro modello. Possiamo dargli un nome diverso (ma dobbiamo evitare caratteri speciali e spazi). Inizia sempre il nome di una classe con un lettera maiuscola. +* `models.Model` significa che il Post è un modello Django, quindi Django sa che dovrebbe essere salvato nel database. + +Ora definiamo le proprietà di cui stavamo parlando: `titolo`, `testo`, `data_creazione`, `data_pubblicazione` e `autore`. Per fare ciò dobbiamo definire un tipo per ogni campo (è un testo? Un numero? Una data? Una relazione con un altro oggetto, i.e. un utente?). + +* `models.CharField` - così si definisce un testo con un numero limitato di lettere. +* `models.TextField` - questo è il codice per definire un testo senza un limite. Sembra l'ideale per i contenuti di un post, vero? +* `models.DateTimeField` - questo per la data ed l'ora. +* `models.ForeignKey` - questo è un link a un altro modello. + +Non spiegheremo ogni pezzo di codice perchè ci vorrebbre troppo tempo. Dovresti dare un'occhiata alla documentazione di Django se vuoi saperne di più sui campi di un modello e come definire altre cose rispetto a quelle descritte sopra (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +Che dire di `def publish(self):`? È esattamente il metodo `pubblicare` di cui stavamo parlando prima. `def` significa che questa è una funzione/metodo e `publish` è il nome del metodo. Puoi modificare il nome del metodo, se vuoi. La regola per la denominazione è usare lettere minuscole e caratteri di sottolineatura al posto degli spazi. Per esempio, un metodo che calcola il prezzo medio potrebbe essere chiamato `calculate_average_price`. + +I metodi spesso `restituiscono` qualcosa. C'è un esempio nel metodo `__str__`. In questo caso, quando chiamiamo `__str__()` otterremo un testo (**stringa**) con il titolo del Post. + +Se c'è qualcosa di poco chiaro sui modelli, sentiti libera/o di chiedere al tuo coach! Sappiamo che è complicato, soprattutto quando impari cosa sono gli oggetti e le funzioni allo stesso tempo. Ma speriamo che sembri un po' meno magico per te per adesso! + +### Crea tabelle per i modelli nel tuo database + +L'ultimo passo è quello di aggiungere un nuovo modello al nostro database. Prima dobbiamo far sapere a Django che ci sono alcuni cambiamenti nel nostro modello (l'abbiamo appena creato!). Digita `python manage.py makemigrations blog`. Il risultato somiglierà a questo: + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +Django ci ha preparato un file di migrazione che dobbiamo applicare nel nostro database. Digita `python manage.py migrate blog` e l'output dovrebbe essere: + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK + + +Evviva! Il nostro modello Post ora è nel database! Sarebbe bello poterlo vedere, vero? Vai al prossimo capitolo per vedere com'è il tuo Post! diff --git a/it/django_orm/README.md b/it/django_orm/README.md new file mode 100644 index 00000000000..4dfb21c3c89 --- /dev/null +++ b/it/django_orm/README.md @@ -0,0 +1,157 @@ +# Django ORM e i QuerySet + +In questo capitolo imparerai come Django si collega al database e archivia i dati al suo interno. Tuffiamoci! + +## Cos'è un QuerySet? + +Un QuerySet, in sostanza, è una lista di oggetti di un determinato Modello. Il QuerySet ti permette di leggere il dato dal database, filtrarlo e ordinarlo. + +È più facile impararlo con un esempio. Proviamo, ti va? + +## La shell di Django + +Apri la tua console locale (non su PythonAnywhere) e digita questo comando: + + (myvenv) ~/djangogirls$ python manage.py shell + + +L'effetto dovrebbe essere come questo: + + (InteractiveConsole) + >>> + + +Ora ti trovi nella consolle interattiva di Django. È come il prompt di python ma con un po' di magia di Django in più :). Qui puoi anche utilizzare tutti i comandi Python, ovviamente. + +### Tutti gli oggetti + +Proviamo a rendere visibili tutti i nostri post prima. Puoi farlo con il seguente comando: + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +Ops! È comparso un errore. Ci dice che non c'è nessun Post. È corretto -- ci siamo dimenticati di importarlo! + + >>> from blog.models import Post + + +È semplice: importiamo il modello `Post` da `blog.models`. Proviamo a rendere di nuovo visibili tutti i post: + + >>> Post.objects.all() + [, ] + + +È una lista di post che abbiamo creato prima! Abbiamo creato questi post usando l'interfaccia di ammisnistrazione di Django. Comunque sia, ora vogliamo creare nuovi post usando Python, quindi come lo facciamo? + +### Creare oggetti + +Così si crea un nuovo oggetto Post nel database: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Ma manca un ingrediente qui: `me`. Dobbiamo passare un'istanza del modello `User` come un autore. Come si fa? + +Importiamo il modello User prima: + + >>> from django.contrib.auth.models import User + + +Quali utenti abbiamo nel nostro database? Prova questo: + + >>> User.objects.all() + [] + + +È il superuser che abbiamo creato prima! Ora prendiamo un'istanza del user: + + me = User.objects.get(username='ola') + + +Come puoi vedere, ora prendiamo `(get)` un `User` con un `username` che è uguale a 'ola'. Ben fatto, devi cambiarlo con il tuo username. + +Adesso possiamo finalmente creare il nostro post: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Evviva! Vuoi controllare se funziona? + + >>> Post.objects.all() + [, , ] + + +Eccolo, un altro post nell'elenco! + +### Aggiungi altri post + +Ora puoi divertirti un po' ed aggiungere altri post per vedere come funziona. Aggiungi altri 2 o 3 e vai alla prossima parte. + +### Filtrare gli oggeti + +Larga parte parte dei QuerySet consiste nell'abilità di filtrarli. Diciamo che vogliamo trovare tutti i post che hanno come autore l'Utente ola. Useremo `filter` invece di `all` in `Post.objects.all()`. Tra parentesi affermeremo le condizioni che un blog post deve soddisfare per finire nel nostro queryset. Nella nostra situazione è `autore` che è uguale a `me`. Il modo di scriverlo in Django è `autore=me`. Ora il nostro pezzo di codice ha questo aspetto: + + >>> Post.objects.filter(author=me) + [, , , ] + + +O magari vogliamo vedere tutti i post che contengono la parola 'titolo' nel campo `titolo`? + + >>> Post.objects.filter(title__contains='title') + [, ] + + +> **Nota** ci sono due caratteri di sottolineatura (`_`) tra `titolo` e `contains`. L'ORM di Django usa questa sintassi per separare i nomi dei campi ("titolo") ed operazioni o filtri ("contiene"). Se usi solo un carattere di sottolineatura, otterrai un errore come "FieldError: non è possibile risolvere la parola chiave title_contains". + +Puoi anche ottenere una lista di tutti i post pubblicati. Lo facciamo filtrando tutti i post che hanno una `published_date` impostata in passato: + + >>> from django.utils import timezone + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + +Purtroppo, il post che abbiamo aggiunto dalla console Python non è ancora pubblicato. Possiamo modificarlo! In primo luogo ottenere un'istanza di un post che vogliamo pubblicare: + + >>> post = Post.objects.get(title="Sample title") + + +Ora pubblicalo con il nostro metodo `publish`! + + >>> post.publish() + + +Ora cerca di ottenere di nuovo l'elenco dei post pubblicati (premere il pulsante di freccia in su 3 volte e premere `invio`): + + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + + +### Ordinare gli oggetti + +I QuerySet ti permettono anche di ordinare le liste di oggetti. Proviamo a ordinarli in base al campo `created_date`: + + >>> Post.objects.order_by('created_date') + [, , , ] + + +Possiamo anche invertire l'ordine aggiungendo `-` all'inizio: + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +### QuerySet di concatenamento + +Puoi anche combinare QuerySet ** concatenandole** insieme: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +È davvero potente e ti permette di scrivere query piuttosto complesse. + +Fantastico! Ora sei pronta per la prossima parte! Per chiudere la shell, digita questo: + + >>> exit() + $ \ No newline at end of file diff --git a/it/django_start_project/README.md b/it/django_start_project/README.md new file mode 100644 index 00000000000..02d16306558 --- /dev/null +++ b/it/django_start_project/README.md @@ -0,0 +1,138 @@ +# Il tuo primo progetto Django! + +> Parte di questo capitolo è basato su esercitazioni di Geek Girls (https://github.com/ggcarrots/django-carrots). +> +> Parti di questo capitolo sono basate sul [django-marcador tutorial][1] sotto la licenza Creative Commons Attributions-ShareAlike 4.0 International License. Il tutorial di django-marcador è protetto da copyright di Markus Zapke-Gründemann et al. + + [1]: http://django-marcador.keimlink.de/ + +Creeremo un semplice blog! + +Il primo passo è quello di iniziare un nuovo progetto di Django. Fondamentalmente, questo significa che eseguiremo alcuni script forniti da Django che creerà per noi lo scheletro di un progetto Django. Si tratta solo di un insieme di directory e file che verranno utilizzati dopo. + +I nomi di alcuni file e cartelle sono molto importanti per Django. Non dovresti modificare i nomi dei file che stiamo per creare. Neanche spostarli in un altro posto è una buona idea. Django deve mantenere una determinata struttura per essere in grado di trovare le cose importanti. + +> Ricordati di eseguire tutto nel virtualenv. Se non vedi un prefisso `(myvenv)` nella tua console devi attivare il tuo virtualenv. Abbiamo spiegato come farlo nel capitolo **installazione Django** nella parte **Lavorando con virtualenv**. Digitando `myvenv\Scripts\activate` su Windows oppure `source myvenv/bin/activate` su Mac OS / Linux farà questo per te. + +Dovresti eseguire nella tua console MacOS o Linux il seguente comando; **non dimenticarti di aggiungere il punto `.` alla fine **: + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +Su Windows; **non dimenticarti di aggiungere il punto `.` alla fine**: + + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> Il punto `.` è cruciale perché dice allo script d'installare Django nell'attuale directory (quindi il punto `.` è un riferimento di abbreviazione) +> +> **Nota** Quando digiti i comandi sopra, ricorda che si digita soltanto la parte che inizia con `django-admin` oppure `django-admin.py`. Le parti mostrate qui come `(myvenv) ~/djangogirls$` e `(myvenv) C:\Users\Name\djangogirls>` sono solo esempi del prompt che starà invitando il tuo input sulla tua command line. + +`django-admin.py` è uno script che creerà le cartelle ed i file per te. Adesso dovresti avere una struttura di directory simile a questa: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +`manage.py` è uno script che aiuta a gestire il sito. Usandolo saremo in grado di avviare un web server sul nostro computer senza dover installare nient'altro, tra l'altro. + +Il file `settings.py` contiene la configurazione del tuo sito web. + +Ricordi quando abbiamo parlato di un postino che controlla dove rilasciare la lettera? il file `urls.py` contiene una lista di schemi usati da `urlresolver`. + +Ignoriamo gli altri file per ora dal momento che non li modificheremo. L'unica cosa da ricordare è di non cancellarli per sbaglio! + +## Modificare le impostazioni + +Facciamo qualche cambiamento in `mysite/settings.py`. Apri il file usando il code editor che hai installato prima. + +Sarebbe bello avere l'ora corretta sul nostro sito Web. Vai alla [lista di fusi orari di wikipedia][2] e copia il tuo fuso orario (TZ). (es. `Europe/Berlin`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +In settings.py, trova la riga che contiene `TIME_ZONE` e modificala per scegliere il tuo fuso orario: + +```python +TIME_ZONE = 'Europe/Berlin' +``` + +Modifica "Europe/Berlin" nel modo corretto + +Avrai anche bisogno di aggiungere un percorso per i file statici (scopriremo tutto su file statici e CSS più avanti nell'esercitazione). Scendi fino alla *fine* del file e sotto la voce `STATIC_URL`, aggiungi un nuovo percorso chiamato `STATIC_ROOT`: + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## Imposta un database + +Ci sono un sacco di software di database diversi che possono immagazzinare dati per il tuo sito. Noi useremo quello di default, `sqlite3`. + +È già impostato in questa parte del file `mysite/settings.py`: + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +Per creare un database per il nostro blog, eseguiamo questo nella console: `python manage.py migrate` (abbiamo bisogno di essere nella directory `djangogirls` che contiene il file `manage.py`). Se funziona, dovresti vedere qualcosa di simile: + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK + + +E abbiamo finito! Tempo di avviare il server web e vedere se il nostro sito Web funziona! + +Devi essere nella directory che contiene il file di `manage.py` (la directory `djangogirls`). Nella console, possiamo avviare il server web eseguendo `python manage.py runserver`: + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Se sei su Windows e non funziona con `UnicodeDecodeError`, usa questo comando: + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Ora tutto quello che devi fare è controllare che il tuo sito sia in esecuzione. Apri il tuo browser (Firefox, Chrome, Safari, Internet Explorer o qualsiasi altro tu usi) e digita l'indirizzo: + + http://127.0.0.1:8000/ + + + +Il server web assumerà il controllo del command prompt finché non lo fermi. Per digitare più comandi mentre è in esecuzione apri una nuova finestra di terminale e attiva il tuo virtualenv. Per fermare il server web, torna alla finestra dove è in esecuzione e premi i pulsanti CTRL+C - Control e C insieme (su Windows, è probabile che tu deva premere Ctrl+Break). + +Congratulazioni! Hai appena creato il tuo primo sito e l'hai avviato usando un web server! Non è fantastico? + +![Ha funzionato!][3] + + [3]: images/it_worked2.png + +Pronto/a per il prossimo passo? È ora di creare un po' di contenuti! diff --git a/it/django_start_project/images/it_worked2.png b/it/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/it/django_start_project/images/it_worked2.png differ diff --git a/it/django_templates/README.md b/it/django_templates/README.md new file mode 100644 index 00000000000..cdf3d99ca3c --- /dev/null +++ b/it/django_templates/README.md @@ -0,0 +1,105 @@ +# I templates di Django + +È l'ora di visualizzare alcuni dati! Django ci dà alcuni **template tags** già pronti per farlo. + +## Cosa sono i template tags? + +In HTML non puoi scrivere codice Python, perché i browser non lo capiscono. Essi conoscono solo l'HTML. Noi sappiamo che l'HTML è piuttosto statico, mentre Python è molto più dinamico. + +I **Django template tags** ci permettono di trasferire le cose simili a Python in HTML, in modo che tu possa costruire siti web in modo più veloce e facile. Accidenti! + +## Mostra il template con la lista di post + +Nel capitolo precedente abbiamo dato al nostro template una lista di posts nella variabile `posts`. Adesso lo mostreremo nell'HTML. + +Per stampare una variabile nel template Django, usiamo doppie parentesi graffe con il nome della variabile all'interno, così: + +```html +{{ posts }} +``` + +Prova questo nel tuo template `blog/templates/blog/post_list.html`. Sostituisci tutto dal secondo `
` al terzo `
` con `{{ posts }}`. Salva il file e aggiorna la pagina per vedere i risultati: + +![Figura 13.1][1] + + [1]: images/step1.png + +Come vedi, quello che abbiamo è: + + [, ] + + +Significa che Django lo vede come una lista di oggetti. Ricordi dalla **Introduzione a Python** come possiamo rendere visibili le liste? Sì, con for loops! In un template Django si fanno così: + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Prova ad inserirlo nel tuo template. + +![Figura 13.2][2] + + [2]: images/step2.png + +Funziona! Ma noi vogliamo che vengano mostrate come i post statici che abbiamo creato prima nel capitolo **Introduzione ad HTML**. Puoi mischiare i tag HTML con quelli di template. Il nostro `body` avrà questo aspetto: + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Tutto quello che hai messo tra `{% for %}` e `{% endfor %}` Sarà ripetuto per ciascun oggetto della lista. Aggiorna la tua pagina:{% endraw %} + +![Figura 13.3][3] + + [3]: images/step3.png + +Ti sei accorto che abbiamo utilizzato una notazione leggermente diversa questa volta `{{ post.title }}` oppure `{{ post.text }}`? Stiamo introducendo i dati in ciascuno dei campi definiti nel nostro modello `Post`. Inoltre le `|linebreaksbr` stanno spingendo il testo dei post attraverso un filtro per trasformare le line-breaks in paragrafi. + +## Un' ultima cosa + +Sarebbe bello vedere se il tuo sito funziona ancora su Internet, giusto? Proviamo a fare il deploy su PythonAnywhere di nuovo. Ecco un riepilogo dei passaggi... + +* Prima di tutto, fai il push del tuo codice verso Github + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push + + +* Poi, ritorna su [PythonAnywhere][4] e vai alla tua **console di Bash** (o iniziane una nuova) ed esegui: + + [4]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ git pull + [...] + + +* Infine, vai sulla [Web tab][5] e premi **Reload** sulla tua web app. L'aggiornamento dovrebbe essere live! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Congratulazioni! Ora vai avanti e prova ad aggiungere un nuovo post nel tuo Admin Django (ricorda di aggiungere una published_date!), sucessivamente aggiorna il tuo sito per vedere se il post compare. + +Funziona come un incantesimo? Ne siamo fieri! Staccati dal computer per un po', ti sei guadagnato/a una pausa. :) + +![Figura 13.4][6] + + [6]: images/donut.png \ No newline at end of file diff --git a/it/django_templates/images/donut.png b/it/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/it/django_templates/images/donut.png differ diff --git a/it/django_templates/images/step1.png b/it/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/it/django_templates/images/step1.png differ diff --git a/it/django_templates/images/step2.png b/it/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/it/django_templates/images/step2.png differ diff --git a/it/django_templates/images/step3.png b/it/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/it/django_templates/images/step3.png differ diff --git a/it/django_urls/README.md b/it/django_urls/README.md new file mode 100644 index 00000000000..b661a07a53a --- /dev/null +++ b/it/django_urls/README.md @@ -0,0 +1,125 @@ +# Django URL + +Stiamo per costruire la nostra pagina web: una homepage per il tuo blog! Ma prima, impariamo un po' di più sulle url di Django. + +## Che cos'è un URL? + +Una URL è semplicemente un indirizzo web. Puoi vedere una URL ogni volta che visiti un sito web - si vede nella barra degli indirizzi del tuo browser. (sì! `127.0.0.1:8000` is a URL! Anche `https://djangogirls.org` è una URL): + +![Url][1] + + [1]: images/url.png + +Ogni pagina internet ha bisogno della sua URL. In questo modo la tua applicazione sa cosa deve mostrare a un utente che visita una URL. In Django usiamo qualcosa chiamato `URLconf` ( configurazione dell'URL). URLconf è un insieme di modelli che Django cercherà di far corrispondere con l'URL ricevuta per trovare la view giusta. + +## Come funzionano le URL in Django? + +Apriamo il file `mysite/urls.py` nel code editor che hai scelto e vediamo com'è: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ +    # Examples: +    # url(r'^$', 'mysite.views.home', name='home'), +    # url(r'^blog/', include('blog.urls')), + +    url(r'^admin/', include(admin.site.urls)), +] +``` + +Come puoi vedere, Django ha già predisposto qualcosa per noi in questo file. + +Le righe che iniziano con `#` sono commenti - questo significa che non verranno lette da Python. Comodo, non è vero? + +L'admin URL , che hai visto nel capitolo precedente è già qui: + +```python +    url(r'^admin/', include(admin.site.urls)), +``` + +Questo significa che per ogni URL che comincia con `admin/` Django troverà la corrispondente *view*. In questo caso stiamo includendo un sacco di admin URL così che non sia tutto imballato in questo piccolo file - è più leggibile e più pulito. + +## Regex + +Per caso ti stai chiedendo come fa Python a far corrispondere URL e view? Beh, questa parte è difficile. Django usa `regex`, abbreviazione di "espressioni regolari". Regex ha molte, (moltissime!) regole che costituiscono un modello di ricerca. Dal momento che i regex sono un argomento avanzato, non analizzeremo nel dettaglio come funzionano. + +Se vuoi capire come abbiamo creato i patterns, eccoti un esempio del procedimento - ci servirà solo un sottoinsieme limitato di regole per esprimere il modello che stiamo cercando, vale a dire: + + ^ per l'inizio del testo + $ per la fine del testo + \d per una cifra + + per indicare che l'elemento precedente dovrebbe essere ripetuto almeno una volta + () per catturare parte del pattern + + +Il resto nella definizione dell'url sarà preso alla lettera. + +Ora immagina di avere un sito Web con un indirizzo così: `http://www.mysite.com/post/12345/`, dove `12345` è il numero del tuo post. + +Scrivere view separate per ogni numero del post sarebbe veramente noioso. Con l'espressione regolare possiamo creare un modello che corrisponde all'url ed estrae il numero per noi: `^ post/(\d+) / $`. Scomponiamo pezzo per pezzo per vedere che cosa stiamo facendo: + +* **^ post /** sta dicendo a Django di prendere tutto ciò che ha `post /` all'inizio dell'url (subito dopo `^`) +* **(\d+)** significa che ci sarà un numero (composto da una o più cifre) e che noi vogliamo che il numero venga catturato ed estratto +* **/** dice a django che ci dovrebbe essere un altro carattere a seguire `/` +* infine, **$** indica la fine dell'URL. Significa che solo le stringhe che terminano con `/` corrisponderanno a questo modello + +## La tua prima Url Django! + +È ora di creare la tua prima URL. Vogliamo usare http://127.0.0.1:8000/ come homepage per il nostro blog e visualizzare il nostro elenco di post. + +Vogliamo anche mantenere il file di `mysite/urls.py` pulito, quindi importeremo le url dalla nostra applicazione `blog` sul file principale `mysite/urls.py`. + +Vai avanti, elimina le righe commentate (che cominciano con `#`) e aggiungi una riga che importerà `blog.urls` nella url principale (`''`). + +Il tuo file `mysite/urls.py` ora dovrebbe avere questo aspetto: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + +Django reindirizzerà ora tutto ciò che viene da 'http://127.0.0.1:8000/' verso `blog.urls` e cercherà ulteriori istruzioni in questo file. + +Quando si scrivono espressioni regolari in Python lo si fa sempre con `r` davanti alla stringa. Questo è un suggerimento utile per Python che la stringa possa contenere caratteri speciali che non sono destinati per lo stesso Python, ma per l'espressione regolare. + +## blog.urls + +Crea un nuovo file `blog/urls.py`. Perfetto! Ora aggiungi queste prime due righe: + +```python +from django.conf.urls import url +from . import views +``` + +Stiamo solo importando metodi che appartengono a Django e tutte le nostre `views` dalla nostra app `blog` (non abbiamo ancora nulla all'interno, ma rimedieremo a questo in un minuto!) + +Dopo di che, possiamo aggiungere il nostro primo modello di URL: + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +Come vedi, stiamo assegnando una `view` nominata `post_list` alla URL `^$`. Questa espressione regolare combinerà`^` (un inizio) seguito da `$` (una fine) - cosicché solo una stringa vuota possa combaciare. È giusto, perché nei resolver di URL di Django, ' http://127.0.0.1:8000 /' non è una parte dell'URL. Questo schema dirà a Django che `views.post_list` è il posto giusto dove andare se qualcuno entra nel tuo sito all'indirizzo 'http://127.0.0.1:8000/'. + +L'ultima parte `name='post_list'` è il nome dell'URL che verrà usata per identificare la view. Può avere lo stesso nome della view, ma può anche essere qualcosa di completamente diverso. Useremo le URL rinominate successivamente nel progetto quindi è importante dare un nome a ciascuna URL nell'app. Inoltre dovremmo cercare di mantenere i nomi delle URL unici e facili da ricordare. + +Tutto fatto? Apri http://127.0.0.1:8000 / nel tuo browser per vedere il risultato. + +![Errore][2] + + [2]: images/error1.png + +Non funziona, vero? Non ti preoccupare, è solo una pagina di errore, niente di cui spaventarsi! In realtà sono molto utili: + +Leggerai che **non c'è un attributo 'post_list**. il *post_list* ti ricorda qualcosa? Abbiamo chiamato la nostra view proprio così! Questo significa che è tutto a posto. Semplicemente non abbiamo ancora creato la nostra *view*. Non ti preoccupare, ci arriveremo. + +> Se vuoi sapere di più sulla configurazione di URL Django, vai alla documentazione ufficiale: https://docs.djangoproject.com/en/1.8/topics/http/urls/ \ No newline at end of file diff --git a/it/django_urls/images/error1.png b/it/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/it/django_urls/images/error1.png differ diff --git a/it/django_urls/images/url.png b/it/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/it/django_urls/images/url.png differ diff --git a/it/django_views/README.md b/it/django_views/README.md new file mode 100644 index 00000000000..a65540fc789 --- /dev/null +++ b/it/django_views/README.md @@ -0,0 +1,38 @@ +# Le views di Django - è arrivata l'ora di creare! + +È ora di liberarsi di quel bug che abbiamo creato nel capitolo precedente :) + +Una *view* è un posto dove viene messa la "logica" della nostra applicazione. Essa richiederà informazioni dal `modello` che hai creato prima e lo passerà ad un `template`. Creeremo un template nel prossimo capitolo. Le views sono solo metodi di Python un po' più complicati di quelli che abbiamo descritto nel capitolo **Introduzione a Python**. + +Le views vengono collocate nel file `views.py`. Noi aggiungeremo le nostre *views* nel file `blog/views.py`. + +## blog/views.py + +OK, apriamo questo file e scopriamo cosa c'è dentro: + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Non c'è molto per ora. La *view* più semplice può essere simile a questa. + +```python +def post_list(request): +    return render(request, 'blog/post_list.html', {}) +``` + +Come puoi vedere, abbiamo creato un metodo (`def`) chiamato `post_list` che prende `request` e `restituisce` un metodo `render` che ci fornirà (metterà insieme) il nostro template `blog/post_list.html`. + +Salva il file, vai su http://127.0.0.1:8000/ e guarda cosa abbiamo ottenuto. + +Un altro errore! Leggi cosa sta succedendo adesso: + +![Error][1] + + [1]: images/error.png + +Questo è facile: *TemplateDoesNotExist*. Sistemiamo il bug e creiamo un template nel prossimo capitolo! + +> Impara di più sulle views di Django leggendo la documentazione ufficiale: https://docs.djangoproject.com/en/1.8/topics/http/views/ \ No newline at end of file diff --git a/it/django_views/images/error.png b/it/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/it/django_views/images/error.png differ diff --git a/it/domain/README.md b/it/domain/README.md new file mode 100644 index 00000000000..e68b8a007e3 --- /dev/null +++ b/it/domain/README.md @@ -0,0 +1,71 @@ +# Dominio + +Heroku ti ha dato un dominio, ma è lungo, difficile da ricordare e brutto. Sarebbe fantastico avere un dominio che sia corto e facile da ricordare, non credi? + +in questo capitolo ti insegneremo come comprare un dominio e dirigerlo verso Heroku! + +## Dove registrare un dominio? + +un dominio costa circa 15 dollari all'anno. Ci sono opzioni più economiche e più costose, a seconda del fornitore. Ci sono tantissime aziende dalle quali puoi comprare un dominio: un semplice [google search][1] darà centinaia di opzioni. + + [1]: https://www.google.com/search?q=register%20domain + +Il nostro preferito è [I want my name][2]. Essi si promuovono come "gestione del dominio indolore" ed è veramente indolore. + + [2]: https://iwantmyname.com/ + +## Come registrare un dominio in IWantMyName? + +Vai su [iwantmyname][3] e digita un dominio che vuoi ottenere nella casella di ricerca. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +Dovresti vedere una lista dei domini disponibili contenenti il termine che hai inserito nella casella di ricerca. Come vedi, una faccina sorridente indica che il dominio è disponibile e può essere comprato, mentre una faccina triste indica che è già stato preso. + +![][5] + + [5]: images/2.png + +Abbiamo deciso di comprare `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Vai alla cassa. Dovresti iscriverti a iwantmyname se non hai ancora un'account. Poi fornisci le informazioni sulla tua carta di credito e compra un dominio! + +Poi clicca su `Domains` nel menù e scegli il tuo nuovo dominio. Infine individua e clicca sul link `manage DNS records`: + +![][7] + + [7]: images/4.png + +Ora devi individuare questo form: + +![][8] + + [8]: images/5.png + +E riempilo con i seguenti dati: - Hostname: www - Type: CNAME - Value: il tuo dominio da Heroku (per esempio djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Clicca il pulsante 'Aggiungi' e 'Salva' in fondo alla pagina per salvare cambiamenti. + +Perchè il tuo dominio cominci a funzionare potrebbero essere necessarie fino ad un paio di ore, quindi sii paziente! + +## Fai la configurazione del dominio su Heroku + +Devi dire a Heroku anche che vuoi utilizzare il tuo dominio personalizzato. + +Vai sulla [Heroku Dashboard][10], fai il login nel tuo account Heroku e scegli la tua app. Poi vai nelle impostazioni dell'app e aggiungi il tuo dominio nella sezione `Domini` e salva le tue modifiche. + + [10]: https://dashboard.heroku.com/apps + +Questo è tutto! \ No newline at end of file diff --git a/it/dynamic_data_in_templates/README.md b/it/dynamic_data_in_templates/README.md new file mode 100644 index 00000000000..b3479a7996f --- /dev/null +++ b/it/dynamic_data_in_templates/README.md @@ -0,0 +1,74 @@ +# I dati dinamici nei templates + +Abbiamo diversi pezzi: il modello `Post` è definito in `models.py`, abbiamo `post_list` nel file `views.py` ed abbiamo aggiunto il template. Ma come faremo a far comparire i nostri post nel nostro template HTML? Perché questo è quello che vogliamo: prendere qualche contenuto (modelli salvati nel database) e farlo vedere in modo carino nel nostro template, giusto? + +Questo è esattamente quello che le *views* dovrebbero fare: collegare i modelli ed i template. Nella nostra `post_list` *view* avremo bisogno di prendere i modelli che vogliamo far vedere e passarli nel template. Quindi praticamente nella *view* decidiamo cosa (modello) renderemo visibile nel template. + +OK, quindi come facciamo a farlo? + +Dobbiamo aprire il nostro `blog/views.py`. Per ora `post_list` *view* si vede così: + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Ricordi quando abbiamo parlato di includere codice scritto in diversi file? Ora è il momento di includere il model che abbiamo scritto in `models.py`. Aggiungeremo questa riga `from .models import Post` così: + +```python +from django.shortcuts import render +from .models import Post +``` + +Il punto dopo il `from` significa *directory attuale* oppure *applicazione attuale*. Dal momento che `views.py` e `models.py` sono nella stessa directory possiamo semplicemente utilizzare `.` ed il nome del file (senza `.py`). Allora importiamo il nome del modello (`Post`). + +Cos'altro bisogna fare? Per poter prendere i post del blog dal modello`Post` ci serve una cosa chiamata `QuerySet`. + +## QuerySet + +Dovresti già sapere come funziona QuerySet. Ne abbiamo parlato nel capitolo [Django ORM (QuerySets) ][1]. + + [1]: ../django_orm/README.md + +Quindi ora ci interessa una lista di post del blog che sono pubblicati e organizzati da `published_date`, giusto? Lo abbiamo già fatto nel capitolo sulle QuerySet! + + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +Adesso mettiamo questo pezzo di codice nel file `blog/views.py` aggiungendolo alla funzione `def post_list(request)`: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + +Nota che abbiamo creato una *variabile* per il nostro QuerySet: `posts`. Vedila come il nome del nostro QuerySet. Da qui in avanti possiamo riferirci ad esso con questo nome. + +Il codice utilizza anche la funzione `timezone.now()`, quindi dobbiamo aggiungere un import per `timezone`. + +L'ultima cosa che manca è passare la QuerySet `posts` nel template (ci occuperemo di come renderlo visibile nel prossimo capitolo). + +Nella funzione `render` abbiamo già un parametro con `request` (quindi tutto quello che riceviamo dal nostro utente via internet) e un file template `'blog/post_list.html'`. Nell'ultimo parametro, che è simile a questo: `{}` possiamo aggiungere cose che il template possa utilizzare. Dobbiamo dargli un nome (ci atterremo a `'posts'` per il momento :)). Si vede così: `{'posts': posts}`. Ti preghiamo di notare che la parte prima di `:` è una stringa; devi metterla tra virgolette `''`. + +Il nostro file `blog/views.py` dovrà risultare così: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +È tutto! Ora di tornare al nostro template e rendere visibile questo QuerySet! + +Se vuoi leggere di più sui QuerySets in Django dovresti dare un'occhiata qui: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ \ No newline at end of file diff --git a/it/extend_your_application/README.md b/it/extend_your_application/README.md new file mode 100644 index 00000000000..be73b5469ec --- /dev/null +++ b/it/extend_your_application/README.md @@ -0,0 +1,193 @@ +# Estendi la tua applicazione + +Abbiamo completato i passi necessari per la creazione del nostro sito: sappiamo come scrivere un modello, una url, una view ed un template. Sappiamo anche come far diventare carino il nostro sito. + +Ora di far pratica! + +La prima cosa di cui abbiamo bisogno nel nostro blog è, ovviamente, una pagina per rendere visibile un post, vero? + +Abbiamo già un modello dei `Post`, quindi non abbiamo bisogno di aggiungere niente in `models.py`. + +## Creare un link di template verso la pagina di dettaglio di un post + +Cominceremo aggiungendo un link all'interno del file `blog/templates/blog/post_list.html`. Per ora dovrebbe avere questo aspetto: + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + + +{% raw %}Vogliamo creare un link che dal titolo di un post facente parte dell'elenco di articoli porti alla pagina di dettaglio. Cambiamo `

{{ post.title }}

` così che linki alla pagina di dettaglio del post:{% endraw %} + +```html +

{{ post.title }}

+``` + +{% raw %}È arrivata l'ora di spiegare il misterioso `{% url 'post_detail' pk=post.pk %}`. Come avrai capito, il simbolo `{% %}` significa che stiamo usando i tag del template di Django. Questa volta ne useremo uno che creerà una URL per noi!{% endraw %} + +`blog.views.post_detail` è un percorso per arrivare alla `post_detail` *view* che vogliamo creare. Nota bene: `blog` è il nome della nostra applicazione (la directory `blog`), `views` viene dal nome del file `views.py` e l'ultima cosa - `post_detail` - è il nome della *view*. + +Adesso quando andremo all'indirizzo: http://127.0.0.1:8000/ avremo un errore (come sapevamo, dal momento che non abbiamo una URL oppure una *view* per `post_detail`). Avrà questo aspetto: + +![Errore: nessuna corrispondenza inversa][1] + + [1]: images/no_reverse_match2.png + +## Crea una URL per i dettagli di un post + +Creiamo una URL in `urls.py` per il nostro `post_detail` *view*! + +Vogliamo che il nostro primo post venga visualizzato a questo **URL **: http://127.0.0.1:8000/post/1/ + +Facciamo sì che l'URL nel file `blog/urls.py` punti Django ad una *view* chiamata `post_detail`, che mostrerà un intero post. Aggiungi la riga `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` al file `blog/urls.py`. Il file dovrebbe assomigliare a questo: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + +Questa parte `^post/(?P[0-9]+)/$` sembra spaventosa, ma non preoccuparti - te la spiegheremo: - inizia ancora con `^` -- "l'inizio" - `post/` semplicemente significa che dopo l'inizio, l'URL dovrebbe contenere la parola **post** e **/**. Fin qui tutto bene. - `(?P[0-9]+)` - questa parte è più complicata. Significa che Django prenderà tutto quello che hai messo qui e lo trasferirà ad una view come variabile denominata `pk`. `[0-9]` ci dice anche che la variabile può essere solo un numero, non una lettera (quindi tutto tra 0 e 9). `+` significa che ci devono essere una o più cifre. Quindi qualcosa di simile a `http://127.0.0.1:8000/post//` non è valido, ma `http://127.0.0.1:8000/post/1234567890/` è perfetto! - `/` Quindi ci serve **/** di nuovo - `$` - "fine"! + +Ciò significa che se digiti `http://127.0.0.1:8000/post/5/` nel tuo browser, Django capirà che stai cercando una *view* chiamata `post_detail` e trasferirà l'informazione che `pk` è uguale a `5` a quella *view*. + +`pk` è un diminutivo di `primary key`. Questo nome viene frequentemente utilizzato nei progetti Django. Ma puoi chiamare la tua variabile come vuoi (ricorda: minuscole e `_` invece degli spazi!). Per esempio invece di `(?P[0-9]+)` potremmo avere la variabile `post_id`quindi questo pezzettino dovrebbe assomigliare a: `(?P[0-9]+)`. + +Ok, abbiamo aggiunto un nuovo schema di URL a `blog/urls.py`! Aggiorniamo la pagina: http://127.0.0.1:8000/ Boom! Ancora un altro errore! Come previsto! + +![Errore attributo][2] + + [2]: images/attribute_error2.png + +Ti ricordi di quale è il prossimo passo? Ma certo: aggiungere una view! + +## Aggiungi una view del post + +Questa volta alla nostra *view* viene data un altro parametro `pk`. La nostra *view* deve prenderlo, vero? Quindi definiremo la nostra funzione come `def post_detail(request, pk):`. Dobbiamo utilizzare esattamente lo stesso nome che abbiamo specificato in urls (`pk`). Omettere questa variabile è sbagliato e genererà un errore! + +Ora, noi vogliamo ottenere un unico post. Per farlo possiamo utilizzare le queryset così: + + Post.objects.get(pk=pk) + + +Ma questo codice presenta un problema. Se non c'è `Post` con `primary key` (`pk`) otterremo un errore bruttissimo! + +![Errore: non esiste][3] + + [3]: images/does_not_exist2.png + +Noi non lo vogliamo! Ma, senza dubbio, Django ha qualcosa che si occuperà del problema per noi: `get_object_or_404`. Nel caso in cui non ci sia `Post` con la data `pk` mostrerà una pagina molto più carina (chiamata `Page Not Found 404`). + +![Pagina non trovata][4] + + [4]: images/404_2.png + +La buona notizia è che in realtà puoi creare la tua pagina `Page not found` modificarla come vuoi e darle un bell'aspetto. Ma non è importantissimo in questo momento, quindi salteremo questa parte. + +Ok, è arrivata l'ora di aggiungere una *view* al nostro file `views.py`! + +Dovremo aprire `blog/views.py` ed aggiungere il seguente codice: + + from django.shortcuts import render, get_object_or_404 + + +Vicino ad altre righe `from` ed alla fine del file aggiungeremo la nostra *view*: + +```python + def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Si, è giunta l'ora di aggiornare la pagina: http://127.0.0.1:8000/ + +![Visualizzazione elenco post][5] + + [5]: images/post_list2.png + +Ha funzionato! Ma cosa succede se clicchi su un link nel titolo del post? + +![Errore: il template non esiste][6] + + [6]: images/template_does_not_exist2.png + +Oh no! Un altro errore! Ma sappiamo già come occuparcene, giusto? Dobbiamo aggiungere un template! + +## Crea un template per il post detail + +Creeremo un file in `blog/templates/blog` chiamato `post_detail.html`. + +Il risultato somiglierà a questo: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Stiamo estendendo ancora una volta il template di base. `base.html`. Nel blocco `content` vogliamo mostrare una published_date del post (se esiste), un titolo ed il testo. Ma dovremmo discutere di alcune cose importanti, vero? + +{% raw %}`{% if ... %} ... {% endif %}` è un tag di template che possiamo utilizzare quando vogliamo controllare qualcosa (ricordi `if ... else ..` dal capitolo **Introduzione a Python**?). In questo caso vogliamo controllare che la `published_date` di un post non sia vuota. {% endraw %} + +Ok, possiamo aggiornare la nostra pagina e vedere se `Page not found` non c'è più. + +![Pagina di dettaglio del post][7] + + [7]: images/post_detail2.png + +Si! Ha funzionato! + +## Ultima cosa: ora di fare il deploy! + +Sarebbe bello vedere se il tuo sito Web sarà ancora funzionante in PythonAnywhere, vero? Proviamo a fare un alrto deploy. + + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push + + +* Poi, in una [console PythonAnywhere Bash][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Infine, vai su il [Web tab][9] e premi **Reload**. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +Fatto! Congratulazioni :) diff --git a/it/extend_your_application/images/404_2.png b/it/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/it/extend_your_application/images/404_2.png differ diff --git a/it/extend_your_application/images/attribute_error2.png b/it/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/it/extend_your_application/images/attribute_error2.png differ diff --git a/it/extend_your_application/images/does_not_exist2.png b/it/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/it/extend_your_application/images/does_not_exist2.png differ diff --git a/it/extend_your_application/images/no_reverse_match2.png b/it/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/it/extend_your_application/images/no_reverse_match2.png differ diff --git a/it/extend_your_application/images/post_detail2.png b/it/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/it/extend_your_application/images/post_detail2.png differ diff --git a/it/extend_your_application/images/post_list2.png b/it/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/it/extend_your_application/images/post_list2.png differ diff --git a/it/extend_your_application/images/template_does_not_exist2.png b/it/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/it/extend_your_application/images/template_does_not_exist2.png differ diff --git a/it/how_the_internet_works/README.md b/it/how_the_internet_works/README.md new file mode 100644 index 00000000000..13f02ddb34d --- /dev/null +++ b/it/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# Come funziona Internet + +> Questo capitolo è ispirato ad un discorso di Jessica McKellar "How the Internet Works" (http://web.mit.edu/jesstess/www/). + +Scommettiamo che usi Internet tutti i giorni. Ma sai davvero che cosa succede quando digiti un indirizzo come https://djangogirls.org nel tuo browser e premi `invio`? + +La prima cosa da capire è che un sito è solo un gruppo di file salvati su un hard disk. Proprio come i tuoi film, la tua musica e le tue immagini. Tuttavia, c'è una caratteristica tipica dei siti web: includono un codice chiamato HTML. + +Se non hai familiarità con la programmazione, può essere difficile da capire l'HTML all'inizio, ma i tuoi web browser (come Chrome, Safari, Firefox, ecc) lo adorano. I browser sono progettati per capire questo codice, seguire le sue istruzioni e presentare questi file che costituiscono il tuo sito web esattamente nel modo desiderato. + +Come per tutti i file, dobbiamo archiviare i file HTML da qualche parte su un hard disk. Per l'Internet, utilizziamo computer speciali e potenti chiamati *servers*. Non hanno uno schermo, un mouse o una tastiera, perché il loro unico proposito è quello di archiviare i dati e fornirli. È per quello che vengono chiamati *servers* -- perché essi *servono* i tuoi dati. + +OK, ma tu vuoi sapere com'è internet, vero? + +Abbiamo creato un'immagine! Ecco com'è: + +![Figura 1.1][1] + + [1]: images/internet_1.png + +Sembra caotico, vero? Infatti è una rete di macchine collegate (i *servers* che abbiamo menzionato prima). Centinaia di migliaia di macchine! Molti, molti chilometri di cavi in tutto il mondo! Puoi visitare un sito di Submarine Cable Map (http://submarinecablemap.com) per vedere quanto è complicata la rete. Ecco uno screenshot dal sito web: + +![Figura 1.2][2] + + [2]: images/internet_3.png + +È affascinante, non è vero? Ma ovviamente, non è possibile avere un cavo fra ogni macchina collegata ad Internet. Quindi, per raggiungere una macchina (per esempio quella in cui è salvato https://djangogirls.org) dobbiamo far passare una richiesta attraverso a molte, molte macchine diverse. + +Assomiglia a questo: + +![Figura 1.3][3] + + [3]: images/internet_2.png + +Immagina che quando digiti https://djangogirls.org invii una lettera che dice: "Caro Django Girls, voglio vedere il sito djangogirls.org. inviamelo, per favore!" + +La tua lettera arriva nell'ufficio postale più vicino a te. Dopo di che va in un altro ufficio postale, che è un po' più vicino al tuo destinatario, poi in un altro ed in un altro ancora finché viene consegnato a destinazione. L'unica cosa è che se invii molte lettere (*pacchi di dati*) allo stesso posto, potrebbero attraversare uffici postali totalmente diversi (*routers*). Questo dipende da come vengono distribuiti presso ogni ufficio. + +![Figura 1.4][4] + + [4]: images/internet_4.png + +Si, è esattamente così. Tu invii messaggi e ti aspetti una risposta. Certo, invece di carta e penna usi i bytes di dati, ma l'idea è la stessa! + +Al posto di indirizzi fisici, ovvero del nome della via, della città, del Cap, e del nome del Paese, usiamo indirizzi IP. Il tuo computer prima chiede il DNS (Domain Name System) per tradurre djangogirls.org in un indirizzo IP. Funziona un po' come i vecchi elenchi telefonici, dove cercando il nome della persona che volevi contattare potevi trovare il numero telefonico e l'indirizzo. + +Quando invii una lettera, deve avere determinate caratteristiche per essere consegnata correttamente: un indirizzo, un timbro, ecc. Inoltre utilizzi un linguaggio che il destinatario è in grado di capire, vero? Lo stesso vale per i *pacchi di dati* che invii per vedere un sito Web. Usiamo un protocollo chiamato HTTP (Hypertext Transfer Protocol). + +Quindi, praticamente, quando hai un sito, devi avere un *server* (macchina) dove archiviarlo. Quando il *server* riceve una *richiesta* (in una lettera), restituisce il tuo sito (in un'altra lettera). + +Dal momento che questo è il tutorial di Django, ti chiederai cosa fa Django. Quando invii una risposta, non vuoi inviare la stessa cosa a tutti. È molto meglio se le tue lettere son personalizzate, soprattutto per la persona che ti ha appena scritto, giusto? Django ti aiuta con la creazione di queste interessanti lettere personalizzate :). + +Basta parlare, è arrivata l'ora di creare! \ No newline at end of file diff --git a/it/how_the_internet_works/images/internet_1.png b/it/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/it/how_the_internet_works/images/internet_1.png differ diff --git a/it/how_the_internet_works/images/internet_2.png b/it/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/it/how_the_internet_works/images/internet_2.png differ diff --git a/it/how_the_internet_works/images/internet_3.png b/it/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/it/how_the_internet_works/images/internet_3.png differ diff --git a/it/how_the_internet_works/images/internet_4.png b/it/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/it/how_the_internet_works/images/internet_4.png differ diff --git a/it/html/README.md b/it/html/README.md new file mode 100644 index 00000000000..cd7287f49d8 --- /dev/null +++ b/it/html/README.md @@ -0,0 +1,209 @@ +# Introduzione all'HTML + +Ti potresti chiedere, cos'è un template? + +Un template è un file che possiamo riutilizzare per presentare informazioni diverse in un formato consistente - per esempio, potresti utilizzare un template per aiutarti a scrivere una lettera, perché anche se ciascuna lettera potrebbe contenere un messaggio diverso ed essere a sua volta indirizzata ad una persona diversa, condivideranno lo stesso formato. + +Un template Django viene descritto in un linguaggio chiamato HTML (è lo stesso HTML che abbiamo menzionato nel primo capitolo **Come funziona l'Internet**). + +## Cos'è l'HTML? + +HTML è un semplice codice che viene interpretato dal tuo browser - come Chrome, Firefox o Safari - per rendere un sito web visibile all'utente. + +HTML sta per "HyperText Markup Language". **HyperText** significa che è un tipo di testo che supporta i collegamenti ipertestuali tra le pagine. **Markup** significa che abbiamo preso un documento e l'abbiamo contrassegnato con il codice per dire a qualcosa (in questo caso, un browser) come interpretare la pagina. Il codice HTML è costruito con **tags**, ognuno inizia con `<` e finisce con `>`. Questi tag rappresentano gli **elementi** di markup. + +## Il tuo primo template! + +Creare un template significa creare un file template. Tutto è un file, vero? Probabilmente l'hai già notato. + +I template vengono salvati in una cartella `blog/templates/blog`. Quindi prima crea una directory chiamata `templates` nella directory del tuo blog. Quindi crea un'altra directory chiamata `blog` all'interno della tua directory templates: + + blog + └───templates + └───blog + + +(Ti chiederai perché abbiamo bisogno di due directory chiamate entrambe `blog` - come scoprirai più tardi, si tratta semplicemente di una denominazione convenzionale che serve a rendere la vita più facile.) + +E ora crea un file `post_list.html` nella directory `blog/templates/blog` (lascialo in bianco per adesso). + +Guarda che aspetto ha il tuo sito adesso: http://127.0.0.1:8000/ + +> Se continui ad avere un errore `TemplateDoesNotExists`, prova a riavviare il server. Vai nella command line, arresta il server premendo Ctrl+C ( I tasti Control e C insieme) e riavvialo utilizzando il comando `python manage.py runserver`. + +![Figura 11.1][1] + + [1]: images/step1.png + +L'errore non c'è più! Congratulazioni :) Tuttavia, il tuo sito in realtà non sta pubblicando niente eccetto una pagina vuota, perché anche il tuo template è vuoto. Dobbiamo sistemarlo. + +Aggiungi quanto segue nel tuo file template: + +```html + +

Hi there!

+

It works!

+ +``` + +Quindi come appare il tuo sito ora? Clicca per scoprirlo: http://127.0.0.1:8000/ + +![Figura 11.2][2] + + [2]: images/step3.png + +Ha funzionato! Ottimo lavoro :) + +* Il comando più basico, ``, è sempre l'inizio di ogni pagina web e `` è sempre la fine. Come puoi vedere, l'intero contenuto del sito va tra il tag iniziale `` ed il tag conclusivo `` +* `

` è un tag per gli elementi paragrafo; `

` conclude ogni paragrafo + +## Head & body + +Ciascuna pagina HTML è a sua volta divisa in due elementi: **head** e **body**. + +* **head** è un elemento che contiene informazioni sul documento non visibili sullo schermo. + +* **body** è l'elemento che contiene tutto ciò che invece viene visualizzato come parte della pagina web. + +Utilizziamo `` per dire al browser come interpretare la configurazione della pagina, e `` per dirgli in realtà cosa c'è nella pagina. + +Per esempio, puoi mettere un elemento di titolo all'interno di ``, così: + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +Salva il file e aggiorna la tua pagina. + +![Figura 11.3][3] + + [3]: images/step4.png + +Hai notato come il browser ha capito che "Il blog di Ola" è il titolo della tua pagina? Ha interpretato `Il blog di Ola` ed ha messo il testo nella barra del titolo sul tuo browser (sarà anche utilizzato per i segnalibri e così via). + +Probabilmente hai anche notato che ogni tag di apertura è abbinato ad un *tag di chiusura*, con un `/`, e che gli elementi sono *annidati* (i.e. non puoi chiudere un tag particolare fino a quando tutti quelli che erano al suo interno sono stati chiusi a loro volta). + +È come mettere le cose in delle scatole. Hai una grossa scatola, ``; al suo interno c'è ``, che contiene scatole ancora più piccole: `

`. + +Devi seguire queste regole di tag *di chiusura*, e di elementi *annidati* - se non lo fai, il browser potrebbe non essere in grado di interpretarli correttamente e la tua pagina verrà visualizzata incorrettamente. + +## Personalizza il tuo template + +Ora puoi divertirti un po' e provare a personalizzare il tuo template! Qua ci sono un po' di tag utili per quello: + +* `

Un'intestazione

` - per la tua intestazione più importante +* `

Un sottotitolo

` per un titolo di livello inferiore +* `

Un sottotitolo più piccolo

` ... e così via, fino a `
` +* `text` enfatizza il tuo testo +* `text` enfatizza fortemente il tuo testo +* `
` va in un'altra riga (puoi mettere qualsiasi cosa dentro br) +* `link` crea un link +* `
  • primo elemento
  • secondo elemento
` fa una lista, proprio come questa qui! +* `
` definisce una sezione della pagina + +Qui c'è un esempio di un template completo: + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` + +Abbiamo creato tre sezioni `div` qui. + +* Il primo elemento `div` contiene il titolo del nostro blog - è un'intestazione ed un link +* Altri tre elementi `div` contengono i nostri post con la loro data di pubblicazione, `h2` con il titolo di un post che è cliccabile e due `p` (paragrafi) di testo, uno per la data e l'altro per i nostri post. + +Ci dà questo effetto: + +![Figura 11.4][4] + + [4]: images/step6.png + +Yaaay! Ma fino adesso, il nostro template mostra esattamente **la stessa informazione** - mentre prima stavamo dicendo che i template ci permettono di mostrare **diverse** informazioni nello **stesso formato**. + +Quello che vogliamo è visualizzare i veri post aggiunti nel nel nostro Django admin - è quello che faremo adesso. + +## Un'ultima cosa: il deploy! + +Sarebbe bello vedere tutto questo live su Internet, giusto? Facciamo un altro deploy su PythonAnywhere: + +### Committa e pubblica il tuo codice su GitHub + +Prima di tutto, vediamo quali file sono cambiati dall'ultimo deploy (esegui questi comandi localmente, non su PythonAnywhere): + + $ git status + + +Assicurati di essere nella directory `djangogirls` e diciamo a `git` di includere tutte le modifiche in questa directory: + + $ git add --all . + + +> **Nota** `-A` (diminutivo di "all") significa che `git` riconoscerà anche il fatto che hai cancellato dei file (per impostazione predefinita, esso riconosce soltanto i file nuovi/modificati). Ricorda anche (dal capitolo 3) che il `.` significa la directory attuale. + +Prima di caricare tutti i file, proviamo a controllare cosa caricherà `git` (tutti i file che caricherà `git` ora appariranno in verde): + + $ git status + + +Ci siamo quasi, ora è il momento di dirgli di salvare questa modifica nella cronologia. Gli daremo un "messaggio di commit" dove descriviamo ciò che abbiamo modificato. Puoi digitare tutto quello che vuoi a questo punto, sarebbe utile scrivere qualcosa di descrittivo in modo da ricordare in futuro cos'hai fatto. + + $ git commit -m "Ho cambiato l'HTML per questo sito." + + +> **Nota** Assicurati di usare doppie virgolette attorno al messaggio di commit. + +Quando hai finito, caricheremo (push) le nostre modifiche su Github: + + git push + + +### Scarica il tuo nuovo codice su PythonAnywhere, e ricarica la tua web app + +* Apri la [pagina Console PythonAnywhere][5] e vai alla tua **Bash console** (o iniziane una nuova). Quindi, esegui: + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +Ed osserva il tuo codice mentre viene scaricato. Se vuoi controllare che sia arrivato, puoi fare un salto alla scheda **Files** e vedere il tuo codice su PythonAnywhere. + +* Infine, fai un salto alla [scheda Web][6] e premi **Reload** sulla tua web app. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +Il tuo aggiornamento dovrebbe essere applicato! Vai avanti ed aggiorna il tuo sito nel brower. Le modifiche dovrebbero essere visibili :) \ No newline at end of file diff --git a/it/html/images/step1.png b/it/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/it/html/images/step1.png differ diff --git a/it/html/images/step3.png b/it/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/it/html/images/step3.png differ diff --git a/it/html/images/step4.png b/it/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/it/html/images/step4.png differ diff --git a/it/html/images/step6.png b/it/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/it/html/images/step6.png differ diff --git a/it/images/application.png b/it/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/it/images/application.png differ diff --git a/it/installation/README.md b/it/installation/README.md new file mode 100644 index 00000000000..06f6a3085f9 --- /dev/null +++ b/it/installation/README.md @@ -0,0 +1,49 @@ +# Se stai facendo il tutorial a casa + +Se stai facendo il tutorial a casa e non durante uno degli [eventi Django Girls ](https://djangogirls.org/events/), puoi saltare questo capitolo e andare direttamente a [Come funziona Internet?](../how_the_internet_works/README.md). + +Copriamo questi argomenti nel tutorial completo, e questa è una pagina aggiuntiva contenente tutte le istruzioni di installazione. L'evento Django Girls include una "serata dedicata all'installazione" in cui installiamo tutto, in modo da non preoccuparcene durante il workshop, quindi questo capitolo è utile per chi partecipa ad uno dei nostri workshop. + +Se lo trovi utile puoi seguire anche questo capitolo. Ma se vuoi iniziare a imparare prima di installare le cose sul tuo computer, salta questo capitolo. Ti spiegheremo l'installazione più avanti. + +Buona fortuna! + +# Installazione + +Nel workshop costruirai un blog, e ci sono alcuni task dedicati all'impostazione che sarebbe bello completare in anticipo, in modo che tu sia pronta a scrivere codice in giornata. + +# Installare Python + +{% include "/python_installation/instructions.md" %} + +# Preparare virtualenv e installare Django + +{% include "/django_installation/instructions.md" %} + +# Installare un editor di codice + +{% include "/code_editor/instructions.md" %} + +# Installare Git + +{% include "/deploy/install_git.md" %} + +# Creare un account GitHub + +Vai su [GitHub.com](https://www.github.com) e iscriviti per un nuovo account gratuito. + +# Creare un account PythonAnywhere + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Inizia la lettura + +Complimenti, ora sei pronta! Se hai un po' di tempo prima del workshop, potrebbe essere utile cominciare a leggere i capitoli iniziali: + + * [Come funziona Internet](../how_the_internet_works/README.md) + + * [Introduzione alla riga di comando](../intro_to_command_line/README.md) + + * [Introduzione a Python](../intro_to_command_line/README.md) + + * [Che cos'è Django?](../django/README.md) diff --git a/it/intro_to_command_line/README.md b/it/intro_to_command_line/README.md new file mode 100644 index 00000000000..fd63b8bfca7 --- /dev/null +++ b/it/intro_to_command_line/README.md @@ -0,0 +1,279 @@ +# Introduzione alla linea di comando + +Eccitante, vero? Scriverai la tua prima riga di codice in pochi minuti :) + +**Ti presentiamo il tuo primo nuovo amico: la linea di comando!** + +I prossimi passaggi ti mostreranno come utilizzare quella 'finestra nera' che tutti gli hacker utilizzano. Ti potrà sembrare un po' allarmante all'inizio, ma è solamente un prompt in attesa dei tuoi comandi. + +> **Nota** Nota bene: in tutto questo tutorial usiamo sia il termine 'directory' che 'cartella' ma sono la stessa cosa. + +## Cos'è la command line? + +La finestra solitamente chiamata **comand-line** o **interfaccia della command-line**, è un'applicazione basata su testo che ti permette di visualizzare, gestire e manipolare i file sul tuo computer. Molto simile a Windows Explorer o al Finder su Mac, ma senza l'interfaccia grafica. Altri nomi per la command line sono: *cmd*, *CLI*, *prompt*, *console* o *terminal*. + +## Aprire l'interfaccia di command-line + +Per cominciare a sperimentare dobbiamo aprire l'interfaccia della nostra command-line. + +### Windows + +Vai a menù Start → tutti i programmi → accessori → prompt dei comandi. + +### Mac OS X + +Applicazioni → utilità → terminal. + +### Linux + +Probabilmente è sotto Applicazioni → Accessori → Terminal, ma quello potrebbe dipendere dal tuo sistema. Se non è lì cercalo su Google :) + +## Prompt + +Ora dovresti essere in grado di vedere una finestra bianca o nera che è in attesa di ricevere un comando. + +Se sei su Mac o Linux, probabilmente vedi `$`, proprio come questo: + + $ + + +Su Windows, è un segno `>`, come questo: + + > + + +Ogni comando sarà preceduto da questo simbolo e da uno spazio, ma tu non hai bisogno di digitarlo. Il computer lo farà per te :) + +> Solo una piccola nota: nel tuo caso ci dovrebbe essere qualcosa come `C:\Users\ola>` oppure `Olas-MacBook-Air:~ ola$` prima del segno di prompt. È corretto al 100%. In questo tutorial lo semplificheremo al massimo. + +## Il tuo primo comando (YAY!) + +Cominciamo con qualcosa di veramente semplice. Digita questo comando: + + $ whoami + + +oppure + + > whoami + + +Premi `invio`. Questo è il nostro risultato: + + $ whoami + olasitarska + + +Come puoi vedere, il computer ha appena stampato il tuo nome utente. Bello, eh?:) + +> Prova a digitare ogni comando, non copiare ed incollare. Ti ricorderai di più in questo modo! + +## Nozioni di base + +Ogni sistema operativo ha un insieme di comandi leggermente diverso per la command line, per cui assicurati di seguire le istruzioni per il tuo sistema operativo. Proviamo questo, ti va? + +### Cartella corrente + +Sarebbe bello sapere dove siamo adesso, vero? Vediamo. Digita questo commando e premi `invio`: + + $ pwd + /Users/olasitarska + + +Se sei su Windows: + + > cd + C:\Users\olasitarska + + +Probabilmente vedrai qualcosa di simile sul tuo computer. Quando apri la command-line normalmente inizi sulla tua directory home. + +> Nota: 'pwd' sta per 'stampa directory di lavoro'. + +* * * + +### Elenco di file e cartelle + +Cosa c'è dentro? Sarebbe bello scoprirlo. Vediamo come: + + $ ls + Applications + Desktop + Downloads + Music + ... + + +Windows: + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### Cambiare cartella corrente + +Ora, andiamo nella nostra directory Desktop: + + $ cd Desktop + + +Windows: + + > cd Desktop + + +Controlla ora se ti sei veramente spostato/a: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Ecco fatto! + +> Suggerimento PRO: se digiti `cd D` e poi premi `tab` sulla tastiera, la command-line completerà automaticamente il resto del nome per cui puoi navigare più velocemente. Se c'è più di una cartella che comincia con "D", premi `tab` due volte per ottenere la lista con tutte le opzioni. + +* * * + +### Creare una directory + +Che ne dici di creare una directory di pratica sul tuo desktop? Puoi farlo in questo modo: + + $ mkdir practice + + +Windows: + + > mkdir practice + + +Questo breve comando creerà una cartella con il nome `practice` sul tuo desktop. Puoi controllare se è lì semplicemente guardando sul tuo desktop oppure eseguendo un commando `ls` oppure `dir`! Provalo :) + +> Suggerimento PRO: se non vuoi digitare lo stesso comando tutte le volte, prova a premere ` freccia in su ` e `freccia in giù` sulla tua tastiera per scorrere tutti i comandi che hai usato fin ora. + +* * * + +### Esercizio! + +Piccola sfida per te: nella tua directory appena creata `practice` crea una directory chiamata `test`. usa i comandi `cd` e `mkdir`. + +#### Soluzione: + + $ cd practice + $ mkdir test + $ ls + test + + +Windows: + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + +Congratulazioni! :) + +* * * + +### Facciamo ordine + +Non vogliamo lasciare un pasticcio, per cui rimuoviamo tutto quello che abbiamo fatto fino a questo punto. + +Per prima cosa dobbiamo tornare al Desktop: + + $ cd .. + + +Windows: + + > cd .. + + +Usando `..` con il comando `cd` cambierai la tua directory attuale alla directory padre (si tratta della cartella che contiene la tua directory attuale). + +Controlla dove ti trovi ora: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Adesso è l'ora di cancellare la directory `practice`: + +> **Attenzione**: cancellare un file usando `del`, `rmdir` o `rm` è irreversibile, *i file cancellati andranno perduti per sempre*! Per cui sii molto prudente nell'utilizzare questi comandi. + + $ rm -r practice + + +Windows: + + > rmdir /S practice + practice, Are you sure ? Y + + +Fatto! Per essere sicuri che sia stato effettivamente cancellato, controlliamo: + + $ ls + + +Windows: + + > dir + + +### Uscire dalla command line + +Questo è tutto per ora! puoi tranquillamente chiudere la tua command line. Facciamolo alla maniera degli hacker, va bene?:) + + $ exit + + +Windows: + + > exit + + +Figo, eh?:) + +## Indice + +Questo è un riepilogo di alcuni comandi utili: + +| Comandi(Windows) | Comandi (Mac OS / Linux) | Descrizione | Esempio | +| ---------------- | ------------------------ | --------------------------- | ------------------------------------------------- | +| exit | exit | chiudi la finestra | **exit** | +| cd | cd | cambiare directory | **cd test** | +| dir | ls | elenco directory/file | **dir** | +| copy | cp | copia un file | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | spostare un file | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | creare una nuova directory | **mkdir testdirectory** | +| del | rm | eliminare un file/directory | **del c:\test\test.txt** | + +Questi sono solo alcuni dei comandi che puoi eseguire sulla tua command line, ma non ne userai altri oltre a quelli spiegati oggi. + +Se sei curioso/a, [ss64.com][1] contiene una guida completa ai comandi per tutti i sistemi operativi. + + [1]: http://ss64.com + +## Fatto? + +Tuffiamoci in Python! diff --git a/it/python_installation/README.md b/it/python_installation/README.md new file mode 100644 index 00000000000..bb131b68683 --- /dev/null +++ b/it/python_installation/README.md @@ -0,0 +1,13 @@ +# Iniziamo con Python + +Finalmente siamo qui! + +Ma prima, permettici di introdurre brevemente cos'è Python. Python è un linguaggio di programmazione molto popolare che può essere utilizzato per creare siti web, giochi, sofware scientifici, grafici e molto, molto altro. + +Python ha avuto origine alla fine degli anni '80 ed il suo obiettivo principale è quello di essere leggibile dagli esseri umani (non solo dalle macchine!). Per questo motivo sembra molto più semplice di altri linguaggi di programmazione. Questo lo rende facile da imparare, ma non ti preoccupare, Python è anche molto potente! + +# Installazione di Python + +> **Nota** Se hai fatto la procedura di installazione, non c'è bisogno di farlo di nuovo - puoi saltare dritto/a al prossimo capitolo! + +{% include "/python_installation/instructions.md" %} diff --git a/it/python_installation/images/add_python_to_windows_path.png b/it/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/it/python_installation/images/add_python_to_windows_path.png differ diff --git a/it/python_installation/instructions.md b/it/python_installation/instructions.md new file mode 100644 index 00000000000..c7db277b102 --- /dev/null +++ b/it/python_installation/instructions.md @@ -0,0 +1,66 @@ +> Questa sezione si basa su un tutorial fatto da Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django è scritto in Python. Abbiamo bisogno di Python per fare qualsiasi cosa in Django. Iniziamo con l'installazione! Vogliamo che sul tuo pc sia installato Python 3.4 quindi se hai una versione precedente, dovrai aggiornarlo. + +### Windows + +Puoi scaricare Python per Windows dal sito web https://www.python.org/downloads/release/python-343/. Dopo aver scaricato il file ***.msi**, lo dovresti eseguire (cliccaci sopra due volte) e segui le istruzioni. È importante ricordare il percorso (la directory) dove ha installato Python. Più tardi sarà necessario! + +Una cosa a cui fare attenzione: sulla seconda schermata dell'installazione guidata, contrassegnata "Customize", assicurati di scorrere verso il basso e di scegliere l'opzione "Add python.exe to the Path", come illustrato qui: + +![Non dimenticare di aggiungere Python al Path](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +È molto probabile che tu abbia Python già installato di default. Per controllare se ce l'hai già installato (e quale versione è), apri una console e digita il seguente comando: + + $ python3 --version + Python 3.4.3 + + +Se non hai Python installato o se vuoi una versione diversa, puoi installarla come segue: + +#### Debian o Ubuntu + +Digita questo comando nella tua console: + + $ sudo apt-get install python3.4 + + +#### Fedora (fino a 21) + +Usa questo comando nella tua console: + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +Usa questo comando nella tua console: + + $ sudo dnf install python3.4 + + +#### openSUSE + +Usa questo comando nella tua console: + + $ sudo zypper install python3 + + +### OS X + +Devi andare sul sito https://www.python.org/downloads/release/python-343/ e scarica il programma d'installazione di Python: + + * Scarica il file *Mac OS X 64-bit/32-bit installer* + * Fai doppio click su *python-3.4.3-macosx10.6.pkg* per eseguire il programma d'installazione. + +Verifica che l'installazione si sia conclusa correttamente aprendo l'applicazione *Terminal* ed eseguendo il comando `python3`: + + $ python3 --version + Python 3.4.3 + + +* * * + +Se hai dubbi o se qualcosa è andato storto e non hai idea di cosa fare dopo - chiedi al tuo insegnante! A volte le cose non vanno come dovrebbero ed è meglio chiedere aiuto a qualcuno con più esperienza. diff --git a/it/python_introduction/README.md b/it/python_introduction/README.md new file mode 100644 index 00000000000..de4f582efea --- /dev/null +++ b/it/python_introduction/README.md @@ -0,0 +1,789 @@ +# Introduzione a Python + +> Parte di questo capitolo è basato su esercitazioni di Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Scriviamo un pò codice! + +## La linea di comando di Python + +Per iniziare a giocare con Python, devi avviare sul tuo computer una *linea di comando*. Dovresti già sapere come farlo -- l'hai imparato nel capitolo [Introduzione a Command Line][1]. + + [1]: ../intro_to_command_line/README.md + +Una volta pronta, segui le istruzioni riportate di seguito. + +Vogliamo aprire una console Python, quindi digita `python` su Windows o `python3` su Mac OS/Linux e premi `invio`. + + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Il tuo primo comando Python! + +Dopo aver eseguito il comando Python, il prompt è cambiato in `>>>`. Significa che per ora dovremmo utilizzare comandi nel linguaggio Python. Non devi digitare `>>>` - Python lo farà per te. + +Se ad un certo punto vuoi uscire dalla console di Python, digita `exit()` oppure usa la scorciatoia `Ctrl + Z` per Windows e `Ctrl + D` per Mac/Linux. Allora non vedrai più `>>>`. + +Per ora non vogliamo uscire dalla console Python. Vogliamo saperne di più. Cominciamo con qualcosa davvero semplice. Per esempio, prova un po' di matematica, come `2 + 3` e premi `invio`. + + >>> 2 + 3 + 5 + + +Fantastico! Hai visto come è comparsa la risposta? Python conosce la matematica! potresti provare altri comandi come: - `4 * 5` - `5 - 1` - `40 / 2` + +Divertiti con questo per un pò e dopo torna qui :). + +Come puoi vedere, Python è una buona calcolatrice. Ora ti starai sicuramente chiedendo cos'altro è capace di fare... + +## Stringhe + +Che ne dici di scrivere il tuo nome? Digitalo tra virgolette così: + + >>> "Ola" + 'Ola' + + +Hai appena creato la tua prima stringa! Una stringa è una sequenza di caratteri che possono essere elaborati da un computer. La stringa deve sempre iniziare e finire con lo stesso carattere. Che può essere una virgoletta semplice (`'`) o doppia (`"`) (non c'è differenza!) Le virgolette dicono a Python che il contenuto al loro interno è una stringa. + +Le stringhe possono essere legate assieme. Prova questo: + + >>> " Ciao " + "Ola" + 'Ciao Ola' + + +Puoi anche moltiplicare le stringhe con un numero: + + >>> "Ola" * 3 + 'OlaOlaOla' + + +Se devi mettere un apostrofo nella tua stringa, hai due modi per farlo. + +Utilizzando le virgolette doppie: + + >>> "Correre verso l'albero" + "Correre verso l'albero" + + +o facendo l'escape dell'apostrofo (cioè trattandolo come un carattere qualunque) con una barra rovesciata ( \ ): + + >>> 'Correre verso l\'albero' + "Correre verso l'albero" + + +Bello, eh? Per vedere il tuo nome in maiuscolo, digita: + + >>> "Ola".upper() + 'OLA' + + +Hai appena usato la funzione `upper` sulla tua stringa! Una funzione (come `upper()`) è una sequenza di istruzioni che Python deve eseguire su un determinato oggetto (`"Ola"`). + +Se vuoi sapere il numero delle lettere presenti nel tuo nome, c'è una funzione anche per quello! + + >>> len("Ola") + 3 + + +Ti stai chiedendo perché certe volte chiami una funzione con un `.` alla fine di una stringa (come `"Ola".upper()`) ed in altri casi chiami prima una funzione e poi metti la stringa tra parentesi? Beh, in alcuni casi, le funzioni appartengono ad oggetti, come `upper()`, che può essere eseguita solo su stringhe. In questo caso, chiamiamo la funzione **metodo**. Altre volte, le funzioni non appartengono a niente di specifico e possono essere utilizzate su diversi tipi di oggetti, proprio come `len()`. Ecco perché stiamo dando `"Ola"` come un parametro alla funzione `len`. + +### Indice + +OK, basta con le stringhe. Ecco fino ad ora quanto hai imparato: + +* **il prompt** - digitare i comandi (codice) nel prompt di Python restituisce risposte in Python +* **numeri e stringhe** - in Python i numeri vengono utilizzati per la matematica e le stringhe per oggetti testuali +* **operatori** - come + e *, combinano i valori per produrne di nuovi +* **funzioni** - come upper() e len(), eseguono azioni su oggetti. + +Queste sono le basi di ogni linguaggio di programmazione che impari. Pronta per qualcosa di più complicato? Scommetto che lo sei! + +## Errori + +Proviamo qualcosa di nuovo. Possiamo ottenere la lunghezza di un numero nella stessa forma in cui abbiamo potuto scoprire la lunghezza del nostro nome? Digita `len(304023)` e premi `Invio`: + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +Abbiamo ottenuto il nostro primo errore! Ci dice che gli oggetti di tipo "int" (integers, numeri interi) non hanno lunghezza. Quindi cosa possiamo fare? Forse possiamo scrivere il nostro numero come una stringa? Le stringhe hanno una lunghezza, vero? + + >>> len(str(304023)) + 6 + + +Ha funzionato! Usiamo la funzione `str` all'interno della funzione `len`. `str()` converte tutto in stringhe. + +* La funzione `str` converte le cose in **stringhe** +* La funzione `int` converte le cose in **numeri interi** + +> Importante: possiamo convertire i numeri in testo, ma non possiamo convertire il testo in numeri - cosa potrebbe essere `int('hello')`? + +## Variabili + +Un concetto importante nella programmazione è quello delle variabili. Una variabile è un nome per un qualcosa che deve essere utilizzato sucessivamente. I programmatori usano queste variabili per archiviare dati, rendere il loro codice più leggibile e per non dover tenere a mente cosa sono queste cose. + +Diciamo che vogliamo creare una nuova variabile chiamata `nome`: + + >>> nome = "Ola" + + +Vedi? È facile! è semplicemente: nome è uguale a Ola. + +Come avrai notato, il programma non ha ritornato nulla, diversamente da prima. Quindi come facciamo a sapere che la variabile esiste? Digita `nome` e premi `enter`: + + >>> nome + 'Ola' + + +Evvai! La tua prima variabile :)! Puoi sempre modificare a cosa si riferisce: + + >>> nome = "Sonja" + >>> nome + 'Sonja' + + +La puoi utilizzare anche nelle funzioni: + + >>> len(nome) + 5 + + +Fantastico, vero? Certo, le variabile possono essere qualsiasi cosa, così come i numeri! Prova questo: + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +Ma cosa succede se utilizziamo il nome sbagliato? Riesci a immaginare cosa succederebbe? Proviamo! + + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + + +Un errore! Come puoi vedere, Python ha diversi tipi di errori e questo qui si chiama **NameError**. Python ti darà questo errore se provi ad utilizzare una variabile che non è stata ancora definita. Se incontri questo errore più tardi, controlla il tuo codice per vedere se hai digitato in modo errato i nomi. + +Giocaci per un po' e vedi cosa puoi fare! + +## La funzione print + +Prova questo: + + >>> nome = 'Maria' + >>> nome + 'Maria' + >>> print(nome) + Maria + + +Quando digiti `nome`, l'interprete di Python risponde con una stringa *rappresentazione* della variabile 'nome', che contiene le lettere M-a-r-i-a, circondate da singole virgolette, ''. Quando dici `print(nome)`, Python "stamperà" i contenuti della variabile sullo schermo, senza le virgolette, che è più pulito. + +Come vedremo dopo, `print()` è anche utile quando vogliamo stampare le cose dall'interno delle funzioni, oppure quando vogliamo stampare le cose in molteplici righe. + +## Liste + +Oltre alle stringhe ed ai numeri interi, Python ha tanti tipi di oggetti. Ora ne introdurremo uno chiamato **lista**. Le liste sono fatte proprio come immagini: sono oggetti che sono liste di altri oggetti :) + +Vai avanti e crea una lista: + + >>> [] + [] + + +Si, questa lista è vuota. Non serve a molto, giusto? Creiamo una lista di numeri della lotteria. Non vogliamo ripetere tutto ogni volta, quindi metteremo la lista in una variabile: + + >>> lotteria = [3, 42, 12, 19, 30, 59] + + +Abbiamo una lista! Cosa possiamo farne? Vediamo quanti numeri della lotteria ci sono nella lista. Hai idea di quale funzione potresti utilizzare per farlo? Lo abbiamo imparato insieme prima! + + >>> len(lotteria) + 6 + + +Si! `len()` può darti il numero di oggetti in una lista. Utile, vero? Forse abbiamo risolto: + + >>> lotteria.sort() + + +Questo comando non dà nessun risultato, ha semplicemente cambiato l'ordine in cui i numeri appaiono nella lista. Stampiamo di nuovo la lista per vedere cosa è successo: + + >>> print(lotteria) + [3, 12, 19, 30, 42, 59] + + +Come puoi vedere, adesso i numeri nella tua lista sono ordinati dal valore più basso a quello più alto. Congratulazioni! + +Vogliamo invertire quell'ordine? Facciamolo! + + >>> lotteria.reverse() + >>> print(lotteria) + [59, 42, 30, 19, 12, 3] + + +Facile, vero? Se vuoi aggiungere qualcosa alla tua lista, puoi farlo digitando questo comando: + + >>> lotteria.append(199) + >>> print(lotteria) + [59, 42, 30, 19, 12, 3, 199] + + +Se vuoi mostrare solo il primo numero, puoi farlo usando gli **indici**. L'indice è il numero che dice la posizione esatta dell'elemento all'interno di una lista. I programmatori preferiscono iniziare a contare da 0, quindi il primo oggetto nella lista è all'indice 0, il successivo all'1, e così via. Prova questo: + + >>> print(lotteria[0]) + 59 + >>> print(lotteria[1]) + 42 + + +Come puoi vedere, puoi accedere a diversi oggetti nella tua lista usando il nome della lista e l'indice dell'oggetto all'interno delle parentesi quadre. + +Per eliminare qualcosa dalla lista dovrai usare **indexes** come abbiamo visto sopra, e lo statement `pop()`. Proviamo a fare qualcosa per rafforzare quanto imparato prima; elimineremo il primo numero della lista. + + >>> print(lotteria) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lotteria[0]) + 59 + >>> lotteria.pop(0) + >>> print(lotteria) + [42, 30, 19, 12, 3, 199] + + +Ha funzionato a meraviglia! + +Prova altri indici: 6, 7, 1000, -1, -6 o -1000. Prova a prevedere il risultato ancora prima di eseguire il comando. Hanno senso i risultati? + +Per saperne di più su i metodi disponibili per le liste puoi consultare questo capitolo della documentazione Python: https://docs.python.org/3/tutorial/datastructures.html + +## Dizionari + +Un dizionario (dictionary) è simile a una lista, ma accedi ai valori cercando una chiave invece di un indice. Una chiave può essere qualsiasi stringa o numero. La sintassi per definire un dizionario vuoto è: + + >>> {} + {} + + +Questo dimostra che hai appena creato un dizionario vuoto. Evviva! + +Ora, prova a scrivere il seguente comando (prova a sostituirlo con le tue informazioni): + + >>> partecipante = {'nome': 'Ola', 'paese': 'Polonia', 'numeri_preferiti': [7, 42, 92]} + + +Con questo comando hai appena creato una variabile chiamata `partecipante` con tre coppie di chiavi-valori: + +* La chiave `nome` va a indicare il valore `'Ola'` (un oggetto `stringa`), +* `paese` indica `'Polonia'` (un'altra `stringa`), +* e `numeri_preferiti` indica `[7, 42, 92]` (una `lista` con tre numeri al suo interno). + +Puoi controllare il contenuto di chiavi individuali con questa sintassi: + + >>> print(partecipante['nome']) + Ola + + +Vedi, assomiglia ad una lista. Ma non devi ricordare l'indice - solo il nome. + +Cosa succede se chiediamo a Python il valore di una chiave che non esiste? Riesci a indovinarlo? Proviamo! + + >>> partecipante['età'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'età' + + +Guarda, un altro errore! Questo qua è un **KeyError**. Python è utile e ti dice che la chiave `'età'` non esiste in questo dizionario. + +Quando usare un dizionario o una lista? Bella domanda. Prova a formulare una soluzione mentalmente prima di vedere la risposta nella prossima riga. + +* Ha bisogno di una sequenza ordinata di elementi? Fai una lista. +* Hai bisogno di associare i valori alle chiavi, così che potrai cercarle agilmente (per chiave) dopo? Usa un dizionario. + +I dizionari, come le liste, sono *mutable*, significa che possono essere cambiati dopo che sono stati creati. Si possono aggiugere nuove coppie chiave/valore ad un dizionario dopo averlo creato: + + >>> partecipante['linguaggio_preferito'] = 'Python' + + +Così come succede se applicato alle liste, il metodo `len()` restituisce il numero di coppie chiave/valore anche quando applicato a un dizionario. Vai e digita il comando: + + >>> len(partecipante) + 4 + + +Spero che abbia senso per te. :) Pronta per divertirti con i dizionari? Vai alla prossima riga per realizzare altre cose fantastiche. + +Puoi usare il comando `pop()` per cancellare un elemento nella directory. Se vuoi cancellare la voce che corrisponde alla chiave `'numeri_preferiti'`, digita il seguente comando: + + >>> partecipante.pop('numeri_preferiti') + >>> partecipante + {'paese': 'Polonia', 'linguaggio_preferito': 'Python', 'nome': 'Ola'} + + +Come puoi vedere dall'output, la coppia chiave-valore corrispondente alla chiave 'numeri_preferiti' è stato cancellata. + +Puoi anche cambiare un valore associato ad una chiave già creata nel dizionario. Digita: + + >>> partecipante['paese'] = 'Germania' + >>> partecipante + {'paese': 'Germania', 'linguaggio_preferito': 'Python', 'nome': 'Ola'} + + +Come puoi vedere, il valore della chiave `'paese'` è stato cambiato da `'Polonia'` a `'Germania'`. :) Eccitante, vero? Evviva! Hai già imparato un'altra cosa fantastica. + +### Indice + +Fantastico! ora sai molto sulla programmazione. In questa ultima parte hai imparato: + +* **errori** - ora sai come leggere e capire gli errori che appaiono se Python non comprende un comando che gli hai dato +* **variabili** - nomi per oggetti. Ti permettono di scrivere codice più semplice e di renderlo più leggibile +* **liste** - liste di oggetti archiviati in un ordine particolare +* **dizionari** - oggetti archiviati come coppie di chiave-valore + +Sei emozionato/a per la prossima parte? :) + +## Confrontare le cose + +Larga parte della programmazione include il confrontare le cose. Qual è la cosa più semplice da confrontare? I numeri, senza dubbio. Vediamo come funziona: + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + + +Abbiamo dato a Python alcuni numeri da mettere a confronto. Come puoi vedere, Python può mettere a confronto non solo numeri, ma anche i risultati dei metodi. Forte, eh? + +Ti sei chiesta perché abbiamo messo due simboli di uguale `==` uno vicino all'altro per confrontare i numeri? Usiamo un singolo `=` per assegnare valori alle variabili. Sempre, **sempre** devi mettere due `==` se vuoi controllare se le cose sono uguali. Possiamo affermare anche che le cose sono diverse tra di loro. Per dirlo, usiamo il simbolo `!=`, come mostrato nell'esempio sopra. + +Dai a Python altri due compiti: + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +`>` e `<` sono facili, ma cosa significano `>=` e `<=`? Leggili così: + +* x `>` y significa: x è maggiore di y +* x `<` y significa: x è minore di y +* x `<=` y significa: x è minore o uguale a y +* x `>=` y significa: x è maggiore o uguale a y + +Fantastico! Vuoi farne due o tre? prova questo: + + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + + +Puoi dare a Python tutti i numeri da confrontare che vuoi, ti darà sempre una risposta! Molto intelligente, vero? + +* **and** - se usi l'operatore `e`, entrambe le cose confrontate devono essere True in modo tale che l'intero comando sia True +* **or** - se usi l'operatore `o`, solo una delle cose messe a confronto deve essere True in modo tale che l'intero comando sia True + +Hai sentito parlare dell'espressione "comparare mele e arance"? Proviamo l'equivalente in Python: + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +Dall'espressione puoi capire che Python non è in grado di mettere a confronto un numero (`int`) e una stringa (`str`). Ci mostra invece un **TypeError** e ci dice che i due tipi non possono essere messi a confronto. + +## Booleano + +Accidentalmente, hai appena imparato un nuovo tipo di oggetto in Python. Si chiama **Boolean** e probabilmente è il tipo più facile che ci sia. + +Ci sono solo due oggetti Boolean: +- True +- False + +Ma perché Python possa capirlo, bisogna sempre scrivere True (prima lettera maiuscola, le altre minuscole). **true, TRUE, tRUE non funzionano -- solo True è corretto.** (Lo stesso vale per False, ovviamente.) + +I Boolean possono anche essere variabili! Guarda qui: + + >>> a = True + >>> a + True + + +Lo puoi fare anche in questa forma: + + >>> a = 2 > 5 + >>> a + False + + +Fai pratica e divertiti con i Boolean provando ad eseguire i seguenti comandi: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Congratulazioni! I valori Boolean sono tra le cose più interessanti della programmazione e tu hai appena imparato ad utilizzarli! + +# Salvalo! + +Finora abbiamo scritto il codice python nell'interprete, che ci permette di inserire una linea di codice per volta. I programmi vengono salvati in file ed eseguiti dall'**interpreter** del nostro linguaggio di programmazione o dal **compiler**. Fino ad ora abbiamo eseguito i nostri programmi una riga per volta nell' **interprete** di Python. Avremo bisogno di più di una riga di codice per i prossimi compiti, quindi dovremo fare queste cose velocemente: + +* Uscire dall'interprete di Python +* Aprire l'editor di codice che abbiamo scelto +* Salvare un po' di codice in un file python +* Eseguirlo! + +Per uscire dall'interprete di Python che è quello che stavamo utilizzando, digita la funzione ```exit()``` : + + >>> exit() + $ + + +Questo ti immetterà nel prompt dei comandi. + +Prima, abbiamo preso un editore di codice dalla sezione [code editor][2]. Dovremo aprire l'editor ora e scrivere un po' di codice in un nuovo file: + + [2]: ../code_editor/README.md + +```python +print('Ciao, Django girls!') +``` + +> **Nota** Dovresti notare una delle cose più belle degli editori di codice: i colori! Nella console Python ogni cosa era dello stesso colore, mentre ora dovresti visualizzare la funzione `print` di un colore differente rispetto alla stringa che la segue. Questa viene chiamata "sintassi evidenziata", ed è veramente utile quando si scrive codice. Il colore serve come suggerimento, ad esempio per una stringa che non è chiusa, o un errore di digitazione di una keyword (come la `def` per le funzioni, che vedremo più avanti). Questo è uno dei motivi per cui usiamo un editor di codice :) + +Ovviamente a questo punto sei una programmatrice Python senior, quindi sentiti libera di scrivere un po' del codice che hai imparato oggi. + +Ora dobbiamo salvare il file e dargli un nome descrittivo. Chiama il file **python_intro.py** e salvalo sulla tua scrivania. Puoi chiamare il file come vuoi, ma è importante assicurarsi che finisca con **.py**. L'estensione **.py** dice al Sistema Operativo che questo è un **file eseguibile python** e che Python può eseguirlo. + +È ora di eseguire il file! Usando le nozioni che hai imparato nella sezione command line, usa il terminal per **cambiare cartella** alla scrivania. + +Su un Mac, il comando assomiglierà a questo: + + $ cd /Users//Desktop + + +Su Linux, sarà come questo (la parola "Desktop" potrebbe essere tradotta nella tua lingua): + + $ cd /home//Desktop + + +E su windows, sara come questo: + + > cd C:\Users\\Desktop + + +Se rimani bloccata, chiedi aiuto. + +Ora usa Python per eseguire il codice nel file: + + $ python3 python_intro.py + Ciao, Django girls! + + +Perfetto! Hai appena eseguito il tuo primo programma Python salvato su un file. Grande, no? + +Ora puoi continuare con uno strumento essenziale nella programmazione: + +## If...elif...else + +Molte cose dovrebbero essere eseguite soltanto quando si incontrano certe condizioni. È per questo che Python ha gli **if statements**. + +Sostituisci il codice nel file **python_intro.py** con questo: + +```python +if 3 > 2: +``` + +Se salviamo questo codice e lo eseguiamo, incontriamo un errore come questo: + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python si aspetta che gli vengano fornite ulteriori istruzioni che saranno eseguite se la condizione `3 > 2` risulterà vera (o `True` se vogliamo). Proviamo a fare in modo che Python stampi "Funziona!". Modifica il tuo codice nel tuo file **python_intro.py** con questo: + +```python +if 3 > 2: + print('Funziona!') +``` + +Vedi come abbiamo indentato la riga successiva usando 4 spazi? Si deve fare così in modo tale che Python sappia quale codice eseguire se il risultato è True. Puoi fare uno spazio, ma circa tutti i programmatori di Python ne fanno 4 per far vedere le cose più ordinate. Anche un signolo `tab` conta come 4 spazi. + +Salvalo ed eseguilo di nuovo: + + $ python3 python_intro.py + Funziona! + + +### E se una condizione non è Vera? + +In esempi precedenti, il codice è stato eseguito solo quando le condizioni erano True. Ma Python ha anche gli `elif` e `else` statements: + +```python +if 5 > 2: + print('5 è infatti maggiore di 2') +else: + print('5 non è maggiore di 2') +``` + +Quando viene lanciato, mostrerà: + + $ python3 python_intro.py + 5 è infatti maggiore di 2 + + +Se 2 fosse un numero maggiore di 5, allora andrebbe in esecuzione il secondo comando. Facile, vero? Andiamo a vedere come funziona `elif`: + +```python +nome = 'Sonja' +if nome == 'Ola': + print('Ciao Ola!') +elif nome == 'Sonja': + print('Ciao Sonja!') +else: + print('Ciao anonimo!') +``` + +ed eseguito: + + $ python3 python_intro.py + Ciao Sonja! + + +Hai visto cosa è successo? `elif` ti consente di aggiungere condizioni supplementari che verranno eseguite se nessuna delle condizioni precedenti viene soddisfatta. + +Allo statement iniziale `if` puoi far seguire tutti gli statement `elif` che vuoi. Per esempio: + +```python +volume = 57 +if volume < 20: + print("Piuttosto basso.") +elif 20 <= volume < 40: + print("Adatto per musica di sottofondo") +elif 40 <= volume < 60: + print("Perfetto, posso apprezzare ogni dettaglio") +elif 60 <= volume < 80: + print("Ideale per le feste") +elif 80 <= volume < 100: + print("Un po' altino!") +else: + print("Oddio, le mie orecchie! :(") +``` + +Python esegue ogni singolo test in sequenza e scrive: + + $ python3 python_intro.py + Perfetto, posso apprezzare ogni dettaglio + + +### Indice + +Nei tre esercizi precedenti hai imparato: + +* come **confrontare le cose** - in Python puoi mettere a confronto le cose usando `>`, `>=`, `==`, `<=`, `<` e gli operatori `e`, `o` +* i **Boolean** - una tipologia di oggetto che può avere solo uno di questi due valori: `True` o `False` +* come **Salvare file** - archiviare codice nei file in modo da poter eseguire programmi più lunghi. +* **if...elif...else** - affermazioni che ti permettono di eseguire codice solo quando vengono incontrate certe condizioni. + +È ora dell'ultima parte del capitolo! + +## Le funzioni personalizzate! + +Ti ricordi quelle funzioni che puoi eseguire in Python come `len()`? Beh, buone notizie, ora imparerai a scrivere delle funzioni tutte tue! + +Una funzione è una sequenza di istruzioni che Python dovrebbe eseguire. Ogni funzione in Python inizia con la parola chiave `def`, viene assegnato un nome e può avere alcuni parametri. Iniziamo con una facile. Sostituisci il codice nel file **python_intro.py** con il seguente: + +```python +def ciao(): + print('Ciao!') + print('Come stai?') + +ciao() +``` + +Okay, la nostra prima funzione è pronta! + +Ti starai chiedendo perché abbiamo scritto il nome della funzione alla fine del file. Perché Python legge il file e lo esegue dall'alto verso il basso. Quindi per poter utilizzare la nostra funzione, dobbiamo riscriverla alla fine. + +Eseguiamolo e vediamo cosa succede: + + $ python3 python_intro.py + Ciao! + Come stai? + + +È stato facile! Costruiamo la nostra prima funzione con parametri. Useremo l'esempio precedente - una funzione che dice 'ciao' alla persona che lo esegue - aggiungendo il nome: + +```python +def ciao(nome): +``` + +Come puoi vedere, abbiamo dato alla nostra funzione un parametro chiamato `nome`: + +```python +def ciao(nome): + if nome == 'Ola': + print('Ciao Ola!') + elif nome == 'Sonja': + print('Ciao Sonja!') + else: + print('Ciao anonimo!') + +ciao() +``` + +Ricorda: La funzione `print` è rientrata di 4 spazi rispetto allo statement `if`. Infatti, la funzione viene eseguita quando la condizione viene soddisfatta. Vediamo ora come funziona: + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + ciao() + TypeError: ciao() missing 1 required positional argument: 'nome' + + +Ops, un errore. Fortunatamente, Python ci fornisce un messaggio di errore che ci può servire. Ci dice che la funzione `ciao()` (quella che abbiamo definito) ha un argomento richiesto (chiamato `nome`) e che ci siamo dimenticati di metterlo quando abbiamo chiamato la funzione. Sistemiamolo alla fine del file: + +```python +ciao("Ola") +``` + +Ed eseguiamo di nuovo: + + $ python3 python_intro.py + Ciao Ola! + + +E se cambiamo il nome? + +```python +ciao("Sonja") +``` + +Ed eseguilo: + + $ python3 python_intro.py + Ciao Sonja! + + +Ora, cosa pensi che succederà se scrivi un altro nome? (non Ola o Sonja) Provaci e vedi se la tua ipotesi è giusta. Dovrebbe stampare questo: + + Ciao anonimo! + + +Fantastico, vero? In questo modo non devi ripetere tutto ogni volta che vuoi modificare il nome della persona che la funzione dovrebbe salutare. Ed è esattamente per questo che abbiamo bisogno delle funzioni - non vuoi ripetere il tuo codice! + +Facciamo una cosa più intelligente -- ci sono più di due nomi, e scrivere una condizione per ognuno sarebbe complicato, vero? + +```python +def ciao(nome): + print('Ciao ' + nome + '!') + +ciao("Rachel") +``` + +Ora chiamiamo il codice: + + $ python3 python_intro.py + Ciao Rachel! + + +Congratulazioni! Hai appena imparato a scrivere delle funzioni :) + +## Loop + +È l'ultima parte. Abbiamo fatto in fretta, vero? :) + +I programmatori non amano ripetere ciò che scrivono. La programmazione mira a automatizzare le cose, non vorremo mica salutare ognuno col suo nome manualmente? Ecco un caso in cui i loop ci tornano comodi. + +Ti ricordi ancora delle liste? Facciamo una lista di ragazze: + +```python +ragazze = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Tu'] +``` + +Vogliamo salutare tutte loro per nome. Abbiamo la funzione `ciao` per farlo, quindi usiamola in loop: + +```python +for nome in ragazze: +``` + +Lo statement `for` si comporta in modo simile allo statement `if`; il codice sottostante deve essere rientrato di quattro spazi. + +Qua c'è l'intero codice che sarà nel file: + +```python +def ciao(nome): + print('Ciao ' + nome + '!') + +ragazze = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Tu'] +for nome in ragazze: + ciao(nome) + print('Prossima ragazza') +``` + +E quando lo eseguiamo: + + $ python3 python_intro.py + Ciao Rachel! + Prossima ragazza + Ciao Monica! + Prossima ragazza + Ciao Phoebe! + Prossima ragazza + Ciao Ola! + Prossima ragazza + Ciao You! + Prossima ragazza + + +Come puoi vedere, tutto quello che metti all'interno di un `for` statement con una spaziatura si ripeterà per ogni elemento della lista `girls`. + +Puoi anche utilizzare `for` su numeri usando la funzione `range`: + +```python +for i in range(1, 6): + print(i) +``` + +Che stamperà: + + 1 + 2 + 3 + 4 + 5 + + +`range` è una funzione che crea una lista di numeri che si seguono uno dopo l'altro (questi numeri vengono forniti da te come parametri). + +Nota che il secondo di questi due numeri non è incluso nella lista prodotta da Python ( ciò significa che `range(1, 6)` conta da 1 a 5, ma non include il numero 6). Questo perché "range" è mezzo-aperto e con ciò intendiamo che include il primo valore, man non l'ultimo. + +## Indice + +È tutto. **Sei grande!** Questo capitolo non era affatto facile, puoi essere orgogliosa di te stessa. Noi siamo fierissimi di te per avercela fatta fino a qui! + +Potresti desiderare di fare brevemente qualcos'altro - stiracchiati, fai due passi, riposa gli occhi - prima di continuare con il prossimo capitolo. :) + +![Cupcake](images/cupcake.png) diff --git a/it/python_introduction/images/cupcake.png b/it/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/it/python_introduction/images/cupcake.png differ diff --git a/it/template_extending/README.md b/it/template_extending/README.md new file mode 100644 index 00000000000..6ceef47e2db --- /dev/null +++ b/it/template_extending/README.md @@ -0,0 +1,123 @@ +# Estendere il template + +Un'altra cosa bella di Django è l'**estensione del template**. Cosa significa? Significa che puoi usare le stesse parti del tuo HTML per pagine diverse del tuo sito. + +Così non hai bisogno di ripetere le stesse informazioni/layout in ogni file. E se vuoi cambiare qualcosa, non devi cambiarlo in ogni templates, ma soltanto una volta! + +## Crea un template di base + +Un template base è il template più semplice. Lo puoi estendere su ogni pagina del tuo sito. + +Creiamo un file `base.html` in `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +Poi aprilo e copia tutto da `post_list.html` e incollalo sul file `base.html`, così: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Poi nel `base.html`, rimpiazza tutto il tuo `` (tutto quello che si trova tra `` e ``) con questo: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +Abbiamo praticamente rimpiazzato tutto quello tra `{% for post in posts %}{% endfor %}` con: + +```html +{% block content %} +{% endblock %} +``` + +Che cosa significa? Che hai appena creato un `blocco`, ovvero un tag di template che ti permette di inserire l'HTML presente in questo blocco all'interno di altri template che estendono `base.html`. Ti mostreremo come farlo tra un attimo. + +Ora salvalo, e apri il tuo `blog/templates/blog/post_list.html` di nuovo. Cancella tutto quello che non è all'interno del body e poi cancella anche ``, in modo che il file appaia così: + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +Ed ora aggiungi questa riga all'inizio del file: + +```python +{% extends 'blog/base.html' %} +``` + +{% raw %}Significa che stiamo estendendo il template `base.html` in `post_list.html`. Rimane solo una cosa da fare: metti tutto (tranne la riga che abbiamo appena aggiunto) tra `{% block content %}` e `{% endblock content %}`. Come questo:{% endraw %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +È tutto! Controlla se il tuo sito sta ancora funzionando correttamente :) + +> Se hai un errore `TemplateDoesNotExists` che dice che non c'è un file `blog/base.html` e hai `runserver` in esecuzione nella console, prova a fermarlo (premendo Ctrl+C - I tasti Control e C insieme) e riavvialo mettendo in esecuzione il comando `python manage.py runserver`. \ No newline at end of file diff --git a/it/whats_next/README.md b/it/whats_next/README.md new file mode 100644 index 00000000000..2a4ea36c1a6 --- /dev/null +++ b/it/whats_next/README.md @@ -0,0 +1,39 @@ +# Quali sono le prospettive? + +Complimenti! **Sei veramente incredibile**. Siamo orgogliosi! < 3 + +### Cosa si fa ora? + +Prenditi una pausa e rilassati. Hai veramente fatto un passo da gigante. + +Dopo di che, assicurati di: + +* Seguire Django Girls su [Facebook][1] o [Twitter][2] per rimanere aggiornata + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Mi puoi consigliare ulteriori risorse? + +Si! Vai avanti e prova il nostro libro dal titolo [Django Girls Tutorial: estensioni][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Più avanti potrai provare le risorse elencate qui sotto. Sono tutte molto consigliate! +- [Django - tutorial ufficiale][4] +- [Tutorial per i nuovi Coder][5] +- [Corso Code Academy Python][6] +- [Corso Code Academy HTML & CSS][7] +- [Tutorial Django Carrots][8] +- [Il libro "Learn Python The Hard Way"][9] +- [Lezioni video "Inizia con Django"][10] +- [Il libro "Two Scoops of Django: Best Practices for Django 1.8 book"][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/ko/GLOSSARY.md b/ko/GLOSSARY.md new file mode 100755 index 00000000000..7f61177d9a9 --- /dev/null +++ b/ko/GLOSSARY.md @@ -0,0 +1,3 @@ +# 코드 에디터 + +코드 에디터는 코드를 저장하고 다시 불러올 수 있는 프로그램입니다. [코드 에디터](./code_editor/README.md) 에서 배울 수 있습니다. diff --git a/ko/README.md b/ko/README.md new file mode 100755 index 00000000000..b885d6db55c --- /dev/null +++ b/ko/README.md @@ -0,0 +1,57 @@ +# 장고 걸스 튜토리얼 (Django Girls Tutorial) + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> 이 튜토리얼은 Creative Commons Attribution-ShareAlike 4.0 International 저작권을 따르고 있습니다. 라이센스 전문은 https://creativecommons.org/licenses/by-sa/4.0/ 에서 확인하세요. + +## 번역 +이 튜토리얼은 [장고걸스서울](https://djangogirls.org/seoul) 운영진 및 코치들과 열정있는 한국인 자원 봉사자들에 의해 한국어로 번역되었습니다. 수고해주신 모든 분들에게 진심으로 감사의 말씀을 전합니다. + +번역 : [Jay Park](http://jinto.pe.kr/), [Veronique Cho](https://www.facebook.com/babygirl13xx?fref=ts), [정광윤](https://twitter.com/initialkommit), innatsu, 임정훈, 문지영, 김휘경, 송석리, 여형석, 심혜민 + +감수 : [이수진](http://sujinlee.me/), [함기훈](https://www.facebook.com/gihun.ham?fref=ts) + +## 들어가며 + +점점 기술이 중요해진 세상에 살고 있지만 '내가 뒤쳐진게 아닐까' 하는 생각이 문득 든 적이 있었나요? 그동안 웹 사이트를 어떻게 만드는지 궁긍했지만 막상 시작하기 어려웠나요? 소프트웨어라는 세상이 너무 복잡해보여 혼자서 직접 만들기엔 엄두가 나지 않았나요? + +여러분에게 반가운 소식이 있습니다! 프로그래밍은 생각만큼 어려운 것이 아니랍니다. 우리는 여러분들에게 프로그래밍이 얼마나 재미있는 것인지 알려드리고 싶어요. + +물론 이 튜토리얼을 읽기만 하면 프로그래머가 되는, 그런 기적은 일어나지 않을 거에요. 프로그래밍에 능숙해지려면 몇 달, 혹은 몇 년이나 공부하고 수련해야하죠. 그러나 프로그래밍이나 웹 사이트 제작은 생각만큼 복잡하지 않아요. 여러분이 겁먹지 않도록 조금씩 설명해 드릴 거에요. + +우리가 그랬듯이 여러분들도 프로그래밍을 사랑할 수 있게 되길 바랍니다! + +## 튜토리얼에서 무엇을 배우게 되나요? + +이 튜토리얼을 끝내면, 여러분들은 간단하고 잘 작동하는 나만의 블로그 사이트를 완성할 수 있어요. 온라인에 웹사이트를 올리는 방법도 배울 거에요. 다른 사람들도 여러분의 작품을 보게 될 거랍니다! + +우리는 아래와 같은 웹 사이트를 완성할 거에요. + +![그림 0.1][2] + + [2]: images/application.png + +> 만약 혼자 튜토리얼을 따라하다 어려움이 생겼지만 주변에 도움받을 사람이 없다면 이 곳에서 질문하세요. +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +우리는 코치와 워크샵 참가자들에게 이 곳에서 도움이 필요한 사람들을 도와달라고 요청해두었답니다! 어떤 질문이든 주저하지 말고 물어보세요! + +자, [기본적인 것부터 시작해볼까요.][3] + + [3]: ./how_the_internet_works/README.md + +## 튜토리얼에 참여하기 + +이 튜토리얼은 [DjangoGirls][4]에서 지속적으로 관리하고 있습니다. 오류를 발견하거나 튜토리얼 내용을 업데이트하고 싶다면 [참여 방법][5]을 참고하세요. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## 다른 언어로 번역하길 원하시나요? + +튜토리얼은 현재 crowdin.com에서 세계 각국어로 번역이 진행되고 있습니다. : + +https://crowdin.com/project/django-girls-tutorial + +여러분이 사용하는 언어가 crowdin에 없다면, [이 곳][6]에 알려주세요. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/ko/SUMMARY.md b/ko/SUMMARY.md new file mode 100755 index 00000000000..ea46b047f13 --- /dev/null +++ b/ko/SUMMARY.md @@ -0,0 +1,26 @@ +# 목차 + +* [들어가며](README.md) +* [설치하기](installation/README.md) +* [인터넷은 어떻게 작동할까요](how_the_internet_works/README.md) +* [Command Line 시작하기](intro_to_command_line/README.md) +* [Python 설치하기](python_installation/README.md) +* [코드 에디터](code_editor/README.md) +* [Python 시작하기](python_introduction/README.md) +* [Django란 무엇인가요?](django/README.md) +* [Django 설치하기](django_installation/README.md) +* [나의 첫 번째 Django 프로젝트!](django_start_project/README.md) +* [Django 모델](django_models/README.md) +* [Django 관리자](django_admin/README.md) +* [배포하기!](deploy/README.md) +* [Django urls](django_urls/README.md) +* [Django 뷰 만들기](django_views/README.md) +* [HTML 시작하기](html/README.md) +* [Django ORM(Querysets)](django_orm/README.md) +* [템플릿의 동적 데이터](dynamic_data_in_templates/README.md) +* [Django 템플릿](django_templates/README.md) +* [CSS - 예쁘게 만들기](css/README.md) +* [템플릿 확장하기](template_extending/README.md) +* [어플리케이션 확장하기](extend_your_application/README.md) +* [Django 양식](django_forms/README.md) +* [더 나아가기](whats_next/README.md) diff --git a/ko/code_editor/README.md b/ko/code_editor/README.md new file mode 100755 index 00000000000..972d341013f --- /dev/null +++ b/ko/code_editor/README.md @@ -0,0 +1,7 @@ +# 코드 에디터 + +이제 코드를 작성하기 위해 코드 에디터를 설치해 봅시다. + +> **주의** 이전 장 설치하기에서 설치를 이미 했다면, 다음 장으로 넘어가세요! + +{% include "/code_editor/instructions.md" %} diff --git a/ko/code_editor/instructions.md b/ko/code_editor/instructions.md new file mode 100755 index 00000000000..d72c2aa4326 --- /dev/null +++ b/ko/code_editor/instructions.md @@ -0,0 +1,28 @@ +코드 편집기는 종류가 많고 다양해 자신의 취향에 따라 선택할 수 있어요. 대부분의 파이썬 프로그래머는 PyCharm과 같이 복잡하지만 강력한 IDE (통합개발환경: Integrated Development Environments)를 이용합니다. 하지만, 초보자에게 적절하지 않는 도구일 수 있어요. 우리는 간단하지만 강력한 기능을 갖춘 에디터들을 추천합니다. + +아래 추천 에디터 프로그램 중 내가 사용하고 싶은 것을 선택해 사용해도 되지만, 여러분의 코치가 현재 어떤 에디트를 사용 중인지도 물어보세요. 같은 에디터를 사용하면 도움받기 더 쉽고 편할 거에요. + +## Gedit + +Gedit는 모든 운영체제에서 사용 가능한 무료 오픈소스에요. +[이 곳](https://wiki.gnome.org/Apps/Gedit#Download)에서 다운받으세요. + +## Sublime Text 3 + +Sublime Text는 인기있는 에디터이면서 무료로 사용할 수 있어요. 설치와 사용이 편리하고 모든 운영체제에서 쓸 수 있어요. +[이 곳](https://www.sublimetext.com/3)에서 다운받으세요. + +## Atom + +Atom은 아주 최근에 [GitHub](https://github.com/)에서 만든 에디터예요. 무료로 제공되는 오픈소스이며, 설치나 사용이 쉬워요. 윈도우, 맥OS, 리눅스에서 쓸 수 있어요. +[이 곳](https://atom.io/)에서 다운받으세요. + +## 왜 코드 에디터를 설치해야 하나요? + +워드나 노트패드가 있는데도, 굳이 코드 에디터 소프트웨어를 설치해야 하는 이유가 궁금할 거에요. + +첫 번째로 코드는 **일반 텍스트**여야 하는데, 워드나 텍스트에딧(Textedit)과 같은 프로그램에서는 일반 텍스트가 아닌 [RTF(Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format)와 같은 사용자 서식을 쓴 리치 텍스트(폰트와 서식이 있는 텍스트) 가 생성되기 때문입니다. + +두 번째 이유는 코드 에디터는 개발에 도움이 되는 여러 기능을 제공하기 때문입니다. 대표적인 예로, 코드를 해석해서 색으로 문법을 하이라이팅해주는 기능이라든가 큰따옴표("")를 자동으로 닫아주는 등과 같은 기능들이지요. + +앞으로 코드 에디터가 어떻게 작동하는지 알아볼 거에요. 곧 여러분은 내가 사용하는 코드 에디터를 제일 좋아하게 될 거랍니다. diff --git a/ko/css/README.md b/ko/css/README.md new file mode 100755 index 00000000000..26af1c229a0 --- /dev/null +++ b/ko/css/README.md @@ -0,0 +1,296 @@ +# CSS - 예쁘게 만들기 + +우리가 만든 블로그가 아직 예쁘지 않죠? 이제 눈에 보기 좋게 예쁘게 만들어 볼 시간이에요. CSS를 사용해 만들어 볼 거에요. + +## CSS는 무엇인가요? + +CSS(Cascading Style Sheets)는 HTML와 같이 마크업랭귀지(markup language)으로 쓰여진 웹사이트를 나타낼 때 사용하는 언어입니다. 우리 웹페이지 얼굴에 예쁘게 메이크업 하는 것과 같아요 ;) + +아무것도 없는 상태에서 시작하기 어렵죠? 이번에도 우리는 개발자들이 만들고 인터넷 무료로 배포된 코드를 사용할 거에요. 바퀴를 다시 발명하는 것은 재미가 없잖아요. + +## Bootstrap을 사용해봐요! + +부트스트랩(Bootstrap)은 예쁜 웹사이트를 개발하기 위해 사용되는 가장 유명한 HTML과 CSS 프레임워크입니다: https://getbootstrap.com/ + +부트스트랩은 트위터 개발자들에 의해 만들어졌고 전 세계 자원봉사자들이 지속적으로 참여해 발전시키고 있어요. + +## Bootstrap 설치하기 + +Bootstrap을 설치하려면, `.html` 파일의 `` 안에 이 링크를 넣어야 합니다. (`blog/templates/blog/post_list.html`): + +```html + + +``` + +이 링크는 프로젝트에 파일을 새로 추가하는 게 아니에요. 인터넷에 있는 파일을 연결하는 거에요. 따라해보고, 웹사이트를 열어 새로고침 버튼을 눌러보세요. 짠! + +![그림 14.1][1] + + [1]: images/bootstrap1.png + +더 보기 좋아졌죠! + +## Django 정적 파일 + +마지막으로 정적 파일( __static files__)을 다뤄볼 거에요. 정적 파일은 CSS과 이미지 모두를 말합니다. 동적 파일이 아니에요. 그렇기 때문에 콘텐츠 요청 내용이 필요없어 모든 유저들이 동일한 내용을 볼 수 있어요. + +### 어디에 정적 파일을 넣어야 하나요 + +서버에서 `collectstatic`를 실행할 때 처럼, 장고는 "admin" 앱에서 정적 파일을 어디서 찾아야하는지 이미 알고 있어요. 이제 `blog`앱에 정적파일을 추가하면 됩니다. + +blog 앱 안에 `static`폴더를 만드세요. : + + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite + + +장고는 app폴더 안에 있는 "static" 폴더를 자동으로 찾아 안에 있는 내용을 불러낼 거에요. + +## 나의 첫 번째 CSS 파일! + +CSS파일을 만들어 나만의 스타일을 가진 웹페이지를 만들어봐요. `static`디렉토리 안에 `css`라고 새로운 디렉토리를 만드세요. 그리고 `css`디렉토리 안에 `blog.css`라는 파일을 만드세요. 준비되셨나요? + + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css + + +CSS를 쓸 차례에요! 여러분이 사용하고 있는 코드에디터에서 `blog/static/css/blog.css`파일을 불러오세요. + +CSS는 꽤 쉽고 워크샵 후에도 스스로 배울 수 있기 때문에 이번에는 CSS에 대해 심도 있게 살펴보지는 않을 거에요. 우리는 여러분이 더 예쁜 웹사이트를 만들 수 있도록 [Codeacademy HTML & CSS course][2]를 실습해보길 추천해요. + + [2]: https://www.codecademy.com/tracks/web + +하지만 조금이라도 해보자구요. 제목 색깔을 바꿔볼까요? 컴퓨터는 특별한 코드를 사용해 색깔을 나타내요. `#`으로 시작해 알파벳(A-F)와 숫자(0-9) 중 6개를 조합해 나타내요. 이 곳에서 색깔 코드를 찾을 수 있어요: http://www.colorpicker.com/ 또는 [미리 정의 된 색][3], 예를 들어 `빨간색` 또는 `녹색` 등도 사용할 수 있습니다. + + [3]: http://www.w3schools.com/colors/colors_names.asp + +`blog/static/css/blog.css`에 아래의 코드를 추가하세요. + +```css +h1 a { + color: #FCA205; +} +``` + +`h1 a`가 CSS 셀렉터(Selector)에요. 즉, 우리는 `h1`요소 안에 어떠한 `a`요소를 넣어 스타일을 적용 할 수 있다는 거죠. (예를 들어 코드가 다음과 같을 때: `

link

`) 이 경우에, 우리는 색을 `#FCA205`, 즉 오렌지색으로 바꾸라고 말한 거에요. 물론, 색을 직접 선택할 수도 있어요! + +CSS파일에서는 HTML 파일에 있는 각 요소들에 스타일을 적용할 수 있어요. 각 요소는 요소 이름(다시 말하면, `a`, `h1`, `body`), `class`상속 아니면 `id`상속에 의해 식별돼요. Class와 id는 여러분들이 붙인 이름을 갖게 되지요. 클래스는 요소들의 그룹을 결정하는 것이고, id는 특정 요소들을 지칭해요. 예를 들어, 다음 태그들은 CSS에서 태그 이름 `a`, 클래스 `external_link`, id `link_to_wiki_page`을 사용해서 식별해요. + +```html + +``` + +W3Schools에서 [CSS Selectors][4]에 대해 읽어보세요.. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +이제 CSS의 내용을 HTML에 적용시킬 차례에요. `blog/templates/blog/post_list.html`파일을 열고 가장 위에 이 라인을 추가하세요: + +```html +{% load staticfiles %} +``` + +정적 파일이 실행되고 있답니다. :) + +다음, ``와 `` 사이에, 부트스트랩 CSS파일 링크 다음(브라우저는 순서대로 파일을 읽기 때문에 부트스트랩 파일에 있는 코드를 무시할 수 있어요.) 다음 코드를 추가하세요. + +```html + +``` + +이제까지 CSS파일이 있는 템플릿에 대해 알아 보았어요. + +여러분이 만든 파일은 아래와 같아야해요. + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +자, 이제 파일을 저장하고 새로고침을 해보세요! + +![그림 14.2][5] + + [5]: images/color2.png + +잘했어요! 웹사이트 왼쪽 여백을 좀더 주고 싶지 않나요? 한 번 해봐요! + +```css + body { + padding-left: 15px; + } +``` + +이 코드를 CSS에 붙여넣고, 파일을 저장하고 어떻게 바뀌었는지 확인해봐요! + +![그림 14.3][6] + + [6]: images/margin2.png + +제목의 폰트를 바꾸고 싶나요? `blog/templates/blog/post_list.html`파일 안에 ``에 아래 코드를 붙여넣기 해보세요. + +```html + +``` + +이 코드 라인은 구글 폰트 (https://www.google.com/fonts) 에서 *Lobster* 폰트를 불러온 거에요. + +이제 CSS에 `font-family: 'Lobster';`를 추가하세요 ; `blog/static/css/blog.css`파일 안에 `h1 a` 안에 있는 블록 (다음 표기가 된 부분 안에 `{` and `}`) 에 추가하고 새로고침을 누르세요. : + +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` + +![그림 14.3][7] + + [7]: images/font.png + +잘했어요! + +앞서 말했듯이, CSS는 클래스 개념을 가지고 있어요. 클래스는 기본적으로 여러분이 HTML의 코드 일부에 이름을 붙이고 그 부분만 특정 스타일을 적용할 수 있게 해줍니다. 두 개의 div가 있는데 각각 다르게 사용되서(예를 들어 하나는 제목에 있고 하나는 글 본문에 있는 경우), 서로 다르게 보여야 할 경우에 매우 유용해요. + +이제 HTML 코드의 일부에 이름을 붙여 봅시다. header에 포함된 `div`에 `page-header`라고 class 이름을 붙여봅시다. 다음과 같이 말이죠. : + +```html + +``` + +그리고 이제 블로그 글 안에 있는 `div`에 `post`라고 class 이름을 붙이세요. + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +다음 각 다른 선택자(selector) 에 정의를 붙여 볼 거에요. 클래스를 나타내는 선택자는 `.`으로 시작합니다. 아래 있는 코드의 이해를 돕기 위해 인터넷에서 CSS에 대한 튜토리얼이나 설명을 참고하면 많은 도움이 될 거에요. 이제 `blog/static/css/blog.css`파일 안에 아래 코드를 복사, 붙여넣기 하세요. : + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +클래스 선언이 있는 post가 있는 곳으로 가세요. 이 부분을 바꿀 거에요. : + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +`blog/templates/blog/post_list.html` 안에 아래 코드를 넣으세요. + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +파일을 저장하고 웹사이트를 새로고침하세요. + +![그림 14.4][8] + + [8]: images/final.png + +와! 멋지지 않나요? 지금까지 붙여넣기한 코드는 이해하기 어렵지 않으니 무슨 뜻인지 이해 할 수 있을 거에요. + +아직 CSS를 다루는 것이 서툴다고 걱정하지 말고 여러분이 바꾸고 싶은 부분을 고쳐보세요. 만약 문제가 생겼다면, 걱정하지말아요. 언제든지 되돌리기를 할 수 있으니까요! + +워크샵 사전 숙제로 CSS로 더 예쁜 웹사이트를 만들기 위해서[Codeacademy HTML & CSS course][2]를 수강해보길 추천해요. + +다음 장을 읽을 준비가 됐나요?! :) diff --git a/ko/css/images/bootstrap1.png b/ko/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/ko/css/images/bootstrap1.png differ diff --git a/ko/css/images/color2.png b/ko/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/ko/css/images/color2.png differ diff --git a/ko/css/images/final.png b/ko/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/ko/css/images/final.png differ diff --git a/ko/css/images/font.png b/ko/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/ko/css/images/font.png differ diff --git a/ko/css/images/images/bootstrap1.png b/ko/css/images/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/ko/css/images/images/bootstrap1.png differ diff --git a/ko/css/images/images/color2.png b/ko/css/images/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/ko/css/images/images/color2.png differ diff --git a/ko/css/images/images/final.png b/ko/css/images/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/ko/css/images/images/final.png differ diff --git a/ko/css/images/images/font.png b/ko/css/images/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/ko/css/images/images/font.png differ diff --git a/ko/css/images/images/margin2.png b/ko/css/images/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/ko/css/images/images/margin2.png differ diff --git a/ko/css/images/margin2.png b/ko/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/ko/css/images/margin2.png differ diff --git a/ko/deploy/README.md b/ko/deploy/README.md new file mode 100755 index 00000000000..5f5ccaca680 --- /dev/null +++ b/ko/deploy/README.md @@ -0,0 +1,312 @@ +# 배포하기! + +> **Note** 이번 장은 따라오기 조금 힘들 수도 있어요. 끝까지 따라와주세요. 배포는 웹사이트 개발의 가장 중요한 부분이에요. 튜토리얼 중간에 이번 장이 있는 이유는 여러분이 코치가 여러분의 웹사이트를 온라인에서 볼 수 있게 도와주기 위해서에요. 시간이 모자르더라도 튜토리얼을 끝낼 수 있어요. + +지금까지는 웹사이트를 내 컴퓨터에서만 볼 수 있었어요. 이제 어떻게 웹사이트를 배포하는지 배워봅시다. 배포(deploy)는 애플리케이션을 인터넷에 올려놓아 다른 사람들도 볼 수 있게 해주는 것 말해요. :) + +앞에서 배웠듯이, 웹사이트는 서버라는 곳에 들어 갑니다. 인터넷에는 많은 종류의 서버 제공 업체들이 있어요. 우리는 이 중에 비교적 배포 과정이 간단한 [PythonAnywhere][1]을 사용할 거에요. PythonAnywhere는 방문자가 아주 많지 않은 소규모 어플리케이션으로 무료로 사용할 수 있답니다. 당연히 지금 우리가 만드는 것도 해당되지요. + + [1]: https://pythonanywhere.com/ + +우리가 사용할 다른 서비스는 [GitHub][2]라는 코드 호스팅 서비스입니다. 프로그래머들이 애용하는 곳들 중 하나로 대부분의 모든 프로그래머가 GitHub 계정을 가지고 있다고 봐도 될 거예요. 이제 여러분도 하나 만들 때가 되었어요! + + [2]: https://www.github.com + +우리는 GitHub를 작성한 코드를 PythonAnywhere에 넣고 빼기 위한 디딤돌로 사용할 거에요. 즉, 코드를 GitHub에 저장하고 GitHub에 저장된 코드를 PythonAnywhere에서 가져다가 작동하는 방법이에요. + +# Git + +Git은 많은 프로그래머들이 사용하고 있는 "버전 관리 시스템(version control system)"이에요. 이 소프트웨어는 변경 내용을 추적할 수 있어 나중에 특정 버전을 다시 호출 할 수 있어요. 마이크로소프트 워드에 있는 "변경 내용 추적하기(track changes)"와 같은 기능이지만 이보다 훨씬 더 강력합니다. + +## Git 설치하기 + +> **Note** 이미 설치를 끝냈다면, 다시 할 필요가 없어요. 이 부분을 넘기고 Git 저장소를 만드는 것부터 시작하세요. + +{% include "/deploy/install_git.md" %} + +## Git 저장소 만들기 + +Git은 코드 저장소(줄여서 "repo"라고 합니다.)에 특정한 파일들 집합의 변화를 추적하여 관리합니다. 이제 프로젝트를 시작해 볼까요? 콘솔창을 열고 `djangogirls` 디렉토리에서 아래 명령어들을 실행하세요. 아래 명령 중에서 Your Name 대신 자신의 이름을, you@example.com 대신에 내 이메일 주소를 입력하세요. + +> **Note** 저장소를 초기화 하기 전에 여러분의 현재 작업 디렉토리가 어디인지 꼭 확인하세요. 맥OS나 Linux라면 `pwd` 명령으로, 윈도우라면 `cd` 명령어를 실행하면 알 수 있을 거에요. 반드시 `djangogirls` 폴더에서 해야합니다. + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +git 저장소 초기화는 프로젝트를 시작할 때 딱 한번만 필요합니다. (또한 두 번째, 세 번째 명령인 username과 email 등록 명령은 계속 적용되기 때문에 이 계정에서는 다시 입력할 필요가 없습니다.) + +Git은 이 디렉토리에 모든 파일들과 폴더들의 변경점을 추적할 거에요. 무시(ignore)하도록 지정한 파일들을 제외하고는 말이죠. 기본 디렉토리에다 `.gitignore`라는 파일을 만들어서 특정 파일이나 폴더를 추적하지 않게 할 수 있습니다. 에디터를 열어 아래 내용을 넣어주세요. : + + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store + + +그리고 "djangogirls" 폴더의 맨 위에다 `.gitignore` 라는 파일로 저장하세요. + +> **Note** 파일명 앞에 마침표로 시작하는 것이 중요합니다! 꼭 붙여주세요. 만약 파일을 만드는 것이 어렵다면 (예를 들어 맥은 파인더에서 마침표로 시작하는 파일을 생성하는 걸 좋아하지 않아요) "다른 이름으로 저장(Save As)" 기능을 사용하세요. 대부분 이렇게 하면 될 거에요. + +`git add`하기 전이나 변경된 것이 있는지 잘 모를 때마다 `git status` 명령어를 사용하는 것은 좋은 방법이에요. 잘못된 파일이 추가된 경우, 이를 멈출 수 있게 도움을 주어요. `git status` 명령은 미추적/수정된/스테이지된 파일들, 브랜치 상태와 그 외 많은 정보들을 보여줍니다. 실행하면 아래와 비슷하게 나타날거에요. : + + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) + + +자 이제 우리가 만든 코드들을 저장소에 넣어봅시다. 콘솔창에 가서 다음 명령어를 실행하세요. : + + $ git add --all . + $ git commit -m "My Django Girls app, 첫번째 커밋" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## GitHub에 코드 넣기 + +[GitHub.com][2]에서 새로운 무료 계정을 만들세요. (워크샵 전에 미리 가입했다면 더 좋죠!) + +그 다음 새 저장소(new repository)를 "my-first-blog"라는 이름으로 생성하세요. "초기화시 README 파일 만들기(initialize with a README)" 체크박스는 체크안 한 상태로 두세요. .gitignore 옵션도 비어있는 상태(위에서 직접 만들었죠?)로 두세요. 라이센스도 None으로 두세요. + +![][3] + + [3]: images/new_github_repo.png + +> **주의** 저장소 이름 `my-first-blog`는 중요합니다. -- 물론 원하는대로 이름을 바꿀 수 있지만, 매번마다 변경해서 사용해야하니 정말 불편할 거에요. 가급적이면 `my-first-blog`라는 저장소 이름을 그대로 사용하는 것이 편할 거에요. + +다음 화면에서 저장소 복제 URL(repo's clon URL) 을 볼 수 있을 거에요. "HTTPS" 버전을 선택해서 그 주소를 복사하세요. 그리고 터미널에다 붙여넣으세요. + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +이제 내 컴퓨터의 Git 저장소를 GitHub에 있는 저장소로 연결해야합니다. + +콘솔에 다음과 같이 입력하세요 (``에 꺽쇠괄호(<>)를 떼고 내 Github 유저네임을 입력하세요. + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +아래와 같은 화면이 나오면 GitHub 유저네임과 암호를 입력하세요. + + Username for 'https://github.com': 여러분의GitHub유저네임 + Password for 'https://hjwp@github.com': 여러분의GitHub암호 + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +이제 여러분의 코드가 GitHub에 저장됐어요! 가서 확인해보세요! [Django][5], [Django Girls Tutorial][6]뿐만 아니라 수많은 훌륭한 오픈소스 소프트웨어 프로젝트들이 GitHub에서 코드를 호스팅하고 있어요. 방금 여러분이 한 것처럼 말이죠. :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# PythonAnywhere에 블로그 설정하기 + +> **Note** 이미 PythonAnywhere 계정이 있으면, 이 부분을 다시 할 필요가 없어요. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## GitHub에서 PythonAnywhere로 코드 가져오기 + +PythonAnywhere에 가입하면 대시보드 또는 "콘솔(Consoles)" 페이지를 볼 수 있을 거에요. "배시(Bash)" 콘솔로 시작하는 옵션을 선택하세요. -- PythonAnywhere 버전의 콘솔로 PC에 있는 커맨드라인 같은 것이라 생각해도 됩니다. + +> **Note** PythonAnywhere는 리눅스 기반으로 윈도우의 커맨드라인 창과 조금 다르게 보일 수 있어요. + +GitHub에 있는 코드를 끌어와 저장소를 "복제"해 PythonAnywhere로 탑재해 볼게요. PythonAnywhere에 있는 콘솔에 다음과 같이 입력하세요. (``대신 내 GitHub 유저네임을 입력하는 것을 잊지 마세요. :) + + $ git clone https://github.com//my-first-blog.git + + +이렇게 PythonAnyWhere에 있는 코드 사본을 끌어올 거에요. `tree my-first-blog`를 입력해 확인하세요. : + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### PythonAnywhere에서 가상환경(virtualenv) 생성하기 + +PythonAnywhere에서도 내 컴퓨터에 있는 것과 같이 작동할 수 있게 가상 환경(virtualenv)을 생성할 수 있어요. 배시 콘솔(Bash console)에 다음과 같이 입력하세요. : + + $ cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + (mvenv) $ pip install django whitenoise + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 + + +> **Note** The `pip install`은 설치가 될 때까지 인내심이 조금 필요해요. 하지만 몇 분 안에 완료될 거니 조금만 기다려보세요. 만약 5분 이상 시간이 지났다면, 무엇인가 잘못된거니 코치에게 물어보세요. + + + +### 정적 파일 모으기 + +"백색소음"을 들어본 적이 있나요? 이 것은 "정적 파일"로 불리는 것들을 제공하는 프로그램이에요. 정적 파일이란 HTML, CSS와 같이 정기적인 수정이 없거나 프로그래밍 코드를 실행하지 않는 파일을 말해요. 서버에서 정적 파일은 컴퓨터와 다르게 작동하기 때문에 정적 파일들을 제공하기 위해서 "백색소음"과 같은 프로그램이 필요해요. + +정적 파일은 튜토리얼 뒷부분에 나오는 CSS 부분에서 좀 더 자세히 알아볼게요. + +이제 서버에서 추가명령인 `collectstatic`을 실행하세요. 이 명령은 장고가 서버에 있는 모든 정적 파일들을 모으는 것을 지시해요. 지금 이 파일들이 관리자 사이트를 예쁘게 만들어주는 것이지요. + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +"yes"라고 입력하고 메시지들이 나오게 내버려두세요! 화면 가득히 텍스트가 출력되어 흘러나올건데 혹시 이런 걸 좋아하는 분 있나요? 저는 텍스트가 나타날 때마다 항상 "브릅, 브릅 브릅..." 같은 소리가 나도록 만들어 놓았어요. 멋지죠? + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### PythonAnywhere에서 데이터베이스 생성하기 + +컴퓨터와 서버가 다른 점이 또 하나 있어요. 바로 다른 데이터베이스를 사용한다는 점이에요. 그래서 사용자 계정과 글은 서버와 여러분의 컴퓨터와 다를 수 있어요. + +지난 번 내 컴퓨터에서 했던 것과 같이 서버에서도 데이터베이스를 초기화 할 거에요. `migrate`와 `createsuperuser`를 사용하세요. : + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + +## web app으로 블로그 배포하기 + +이제 우리의 코드는 PythonAnywhere에 있고 우리의 가상환경(virtualenv)도 준비가 되었으며, 정적 파일들도 모아져 있고, 데이터베이스도 초기화되었네요. 이제 우리는 web app으로 배포할 준비가 되었어요. + +로고를 클릭해 PythonAnywhere 대시보드로 와서 **Web**을 클릭하고 **Add a new web app**를 선택하세요. + +도메인 이름을 확정한 후, 대화창에 **수동설정(manual configuration)** ("Django"옵션이 *아니에요.*) 을 클릭하세요. 다음, **Python 3.4**을 선택하고 다음(Next)를 클릭하면 마법사가 종료됩니다. + +> **Note** " Django"가 아니라 꼭 "수동설정(Manual configuration)"을 선택하세요. 기본 PythonAnywhere Django 설정을 위해서는 이렇게 하는 것이 더 좋아요. ;-) + +### 가상환경(virtualenv) 설정하기 + +이제 우리는 webapp을 위한 PythonAnywhere 설정 화면을 볼 수 있어요. 서버에 있는 앱에 변경사항이 생기면 필요한 화면이에요. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +"가상환경(Virtualenv)" 섹션에서 "가상환경 경로를 입력해주세요(Enter the path to a virtualenv)"라고 써져있는 빨간색 글자를 클릭하고 `/home//my-first-blog/myvenv/` 라고 입력합니다. 이동 경로 저장을 하려면 파란색 박스에 체크 표시를 하고 클릭하세요. + +> **주의**: 가상환경 경로를 적당한 것으로 변경하세요. 실수를 하면 PythonAnywhere가 작은 경고 메시지를 보여줄 거에요. + +### WSGI 파일 설정하기 + +장고는 "WSGI 프로토콜"을 사용해 작동합니다. 이 프로토콜은 파이썬을 이용한 웹사이트를 서비스하기 위한 표준으로 PythonAnywhere에서도 지원합니다. WSGI 설정을 파일을 수정해 우리가 만든 장고 블로그를 PythonAnywhere에서 인식하게 해봅시다. + +"WSGI 설정 파일(WSGI configuration file)" 링크(페이지의 상단 근처에 있는 "코드(Code)" 섹션에 있습니다. -- 아마 `/var/www/_pythonanywhere_com_wsgi.py`와 같이 나타나있을 것입니다.)를 클릭하면 에디터를 볼 수 있을 것입니다. + +모든 내용을 삭제하고 아래 내용을 넣으세요. : + +```python + import os + import sys + + path = '/home//my-first-blog' # 여러분의 유저네임을 여기에 적어주세요. + if path not in sys.path: + sys.path.append(path) + + os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + + from django.core.wsgi import get_wsgi_application + from whitenoise.django import DjangoWhiteNoise + application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Note** ``에 내 유저네임을 넣는 것을 잊지 마세요. + +이 파일은 PythonAnywhere에게 작동 할 우리의 web app 위치를 알려주고 장고 세팅 파일 이름을 알려주는 역할을 하죠. 또 "백색소음" 정적 파일 툴을 설정해줍니다. + +**저장(Save)**을 누르고 **웹(Web)** 탭을 누릅니다. + +다 되었어요! 큰 녹색 **다시 불러오기(Reload)** 버튼을 누르면 여러분은 여러분의 어플리케이션을 볼 수 있을 거에요. 여러분은 페이지 최 상단에 가는 링크를 발견할 수 있을 거에요. + +## 디버깅 팁 + +본인의 사이트에 접속할 때 오류가 보이면, 제일 먼저 **error log(오류 로그)**에서 디버깅 정보를 찾아보세요. PythonAnywhere [Web tab][8]에서 이 링크를 찾을 수 있어요. 여기서 오류 메세지가 있는지 확인하세요. 대부분의 가장 최근의 오류 메세지는 맨 하단에 있어요. 일반적으로 많이 일어나는 문제들은 아래와 같습니다. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* virtualenv를 생성하고 활성화할 때, Django를 설치할 때, Collestac을 돌릴 때, 데이터베이스를 설치할 때 같은 각 단계를 위한 콘솔 작업을 할 때 한 단계를 빼먹는 경우 + +* web tab에서 virtualenv 경로를 쓸 때 오타가 났을 때 - 이런 경우 빨간 작은 에러 메시지가 뜰 것입니다. + +* WSGI 설정 파일에 실수가 있을 때 -- my-first-blog-folder 폴더의 경로를 올바르게 입력했었나요? + +* Web app에서 그랬듯이 virtualenv에도 동일한 파이썬 버전을 선택했나요? 둘다 모두 3.4 버전이어야해요. + +* [PythonAnywhere 위키에서 일반적인 디버깅 팁][9]을 확인할 수 있어요. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +기억하세요, 여러분의 코치들은 여러분들에게 도움을 주기 위해 여기 있답니다! + +# 내 웹사이트가 나왔어요! + +여러분 사이트의 기본 페이지(default page) 가 PC와 같이 "Welcome to Django"라는 메시지를 보여줘야해요. URL 뒤에 `/admin/`를 붙여서 다시 접속해 보세요. 이제 관리자 사이트를 볼 수 있어요. 서버에서 유저네임과 암호를 입력해서 로그인하면 새 글을 작성할 수 있음을 알 수 있어요. + +이제까지 수고한 모두에게 *큰* 격려를 해주세요! 서버 배포는 웹 개발 단계 중 가장 까다로운 부분 중 하나이기 때문에 작업 완성까지 몇 일이 걸리기도 해요. 하지만 이제 우리 사이트는 실제 인터넷에서 접속이 가능해요. 쉽게 잘 해냈어요! diff --git a/ko/deploy/images/github_get_repo_url_screenshot.png b/ko/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/ko/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/ko/deploy/images/new_github_repo.png b/ko/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/ko/deploy/images/new_github_repo.png differ diff --git a/ko/deploy/images/pythonanywhere_web_tab_virtualenv.png b/ko/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/ko/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/ko/deploy/install_git.md b/ko/deploy/install_git.md new file mode 100755 index 00000000000..21e7ba65422 --- /dev/null +++ b/ko/deploy/install_git.md @@ -0,0 +1,17 @@ +### 윈도우 + +Git은 [git-scm.com](https://git-scm.com/)에서 다운로드 할 수 있습니다. 다운받은 파일을 설치하는 것은 참 쉬워요. 딱 한 단계만 빼고 기본 설정대로 "다음 다음 다음"을 계속 눌러주면 쉽게 설치할 수 있어요. ; 주의해야할 단계는 다섯 번째 "PATH 환경 설정(Adjusting your PATH environment)" 화면이에요. "윈도우 커맨드라인에서 Git과 유닉스 도구를 실행(Run Git and associated Unix tools from the Windows command-line)"을 선택하세요. (옵션 아래쪽에 있어요.) 나머지는 모두 기본 설정대로 해도 됩니다. 윈도우 스타일, 유닉스 스타일로 라인엔딩 커밋하기(commit Unix-style line endings) 를 체크하는 것도 좋습니다. + +### MacOS + +[git-scm.com](https://git-scm.com/)에서 맥용 설치파일을 다운받은 다음 실행해 나오는 지시 사항에 따라 설치하시면 됩니다. + +### 리눅스 + +설치가 안되었다면, 패키지 관리자로 git 설치를 해야해요. 다음과 같이 해보세요: + + sudo apt-get install git + # 또는 + sudo yum install git + # 또는 + sudo zypper install git diff --git a/ko/deploy/signup_pythonanywhere.md b/ko/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..65f4aaa75fc --- /dev/null +++ b/ko/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +다음 PythonAnywhere에서 무료 계정인 "초보자(Beginner)"로 회원가입 하세요. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Note**: 여러분의 유저네임을 정할 때 블로그 주소의 일부가 여러분의 유저네임으로 되는 것을 염두하고 정하세요. 예를 들어 유저네임이 yourusername이라면 여러분의 블로그 URL은 `yourusername.pythonanywhere.com`이 된답니다. diff --git a/ko/django/README.md b/ko/django/README.md new file mode 100755 index 00000000000..659ddfc9c98 --- /dev/null +++ b/ko/django/README.md @@ -0,0 +1,27 @@ +# Django란 무엇인가요? + +Django (*/ˈdʒæŋɡoʊ/ jang-goh/쟁고/장고*)는 파이썬으로 만들어진 무료 오픈소스 웹 어플리케이션 프레임워크(web application framework) 입니다. 쉽고 빠르게 웹사이트를 개발할 수 있도록 돕는 구성요소로 이루어진 웹 프레임워크이랍니다. + +웹사이트를 구축할 때, 비슷한 유형의 요소들이 항상 필요합니다. 회원가입, 로그인, 로그아웃과 같이 사용자 인증을 다루는 방법이나 웹사이트의 관리자 패널, 폼, 파일 업로드와 같은 것들 말이지요. + +그런데 정말 다행이게도, 오래 전에 어떤 웹 개발자들이 새로운 웹 사이트를 개발할 때 서로 비슷한 문제들에 직면한다는 것을 깨달았습니다. 그래서 팀을 조직했구요. 바로 사용할 수 있는 구성요소들을 갖춘 여러 프레임워크를 만들었답니다. (장고도 그 중에 하나인거죠.) + +프레임워크는 다시 발명해야하는 문제로부터 해방감을 주고요. 새로운 웹사이트를 개발할 때 뒤따르는 간접비용의 부담을 덜어준답니다. + +## 왜 프레임워크가 필요한가요? + +장고라는 것이 실제로 무엇을 위한 것인지 이해하기 위해서는 서버에 대해서 자세히 살펴볼 필요가 있어요. 먼저, 서버가 여러분에게 웹 페이지를 제공하길 원하는지 알아야 해요. + +편지(request, 요청) 이 도착했는지 확인해주는 메일박스(port, 포트) 가 있다고 상상해보세요. 이 것은 웹 서버가 해주는 일이에요. 웹 서버는 받은 편지를 읽고 웹 페이지와 함께 답장을 준답니다. 그런데 무언가를 주고 싶을 때는 그 안에 내용이 있어야하죠. 장고는 그 특정 컨텐츠를 만들 수 있는 역할을 합니다. + +## 누군가가 서버에 웹 사이트를 요청하면 어떤 일이 벌어질까요? + +웹 서버에 요청이 오면 장고로 전달됩니다. 그러면 장고는 실제로 어떤 요청이 들어왔는지 확인합니다. 첫 번째로 웹 페이지의 주소를 가져와 무엇을 할지 확인합니다. 이 것이 바로 장고의 **urlresolver**가 하는 역할이에요. (웹 사이트 주소는 URL - Uniform Resource Locator을 말합니다. 그래서 *urlresolver*가 이해하게 됩니다.) 패턴 목록을 가져와 URL과 맞는지 하나 씩 대조해보는 것은 그리 똑똑한 방법이 아니죠. 그러나 장고는 위에서 부터 아래로 그 패턴을 확인해봅니다. 만약 일치하는 게 있다고 하면, 장고는 그 요청을 관련된 함수(*view*) 에 넘겨줍니다.). + +우편배달부를 생각해보세요. 거리를 걸으며 집집마다 편지와 대조해서 주소와 번지를 확인합니다. 주소와 번지가 일치하면 우편배달부는 그 곳에 편지를 배달합니다. Urlresolver 가 바로 이와 같은 일을 합니다. + +모든 재미난 일들은 *view* 함수에서 모두 처리됩니다: 특정 정보를 데이터베이스에서 찾을 수 있어요. 그런데 만약 사용자가 데이터를 바꿔달라고 수정을 요청한다면 어떻게 될까요? "제 직업에 대한 설명을 바꿔주세요."와 같은 편지를 받았다고 생각해봅시다. *view*함수는 수정할 수 있는 권한이 있는지 확인하고나서, 직업에 대한 설명을 수정해 다시 답장을 주겠지요. "완료했습니다!" 라고요. 그리고 나서 *view*는 답장을 생성하여, 장고는 그 답장을 그 사용자의 웹 브라우저에 보내주는 역할을 합니다. + +물론 지금까지의 설명은 아주 간단히 설명한 것에 불과해요. 하지만 모든 기술적인 부분까지 자세히 알 필요가 없답니다. 이 정도 아는 것만으로도 충분하답니다. + +좀 더 자세히 아는 것보다, 지금부터는 장고를 이용해 간단하게 조그만 것부터 만들어봐요. 그렇게 하면서 중요한 모든 것들을 하나씩 배워나가도록 해요. diff --git a/ko/django_admin/README.md b/ko/django_admin/README.md new file mode 100755 index 00000000000..57b771720ac --- /dev/null +++ b/ko/django_admin/README.md @@ -0,0 +1,46 @@ +# Django 관리자 + +방금 막 모델링한 글들을 장고 관리자에서 추가하거나 수정, 삭제할 수 있어요. + +이제 `blog/admin.py` 파일을 열어서 내용을 다음과 같이 바꾸세요. : + + from django.contrib import admin + from .models import Post + + admin.site.register(Post) + +코드에서 알 수 있듯이 앞 챕터에서 정의했던 Post 모델을 가져오고(import) 있어요. 관리자 페이지에서 만든 모델을 보려면 `admin.site.register(Post)`로 모델을 등록해야해요. + +자, 이제 Post 모델을 볼까요? 웹 서버를 실행하려면 콘솔창에서 `python manage.py runserver`를 실행하는걸 잊지마세요. 브라우저를 열고 주소 창에 http://127.0.0.1:8000/admin/ 입력하면아래와 같은 로그인 페이지를 볼 수 있어요. + +![로그인 페이지][1] + + [1]: images/login_page2.png + +로그인을 하기 위해서는, 모든 권한을 가지는 *슈퍼유저(superuser)*를 생성해야해요. 커맨드라인으로 돌아가서 `python manage.py createsuperuser`을 입력하고 엔터를 누르세요. 메시지가 나타나면 사용자 이름 (소문자, 공백 없이), 이메일 주소 및 암호를 입력합니다. password 를 입력할 때 화면에 글자가 보이지 않는다고 해도 걱정하지 마세요. 원래 password 는 화면에 보이지 않습니다. 작성한 후에 `enter`를 누르세요. 실행화면은 아래와 같을 거에요. (슈퍼유저로 사용 될 username 과 email 주소는 본인 것이어야해요) + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +브라우저로 돌아와서 장고 관리자 페이지에서 슈퍼유저로 로그인한 후 대시보드를 확인하세요. + +![Django 관리자][2] + + [2]: images/django_admin3.png + +게시글로 가서 이것 저것 시도해보세요. 5 - 6개 블로그 포스트를 올려보세요. 안에 내용은 걱정하지 마세요. 튜토리얼에 있는 텍스트를 그냥 복사-붙여넣기 할 수 있으니까요. + +최소한 2, 3개의 글들에 게시 날짜가 있는지 확인하세요. (모두 볼 필요는 없어요) 이건 나중에 도움이 될 거에요. + +![Django 관리자][3] + + [3]: images/edit_post3.png + +장고 관리자에 대해서 좀 더 알고 싶다면 장고 공식 문서를 참고하세요. : https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +자, 여러분은 내 첫 번째 장고 모델을 만들었어요! 잠깐 쉴 시간이 필요해요. 열심히 했으니 재충전을 위해 커피 한 잔(또는 차 한 잔) 또는 뭔가 먹고 돌아오세요. diff --git a/ko/django_admin/images/django_admin3.png b/ko/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/ko/django_admin/images/django_admin3.png differ diff --git a/ko/django_admin/images/edit_post3.png b/ko/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/ko/django_admin/images/edit_post3.png differ diff --git a/ko/django_admin/images/images/django_admin3.png b/ko/django_admin/images/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/ko/django_admin/images/images/django_admin3.png differ diff --git a/ko/django_admin/images/images/edit_post3.png b/ko/django_admin/images/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/ko/django_admin/images/images/edit_post3.png differ diff --git a/ko/django_admin/images/images/login_page2.png b/ko/django_admin/images/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/ko/django_admin/images/images/login_page2.png differ diff --git a/ko/django_admin/images/login_page2.png b/ko/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/ko/django_admin/images/login_page2.png differ diff --git a/ko/django_forms/README.md b/ko/django_forms/README.md new file mode 100755 index 00000000000..0397f7b6b3e --- /dev/null +++ b/ko/django_forms/README.md @@ -0,0 +1,402 @@ +# Django 폼 + +이제 한 가지만 더 하면 웹사이트가 완성되어요. 바로 블로그 글을 추가하거나 수정하는 멋진 기능을 추가하는 것이죠. 장고의 `관리자` 기능도 충분히 멋있기는 하지만, 좀 더 입맛에 맞게 바꾸고 예쁘게 꾸미기에는 좀 한계가 있습니다. `폼(양식, forms)`으로 강력한 인터페이스를 만들 수 있어요. - 우리가 상상할 수 있는 거의 모든 것을 할 수 있거든요! + +장고 폼이 정말 멋진 것은 아무런 준비 없이도 양식을 만들 수 있고, `ModelForm`을 생성해 자동으로 모델에 결과물을 저장할 수 있다는 거에요. + +이 기능이 지금 우리가 할 내용이에요: 폼을 하나 만들어서 `Post` 모델에 적용해봅시다. + +장고의 모든 중요한 부분과 마찬가지로, 폼도 폼만의 파일을 만들어요: `forms.py`. + +우리는 이 이름으로 `blog` 디렉토리 안에 파일을 만들 거에요. + + blog + └── forms.py + + +좋아요, 이제 이 파일을 열고 아래 코드를 작성해봐요. : + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +위 코드를 보면 첫 번째로 forms model을 import 해야하고 (`from django import forms`), 그 다음으로 `Post` model 도 import 해야합니다. (`from .models import Post`). + +`PostForm` 은 이미 다들 예상 하셨듯이 우리가 만들 폼의 이름이에요. 그리고 장고에게 이 폼이 `ModelForm`이라는 것을 알려줘야해요. (그러면 장고가 뭔가 마술을 부릴 거에요) - `forms.ModelForm`은 ModelForm이라는 것을 알려주는 구문이에요. + +자, 이제 다음으로 `class Meta`가 나오는데요, 이 구문은 이 폼을 만들기 위해서 어떤 model이 쓰여야 하는지 장고에게 알려주는 구문입니다. (`model = Post`). + +마지막으로, 이 폼에 필드를 넣으면 완성되겠죠. 이번 폼에서는 `title` 과 `text` 만 보여지게 해 봅시다. - `author` 는 현재 로그인 하고 있는 사람이 될 것이고 (바로 당신이요!) 그리고 `created_date` 는 글이 등록되는 시간이 될 것입니다. (예를 들어, code 상에서요), 됐죠? + +마쳤습니다! 이제 *뷰* 에서 이 폼을 사용해 템플릿에서 보여주기만 하면 되네요. + +다음에는 링크, URL, 뷰 그리고 템플릿을 만들 거에요. + +## 폼과 페이지 링크 + +`blog/templates/blog/base.html` 파일을 열어봅시다. `page-header` 라는 `div` class 에 링크를 하나 추가할거에요. + +```html + +``` + +이 새로운 뷰를 `post_new` 라고 부를게요. + +위 구문을 추가하고 나면, 이제 html 파일이 아래처럼 보일 거에요. + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +페이지를 저장하고 나서 http://127.0.0.1:8000 페이지를 새로고침 해보면, `NoReverseMatch`이 에러가 나타나죠? + +## URL + +이제 `blog/urls.py` 을 열고 아래 구문을 추가하겠습니다: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + +전체 코드는 아래와 같을 거에요. + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +브라우저에 사이트를 다시 불러오면 `AttributeError`가 보이게 됩니다. 왜냐하면 아직 우리는 `post_new`뷰를 구현하지 않았기 때문이죠. 이제 하나 추가해봅시다. + +## post_new view + +`blog/views.py` 파일을 열어서 `from` 줄에 아래와 같은 코드를 추가합니다. + +```python +from .forms import PostForm +``` + +그리고 *view* 에 추가합니다. + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +새 `Post` 폼을 추가하기 위해 `PostForm()` 함수를 호출하도록 하여 템플릿에 넘깁니다. 이따가 *view* 로 다시 돌아와서 이 작업을 하겠지만, 지금 당장은 폼을 위한 템플릿을 먼저 빨리 만들어보도록 할게요. + +## 템플릿 + +이번에는 `blog/templates/blog` 디렉토리 안에 `post_edit.html` 파일을 생성해 폼이 작동할 수 있게 만들거에요. + +- 먼저 폼이 보여져야합니다. 그 예로, `{% raw %}{{ form.as_p }}{% endraw %}`로 간단히 만들 수 있어요.. +- 위 코드를 HTML태그로 폼을 감싸세요. `...` +- `Save` 버튼이 필요합니다. 이 것은 HTML 버튼으로 만들 수 있어요: `` +- 마지막으로 `
`을 열어 `{% raw %}{% csrf_token %}{% endraw %}`를 추가하세요. 이 작업은 폼 보안을 위해 중요하답니다! 이 작업을 빼먹고 저장하면 장고는 이렇게 불평할 거에요. + +![CSFR 서버가 허용하지 않는 웹 페이지(Forbidden page)][1] + + [1]: images/csrf2.png + +네, 이제 `post_edit.html` 파일의 HTML을 확인해볼게요: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +다 작성했으면 화면을 다시 불러옵시다! 여러분의 폼이 이렇게 나타났나요! + +![새 폼(New form)][2] + + [2]: images/new_form2.png + +그런데, 잠깐만요! `title`과 `text` 필드에 아무거나 입력하고 저장해보세요. 어떻게 됐나요? + +글이 사라졌어요! 한번 더 해봐도 내가 입력한 글들은 어디론가로 사라지고는 새 글이 추가되지 않아요. 뭐가 잘못된 걸까요? + +정답은요: 여러분이 잘못한 게 없어요. 단지 *view* 에 조금 작업이 필요할 뿐이에요. + +## 폼 저장하기 + +`blog/views.py` 다시 여세요. 지금 여러분이 보고 있는 `post_new` 뷰는 아래와 같을 거에요: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +폼을 제출할 때, 동일한 뷰를 불러오게 됩니다. 이 때 `request`에는 우리가 입력했던 데이터들을 가지고 있는데, `request.POST`가 이 데이터를 가지고 있습니다. (POST는 글 데이터를 "등록하는(posting)"하는 것을 의미합니다. 블로그 "글"을 의미하는 "post"과 관련이 없어요.) HTML에서 `
`정의에 `method="POST"`라는 속성이 있던 것이 기억나나요? 이렇게 POST로 넘겨진 폼 필드의 값들은 이제 `request.POST`에 저장됩니다. `POST`로 된 값을 다른 걸로 바꾸면 안돼요.(`method` 속성의 값으로 넣을 수 있는 유효한 값 중에 `GET` 같은 것도 있지만 post와 어떤 차이점이 있는지 등에 대해서 다루기에는 너무 길어질 것 같아 생략할게요.) + +이제 *view* 에서 두 상황으로 나누어 처리해볼게요. +첫 번째: 처음 페이지에 접속했을 때입니다. 당연히 우리가 새 글을 쓸 수 있게 폼이 비어있어야겠죠. +두번째: 폼에 입력된 데이터를 *view* 페이지로 가지고 올 때입니다. 여기서 조건문을 추가시켜야해요. (`if`을 사용하세요.) + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +이제 생략된 `[...]`부분에 코드를 추가해봅시다. 만약 `method`가 `POST`라면, 폼에서 받은 데이터를 `PostForm`으로 넘겨줘야겠죠? 이렇게 작성하면 됩니다. : + +```python +form = PostForm(request.POST) +``` + +참 쉽죠! 다음에는 폼에 들어있는 값들이 올바른지를 확인해야합니다.(모든 필드에는 값이 있어야하고 잘못된 값이 있다면 저장하면 되지 않아야해요.) 이를 위해 `form.is_valid()`을 사용할거에요. + +폼에 입력된 값이 올바른지 확인한 다음, 저장되는거죠! + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +일반적으로, 이 작업을 두 단계로 나눌 수 있어요. : `form.save`로 폼을 저장하는 작업과 작성자를 추가하는 작업입니다.(`PostForm`에는 `작성자(author)` 필드가 없지만, 필드 값이 필요하죠!) `commit=False`란 넘겨진 데이터를 바로 `Post` 모델에 저장하지는 말라는 뜻입니다. - 왜냐하면 작성자를 추가한 다음 저장해야하니까요. 대부분의 경우에는 `commit=False`를 쓰지 않고 바로 `form.save()`를 사용해서 저장해요. 다면 여기서는 작성자 정보를 추가하고 저장해야하기 때문에 commit=False를 사용하는 거에요. `post.save()`는 변경사항(작성자 정보를 포함)을 유지할 것이고 새 블로그 글이 만들어질 거에요! + +끝으로, 새 블로그 글을 작성한 다음에 `post_detail` 페이지로 이동할 수 있으면 좋겠죠? 이 작업을 하려면 한 가지를 더 불러와야해요. + +```python +from django.shortcuts import redirect +``` + +위 코드를 여러분의 파일 맨 위에 추가하세요. 그리고 새로 작성한 글을 볼 수 있도록 `post_detail` 페이지로 가라고 수정합시다. + +```python +return redirect('post_detail', pk=post.pk) +``` + +`post_detail`은 우리가 이동해야 할 뷰의 이름이에요 *post_detail 뷰* 는 `pk`변수가 필요한 거 기억하고 있겠죠? `pk=post.pk`를 사용해서 뷰에게 값을 넘겨줄 거에요. 여기서 `post`는 새로 생성한 블로그 글이에요. + +잘 했어요. 너무 설명이 길어졌네요. 이제 *view* 의 전체 코드를 확인할게요. + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +잘 작동하는지 확인해보세요. http://127.0.0.1:8000/post/new/ 페이지로 접속해서 `title`과 `text`를 입력하고, 저장하세요... 그리고.. 짜잔!!! 새로운 블로그 글이 추가되고 `post_detail` 페이지가 나타났어요! + +블로그 글을 저장하기 전에 출판일을 설정하고 싶나요. __장고 걸스 튜토리얼 심화 : (Django Girls Tutorial: Extensions)__ 에서 _publish button_ 에 대해 확인할 수 있어요. + +모두 잘 해냈어요! + +## 폼 검증하기 + +이제 장고 폼이 얼마나 멋진지 알아볼 차례에요. 블로그 글은 `title`과 `test` 필드가 반드시 있어야해요. 우리가 만든 `Post` 모델에서는 이 필드 값들이 필요없다고 했지만(`published_date`는 제외하고) 장고는 모두 기본 값으로 설정되어 있다고 생각합니다. + +`title`와 `text`가 없이 폼을 저장해보세요. 어떻게 될지 생각해보세요! + +![폼 검증하기][3] + + [3]: images/form_validation2.png + +장고는 모든 필드의 값이 올바른지 검증할 수 있답니다. 정말 멋지죠? + +> 앞서 우리가 사용한 장고 관리자 인터 페이스처럼 로그인 된 상태라고 생각해봅시다. 하지만 사용자가 로그아웃이 되는 상황이 발생하기도 하죠.(브라우저가 닫히거나, DB가 재시작된다던가 등) 만약 로그인 되지 않은 상태에서 새 글을 저장한다면, 사용자가 로그인되어있지 않아 누가 글을 작성한지 알 수 없어요. 때문에 글을 저장할 때 오류가 발생하고, 로그인시키도록 http://127.0.0.1:8000/admin 관리자 페이지가 나타나게 될 거에요. 이 문제는 금방 해결할 수 있어요. 다만 이건 이 튜터리얼 후에 해야할 __과제(Homework): 여러분의 사이트에 보안 추가하기__ 챕터로 남겨놓겠습니다. + +![로그인 오류 (Logged in error)][4] + + [4]: images/post_create_error.png + +## 폼 수정하기 + +지금까지 새 폼을 추가하는 방법에 대해 배웠어요. 하지만 이미 있던 글을 수정하려면 어떻게 해야할까요? 이 것도 앞서 했던 것과 매우 비슷해요. 빨리 해보도록 합시다!(만약 여러분이 뭔가 이해하지 못하는 부분이 있다면, 여러분의 코치에게 이전 챕터의 내용에 대해서 물어보고 차례대로 하나씩 해결해 나가야합니다) + +`blog/templates/blog/post_detail.html` 파일을 열어 아래 내용을 추가하세요: + +```python + +``` + +이제 템플릿이 아래처럼 보일 거에요. : + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +`blog/urls.py`에 아래 코드를 추가합니다. + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +우리는 `blog/templates/blog/post_edit.html` 템플릿을 재사용할 거에요. 마지막으로 할 일은 *view* 를 만드는 것입니다. + +`blog/views.py` 파일을 열어서 파일의 맨 밑에 코드를 추가해봅시다. : + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +음.. 코드가 `post_new`과 거의 비슷해보이지 않나요? 하지만 완전히 같지는 않아요. +첫 번째: url로부터 추가로 `pk` 매개변수를 받아서 처리합니다. +두 번째: `get_object_or_404(Post, pk=pk)`를 호출하여 수정하고자 하는 글의 `Post` 모델 `인스턴스(instance)`로 가져옵니다. (원하는 글은 pk를 이용해 찾습니다.) 이렇게 가져온 데이터를 폼을 만들 때와(글을 수정할 때 폼에 이전에 입력했던 데이터가 있어야 하겠죠?) 폼을 저장할 때 사용하게 됩니다. : + +```python +form = PostForm(request.POST, instance=post) +``` + +그리고 폼에 아래와 같이 수정했어요: + +```python +form = PostForm(instance=post) +``` + +잘했어요. 이제 잘 작동하는지 확인해보세요! `post_detail` 페이지로 가보세요. 거기에 우측 상단에 수정 버튼이 있어야 합니다. + +![수정 버튼(Edit button)][5] + + [5]: images/edit_button2.png + +수정 버튼을 누르면 우리가 쓴 블로그 글이 들어가 있는 폼을 볼 수 있을 거에요. + +![폼 수정하기][6] + + [6]: images/edit_form2.png + +자유롭게 제목과 텍스트를 수정하고 저장해보세요! + +축하합니다! 여러분의 어플리케이션이 점점 더 완벽해지고 있어요! + +장고 폼에 대해 자세한 정보가 필요하다면 공식 문서를 읽어보세요. : https://docs.djangoproject.com/en/1.8/topics/forms/ + +## 보안 + +링크를 클릭해 새로운 포스트가 나오게 만드는 것은 멋져요! 지금은 웹사이트를 방문하는 누구든지 글을 쓸 수 있지만, 그렇게 하고 싶지 않을 수 있어요. 나에게만 보이고 다른 사람에게는 보이지 않는 버튼을 만들어 볼게요. + +`blog/templates/blog/base.html` 파일에서, `page-header` `div`를 찾아 그 위에 아래와 같이 입력합니다. : + +```html + +``` + +여기에 `{% if %}` 태그를 추가해 관리자로 로그인한 유저들만 링크가 보일 수 있게 만들 거에요. 그게, 바로 여러분이죠! ``태그를 아래와 같이 변경하세요. : + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +이 `{% if %}`는 브라우저에 페이지를 요청 하는 사용자가 로그인 하는 경우 링크가 발생됩니다. 이는 새 게시글을 완전히 보호해주는 것은 아니지만, 바람직한 방법입니다. 이 부분은 튜토리얼 심화에서 좀더 자세히 다룰거에요. + +로그인 후, 페이지를 새로고침해야하는 경우, 아무것도 변화가 없으면 안되겠죠. 새로운 브라우저 시크릿 창에서 로그인해도 링크가 보이지 않아요! + +## 한 가지만 더: 배포하세요! + +모든 작업을 끝마쳤으면 PythonAnywhere로 배포해야죠! + +* 제일 먼저, 여러분의 코드를 커밋하고 Github로 푸시합니다. + +``` +$ git status +$ git add --all . +$ git status +$ git commit -m "Added views to create/edit blog post inside the site." +$ git push +``` + +* 그 다음 [PythonAnywhere Bash console(배시 콘솔)][7]을 여세요. : + + [7]: https://www.pythonanywhere.com/consoles/ + + ``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + ``` + +* 마지막으로 [웹 탭(Web tab)][8]에서 **다시 불러오기(Reload)** 를 누르세요. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +이제 배포가 완료 되었어요. 잘 작동되는지 확인하세요! 축하합니다. :) diff --git a/ko/django_forms/images/csrf2.png b/ko/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/ko/django_forms/images/csrf2.png differ diff --git a/ko/django_forms/images/drafts.png b/ko/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/ko/django_forms/images/drafts.png differ diff --git a/ko/django_forms/images/edit_button2.png b/ko/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/ko/django_forms/images/edit_button2.png differ diff --git a/ko/django_forms/images/edit_form2.png b/ko/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/ko/django_forms/images/edit_form2.png differ diff --git a/ko/django_forms/images/form_validation2.png b/ko/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/ko/django_forms/images/form_validation2.png differ diff --git a/ko/django_forms/images/images/csrf2.png b/ko/django_forms/images/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/ko/django_forms/images/images/csrf2.png differ diff --git a/ko/django_forms/images/images/drafts.png b/ko/django_forms/images/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/ko/django_forms/images/images/drafts.png differ diff --git a/ko/django_forms/images/images/edit_button2.png b/ko/django_forms/images/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/ko/django_forms/images/images/edit_button2.png differ diff --git a/ko/django_forms/images/images/edit_form2.png b/ko/django_forms/images/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/ko/django_forms/images/images/edit_form2.png differ diff --git a/ko/django_forms/images/images/form_validation2.png b/ko/django_forms/images/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/ko/django_forms/images/images/form_validation2.png differ diff --git a/ko/django_forms/images/images/new_form2.png b/ko/django_forms/images/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/ko/django_forms/images/images/new_form2.png differ diff --git a/ko/django_forms/images/images/post_create_error.png b/ko/django_forms/images/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/ko/django_forms/images/images/post_create_error.png differ diff --git a/ko/django_forms/images/new_form2.png b/ko/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/ko/django_forms/images/new_form2.png differ diff --git a/ko/django_forms/images/post_create_error.png b/ko/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/ko/django_forms/images/post_create_error.png differ diff --git a/ko/django_installation/README.md b/ko/django_installation/README.md new file mode 100755 index 00000000000..2630ddf2662 --- /dev/null +++ b/ko/django_installation/README.md @@ -0,0 +1,5 @@ +# Django 설치 + +> **Note** 만약 앞 장에서 이미 모든 설치를 마쳤다면 - 다음 장으로 바로 넘어가세요! + +{% include "/django_installation/instructions.md" %} diff --git a/ko/django_installation/instructions.md b/ko/django_installation/instructions.md new file mode 100755 index 00000000000..af2c27f7d8b --- /dev/null +++ b/ko/django_installation/instructions.md @@ -0,0 +1,114 @@ +> 이 장의 일부는 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots)의 튜토리얼을 기반으로 작성되었습니다. +> +> Creative Commons Attribution-ShareAlike 4.0 International License 에 따라 [django-marcador 튜토리얼](http://django-marcador.keimlink.de/)를 바탕으로 작성되었습니다. django-marcador 튜토리얼은 Markus Zapke-Gründemann et al에게 저작권이 있습니다. + +## 가상 환경 + +장고를 설치하기 전에, 개발 환경을 깔끔하게 관리하는데 큰 도움이 되는 도구를 설치해보겠습니다. 이 단계를 건너뛸 수 있지만, 한번 직접 해보는 것을 추천합니다. 제대로 설치해야 나중에 문제가 발생하지 않거든요! + +자, 이제부터 **가상 환경**(*virtualenv*라고 불러요)을 만들어보겠습니다. Virtualenv는 프로젝트 기초 전부를 Python/Django와 분리시켜줍니다. 다시 말해 웹사이트가 변경되어도 개발 중인 것에 영향을 미치지 않다는 것입니다. 어때요, 깔끔하죠? + +`virtualenv`를 만드는 데 필요한 것은 생성할 곳을 정하는 것 뿐입니다. 예를 들면, home 디렉토리와 같은 곳이면 적당합니다. 윈도우 환경에서는 `C:\Users\Name` 일 거에요. (`Name` 이라는 것은 윈도우에 로그인할 때 사용한 아이디를 말합니다.) + +이 튜토리얼에서는 home 디렉토리 아래 `djangogirls`라는 디렉토리를 새로 만들어 사용하도록 할게요. + + mkdir djangogirls + cd djangogirls + + +이제 `myenv` 라는 이름의 가상 환경을 만들어 볼게요. 아래와 같은 형식의 명령을 실행하세요. + + python3 -m venv myvenv + + +### 윈도우 + +`virtualenv`를 생성하려면 console창을 열고, (앞쪽 챕터에서 얘기했는데, 기억나죠?) 그리고 `C:\Python34\python -m venv myvenv`를 실행해야해요. 아마도 화면에는 이런 것들이 보이겠죠? + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + + +여기서 `C:\Python34\python` 은 파이썬이 설치된 디렉토리이고, `myvenv` 는 설치할 `가상 환경`의 이름이예요. 이름은 마음대로 정할 수 있지만, 소문자여야하고 공백은 없어야하고 특수문자도 사용하면 안돼요. 이름은 짧게 만드는 것이 좋아요. 자주 입력해야하니까요. + +### 리눅스와 맥OS + +리눅스와 맥에서 `virtualenv`를 생성하려면 간단하게 `python3 -m venv myvenv`를 실행하면 됩니다. 화면에 이렇게 나타날 거에요: + + ~/djangogirls$ python3 -m venv myvenv + + +여기서 `myvenv` 는 `가상 환경`의 이름이예요. 이름은 마음대로 정할 수 있지만, 소문자여야하고 공백은 없어야해요. 이름은 짧게 만드는게 좋아요. 자주 입력해야하니까요. + +> **주의:** 우분투 14.04 에서는 이런 오류가 뜰 수 있어요. +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> 이 문제를 해결하려면 `virtualenv` 명령을 사용해야해요. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## 가상환경 사용하기 + +앞의 명령을 사용하면 `myvenv`라는 디렉토리가 만들어져요. (이름을 다르게 했다면 그 이름의 디레토리가 만들어집니다.) 그리고 그 디렉토리에 우리가 사용할 가상 환경이 들어있어요. (디렉토리와 파일들이 있어요.) + +#### 윈도우 + +다음과 같이 가상환경을 실행하세요. + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +#### 리눅스와 맥OS + +다음과 같이 가상환경을 실행하세요. + + ~/djangogirls$ source myvenv/bin/activate + + +실행할 때 `myvenv` 부분에 자신이 선택한 `가상 환경`의 이름을 적어야 해요! + +> **주의:** 간혹 `source` 명령이 동작하지 않을 수도 있어요. 그럴 때는 이렇게 하세요. +> +> ~/djangogirls$ . myvenv/bin/activate +> + +`가상환경`이 실행되었는지는 콘솔의 프롬프트를 보면 알 수 있어요. + + (myvenv) C:\Users\Name\djangogirls> + + +또는 + + (myvenv) ~/djangogirls$ + + +앞쪽에 `(myvenv)`가 보이지요? + +가상 환경을 시작하고 나면 `python`이라고만 해도 지정한 버전의 파이썬이 실행되기 때문에 `python3` 대신 `python`이라고 입력해도 된답니다. + +자, 이제 필요한 것들이 준비되었어요. 드디어 장고를 설치할 수 있어요! + +## 장고 설치하기 + +이제 `virtualenv` 가 시작되었으니, `pip`를 이용해 장고를 설치할 수 있어요. 콘솔에서 `pip install django==1.8`를 실행해보세요. (조심하세요. 이퀄기호가 두 개예요: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +윈도우에서는 + +> 만약 윈도우에서 pip를 실행했는데 오류가 발생했다면 경로에 공백이나 특수문자가 없는지 (`C:\Users\User Name\djangogirls` 처럼요) 확인하세요. 만약 그렇다면 (`C:\djangogirls` 처럼) 공백이나 특수문자가 없는 곳으로 옮겨보세요. 옮긴 후에 다시 한 번 시도해보세요. + +리눅스에서는 + +> 우분투 12.04에서 오류가 발생했다면 `python -m pip install -U --force-reinstall pip` 명령으로 가상환경 내의 pip를 고쳐주세요. + +잘했어요! 드디어 장고 어플리케이션을 만들 준비가 끝났습니다! diff --git a/ko/django_models/README.md b/ko/django_models/README.md new file mode 100755 index 00000000000..38a569fbc66 --- /dev/null +++ b/ko/django_models/README.md @@ -0,0 +1,176 @@ +# Django 모델 + +이번에는 블로그 내 모든 포스트를 저장하는 부분을 만들 거에요. 먼저 우리는 `객체(object)`에 대해서 조금 알고 있어야해요. + +## 객체(Object) + +프로그래밍 개발 방법 중에는 `객체 지향 프로그래밍`이라 부르는 개념이 있어요. 이 개발 방법은 프로그램이 어떻게 작동해야하는지 모든 것을 하나하나 지시하는 것 대신, 모델을 만들어 그 모델이 어떤 역할을 가지고 어떻게 행동해야하는지 정의하여 서로 알아서 상호작용할 수 있도록 만드는 것입니다. + +그렇다면 객체란 무엇일까요? 객체란 속성과 행동을 모아놓은 것이라고 할 수 있어요. 낯설게 느껴지지만 예를 들어보면 별 것 아님을 알게 될 거에요. + +예를 들어 `고양이(Cat)`라는 객체를 모델링한다고 해볼게요. 이 고양이는 여러 속성을 가지고 있어요: `색깔`, `나이`, `분위기`(착한, 나쁜, 졸려워하는), `주인`(주인이 `사람`일 수도 있지만, 길고양이면 주인이 없으니 속성이 빈 값이 될 수 있어요.) 등이 될 수 있겠지요. + +또 `고양이는` 특정 행동을 할 수 있어요: `야옹야옹하기`, `긁기`, 또는 `먹기` 등이 있겠네요. (`맛`과, 고양이에게 `고양이먹이`는 행동하는 객체가 달라요). + + 고양이 + -------- + 색깔 + 나이 + 분위기 + 주인 + 야옹야옹하기() + 긁기() + 먹기(음식) + + 고양이먹이 + -------- + 맛 + + +기본적으로 객체지향설계 개념은 현실에 존재하는 것을 속성과 행위로 나타내는 것입니다. 여기서 속성은 `객체 속성(properties)`, 행위는 `메서드(methods)`로 구현됩니다). + +그렇다면 블로그 글을 모델로 만들 수 있을까요? 우리는 블로그를 만들고 싶잖아요, 그렇죠? + +우리는 다음 질문에 답할 수 있어야 해요: 블로그 글이란 무엇일까? 어떤 속성들을 가져야 할까? + +블로그는 제목과 내용이 필요하죠? 그리고 누가 썼는지도 알 수 있게 작성자(author) 도 추가하면 좋을 것 같아요. 마지막으로, 그 글이 작성된 날짜와 게시된 날짜도 알면 좋겠어요. + + Post + -------- + title + text + author + created_date + published_date + + +블로그 글로 할 수 있는 것은 어떤 것들이 있을까요? 글을 출판하는 `메서드(method)`가 있으면 좋겠죠? + +그래서 우리는 `publish` 메서드도 만들어야 합니다. + +이제 무엇을 만들어야하는지 이미 알았으니, 장고에서 모델을 만들어 봅시다! + +## 장고 모델 + +객체(object) 가 어떻게 구성되어야 하는지 이전에 살펴봤으니, 이번에는 블로그 글을 위한 장고 모델을 만들어봅시다. + +장고 안의 모델은 객체의 특별한 종류입니다. 이 모델을 저장하면 그 내용이 `데이터베이스`에 저장되는 것이 특별한 점이죠. 데이터베이스란 데이터의 집합입니다. 데이터들이 모아져 있는 곳이지요. 이곳에 유저에 대한 정보나 여러분의 블로그 글 등등이 저장되어 있습니다. 우리는 데이터를 저장하기 위해서 여러가지 데이터베이스를 입맛에 맞게 고를 수 있는데요, 여기서는 SQLite 데이터베이스를 사용하겠습니다. 'Sqlite 데이터베이스는 기본 장고 데이터베이스 어댑터입니다.' 라는 것까지만 알고 있어도 충분해요. 어댑터가 무엇인지를 알려면 내용이 너무 길어지니 일단 여기까지만 알고 계세요. + +쉽게 말해 데이터베이스안의 모델이란 엑셀 스프레드시트와 같다고 말할 수 있어요. 엑셀 스프레드시트를 보면 열(필드) 와 행(데이터) 로 구성되어 있죠? 모델도 마찬가지입니다. + +### 어플리케이션 제작하기 + +잘 정돈된 상태에서 시작하기 위해, 프로젝트 내부에 별도의 어플리케이션을 만들어볼 거에요. 처음부터 모든 것이 잘 준비되어있다면 훌륭하죠. 어플리케이션을 만들기 위해 콘솔창(`djangogirls` 디렉토리에서 `manage.py` 파일)에서 아래 명령어를 실행하세요. + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +이제 `blog` 디렉토리가 생성되고 그 안에 여러 파일들도 같이 들어있는 것을 알 수 있어요. 현재 디렉토리와 파일들은 다음과 같을 거에요. : + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +어플리케이션을 생성한 후 장고에게 사용해야한다고 알려줘야 합니다. 이 역할을 하는 파일이 `mysite/settings.py`입니다. 이 파일 안에서 `INSTALLED_APPS`를 열어, `)`바로 위에 `'blog'`를 추가하세요. 최종 결과물은 아래와 다음과 같을 거에요. + +```python + INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', + ) +``` + +### 블로그 글 모델 만들기 + +모든 `Model` 객체는 `blog/models.py` 파일에 선언하여 모델을 만듭니다. 이 파일에 우리의 블로그 글 모델도 정의할 거에요. + +`blog/models.py` 파일을 열어서 안에 모든 내용을 삭제한 후 아래 코드를 추가하세요. : + +```python + from django.db import models + from django.utils import timezone + + + class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> `str`양 옆에 언더스코어(`_`) 를 두 개씩 넣었는지 다시 확인하세요. 이건 관습은 파이썬에서 자주 사용되는데, "던더(dunder; 더블-언더스코어의 준말)"라고도 불려요. + +으음... 코드가 좀 무서워졌죠? 걱정마세요. 각 줄마다 어떤 의미인지 설명해드릴거에요. + +`from` 또는 `import`로 시작하는 부분은 다른 파일에 있는 것을 추가하라는 뜻입니다. 다시 말해, 매번 다른 파일에 있는 것을 복사&붙여넣기로 해야하는 작업을 `from이 대신 불러와주는 거죠 .

+ +

class Post(models.Model):`는 모델을 정의하는 코드입니다. (모델은 `객체(object)`라고 했죠?). + +* `class`는 특별한 키워드로, 객체를 정의한다는 것을 알려줍니다. +* `Post`는 모델의 이름입니다. (특수문자와 공백 제외한다면) 다른 이름을 붙일 수도 있습니다. 항상 클래스 이름의 첫 글자는 대문자로 써야 합니다. +* `models.Model`은 Post가 장고 모델임을 의미합니다. 이 코드 때문에 장고는 Post가 데이터베이스에 저장되어야 된다고 알게 됩니다. + +이제 속성을 정의하는 것에 대해서 이야기 해볼게요. : `title`, `text`, `created_date`, `published_date`, `author`에 대해서 말할 거에요. 속성을 정의하기 위해, 각 필드마다 어떤 종류의 데이터 타입을 가지는지를 정해야해요. 여기서 데이터 타입에는 텍스트, 숫자, 날짜, 유저 같은 다른 객체 참조 등이 있습니다. + +* `models.CharField` - 글자 수가 제한된 텍스트를 정의할 때 사용합니다. 글 제목같이 대부분의 짧은 문자열 정보를 저장할 때 사용합니다. +* `models.TextField` - 글자 수에 제한이 없는 긴 텍스트를 위한 속성입니다. 블로그 콘텐츠를 담기 좋겠죠? +* `models.DateTimeField` - 이것은 날짜와 시간을 의미합니다. +* `models.ForeignKey` - 다른 모델이 대한 링크를 의미합니다. + +시간 관계 상 모든 코드들을 하나하나 다 설명하지는 않을 거에요. 대신 모델의 필드와 정의하는 방법에 궁금하다면 아래 장고 공식 문서를 꼭 읽어보길 바랍니다. (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +`def publish(self):`는 무슨 뜻일까요? 이 것이 바로 앞서 말했던 `publish`라는 메서드(method) 입니다. `def`는 이 것이 함수/메서드라는 뜻이고, `publish`는 메서드의 이름입니다. 원한다면 메서드 이름을 변경할 수도 있어요. 이름을 붙일 때는 공백 대신, 소문자와 언더스코어를 사용해야 합니다. 예를 들어, 평균 가격을 계산하는 메서드는 `calculate_average_price`라고 부를 수 있겠네요. + +메서드는 자주 무언가를 되돌려주죠. (`return`) 그 예로 `__str__` 메서드를 봅시다. 이 시나리오대로라면, `__str__`를 호출하면 Post 모델의 제목 텍스트(**string**) 를 얻게 될 거에요. + +아직 모델에 대해서 잘 모르는 부분이 있다면, 코치에게 자유롭게 물어보세요! 지금 배운 내용이 너무 복잡하게 느껴질 수 있어요. 객체와 함수를 배운 적이 없는 분들이 한꺼번에 배우게 된다면 특히 그렇겠죠. 그래도 해 볼 만한 마법이라고 생각했으면 좋겠어요! + +### 데이터베이스에 모델을 위한 테이블 만들기 + +이 장의 마지막 단계입니다. 이제 데이터베이스에 우리의 새 모델, Post 모델을 추가할 거에요. 먼저 우리는 장고 모델에 (우리가 방금 만든!) 몇 가지 변화가 생겼다는 걸 알게 해줘야 합니다. `python manage.py makemigrations blog` 를 입력해 보세요. 아마도 화면에 이렇게 보이겠죠? + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +장고는 데이터베이스에 지금 반영할 수 있도록 마이그레이션 파일(migration file)이라는 것을 준비해 두었답니다. 이제 `python manage.py migrate blog` 명령을 실행해, 실제 데이터베이스에 모델 추가를 반영하겠습니다. : + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK + + +만세! 드디어 글 모델이 데이터베이스에 저장되었습니다. 너무 멋지 않나요? 빨리 다음 장으로 넘어가서 블로그 글을 확인하러 가요! diff --git a/ko/django_orm/README.md b/ko/django_orm/README.md new file mode 100755 index 00000000000..b725c84a6ce --- /dev/null +++ b/ko/django_orm/README.md @@ -0,0 +1,157 @@ +# Django ORM과 QuerySets + +이번 장에서는 장고를 데이터베이스에 연결, 데이터를 저장하는 방법에 대해서 알아볼 거에요. 함께 시작해봅시다! + +## 쿼리셋(QuerySet)이란 무엇인가요? + +핵심만 말하자면, 쿼리셋은 전달받은 모델의 객체 목록입니다. 쿼리셋은 데이터베이스로부터 데이터를 읽고, 필터를 걸거나 정렬을 할 수 있습니다. + +가장 쉽게 배우는 방법은 예제로 배우는 것이죠. 함께 해볼까요? + +## 장고 쉘(shell) + +PythonAnywhere가 아닌 로컬 컨솔에서 아래 명령을 입력하세요. : + + (myvenv) ~/djangogirls$ python manage.py shell + + +실행하면 아래처럼 나올 거에요. + + (InteractiveConsole) + >>> + + +여러분은 이제 장고 인터랙티브 콘솔(interactive console) 로 들어왔습니다. 파이썬 프롬프트와 비슷하지만 장고만의 마법을 부릴 수 있는 곳이기도 하지요. :) 물론 파이썬의 모든 명령어를 여기서 사용할 수 있습니다. + +### 모두 보기 + +자, 이제 먼저 입력했던 모든 글들을 출력하겠습니다. 아래와 같이 입력하세요. + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +이런! 에러가 나타났어요. 글이 없다고 하네요. 이럴수가... 그런데 이렇게 나오는 것이 맞는 거랍니다. 이 글을 먼저 불러오는 것(import)을 잊었네요! + + >>> from blog.models import Post + + +간단합니다. : 우리는 `Post`모델을 `blog.models`에서 불러왔어요. 이제 모든 글들을 출력해봅시다. + + >>> Post.objects.all() + [, ] + + +우리가 만들었던 그 글 목록이 나타났네요! 장고 관리자 인터페이스로 만들었던 것들이에요. 그런데 파이썬으로 새 글을 포스팅하려면, 어떻게 해야할까요? + +### 객체 생성하기 + +데이터베이스에 새 글 객체를 저장하는 방법에 대해 알아봅시다. + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +하지만 여기에 뭔가 빼먹은 것이 하나 있어요.: `me` (나) 를 빼먹었네요. 작성자로서 `User`(사용자) 모델의 인스턴스를 가져와 전달해줘야 합니다. 어떻게 해야 할까요? + +먼저 User 모델을 불러옵니다. : + + >>> from django.contrib.auth.models import User + + +데이터베이스에서 user는 어떤 일을 할까요? 함께 알아봅시다. : + + >>> User.objects.all() + [] + + +슈퍼유저로 등록했었던 그 사용자군요! 이제 이 사용자의 인스턴스(instance)를 가져와 봅시다. : + + me = User.objects.get(username='ola') + + +보셨듯이, `유저이름(username)`이 'ola'인 `User` 인스턴스를 받아왔어요. 사용자 이름을 바꿨다면, 바뀐 이름을 넣어줘야겠죠. + +드디어 우리 게시물을 만들었네요. : + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +만세! 그런데 제대로 작동했는지 확인해봐야죠? + + >>> Post.objects.all() + [, , ] + + +보세요, 목록에 게시글 하나가 더 늘었네요! + +### 글 더 추가하기 + +점점 재밌어질 거에요. 몇 개 글을 더 추가해서 잘 작동하는지 확인하세요. 2-3개 정도만 더 추가해보고 다음 내용으로 넘어갈게요. + +### 필터링하기 + +쿼리셋의 중요한 기능은 데이터를 필터링하는 거에요. 예를 들어, 우리는 ola라는 User가 작성한 모든 글을 찾고 싶다고 해볼게요. 이런 경우 `Post.objects.all()`에서 `all` 대신, `filter`를 사용합니다. 쿼리셋 안에 있는 괄호 안에 우리가 원하는 조건(들)을 넣어줄 거에요. 지금 이 경우에는 `author`가 `me`인 조건을 넣어야겠죠. 이걸 장고로 표현한다면 `author=me`가 됩니다. 이제 이 조건이 반영된 코드를 볼까요. : + + >>> Post.objects.filter(author=me) + [, , , ] + + +또는 모든 글들 중, `제목(title)`에 'title'이라는 글자가 들어간 글들만을 뽑아내서 보고 싶다면요? + + >>> Post.objects.filter( title__contains='title' ) + [, ] + + +> **Note** `title`와 `contains` 사이에 있는 밑줄(`_`)이 2개입니다. 장고 ORM은 필드 이름("title")과 연산자과 필터("contains")를 밑줄 2개를 사용해 구분합니다. 밑줄 1개만 입력한다면, "FieldError: Cannot resolve keyword title_contains"라는 오류가 뜰 거에요. + +우리는 출판된 글 목록을 볼 수 있어요. 이를 위해 `출판 날짜(published_date)`가 과거인 글들을 필터링하면 가져오면 되겠죠. + + >>> from django.utils import timezone + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + +안타깝게도, 파이썬 콘솔에서 추가한 게시물은 아직 보이지 않네요. 하지만 바꿀 수 있어요! 먼저 게시하려는 게시물의 인스턴스를 얻어야 해요. : + + >>> post = Post.objects.get(title="Sample title") + + +그리고 `publish` 메서드를 사용해서 출판합시다! + + >>> post.publish() + + +이제 (위쪽 화살표 버튼 3번을 누르고 `enter`를 눌러) 다시 게시된 글의 목록을 가져와 봅시다. + + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + + +### 정렬하기 + +퀘리셋은 객체 목록을 정렬도 할 수 있어요. 이제 `created_date` 필드를 정렬해봅시다. : + + >>> Post.objects.order_by('created_date') + [, , , ] + + +`-`을 맨 앞에 붙여주면 내림차순으로 정렬도 가능해요. : + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +### 쿼리셋(QuerySets) 연결하기 + +쿼리셋들을 함께 **연결(chaining)**할 수도 있어요. + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +이 방법은 정말 강력해 복잡한 쿼리도 작성할 수 있게 해준답니다. + +좋아요! 이제 다음 내용으로 넘어갈 때로군요! 다음 명령을 입력해, 쉘을 종료하세요. : + + >>> exit() + $ diff --git a/ko/django_start_project/README.md b/ko/django_start_project/README.md new file mode 100755 index 00000000000..6df66517785 --- /dev/null +++ b/ko/django_start_project/README.md @@ -0,0 +1,137 @@ +# 나의 첫 번째 Django 프로젝트! + +> 이번 장은 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) 의 튜토리얼을 바탕으로 작성되었습니다. +> +> 이번 장의 일부는 Creative Commons Attribution-ShareAlike 4.0 International License를 준수하여 [django-marcador tutorial][1]을 바탕으로 작성되었습니다. Django-marcador 튜토리얼은 Markus Zapke-Gründemann et al에게 저작권이 있습니다. + + [1]: http://django-marcador.keimlink.de/ + +이제 우리는 아주 간단한 블로그를 만들어 볼 거에요! + +첫 단계는 장고 프로젝트를 시작하는 거에요. 다시 말해 장고의 기본 골격을 만들어주는 스크립트를 실행할 거에요. 이 디렉토리와 파일 묶음은 나중에 사용할 것입니다. + +장고에서는 디렉토리나 파일 이름이 매우 중요하답니다. 우리가 생성할 그 파일들의 이름을 마음대로 변경해서는 안됩니다. 또한 그 파일들을 다른 곳으로 옮겨도 안됩니다. 장고는 중요한 것들을 찾을 수 있게 특정한 구조를 유지해야합니다. + +> 모든 것은 가상환경(virtualenv) 안에서 해야한다는 것을 기억하세요. 현재 콘솔창에서 접두어로 `(myvenv)`가 안보인다면 먼저 virtualenv를 활성화해야 합니다. **Django 설치하기**장의 **virtualenv 작동법**에서 이미 다루었던 내용입니다. 윈도우에서는 `myvenv\Scripts\activate`를 타이핑하고 Mac OS / Linux에서는 `source myvenv/bin/activate`을 입력하세요. + +맥과 리눅스 콘솔에서는 다음과 같이 명령을 실행해야해요. **명령어 끝에 `.`(점, 마침표) 을 입력하는 것을 잊지마세요.** : + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +윈도우에서도 **명령 끝에 `.`(점) 을 입력하는 것을 잊지마세요.**: + + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> 점 `.`은 현재 디렉토리에 장고를 설치하라고 스크립트에 알려주기 때문에 중요해요. (축약된 표시입니다) +> +> **Note** 위 명령을 입력할 때 `django-admin` 또는 `django-admin.py`로 시작하는 부분만 입력하세요. 여기에 보이는 `(myvenv) ~/djangogirls$`과 `(myvenv) C:\Users\Name\djangogirls>` 부분은 커맨드라인에 입력을 가져오게 하는 메세지(프롬트프 prompt) 입니다. + +`django-admin.py`은 스크립트로 디렉토리와 파일들을 생성합니다. 스크립트 실행 후에는 아래와 같이 새로 만들어진 디렉토리 구조를 볼 수 있을 거에요. + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +`manage.py` 파일 또한 스크립트인데, 사이트 관리를 도와주는 역할을 합니다. 이 스크립트로 다른 설치 작업 없이, 컴퓨터에서 웹 서버를 시작할 수 있습니다. + +`settings.py`는 웹사이트 설정이 있는 파일입니다. + +앞에 우편 배달부는 어느 곳으로 편지를 배달해야하는지 판단해야한다고 말했던 것을 기억하고 있나요? `urls.py` 파일은 `urlresolver`가 사용하는 패턴 목록을 포함하고 있습니다. + +지금 그 파일들을 수정하지 않을 거니 무시하세요. 실수로 파일을 지우지 않게 조심하세요! + +## 설정 변경 + +`mysite/settings.py`을 조금 고쳐 볼게요. 설치한 코드 에디터를 열어 파일을 열어주세요. + +웹사이트에 정확한 현재 시간을 넣으면 좋겠죠. [위키피디아 타임존 리스트][2]에 가서 해당 시간대(타임존) 를 복사하세요. (예: `Europe/Berlin`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +Settings.py에서 `TIME_ZONE`있는 줄을 찾으세요. 그리고 이를 해당 시간대로 변경하세요. + +```python + TIME_ZONE = 'Asia/Seoul' +``` + +"Asia/Seoul"를 수정하세요. + +다음으로 정적파일 경로를 추가할 거에요. (정적 파일은 튜토리얼 후반부에서 CSS와 함께 다룰 거에요) 파일의 *끝(end)*으로 내려가서, `STATIC_URL`항목 바로 아래에 `STATIC_ROOT`을 추가하세요. : + +```python + STATIC_URL = '/static/' + STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## 데이터베이스 설정하기 + +사이트 내 데이터를 저장하기 위한 많은 다양한 데이터베이스 소프트웨어들이 있습니다. 그 중에서 우리는 `sqlite3`을 사용할 거에요. + +사실 이미 `mysite/settings.py` 파일 안에 설치가 되어있어요. : + +```python + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } +``` + +블로그에 데이터베이스를 생성하기 위해서 콘솔창에서 아래 코드를 실행하세요: `python manage.py migrate` (이 명령을 실행하기 위해서는 `djangogirls`디렉토리 안에 있는 `manage.py` 필요합니다) 잘 작동되면, 아래와 같은 내용이 나옵니다. : + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK + + +잘했네요! 이제 웹 서버를 시작해 웹사이트가 잘 작동하는지 확인해봐요! + +프로젝트 디렉토리(the `djangogirls` directory)에 `manage.py` 파일이 있어야 합니다. 콘솔에서는 `python manage.py runserver` 명령을 실행해, 웹서버를 바로 시작할 수 있습니다. : + + (myvenv) ~/djangogirls$ python manage.py runserver + + +윈도우에서 `UnicodeDecodeError`를 썼는데 오류가 난다면 아래 명령을 대신 써보세요. : + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +웹 사이트가 모두 잘 작동하는지 확인해봐요. 사용하는 브라우져(파이어폭스, 크롬, 사파리, 인터넷 익스플로어 등 여러분의 원하는대로)를 열어서 주소를 입력하세요. : + + http://127.0.0.1:8000/ + + +웹서버는 멈출 때까지 명령 프롬프를 실행할 거에요. 실행 중 다른 명령을 입력하려면 새로운 창을 열어 virtualenv를 활성화시키면 됩니다. 웹 서버를 중지하려면, 실행되고 있는 창으로 돌아가 CTRL+C를 동시에 누르세요. (윈도우라면, Ctrl+Break를 눌러야 할지도 모릅니다) + +축하해요! 여러분은 방금 웹 서버를 활용한 첫 웹사이트를 만들었어요! 정말 멋지죠? + +![잘 작동합니다!][3] + + [3]: images/it_worked2.png + +다음 단계로 넘어갈 준비가 되셨나요? 이제는 새로운 내용을 만들어 볼 시간이에요! diff --git a/ko/django_start_project/images/images/it_worked2.png b/ko/django_start_project/images/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/ko/django_start_project/images/images/it_worked2.png differ diff --git a/ko/django_start_project/images/it_worked2.png b/ko/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/ko/django_start_project/images/it_worked2.png differ diff --git a/ko/django_templates/README.md b/ko/django_templates/README.md new file mode 100755 index 00000000000..5caa17c549c --- /dev/null +++ b/ko/django_templates/README.md @@ -0,0 +1,107 @@ +# Django 템플릿 + +이제 데이터를 보여줄 차례에요! 이를 위해 장고는 내장된 __template tags__ 라는 유용한 기능을 제공합니다. + +## 템플릿 태그는 무엇인가요? + +HTML에 여러분은 파이썬 코드를 바로 넣을 수 없어요. 브라우져는 파이썬 코드를 이해할 수 없기 때문이에요요 브라우저는 HTML만을 알고 있어요. 알다시피 HTML는 정적이지만, 파이썬은 동적입니다. + +__장고 템플릿 태그(Django template tags)__ 는 파이썬을 HTML로 바꿔주어, 빠르고 쉽게 동적인 웹사이트를 만들 수 있게 도와주어요. 야호! + +## post 목록 템플릿 보여주기 + +이전 장에서 글 목록이 들어있는 `posts` 변수를 템플릿에 넘겨주었습니다. 이제 넘겨진 posts 변수를 받아서 HTML에 나타나도록 해볼 차례예요. + +장고 템플릿 안에 있는 값을 출력하려면, 변수 이름안에 중괄호를 넣어 표시해야합니다. 이렇게요. : + +```html +{{ posts }} +``` + +`blog/templates/blog/post_list.html` 템플릿에서 하세요. 두 번째 `

`에서 세 번째 `
`까지를 `{{ posts }}`로 바꾸세요. 파일을 저장하고 페이지를 새로 고침하면 이렇게 보입니다. : + +![그림 13.1][1] + + [1]: images/step1.png + +우리는 아래와 같이 만들었어요. : + + [, ] + + +이는 장고가 {{ posts}} 를 객체들의 목록으로 이해하고 처리했다는 것을 의미해요. **파이썬 들어가기** 에서 어떻게 목록을 보여줬는지 기억하고 있나요? 맞아요, for loop을 이용해서죠! 장고 템플릿에서는 이렇게 해야합니다. : + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +여러분의 템플릿 파일에 적용해 보세요. + +![그림 13.2][2] + + [2]: images/step2.png + +잘 작동하네요! 그런데 디자인이 별로죠. 앞에서 __HTML 소개__ 챕터에서 했던 정적 글들처럼 보이면 참 좋을텐데 말이에요. HTML과 템플릿 태그를 섞어 사용하면 멋있게 만들 수 있어요. 우리의 `body`는 다음과 같을 거에요. : + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %} `{% for %}` 와 `{% endfor %}`사이에 넣은 모든 것은 목록의 모든 객체를 반복하게 됩니다. 페이지를 새로고침 해보세요: {% endraw %} + +![그림 13.3][3] + + [3]: images/step3.png + +`{{ post.title }}`라던가 `{{ post.text }}` 같이 이전과 다른 표기법을 사용한 것을 눈치 채셨나요? `Post` 모델에서 정의한 각 필드의 데이터에 접근하기 위해 이 표기법을 사용합니다. 또한 `|linebreaksbr` 같이 파이프 문자(|)도 사용해요. 이건 블로그 글 텍스트에서 행이 바뀌면 문단으로 변환하도록 하라는 의미입니다. 행바뀜을 문단으로 변환하는 필터를 적용한다는 표현을 쓰기도 합니다. + +## 한 가지 더 + +나혼자만 웹 사이트를 보는게 아니라 다른 사람들도 인터넷으로 볼 수 있으면 참 좋겠죠? 이제 PythonAnywhere에 다시 여러분이 만든 블로그를 배포해봅시다. 아래에 각 단계별로 요약했어요. + +* 제일 먼저, Github에 여러분의 코드를 git의 push를 사용해서 넣으세요. + +``` +$ git status +[...] +$ git add --all . +$ git status +[...] +$ git commit -m "Modified templates to display posts from database." +[...] +$ git push +``` + +* 다음 [PythonAnywhere][4]로 돌아와 **배시 콘솔창(Bash console)** 으로 가서(또는 이미 닫았다면 새 콘솔창을 여세요), 다음 명령어를 실행하세요. : + + [4]: https://www.pythonanywhere.com/consoles/ + + ``` + $ cd my-first-blog + $ git pull + [...] + ``` + +* 마지막으로 [웹 탭(Web tab)][5]에서 **다시 불러오기(Reload)** 를 누르세요. 업데이트가 보여야 해요! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +축하합니다! 이제 장고 관리자로 가서 새로운 블로그 글을 추가하고(출판 날짜를 추가하는 것을 잊지 마세요!) 다시 새로고침 하세요. 그러면 새 글이 보일 거에요. + +잘 작동하니까 멋지죠? 참 자랑스러워요! 잠시 쉬고 오세요. :) + +![그림 13.4][6] + + [6]: images/donut.png diff --git a/ko/django_templates/images/donut.png b/ko/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/ko/django_templates/images/donut.png differ diff --git a/ko/django_templates/images/images/donut.png b/ko/django_templates/images/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/ko/django_templates/images/images/donut.png differ diff --git a/ko/django_templates/images/images/step1.png b/ko/django_templates/images/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/ko/django_templates/images/images/step1.png differ diff --git a/ko/django_templates/images/images/step2.png b/ko/django_templates/images/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/ko/django_templates/images/images/step2.png differ diff --git a/ko/django_templates/images/images/step3.png b/ko/django_templates/images/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/ko/django_templates/images/images/step3.png differ diff --git a/ko/django_templates/images/step1.png b/ko/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/ko/django_templates/images/step1.png differ diff --git a/ko/django_templates/images/step2.png b/ko/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/ko/django_templates/images/step2.png differ diff --git a/ko/django_templates/images/step3.png b/ko/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/ko/django_templates/images/step3.png differ diff --git a/ko/django_urls/README.md b/ko/django_urls/README.md new file mode 100755 index 00000000000..d95aee15c73 --- /dev/null +++ b/ko/django_urls/README.md @@ -0,0 +1,121 @@ +# Django urls + +첫 웹페이지를 만들어 보기로 해요. : 여러분의 블로그를 위한 홈페이지요! 하지만 먼저 장고 url에 대해서 조금 배워보기로 합시다. + +## URL이란 무엇인가요? + +URL은 단순히 웹 주소랍니다. 웹사이트를 방문할 때마다 URL을 볼 수 있죠. 브라우저의 주소창에 보이죠, 맞아요! `127.0.0.1:8000`가 바로 URL이에요! 그리고 `https://djangogirls.org` 또한 URL이랍니다. : + +![URL][1] + + [1]: images/url.png + +인터넷에 있는 모든 페이지들은 자신만의 URL을 가지고 있어야 해요. 이런 방식으로 어플리케이션은 URL을 입력한 사용자에게 어떤 내용을 보여줘야 할지 알게 됩니다. 장고는 `URLconf` (URL configuration)를 사용합니다. URLconf는 장고에서 URL과 일치하는 뷰를 찾기 위한 패턴들의 집합입니다. + +## Django에서 URL은 어떻게 작동할까요? + +코드 에디터에서 `mysite/urls.py`파일을 열면 아래와 같을 거예요. : + +```python + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + ] +``` + +장고가 이미 어떤 내용을 넣어 두었네요. + +`#`로 시작되는 줄은 주석이에요. 이 말은 파이썬은 이 줄을 실행하지 않는다는 뜻이지요. 꽤 유용하겠죠? + +이전 장에서 봤던 관리자 URL도 여기에 이미 있어요. : + + url(r'^admin/', include(admin.site.urls)), + + +이 의미는 `admin/`으로 시작하는 모든 URL을 장고가 *view*와 대조해 찾아낸다는 뜻입니다. 이 경우 많은 admin URL을 포함해야 하기 때문에 작은 파일안에 모두 들어가지 않아요. 여기에 좀 더 읽기 좋고 깔끔한 방법이 있어요. + +## 정규표현식(Regex) + +장고가 URL을 뷰에 매칭시키는 방법이 궁금하죠? 이 부분은 조금 까다로울 수 있어요. 장고는 `regex`를 사용하는데, "정규표현식(regular expressions)"의 줄임말입니다. 정규식은 정말 (아주!) 많은 검색 패턴의 규칙을 가지고 있어요. 정규식은 심화 내용이기 때문에, 자세한 내용은 다루지 않을 거예요. + +패턴을 만드는 방법이 궁금하다면, 아래에 있는 표기법을 확인하세요. 우리는 패턴을 찾는데 필요한 몇 가지 규칙만 필요합니다. : + + ^ 문자열이 시작할 때 + $ 문자열이 끝날 때 + \d 숫자 + + 바로 앞에 나오는 항목이 계속 나올 때 + () 패턴의 부분을 저장할 때 + + +이외에 url 정의는 문자적으로 만들 수 있어요. + +이런 사이트 주소가 있다고 해봅시다. : `http://www.mysite.com/post/12345/` 여기에서 `12345`는 글 번호를 의미합니다. + +뷰마다 모든 글 번호을 작성하는 것은 정말 힘든 일이 될 거에요. 정규 표현식으로 url과 매칭되는 글 번호를 뽑을 수 있는 패턴을 만들 수 있어요. 이렇게 말이죠. : `^post/(\d+)/$`. 어떤 뜻인지 하나씩 나누어 어떤 뜻인지 알아볼게요. : + +* **^post/**는 장고에게 url 시작점에 (오른쪽부터) `post/`가 있다는 것을 말해 줍니다. `^`) +* **(\d+)**는 숫자(한 개 또는 여러개) 가 있다는 뜻입니다. 내가 뽑아내고자 글 번호가 되겠지요. +* **/**는 장고에게 `/`뒤에 문자가 있음을 말해 줍니다. +* **$**는 URL의 끝이 방금 전에 있던 `/`로 끝나야 매칭될 수 있다는 것을 나타냅니다. + +## 나의 첫 번째 Django url! + +첫 번째 URL을 만들어 봅시다! 우리는 'http://127.0.0.1:8000/'가 홈페이지 주소로 만들어 글 목록이 보이게 만들어 볼 거에요. + +또한 `mysite/urls.py`파일을 깨끗한 상태로 유지하기 위해, `blog` 어플리케이션에서 메인 `mysite/urls.py`파일로 url들을 가져올 거에요. + +먼저 `#`로 시작하는 줄을 삭제하고 main url ('')로 `blog.urls`를 가져오는 행을 추가해 봅시다. + +이제 `mysite/urls.py` 파일은 아래처럼 보일 거에요. + + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), + ] + + +지금 장고는 'http://127.0.0.1:8000/'로 들어오는 모든 접속 요청을 `blog.urls`로 전송하고 추가 명령을 찾을 거예요. + +파이썬에서 정규 표현식을 작성할 때는 항상 문자열 앞에 `r`을 붙입니다. 이는 파이썬에게는 별 의미가 없지만, 파이썬에게 문자열에 특수 문자를 있다는 것을 알려줍니다. + +## blog.urls + +`blog/urls.py`이라는 새 파일을 생성하세요. 좋아요! 이제 다음 두 줄을 추가하세요. + + from django.conf.urls import url + from . import views + + +우리는 장고의 메소드와 `blog` 어플리케이션에서 사용할 모든 `views`들을 불러오고 있어요. (물론 아직 뷰를 하나도 안 만들었지만, 곧 만들 거니 조금만 기다리세요!) + +그다음, 첫 번째 URL 패턴을 추가하세요. + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + ] + + +이제 `post_list`라는 이름의 `view`가 `^$` URL에 할당되었습니다. 이 정규표현식은 `^`에서 시작해 `$`로 끝나는 지를 매칭할 것입니다. 즉 문자열이 아무것도 없는 경우만 매칭하겠죠. 틀린 것이 아니에요. 왜냐하면 장고 URL 확인자(resolver)는 'http://127.0.0.1:8000/' 는 URL의 일부가 아니기 때문입니다. 이 패턴은 장고에게 누군가 웹사이트에 'http://127.0.0.1:8000/' 주소로 들어왔을 때`views.post_list`를 보여주라고 말할 거에요. + +마지막 부분인 `name='post_list'` 는 URL에 이름을 붙인 것으로 뷰를 식별합니다. 이 부분은 뷰의 이름과 같을 수도 완전히 다를 수도 있습니다. 이름을 붙인 URL은 프로젝트의 후반에 사용할 거에요. 그러니 앱의 각 URL을 이름짓는 것은 중요합니다. 또 URL에 고유한 이름을 붙여, 외우고 부르기 쉽게 만들어야 해요. + +모두 잘 되고 있나요? http://127.0.0.1:8000/ 으로 접속해 결과를 확인해보세요. + +![Error][2] + + [2]: images/error1.png + +이런, 잘 "작동" 하는 것 같지 않다구요? 걱정마세요. 이건 그냥 오류 페이지에요. 그러니 무서워하지마세요! 오류는 꽤 유용하게 쓰인 답니다. : + +페이지에서 **no attribute 'post_list'**라는 오류가 보일 거에요. *post_list*에서 혹시 떠오르는 것이 있나요? 바로 뷰(view) 를 말하는 거죠! 모두 준비가 되었다는 뜻이에요. 아직 *view*를 안 만들었다는 것만 빼고요. 걱정 마세요. 금방 만들어 볼 거에요. + +> 장고 URL 설정에 대해 더 알고 싶다면 공식 문서를 읽어보세요. : https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/ko/django_urls/images/error1.png b/ko/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/ko/django_urls/images/error1.png differ diff --git a/ko/django_urls/images/images/error1.png b/ko/django_urls/images/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/ko/django_urls/images/images/error1.png differ diff --git a/ko/django_urls/images/images/url.png b/ko/django_urls/images/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/ko/django_urls/images/images/url.png differ diff --git a/ko/django_urls/images/url.png b/ko/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/ko/django_urls/images/url.png differ diff --git a/ko/django_views/README.md b/ko/django_views/README.md new file mode 100755 index 00000000000..f84358f74d8 --- /dev/null +++ b/ko/django_views/README.md @@ -0,0 +1,38 @@ +# Django 뷰 만들기 + +지난 장에서 만들었던 버그를 잡을 시간이 왔어요 :) + +뷰(*view*) 는 어플리케이션의 "로직"을 넣는 곳이에요. 뷰는 앞 챕터에서 만들었던 `모델`에게서 필요한 정보를 받아와서 `템플릿`에 전달하는 역할을 합니다. 다음 장에서 템플릿을 만들어 볼 거에요. 뷰는 **파이썬 들어가기** 장에서 했던 것 보다 조금 복잡해 보이지만, 그래도 결국 파이썬의 메서드일 뿐이에요. + +뷰는 `views.py` 파일 안에 있습니다. 우리는 *views* 를 `blog/views.py` 파일 안에 추가할 거에요. + +## blog/views.py + +좋아요. 이제 이 파일을 열고 안에 있는 내용을 살펴봅시다. : + +```python + from django.shortcuts import render +``` + # Create your views here. + + +여기에는 별 내용이 없네요. 가장 간단한 *view* 를 이렇게 만들어봅시다. + +```python + def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +방금 우리는 `post_list`라는 메서드를 만들었습니다. (`def`가 메서드를 만들 때 사용하는 키워드였죠?) 그리고 이 메서드는 `요청(request)`을 넘겨받아 `render` 메서드를 호출합니다. render 메서드는 넘겨진 요청(request)과 `blog/post_list.html` 템플릿 받아 리턴된 내용이 브라우저에 보여지게 됩니다. + +파일을 저장하고, http://127.0.0.1:8000/로 접속해 결과를 확인해보세요. + +에러가 발생했어요! 이제 아래 내용을 읽어보세요. : + +![오류][1] + + [1]: images/error.png + +*TemplateDoesNotExist* 는 쉽게 해결할 수 있습니다. : 잘 따라왔다면 이러한 에러가 발생하는게 맞아요. 다음 장에서 이 버그를 해결하기 위해 템플릿 파일을 만들 거에요! + +> Django 뷰에 대해 자세히 알고 싶으시면 공식 문서를 읽어 보세요. https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/ko/django_views/images/error.png b/ko/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/ko/django_views/images/error.png differ diff --git a/ko/django_views/images/images/error.png b/ko/django_views/images/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/ko/django_views/images/images/error.png differ diff --git a/ko/domain/README.md b/ko/domain/README.md new file mode 100755 index 00000000000..a3008963445 --- /dev/null +++ b/ko/domain/README.md @@ -0,0 +1,71 @@ +# 도메인 + +Heroku(헤로쿠) 에서 도메인을 받을 수 있지만 너무 길어 기억하기도 힘들고 썩 좋아보이지도 않네요. 간단하고 기억하기 쉬운 멋진 도메인이 있다면 참 좋겠죠? + +이번 장에서는 구입한 도메인을 헤로쿠에 설정하는 방법에 대해 배울 거에요. + +## 어디에서 도메인을 등록하나요? + +어떤 도메인을 선택하냐에따라 가격이 다르지만, 일반적으로 1년에 15, 000원정도 비용이 들어요. 또한 같은 도메인이라고 하더라도 어느 회사를 고르냐에 따라서 더 쌀 수도, 비쌀 수도 있습니다. 도메인을 구입할 수 있는 곳은 참 다양하고 많은데요, 간단히 [구글 검색][1]을 해봐도 얼마나 많은지 알 수 있을거에요. + + [1]: https://www.google.com/search?q=register%20domain + +우리가 선호하는 한 회사는 [I want my name][2]이에요. 이 곳에서는 "고통없는 도메인 관리를 할 수 있습니다(painless domain management)"라고 광고를 하고 있고 실제로도 그렇더군요. + + [2]: https://iwantmyname.com/ + +## IWantMyName에서 어떻게 도메인을 등록할까요? + +[iwantmyname][3]에 가셔서 검색창에 내가 원하는 도메인 이름을 입력하세요. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +그러면 검색창에 입력한 단어가 들어간 모든 도메인 목록을 볼 수 있어요. 웃는 얼굴 아이콘이 있다면 구매가 가능한 도메인이고, 슬픈 얼굴 아이콘이 있다면 이미 누군가가 구입한 도메인입니다. + +![][5] + + [5]: images/2.png + +여기서 우리는 `djangogirls.in` 를 사기로 결정했어요. : + +![][6] + + [6]: images/3.png + +결제할게요. 아직 iwantmyname에 회원가입을 안했다면 먼저 가입부터 하세요. 이후에 도메인 결제를 위해 여러분의 신용카드를 입력하세요! + +그 다음, 메뉴에 있는 `도메인(Domains)`을 클릭하고 방금 새로 구입한 도메인을 선택하세요. 이후 `DNS 레코드 관리(manage DNS records)` 링크를 클릭하세요. : + +![][7] + + [7]: images/4.png + +아래 그림의 입력폼이 있는 곳으로 가세요. : + +![][8] + + [8]: images/5.png + +아래 세부 내용을 기입하세요: - Hostname: www - Type: CNAME - Value: your domain from Heroku (for example djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +"추가" 버튼을 누른 후 하단의 "변경사항 반영" 버튼도 클릭하세요. + +도메인 작동까지 몇 시간이 걸릴 수 있으니, 조금 기다려보세요! + +## 헤로쿠에서 도메인 설정하기 + +사용자 지정 도메인을 사용하고자하는 경우에도 헤로쿠에게 말해야해요. + +[Heroku Dashboard][10]로 가서, 헤로쿠에 로그인 한 다음, 앱을 선택하세요. 앱 설정으로 들어가 `도메인`영역에 내 도메인을 추가하고 저장하세요. + + [10]: https://dashboard.heroku.com/apps + +잘했어요! diff --git a/ko/dynamic_data_in_templates/README.md b/ko/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..b84d6edc329 --- /dev/null +++ b/ko/dynamic_data_in_templates/README.md @@ -0,0 +1,75 @@ +# 템플릿의 동적 데이터 + +블로그 글이 각각 다른 장소에 조각조각 나눠져있어요. `Post` 모델은 `models.py`파일에 정의되어 있고, `post_list` 모델은 `views.py` 파일에 정의되어 있습니다. 템플릿도 추가해야해요. 하지만 실제로 HTML 템플릿에서 글들이 어떻게 보여질까요? 보여주고자 하는 컨텐츠(데이터베이스 안에 저장되어 있는 모델들) 를 가져와서 우리의 템플릿에 넣어서 멋있게 보여줄 것입니다. + +여기서 *views* 가 모델과 템플릿을 연결하는 역할을 한다는 것을 알 수 있어요. `post_list` *view* 에서 보여주고 템플릿에 넘기기 위해서 모델을 가져와야해요. 그래서 기본적으로 *view* 에서는 템플릿에서 무엇을 보여줄 지 (모델) 을 선택을 하지요. + +자, 모두 했나요? + +이제 `blog/views.py` 파일을 열어봅시다. `post_list` *view* 파일이 아래처럼 보일 거에요. + +```python + from django.shortcuts import render + + def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +다른 파일들에 있는 코드를 가져오는 것에 대해서 이야기 했던거 기억나나요? 이제 `models.py` 파일에서 정의한 모델을 가져올 때입니다. 이제 `from .models import Post` 행을 추가해 봅시다. 아래와 같을 거에요. : + +```python + from django.shortcuts import render + from .models import Post +``` + +`from` 다음에 있는 마침표(.)는 *현재 디렉토리* 또는* 현재 어플리케이션*을 의미합니다. `views.py`와 `models.py` 파일들이 같은 디렉토리에 있기 때문에 우리는 `.`와 (`.py` 확장자를 붙이지 않아도) 파일의 이름만으로도 쉽게 사용할 수 있습니다. 자 다음은 모델(`Post`)의 이름을 불러옵니다.). + +그럼 그 다음은요? `Post` 모델에서 실제 블로그 글들을 가져와야 하는데 이때 필요한 특별한 것이 바로 `QuerySet`입니다. + +## 쿼리셋(QuerySet) + +여러분은 쿼리셋이 어떻게 동작하는지를 이미 친숙해져 있어야해요. 자세한 내용은 [Django ORM (쿼리셋)][1]에서 다루었어요. + + [1]: ../django_orm/README.md + +자, 이제는 블로그 글 목록을 주의깊게 봅시다. 글 목록이 출판되고 `출판된 날짜(published_date)` 기준으로 정렬되면 좋겠죠? 사실 이미 쿼리셋 챕터에서 해놓어요! + +```python + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +이제 `blog/views.py` 파일의 `def post_list(request)` 함수에다 이 코드 조각을 넣어봅시다. + +```python + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + +우리는 지금 `posts`쿼리셋을 나타내는 *변수* 를 만들고 있다는 것을 주의하세요. 이 변수는 퀴리셋의 이름으로 취급하며 이 이름으로 참조할 수도 있습니다. + +위 코드에서 `timezone.now()` 함수를 쓰기 때문에 `timezone` 모듈 import가 필요합니다. + +마지막 부족한 부분은 `posts` 쿼리셋을 처리해서 템플릿에 보내는 것입니다.(이 부분은 다음 장에서 다룰 거에요.) + +`render`함수에서는 이미 요청 시 매개변수`request`와 템플릿 파일 'blog/post_list.html'를 가지고 있습니다. `{}` 와 같이 보이는 마지막 매개 변수는 템플릿을 사용하기 위해 무엇인가를 추가하는 장소입니다. 이름을 넣어줘야 합니다. (여기서는 `'posts'`이에요.) 이렇게 보일지도 모르겠어요. : `{'posts': posts}`. `:` 표시를 해 구분하는 것을 잊지 마세요. ; 양쪽에 작은 따옴표를 붙이는 것도요. `''`. + +그래서 최종적으로 `blog/views.py` 파일이 아래처럼 될 거에요. : + +```python + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +다 되었습니다! 이제 템플릿 파일로 돌아가서 이 쿼리셋을 보이게 해볼 차례에요. + +쿼리셋에 대해서 좀 더 자세히 알고 싶다면 장고 공식 문서를 읽어보세요. : https://docs.djangoproject.com/en/1.8/ref/models/querysets/ diff --git a/ko/extend_your_application/README.md b/ko/extend_your_application/README.md new file mode 100755 index 00000000000..48cbcea26e0 --- /dev/null +++ b/ko/extend_your_application/README.md @@ -0,0 +1,194 @@ +# 프로그램 어플리케이션 확장하기 + +우리는 지금까지 웹사이트 제작에 필요한 모든 단계들을 마쳤어요. 모델, url, 뷰와 템플릿을 만드는지 알게 되었고요. 또 웹사이트를 어떻게 멋지게 꾸미는지 알게 되었어요. + +이제 연습해 봅시다! + +블로그에 가장 필요한 것은 페이지에 포스트가 보이게 만드는 것이겠죠? + +이미 앞에서 `Post` 모델을 만들었으니 `models.py`에 추가할 내용은 없습니다. + +## Post에 템플릿 링크 만들기 + +`blog/templates/blog/post_list.html` 파일에 링크를 추가하는 것부터 시작합시다. 아마 아래와 같을 거에요. : + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +{% raw %}우리는 post 목록에 있는 제목에서 post의 내용 페이지로 가는 링크를 만들 거에요. `

{{ post.title }}

` 를 변경해 봅시다. post의 상세 페이지는 {% endraw %} 로 연결됩니다. + +```html +

{{ post.title }}

+``` + +`{% url 'post_detail' pk=post.pk %}`에 대해 설명할 때가 왔군요! 예상하셨겠지만 `{% %}` 표기는 장고 템플릿 태그를 사용하고 있는 것을 말합니다. 이번에는 우리를 위한 URL를 만들어 사용해 봅시다! + +`blog.views.post_detail`는 우리가 만들려고 하는 경로인 `post_detail` *view* 입니다. 반드시 주의하세요 : `blog`는 우리의 응용 프로그램 (디렉토리 `blog`)의 이름이에요. `views`는 `views.py` 파일의 이름에서 나온 것이에요. 마지막인 `post_detail`는 *view* 의 이름입니다. + +http://127.0.0.1:8000/를 열어보세요. 오류 메세지가 나올 거에요. (예상대로, 아직 `post_detail`을 위한 *view* 파일 만들지 않아 오류가 나는 것이죠.) 아마 이렇게 나왔을 거에요. : + +![NoReverseMatch error][1] + + [1]: images/no_reverse_match2.png + +## Post 상세 페이지에 URL 만들기 + +`urls.py` 파일에 `post_detail` *view* 를 위한 URL를 만들어 봅시다! + +첫 번째 게시물의 상세 **URL** 은 이렇게 나올 거에요. : http://127.0.0.1:8000/post/1/ + +`blog/urls.py`파일에 URL을 만들어, 장고가 `post_detail`이란 *view* 로 보내, 전체 블로그 글이 보일 수 있게 만들어 봅시다. `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail')` 코드를 `blog/urls.py` 파일에 추가하세요. 그러면 아래처럼 보일 거에요. : + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + +`^post/(?P[0-9]+)/$` 이 부분이 무섭게 보이지만, 걱정하지 마세요. 하나씩 차근차근 설명해드릴 거에요. + - `^`은 "시작"을 뜻합니다. + - 첫 부분 다음부터 나오는 `post/`는 URL이 __post__ 를 포함해야한다는 것을 뜻합니다. 아직까지 할 만 하죠? + - `(?P[0-9]+)` - 이 부분은 좀 까다롭습니다. 이 정규 표현식의 의미는 장고가 여러분이 여기에 넣은 모든 것을 `pk`변수에 넣어 뷰로 전송하겠다는 뜻입니다. `[0-9]`은 문자를 제외하고, 숫자 0부터 9까지 하나의 숫자만 있다는 뜻입니다. `+`는 하나 또는 그 이상의 숫자가 와야한다는 것을 의미합니다. 따라서 `http://127.0.0.1:8000/post//`라고 하면 post/ 다음에 숫자가 없기 때문에 해당이 안되지만, `http://127.0.0.1:8000/post/1234567890/`는 완벽하게 매칭됩니다. + - `/` - 다음에 __/__ 가 한번 더 와야 한다는 의미입니다. + - `$` - "마지막"! 입니다. 그 뒤로 더이상 문자가 오면 안됩니다. + +브라우저에 `http://127.0.0.1:8000/post/5/`입력하면, 장고는 `post_detail`인 *view* 를 찾고 있다고 생각하고 `pk`가 `5`와 일치한 *view* 로 정보를 보내게 됩니다.. + +`pk`는 `primary key`의 약자입니다. 장고 프로젝트에서 자주 사용되는 이름이에요. 물론 여러분은 내가 원하는 변수 이름을 사용할 수 있어요. (기억하세요 : 변수 이름에 공백문자는 사용할 수 없으며 소문자와 `_`를 사용할 수 있습니다.) 예를 들어, `(?P[0-9]+)`의 변수를 `post_id`바꾼다면 하면 정규표현식도 `(?P[0-9]+)`으로 바뀌게 됩니다. + +좋아요, 이제 새로운 URL 패턴을 `blog/urls.py` 파일에 추가했어요! 이제 페이지를 새로고침 하세요. : http://127.0.0.1:8000/ 쾅! 또 에러가 났어요! 예상대로에요! + +![AttributeError][2] + +다음 단계는 무엇일까요? 그렇죠. : view를 추가해야죠! + +## Post 상세 페이지에 뷰 추가하기 + +이제 *view* 는 추가적으로 매개 변수`pk`를 받아야합니다. *view* 에 가져다가 써야겠죠? 그래서 함수를 정의할 때, pk를 받도록 `def post_detail(request, pk):`라고 정의 할 것입니다. 기입된 urls(`pk`)에 지정한 것과 정확히 똑같은 이름을 사용해야함을 주의하세요. 변수가 생략되면 문제가 생겨 오류가 날 거에요! + +이제, 우리는 딱 한 개 블로그만 보고 싶어요. 이를 위해 다음과 같이 쿼리셋(queryset)을 사용해야해요. : + +```python + Post.objects.get(pk=pk) +``` + +하지만 이 코드에는 문제가 있어요. `primary key` (`pk`)가있는 `Post`가 없다면 보고 싶지 않은 오류가 나올 거에요! + +![DoesNotExist error][3] + +우리가 원하는게 아니에요! 장고에서는 이를 해결 하기위해 특별한 기능을 제공해요. : `get_object_or_404`이에요. 이 기능을 사용하면 `pk`에 맞는 `Post`가 없을 경우, 멋진 페이지(`페이지 찾을 수 없음 404 : Page Not Found 404)`를 보여줄 거에요. + +![Page not found][4] + +좋은 점은 여러분 만의 `페이지 찾을 수 없음(Page not found)` 페이지를 예쁘게 만들 수 있다는 거에요. 지금 당장 중요한 것이 아니까 생략할게요. + +좋아요. 이제 `views.py` 파일에 *view* 를 추가합시다! + +`blog/views.py` 파일을 열어서 아래 코드를 추가하세요. : + +```python + from django.shortcuts import render, get_object_or_404 +``` + +`from`행 근처로 가서, 파일 맨 끝에 *view* 를 추가하세요. : + +```python + def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +브라우저를 새로고침 해보세요. : http://127.0.0.1:8000/ + +![Post list view][5] + +잘 되네요! 그런데 블로그 제목 안의 링크를 클릭하면 어떻게 되나요? + +![TemplateDoesNotExist error][6] + +이런! 또 에러가 나왔네요! 하지만 이제는 이런 걸 어떻게 다뤄야하는지 알고 있죠? 우리는 이제 템플릿을 추가해 볼 거에요! + +## Post 상세 페이지에 템플릿 만들기 + +`blog/templates/blog` 디렉토리 안에 `post_detail.html`라는 새 파일을 생성하세요. + +아마도 화면에는 이런 것들이 보이겠죠? + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +다시 한 번 `base.html`을 확장해 봅시다. `content` 블록에서, 블로그 글의 published_date 출판일(존재한다면) 과 제목, 내용을 보이게 할 거에요. 그런데 제일 중요한 것을 얘기해봐야하지 않겠어요? + +{% raw %}`{% if ... %} ... {% endif %}` 는 무엇인가를 확인할 때 사용하는 템플릿 태그 입니다. (`if ... else ..` 를 __파이썬 들어가기__ 장에서 본 기억이나나요?) 우리는 post의 `출판 날짜(published_date)`가 비어있는지 아닌지 확인하고 싶어요. {% endraw %} + +페이지를 새로고침하면 `페이지 찾을 수 없음(Page not found)` 페이지가 없어진 것을 알 수 있어요. + +![Post detail page][7] + +야호! 잘 되네요! + +## 한 가지만 더: 배포하세요! + +PythonAnywhere에서도 웹사이트가 잘 작동하는지 봐야겠죠? 다시 한 번 배포해봅시다. + +``` +$ git status +$ git add --all . +$ git status +$ git commit -m "Added view and template for detailed blog post as well as CSS for the site." +$ git push +``` + +* 그 다음 [PythonAnywhere Bash console][8]을 여세요: + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* 마지막으로 [웹 탭(Web tab)][9]에서 **다시 불러오기(Reload)** 를 누르세요. + +이제 배포가 완료 되었어요. 잘 작동되는지 확인해 보세요! 축하합니다. :) + + [2]: images/attribute_error2.png + [3]: images/does_not_exist2.png + [4]: images/404_2.png + [5]: images/post_list2.png + [6]: images/template_does_not_exist2.png + [7]: images/post_detail2.png + [8]: https://www.pythonanywhere.com/consoles/ + [9]: https://www.pythonanywhere.com/web_app_setup/ diff --git a/ko/extend_your_application/images/404_2.png b/ko/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/ko/extend_your_application/images/404_2.png differ diff --git a/ko/extend_your_application/images/attribute_error2.png b/ko/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/ko/extend_your_application/images/attribute_error2.png differ diff --git a/ko/extend_your_application/images/does_not_exist2.png b/ko/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/ko/extend_your_application/images/does_not_exist2.png differ diff --git a/ko/extend_your_application/images/no_reverse_match2.png b/ko/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/ko/extend_your_application/images/no_reverse_match2.png differ diff --git a/ko/extend_your_application/images/post_detail2.png b/ko/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/ko/extend_your_application/images/post_detail2.png differ diff --git a/ko/extend_your_application/images/post_list2.png b/ko/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/ko/extend_your_application/images/post_list2.png differ diff --git a/ko/extend_your_application/images/template_does_not_exist2.png b/ko/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/ko/extend_your_application/images/template_does_not_exist2.png differ diff --git a/ko/how_the_internet_works/README.md b/ko/how_the_internet_works/README.md new file mode 100755 index 00000000000..f7c37d237c7 --- /dev/null +++ b/ko/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# 인터넷은 어떻게 작동할까요 + +> 이번 장은 Jessica McKellar의 "How the internet works" 에서 영감을 받아 작성되었습니다. (http://web.mit.edu/jesstess/www/) + +우리는 매일 인터넷을 사용하고 있어요. 하지만 브라우저 주소창에 https://djangogirls.org 를 입력하고 `엔터`키를 누르면 어떤 일이 일어나는지 혹시 알고 있었나요? + +먼저 알아야 할 것은 웹사이트란 하드 디스크에 저장된 파일묶음이라는 거에요. 동영상, 음악, 사진 파일처럼요. 웹사이트가 다른 파일과 다른 점은 HTML이라는 컴퓨터 코드가 들어있다는 것이에요. + +만약 프로그래밍에 익숙하지 않다면, HTML을 이해하는 게 어려울 수도 있어요. 하지만 브라우저들(크롬, 사파리, 파이어폭스 같은 것들요) 은 HTML을 사랑한답니다. 웹 프라우저는 코드를 이해하고 지시에 따르고, 내가 원하는 방식으로 정확하게 구현될 수 있도록 설계되었어요. + +다른 파일처럼 HTML 파일도 하드 디스크 어딘가에 저장해야합니다. 인터넷에선 *서버* 라는 특별하고 강력한 컴퓨터를 사용해요. 데이터를 저장하고 제공하는 것이 주된 목적이기 때문에 모니터나 마우스, 키보드가 필요없지요. 데이터를 *제공(serve)* 하는 일을 하기 때문에 *서버(server)* 라고 부릅니다. + +그래요, 하지만 인터넷이 어떻게 생겼는지 궁금하지 않나요? + +그림을 그려봤습니다. 이렇게 생겼어요. : + +![그림 1.1][1] + + [1]: images/internet_1.png + +조금 지저분해 보이죠? 사실 인터넷은 수 많은 기계들이 연결된(앞서 얘기한 *서버* 라는) 의 하나의 네트워크랍니다. 수백, 수천 대의 기계들이요! 긴, 아주 긴 케이블들이 지구 전체를 둘러싸고 있답니다! 해저 케이블 지도 사이트 (http://submarinecablemap.com/)에 가보면 케이블이 얼마나 복잡하게 연결되어있는지 알 수 있어요. 아래 사진은 웹사이트에서 가져온 스크린 샷입니다. + +![그림 1.2][2] + + [2]: images/internet_3.png + +멋지지 않나요? 그러나 인터넷에 연결되어 있는 모든 기계들을 전부 연결하는 것은 불가능한 일입니다. 그래서 어떤 기계(예를 들어 https://djangogirls.org 이 저장되어 있는 것 같은)에 도달하기 위해서는 수없이 많은 다른 기계들을 통과해야 한답니다. + +그림으로 보면 다음과 같습니다. + +![그림 1.3][3] + + [3]: images/internet_2.png + +주소창에 https://djangogirls.org 을 입력하는 건, "사랑하는 장고 걸즈 여러분, 저는 장고걸즈 웹사이트를 보고 싶어요. 저에게 그 웹 사이트를 보여주세요!"라고 편지를 써서 보내는 것과 같아요. + +이 편지는 나와 가장 가까이에 있는 동네 우체국으로 갑니다. 받을 사람에게 가까운 다른 우체국으로, 다른 우체국으로 전달되면서 주소지에 최종 도착하게 됩니다. 특이한 점은 같은 장소에서 많은 양의 편지(*데이터 패킷*을 보내면, 각기 다른 우체국(*라우터*) 을 통해 전달됩니다. 또 우체국마다 배포되는 방법이 다르지요. + +![그림 1.4][4] + + [4]: images/internet_4.png + +맞아요, 간단해요. 메시지를 보내고 답장을 기다리는 거죠. 물론 종이랑 펜 대신 몇 바이트의 데이터를 사용하는 것이지만, 기본 개념은 같답니다! + +그리고 도로명과 도시이름, 우편번호를 쓰는 대신 IP주소라는 것을 써야해요. 컴퓨터는 먼저 DNS(도메인 주소 시스템)에게 djangogirls.org 의 IP주소가 무엇인지 물어봅니다. 전화주소록에서 연락하고 싶은 대상의 이름을 찾아 전화번호와 주소를 찾아내는 방법과 비슷하지요. + +편지를 보낼 때는 몇가지 규칙을 지켜야 제대로 배달되어요. 주소가 적혀있어야 하고, 우표가 있어야 해요. 수령인이 이해할 수 있는 언어로 적혀져야하구요. 그렇죠? 이처럼 *데이터 패킷*에도 동일하게 적용되어야 웹사이트를 볼 수 있습니다. 우리는 HTTP (하이퍼텍스트 전송 프로토콜) 라는 프로토콜을 사용합니다. + +따라서 기본적으로 웹사이트를 만들려면 그 웹사이트가 동작할 *서버* (기계) 가 필요해요. *서버*에서 *요청*(편지) 을 받으면, 다시 웹사이트(다른 편지) 로 되돌려줍니다. + +장고 튜토리얼을 시작할 때부터, 장고가 무슨 일을 하는지 궁금하셨죠? 여러분이 답장을 보낼 때, 모든 사람에게 항상 동일한 내용을 보내고 싶지 않을 거에요. 받는 사람에 따라 각각 다른 답장을 보내면 더 좋지 않을까요? 이와 같이 장고는 맞춤형 편지를 보낼 수 있도록 도와준답니다. :) + +이제 수다는 그만하고, 정말 뭔가 만들어 보자구요! diff --git a/ko/how_the_internet_works/images/internet_1.png b/ko/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/ko/how_the_internet_works/images/internet_1.png differ diff --git a/ko/how_the_internet_works/images/internet_2.png b/ko/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/ko/how_the_internet_works/images/internet_2.png differ diff --git a/ko/how_the_internet_works/images/internet_3.png b/ko/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/ko/how_the_internet_works/images/internet_3.png differ diff --git a/ko/how_the_internet_works/images/internet_4.png b/ko/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/ko/how_the_internet_works/images/internet_4.png differ diff --git a/ko/html/README.md b/ko/html/README.md new file mode 100755 index 00000000000..db9c62f970f --- /dev/null +++ b/ko/html/README.md @@ -0,0 +1,209 @@ +# HTML 시작하기 + +템플릿이 무엇인지 궁금하셨죠? + +템플릿이란 서로 다른 정보를 일정한 형태로 표시하기 위해 재사용 가능한 파일이예요. 예를 들면 편지를 쓸때도 템플릿을 사용할 수 있어요. 편지의 내용이나 수신인 주소는 달라져도 동일한 디자인, 레이아웃을 사용하는 경우가 있으니까요. + +장고의 템플릿 양식은 HTML을 사용합니다. (HTML은 첫 번째 장 **인터넷은 어떻게 작동할까요** 에서 들어봤죠) + +## HTML이란 무엇일까요? + +HTML은 크롬이나 파이어폭스, 사파리같은 웹브라우저가 해석할 수 있는 간단한 코드예요. 사용자에게 웹페이지를 표시할 때 사용해요. + +HTML은 "HyperText Markup Language"의 줄인 말입니다. **하이퍼텍스트(HyperText)** 는 텍스트인데 페이지간에 하이퍼링크를 담을 수 있다는 뜻이예요. **마크업(Markup)** 이란 누군가에게(여기서는 브라우저) 문서를 해석하는 방법을 표시(mark)를 했다는 뜻이에요. HTML 코드는 **태그(tag)** 들로 이루어져있어요. 태그는 `<` 로 시작하고 `>`로 끝나요. 이런 태그들은 마크업 **요소(elements)** 를 나타냅니다. + +## 첫번째 템플릿! + +템플릿을 만드는 것은 템플릿 파일을 만든다는 뜻이예요. 모든 것은 파일에 저장되겠죠? 이미 눈치챘을 것 같군요. + +템플릿은 `blog/templates/blog` 디렉토리에 저장됩니다. 그러니까 먼저 블로그 디렉토리에 `templates` 디렉토리를 생성해야해요. 그리고, 템플릿 디렉토리에 `blog` 라는 디렉토리를 만드세요. + + blog + └───templates + └───blog + + +(왜 `blog` 디렉토리를 하나 더 만들어야하는지 궁금할 거에요. 나중에 알게 되겠지만, 작업이 좀더 복잡해질 때 편하게 만들기 위해 사용하는 관습같은 거에요.) + +다음 `blog/templates/blog` 디렉토리에 `post_list.html` (비어있는) 파일을 만드세요. + +웹사이트를 확인해보세요. : http://127.0.0.1:8000/ + +> 여전히 `TemplateDoesNotExists` 에러가 나온다면, 웹 서버를 다시 시작하세요. 커맨드라인(혹은 콘솔창)으로 가서 Ctrl + C를 눌러 웹 서버 작동을 멈춥니다. 그런 후 다시 `python manage.py runserver` 명령을 실행해 서버를 재시작합니다. + +![그림 11.1][1] + + [1]: images/step1.png + +이제 에러가 사라졌어요! 축하합니다. :) 하지만 웹사이트가 비어있어 아무 내용도 보여지지 않네요. 이제 고쳐나가 봅시다. + +템플릿 파일 post_list.html에 아래 내용을 넣어주세요. : + +```html + +

Hi there!

+

It works!

+ +``` + +웹 사이트가 어떻게 보이나요? 확인해보세요. : http://127.0.0.1:8000/ + +![그림 11.2][2] + + [2]: images/step3.png + +잘 작동하네요! 잘 했습니다. :) + +* 모든 웹 페이지는 ``로 시작해서 ``로 끝나게 됩니다. 가장 기본적인 태그이지요. 웹사이트의 모든 내용은 시작 태그 ``과 닫는 태그인`` 사이에 넣어야만 합니다. +* `

`는 문단 태그입니다. 문단의 끝은 `

`로 닫습니다. + +## Head & body + +각 HTML 페이지는 두 가지 요소, **head** 와 **body** 로 구분됩니다. + +* **head** 는 문서에 대한 정보를 담고 있지만 이 정보는 화면에 직접적으로 보여지 않습니다. + +* **body** 는 웹사이트에 보여지는 모든 내용을 담고 있습니다. + +``는 브라우저에 페이지에 대한 설정들을 알려주고, ``는 실제 페이지에 보여줄 내용을 알려줍니다. + +그 예로, `` 안에 웹페이지의 제목을 넣어봅시다. : + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + +파일을 저장하고 페이지를 새로고침 해보세요. + +![그림 11.3][3] + + [3]: images/step4.png + +브라우저가 어떻게 "Ola's blog"를 웹 페이지의 제목으로 이해했을까요? 바로 브라우저가 `Ola's blog`를 해석해 브라우저 제목 표시줄에 내용을 반영한 것입니다. (북마크를 할 때도 이렇게 사용됩니다.) + +태그는 `/`로*태그 마침*하고 *중첩(nested)* 해서 사용할 수 있습니다. (모든 태그가 닫힐 때까지 특정 태그 하나만 닫을 수 없습니다.) + +이 개념은 박스에 뭔가 집어 넣는 것과 같아요. 여러분에게 ``라고 하는 큰 박스가 있습니다. 박스 안에는 `` 박스가 있고, 또 그 박스 안에는 `

`라는 더 작은 박스들이 있는 것이죠. + +*태그 마침* 과 *중첩* 의 규칙을 잘 따라야 해요. 그렇지 않으면, 브라우저가 해석을 할 수 없어, 페이지가 원하는 모습으로 나오지 않게 됩니다. + +## 맞춤형 템플릿 만들기 + +여러분은 이제 좀 더 재밌어질 것입니다. 여러분만의 템플릿을 만들어봅시다! 여기 몇 가지 유용한 태그들이 있습니다. : + +* `

A heading

` - 가장 중요한 머리말에 사용하는 태그 +* `

A sub-heading

` 그 다음 수준의 머리말에 사용하는 태그 +* `

A sub-sub-heading

` ... 그 다음 머리말.. `
` 까지 계속 수준이 낮아집니다. +* `text` 텍스트를 강조할 때 사용하는 태그 +* `text` 여러분의 텍스트를 강력하게 강조할 때 사용하는 태그 +* `
` 개행. 행을 내누기(br 태그 안에는 속성으로 아무 것도 넣을 수 없습니다.) +* `link` 링크 걸기 +* `
  • first item
  • second item
` 목록을 만듭니다. 지금 여러분이 보고 있는 목록처럼요! +* `
` 페이지의 섹션을 정의합니다. + +여기에 완전한 템플릿 예제가 있습니다. : + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` + +이 템플릿에는 세 개의 `div` 섹션이 있습니다. + +* 첫 번째 `div`는 블로그 제목을 가지고 있어요. 머리말과 링크이지요. +* 나머지 두 `div`는 블로그 글 출판 날짜와 클릭할 수 있는 `h2`로 된 블로그 제목을 가지고 있습니다. 두 `p`(문단)의 하나는 날짜를, 다른 하나는 블로그를 위한 거에요. + +이 태그들로 이렇게 변합니다. : + +![그림 11.4][4] + + [4]: images/step6.png + +야호! 지금까지 만든 우리 템플릿은 계속 **같은 내용**만 보여주었죠. 그러나 앞에서 템플릿은 **같은 양식**을 사용하지만 **다른** 정보들을 보여줄 때 사용한다고 말했었죠.. + +장고 관리자에서 실제 추가한 글들을 보여주는 방법은 앞으로 배우게 될 거에요. + +## 하나 더: 배포하기! + +방금 작업했던 것이 인터넷에서도 볼 수 있으면 좋겠죠? PythonAnywhere으로도 배포해 봅시다. : + +### Github에 코드를 커밋, 푸시하세요! + +제일 먼저, 마지막 배포 이후 수정된 파일을 확인해 봅시다. (PythonAnywhere가 아닌 로컬에서 실행하세요.) : + + $ git status + + +`djangogirls` 디렉토리에서 `git`에게 현재 폴더에 있는 모든 변경 내용을 포함라고 말합니다. + + $ git add --all . + + +> **Note** `-A` ("all"의 축약어) 는 `git`이 삭제한 파일을 인식합니다. (기본적으로, 새로 추가하거나 변경한 파일만 인지합니다.) 또한 `.`의미가 현재 디렉토리라는 것을 기억하고 있죠? (3장에서 언급한 내용이에요.) + +파일 업로드 전, `git`으로 업로드 할 파일들을 확인해봅시다. (`git`에서 업로드 할 모든 파일들이 녹색으로 나타나야 합니다.) : + + $ git status + + +거의 다 왔습니다. 이제 저장소에 변경 사항을 저장할 단계예요. 우리는 "커밋 메시지(commit message)"를 주어, 어떤 것이 수정 변경되었는지 알려줄 거에요. 이번에는 아무거나 적어도 괜찮습니다. 하지만 앞으로는 내가 수정한 내용을 간략하게 적어 다음에 기억할 수 있도록 하는 것이 좋을 거에요. + + $ git commit -m "Changed the HTML for the site." + + +> **Note** 커밋 메시지는 쌍따옴표(")로 감싸주세요. + +완성되면, Github으로 업로드(푸쉬) 하세요. : + + git push + + +### PythonAnywhere에서 새 코드를 가져와, 웹 앱을 다시 불러옵니다. + +* [PythonAnywhere 콘솔 페이지][5]를 열고 **배시 콘솔** (또는 새로운 창)을 준비합니다. 그 다음, 명령어를 입력합니다. : + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +그러면 코드가 다운되는 것을 볼 수 있어요. 다 되었는지 확인하고 싶으면 **파일 탭(Files tab)**에 가서 내 코드가 PythonAnywhere에 있는지 확인합니다. + +* 마지막으로 [웹 탭(Web tab)][6]으로 가서 여러분의 웹 앱을 **다시 불러오기** 하세요. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +인터넷에도 업데이트 되었네요! 브라우저로 가서 웹사이트를 새로고침하세요. 변경한 내용들이 보일 거에요. :) diff --git a/ko/html/images/step1.png b/ko/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/ko/html/images/step1.png differ diff --git a/ko/html/images/step3.png b/ko/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/ko/html/images/step3.png differ diff --git a/ko/html/images/step4.png b/ko/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/ko/html/images/step4.png differ diff --git a/ko/html/images/step6.png b/ko/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/ko/html/images/step6.png differ diff --git a/ko/images/application.png b/ko/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/ko/images/application.png differ diff --git a/ko/installation/README.md b/ko/installation/README.md new file mode 100755 index 00000000000..1afda107099 --- /dev/null +++ b/ko/installation/README.md @@ -0,0 +1,49 @@ +# 집에서 튜토리얼을 보시는 분들에게 + +[장고 걸스 이벤트](https://djangogirls.org/events/)가 아닌 집에서 튜토리얼을 자습하시는 분들은 이 장을 건너뛰고 [인터넷은 어떻게 작동할까요?](../how_the_internet_works/README.md) 부터 읽으세요. + +이번 장에는 설치와 관련된 모든 내용을 모았습니다. 장고 걸스 이벤트에서는 워크샵 사전에 설치과정을 완벽하게 마치는 '설치의 밤'이 있습니다. 워크샵 중간 중간에 설치 문제로 진행에 어려움을 겪지 않게 하기 위해서지요. + +이 방법이 괜찮다면, 컴퓨터에 먼저 모든 설치를 끝내고 내용을 따라가도 좋습니다. 혹은 먼저 학습을 시작하고 싶다면 이번 장을 넘기세요. 뒷 부분에서도 설치 방법에 대해 다룹니다. + +모두 행운을 빌어요! + +# 설치하기 + +우리는 워크샵에서 블로그를 완성할 거에요. 워크샵 사전에 몇 가지 설치를 끝낸다면, 하루 종일 코딩할 준비가 된 거랍니다. + +# Python 설치하기 + +{% include "/python_installation/instructions.md" %} + +# virtualenv 설정하고 Django 설치하기 + +{% include "/django_installation/instructions.md" %} + +# 코드 에디터 설치하기 + +{% include "/code_editor/instructions.md" %} + +# Git 설치하기 + +{% include "/deploy/install_git.md" %} + +# GitHub 계정 만들기 + +[GitHub.com](https://www.github.com)에 가서 무료 사용자 계정으로 회원가입을 하세요. + +# PythonAnywhere 계정 만들기 + +{% include "/deploy/signup_pythonanywhere.md" %} + +# 코딩 시작 + +축하합니다. 드디어 여러분은 시작할 준비가 되었답니다! 워크샵 전에 튜토리얼의 앞 부분을 미리 읽어두면 시작하는데 도움이 될 거에요. : + + * [인터넷은 어떻게 작동할까요?](../how_the_internet_works/README.md) + + * [커맨드라인(command line) 시작하기](../intro_to_command_line/README.md) + + * [파이썬(python) 시작하기](../intro_to_command_line/README.md) + + * [Django란 무엇일까요?](../django/README.md) diff --git a/ko/intro_to_command_line/README.md b/ko/intro_to_command_line/README.md new file mode 100755 index 00000000000..9e20fa8ab1d --- /dev/null +++ b/ko/intro_to_command_line/README.md @@ -0,0 +1,279 @@ +# Command Line 시작하기 + +재미있을 것 같지 않아요? 조금만 더 하면 여러분은 첫 번째 코드를 쓸 수 있어요 :) + +**여러분에게 첫 번째 친구를 소개합니다: 바로, 커맨드 라인(command line) 입니다!** + +해커들이 사용하는 까만 윈도우 창을 어떻게 사용하는지 보여드릴 거에요. 처음에는 이 검은색 창이 약간 무서워 보일 수도 있지만, 여러분의 명령어를 기다리는 녀석일 뿐이에요. + +> **Note** 이 설명서에서 '디렉토리(directory)'와 '폴더(folder)'라는 두가지 단어를 사용하지만 둘다 같은 뜻이랍니다. + +## command line이란 무엇일까요? + +**커맨드 라인(command line)** 또는 **커맨드-라인 인터페이스(command-line interface)**라고도 불리는 윈도우는 컴퓨터에서의 보기, 처리, 그리고 파일 조작을 위한 텍스트 기반 응용 프로그램입니다. 윈도우 익스플로어나 맥OS의 Finder와 같아요. 하지만 그래픽 인터페이스는 없답니다. 커맨드 라인은 *cmd*, *CLI*, *프롬프트(prompt)*, *콘솔(console)* 혹은 *터미널(terminal)*로 불립니다. + +## 커맨드 라인 열기 + +커맨드 라인을 열고 몇 가지 실험을 해봅시다. + +### 윈도우 + +시작메뉴로 가서 → 모든 프로그램 → 보조프로그램 → 명령 프롬프트. + +### Mac OS X + +응용 프로그램 → 유틸리티 → 터미널. + +### 리눅스 + +프로그램 → 보조 프로그램 → 터미널을 실행하면 될 거에요. 하지만 시스템에 따라 다를 수도 있어요. 그럴 때는 구글에서 찾아보세요. :) + +## 프롬프트(prompt) + +이제 까만 배경이나 하얀 배경의 윈도우가 뭔가를 지시해주길 기다리고 있을 거에요. + +맥이나 리눅스의 경우, 이런 `$` 기호가 보일 거예요. : + + $ + + +윈도우의 경우, 이런 `>` 기호가 보일 거에요. : + + > + + +각각의 명령어는 접두어로 위와 같은 기호와 공백 한 칸이 붙습니다. 하지만 여러분이 입력할 필요는 없어요. 컴퓨터가 대신 해줄 거예요 :) + +> 잠깐만요 : 상황에 따라 프롬트 기호 앞에 `C:\Users\ola>` 혹은 `Olas-MacBook-Air:~ ola$` 같은 것이 보일 수 있는데, 문제가 있는 것이 아니라 아주 잘 동작하는 거랍니다. 이 튜토리얼에서는 제일 간단한 형태로 표시하는 거예요. + +## 나의 첫 번째 명령 (야호!) + +쉬운 것 부터 시작할게요. 아래 명령어를 입력해 보세요. : + + $ whoami + + +또는 + + > whoami + + +그리고 `enter`를 누르세요. 다음과 같이 보일 거에요. + + $ whoami + olasitarska + + +컴퓨터는 유저이름을 스크린에 보여줍니다. 이거 좀 괜찮죠? :) + +> 복사해서 붙여넣기 하지 말고, 직접 입력해 보세요. 더 잘 외워질 거예요! + +## 기본 명령어 + +각각의 운영체제에 따라, 명령어들이 조금씩 다를 수도 있으니까, 여러분의 운영체제에 해당하는 설명을 따라주세요. 그럼 같이 해볼까요? + +### 현재 디렉토리 + +우리가 어디쯤 있는지 알면 좋겠죠? 아래의 명렁을 입력하고 `enter`를 눌러보세요. : + + $ pwd + /Users/olasitarska + + +윈도우의 경우 : + + > cd + C:\Users\olasitarska + + +위와 비슷한 결과가 출력되었을 거예요. 커맨드라인을 열면, 항상 '홈 디렉토리' 에서 시작합니다. + +> Note: 'pwd' 는 'print working directory' 의 줄임말이에요. + +* * * + +### 파일과 디렉토리 목록 보기 + +여기에는 뭐가 있는지 알아낼 수 있다면 좋겠지요? 그럼 같이 해봐요. + + $ ls + Applications + Desktop + Downloads + Music + ... + + +윈도우의 경우 : + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### 현재 디렉토리 변경 + +자, 바탕화면 디렉토리로 가볼까요. : + + $ cd Desktop + + +윈도우의 경우 : + + > cd Desktop + + +변경되었는지 확인해 볼까요. : + + $ pwd + /Users/olasitarska/Desktop + + +윈도우의 경우 : + + > cd + C:\Users\olasitarska\Desktop + + +맞군요! + +> 전문가 팁 : `cd D`까지 입력하고 `tab`(탭) 키를 누르면, 커맨드 라인이 자동으로 나머지 부분을 완성해 주기 때문에, 시간을 절약할 수 있어요. "D"로 시작하는 폴더가 2개 이상일 경우, `tab`(탭) 키를 두 번 누르면, 해당하는 폴더들을 모두 보여줍니다. + +* * * + +### 새 디렉토리 만들기 + +바탕 화면에 연습 디렉터리를 만들어 볼까요? 이렇게 하면 됩니다. : + + $ mkdir practice + + +윈도우의 경우 : + + > mkdir practice + + +이 간단한 명령어가, 바탕화면에 `practice` 라는 이름의 폴더를 만들어 줍니다. 바탕화면에서 직접 보거나, 명령어 `ls` 혹은 `dir`을 실행해서 확인할 수 있어요! 한 번 해보세요. :) + +> 전문가 팁 : 같은 명령어를 여러 번 반복해서 입력하고 싶지 않다면, 키보드의 `위 화살표`와 `아래 화살표`를 눌러서 최근 사용한 명령어들을 볼 수 있어요. + +* * * + +### 연습문제! + +작은 도전 과제를 드릴게요. : 새로 만든 `practice` 디렉토리 안에 `test` 라는 이름의 디렉토리를 만들어 보세요. 명령어 `cd` 와 `mkdir`을 사용하세요. + +#### 답 : + + $ cd practice + $ mkdir test + $ ls + test + + +윈도우의 경우: + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + +축하합니다 :) + +* * * + +### 정리 + +어지럽힌 흔적은 남기고 싶지 않지요, 지금까지 한 것들을 모두 지워봅시다! + +우선, 바탕화면으로 돌아가야해요. + + $ cd .. + + +윈도우의 경우 : + + > cd .. + + +`..`과 `cd` 명령은 현재 디렉토리에서 (현재 디렉토리보다 한수준 위인) 부모 디렉토리로 보내줄겁니다. + +현재 위치를 확인해 보세요. : + + $ pwd + /Users/olasitarska/Desktop + + +윈도우의 경우 : + + > cd + C:\Users\olasitarska\Desktop + + +이제 `practice` 디렉토리를 삭제할 시간이에요.: + +> **주의**: `del`, `rmdir` 혹은 `rm` 을 사용하여 파일을 지울 경우, 복구할 수가 없습니다. *지워진 파일들을 영원히 사라지게 됩니다!* 그러니, 이 명령어들은 주의해서 사용하세요. + + $ rm -r practice + + +윈도우의 경우 : + + > rmdir /S practice + practice, Are you sure ? Y + + +완료되었습니다! 정말 삭제되었는지 확인해 보세요. : + + $ ls + + +윈도우의 경우 : + + > dir + + +### 종료 + +여기까지 입니다! 이제 커맨드 라인을 닫으시면 됩니다. 해커 스타일로 해볼까요, 괜찮죠?:) + + $ exit + + +윈도우의 경우 : + + > exit + + +멋지지 않나요? :) + +## 요약 + +유용한 명령어들을 요약한 표입니다. : + +| 명령어(윈도우) | 명령어(맥 OS/리눅스) | 설명 | 예시 | +| -------- | ------------- | ------------------- | ------------------------------------------------- | +| exit | exit | 창을 닫는다 | **exit** | +| cd | cd | 디렉토리를 변경한다 | **cd test** | +| dir | ls | 디렉토리 혹은 파일 목록을 보여준다 | **dir** | +| copy | cp | 파일을 복사한다 | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | 파일을 이동한다 | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | 새 디렉토리를 만든다 | **mkdir testdirectory** | +| del | rm | 디렉토리 혹은 파일을 지운다 | **del c:\test\test.txt** | + +커맨드 라인 명령어들 중에, 몇 가지만 알아보았어요. 이번에는 이 정도만 알고 있어도 괜찮습니다. + +더 알고 싶다면, [ss64.com][1]에서 각 운영체제별로 정리된 명령어 모음을 볼 수 있어요. + + [1]: http://ss64.com + +## 준비되셨나요? + +이제 파이썬의 세계로 빠져봅시다! diff --git a/ko/python_installation/README.md b/ko/python_installation/README.md new file mode 100755 index 00000000000..e94f9b80653 --- /dev/null +++ b/ko/python_installation/README.md @@ -0,0 +1,13 @@ +# Python 시작하기 + +여기까지 오셨군요! + +먼저 파이썬(Python) 이란 무엇인지부터 알려드릴게요. 파이썬은 아주 인기있는 프로그래밍 언어로, 파이썬을 이용하면 웹사이트, 게임, 과학용 소프트웨어, 그래픽 소프트웨어 등을 만들 수 있답니다. + +파이썬은 1980년대 후반에 만들어졌어요. 기계 뿐만 아니라 인간도 읽을 수 있도록 만드는 것이 목적이었어요. 파이썬이 다른 프로그래밍 언어보다 훨씬 간단하게 보이는 이유도 그 때문이죠. 그리고 배우기 쉽습니다. 하지만 파이썬은 아주 강력한 언어랍니다. + +# Python 설치 + +> **Note** 만약 이미 설치 단계를 마쳤다면 이 부분을 다시 할 필요가 없으니, 바로 다음 장으로 넘어 가세요. + +{% include "/python_installation/instructions.md" %} diff --git a/ko/python_installation/images/add_python_to_windows_path.png b/ko/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/ko/python_installation/images/add_python_to_windows_path.png differ diff --git a/ko/python_installation/instructions.md b/ko/python_installation/instructions.md new file mode 100755 index 00000000000..39cd7295313 --- /dev/null +++ b/ko/python_installation/instructions.md @@ -0,0 +1,68 @@ +> 위 내용은 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) 을 바탕으로 작성되었습니다. + +장고는 파이썬으로 만들어졌습니다. 장고를 하기 위해서는 파이썬이 있어야 합니다. 우선 설치부터 해볼까요! 우리는 파이썬 3.4를 사용할 거예요. 그보다 낮은 버전이 설치되었다면, 업그레이드가 필요합니다. + +### 윈도우 + +윈도우용 파이썬은 https://www.python.org/downloads/release/python-343/에서 다운 받을 수 있습니다. 사이트에서 ***.msi** 파일을 다운 받고, 실행(더블클릭으로)한 다음, 지시 사항을 따라가세요. 파이썬을 설치한 경로(디렉토리)를 기억해두어야 합니다. 나중에 필요하거든요! + +한가지 주의할 것은 설치 마법사의 "Customize"라는 두 번째 화면입니다. 여기서 보이듯이 스크롤을 내려 아래쪽에 있는 "Add python.exe to the Path" 항목을 체크해주세요. + +![파이썬을 패쓰(path)에 추가하는 것을 잊지 마세요!][9] + + [9]: ../python_installation/images/add_python_to_windows_path.png + +### 리눅스 + +아마 이미 파이썬이 설치되었을 거에요. 설치되어있는지 (그리고 어떤 버전인지) 확인하려면, 콘솔을 열어 다음 명령을 실행하세요. + + $ python3 --version + Python 3.4.3 + + +파이썬이 설치되어 있지 않거나 버전이 다르면 이렇게 해보세요. : + +#### Debian 또는 Ubuntu + +콘솔에서 다음 명령을 실행하세요. + + $ sudo apt-get install python3.4 + + +#### Fedora (21까지) + +콘솔에서 다음 명령을 실행하세요. + + $ sudo yum install python3.4 + + +#### Fedora (22부터) + +콘솔에서 다음 명령을 실행합니다. + + $ sudo dnf install python3.4 + + +#### openSUSE + +콘솔에서 다음 명령을 실행합니다. + + $ sudo zypper install python3 + + +### OS X + +https://www.python.org/downloads/release/python-343/ 에서 파이썬 설치프로그램을 다운 받아야 합니다. + + * *Mac OS X 64-bit/32-bit installer* 파일을 다운 받으세요. + * *python-3.4.3-macosx10.6.pkg* 을 더블 클릭해 설치 프로그램을 시작하세요. + +*터미널*을 열고 `python3` 명령을 실행해 잘 설치되었는지 확인하세요. + + $ python3 --version + Python 3.4.3 + + +* * * + +더 알고 싶은 것이 있거나, 설치가 잘 되지 않고 어찌 해야할지 모르겠다면 코치를 불러주세요! 잘 설치 되지 않는 경우도 있을 수 있습니다. 그럴 때는 경험이 있는 분에게 도움을 구해보세요. diff --git a/ko/python_introduction/README.md b/ko/python_introduction/README.md new file mode 100755 index 00000000000..4d836cc57ea --- /dev/null +++ b/ko/python_introduction/README.md @@ -0,0 +1,795 @@ +# Python 시작하기 + +> 이번 장의 일부는 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots)의 튜토리얼을 바탕으로 작성되었습니다. + +자, 코딩 한 번 해봅시다! + +## 파이썬 프롬프트(Python prompt) + +파이썬과 놀기 위해서는 *커맨드 라인*을 열어야 합니다. [커맨드 라인 시작하기][1]에서 배웠던 걸 기억하고 있겠지요? + + [1]: ../intro_to_command_line/README.md + +준비되었다면, 아래 내용을 잘 따라오세요. + +파이썬 콘솔을 실행하기 위해 윈도우에서는 `python`을 입력하고, 맥OS나 리눅스라면 `python3`를 입력하고 `엔터`를 입력하세요. + + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## 나의 첫 번째 파이썬 명령! + +파이썬을 실행시키고 나면 프롬프트가 `>>>`로 바뀝니다. 이제부터는 파이썬 언어의 명령어만 사용할 수 있다는 뜻이예요. `>>>`를 입력할 필요 없어요. 파이썬이 대신해 줄 테니까요. + +파이썬 콘솔에서 나가려면 `exit()` 을 입력하거나, 윈도우에서는 `Ctrl + Z` 를, 맥이나 리눅스에서는 `Ctrl + D`를 입력하면 됩니다. 그러면 `>>>` 는 사라질 거에요. + +물론 지금 파이썬 콘솔을 종료할 필요가 없답니다. 아직 파이썬 콘솔에 대해 좀 더 배워야하니까요. 아주 간단한 것부터 시작해봅시다. 먼저, 수학 사칙연산처럼 `2 + 3`을 입력하고 `엔터`를 쳐보세요. + + >>> 2 + 3 + 5 + + +잘했어요! 값이 출력되었나요? 파이썬은 수학을 할 줄 알아요. 다른 명령도 테스트해 보세요. : - `4 * 5` - `5 - 1` - `40 / 2` + +조금 놀아봤다면 다시 여기로 돌아와주세요. :) + +보시다시피, 파이썬은 훌륭한 계산기랍니다. 그 밖에 여러분들이 할 수 있는 것들이 궁금하다면... + +## 문자열(String) + +이름은 어떨까요? 따옴표로 이름을 감싸서 입력해보세요. + + >>> "Ola" + 'Ola' + + +처음으로 문자열을 만들었군요! 문자열은 컴퓨터가 처리할 수 있는 연속된 문자를 말해요. 문자열은 반드시 시작과 끝이 같은 문자여야 해요. 문자열은 작은따옴표(`'`) 나 큰따옴표(`"`)로 감싸야 해요. (둘 간의 차이점은 없어요. 단지 하나로 감싸나 둘로 감싸나 차이일 뿐이에요) 이 따옴표는 파이썬에게 안에 문자열이 들어있다고 알려줍니다. + +문자열들은 줄줄이 사탕처럼 연결될 수 있어요. 이렇게요. : + + >>> "Hi there " + "Ola" + 'Hi there Ola' + + +문자열이랑 숫자를 곱할 수도 있어요. + + >>> "Ola" * 3 + 'OlaOlaOla' + + +문자열 안에 작은따옴표를 넣고 싶다면, 두 가지 방법이 있어요. + +큰따옴표를 사용하는 방법과 + + >>> "Runnin' down the hill" + "Runnin' down the hill" + + +백슬래시 (``) 기호를 이용하는 방법이예요. + + >>> 'Runnin\' down the hill' + "Runnin' down the hill" + + +알겠나요? 이제 이름을 대문자로 만들어볼까요. : + + >>> "Ola".upper() + 'OLA' + + +방금 문자열에 `upper`이라는 **함수(function)**를 사용했어요! 함수(`upper()` 같은 것)란 파이썬이 주어진 대상(`"Ola"`같은)에 대해서 수행할 수 있는 일련의 명령을 말해요. + +이름에 들어있는 글자의 수를 알고 싶을 때, 사용하는 함수도 있어요. + + >>> len("Ola") + 3 + + +함수 호출 시, 어떤 함수는 문자열 뒤에 `.`를 붙이고, (`"Ola".upper()` 처럼), 또 어떤 함수는 함수 뒤에 문자열이 들어간 괄호를 붙이는지 궁금하셨죠? `upper()`와 같은 함수는 객체에 속하게 되어 해당 문자열에서만 수행되기 때문이죠. 이 같은 경우, 함수를 **메서드(method)**라고 합니다. 그리고, `len()`과 같은 함수들은 특정한 대상에 속하지 않고 여러 가지 객체를 대상으로 사용할 수 있습니다. 그래서 `len` 함수에 `"Ola"`를 매개 변수(parameter)로 준 거예요. + +### 요약 + +자, 문자열은 충분히 다루었어요. 지금까지 우리가 공부한 것들을 정리해봅시다. : + +* **프롬프트(the prompt)** - 명령어(코드)를 파이썬 프롬프트에 입력하면 파이썬이 응답합니다. +* **숫자와 문자열(numbers and strings)** - 파이썬에서는 셈을 할 때는 숫자를 사용하고 글을 다룰 때는 문자열을 사용합니다. +* **연산자(operators)** - 값들을 이용해서 새로운 값을 만들 때는 + 나 * 같은 연산자를 이용합니다. +* **함수(functions)** - upper()나 len()처럼 대상에 명령을 수행합니다. + +지금까지 프로그래밍 언어의 기초에 대해 알아보았어요. 더 어려운 부분으로 넘어가도 괜찮겠죠? 그럼요! + +## 오류 + +이제 새로운 것을 해봅시다. 이름의 글자 길이를 알아냈듯이 숫자의 길이도 알 수 있을까요? `len(304023)` 을 입력하고 `엔터`를 입력해보세요. : + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +첫 번째 에러가 나타났어요! "int" (정수) 형식의 객체는 길이가 없기 때문이지요. 이제 어떻게 할 수 있을까요? 숫자(number)를 문자열(String)로 바꿔 쓸 수 있지 않을까요? 문자열은 길이를 갖고 있으니까요, 그렇죠? + + >>> len(str(304023)) + 6 + + +잘 되네요! 앞에서 우리는 `len` 함수 내부에 `str` 함수를 사용했어요. `str` 함수는 모든 것을 문자열로 변환한답니다. + +* `str`함수는 대상을 **문자열** 로 변환합니다 +* `int` 함수는 대상을 **정수** 로 변환합니다. + +> 중요 : 우리는 숫자를 텍스트로 변환할 수는 있지만, 반드시 텍스트를 숫자로 변환할 수 있는건 아닙니다. - `int('hello')` 가 어떻게 될 것 같나요? + +## 변수 + +변수는 프로그래밍에서 중요한 개념입니다. 변수란 어떤 것을 나중에도 사용할 수 있도록 이름을 붙인 것일 뿐 입니다. 프로그래머들은 이 변수를 데이터 저장하는데 사용하고, 작성한 코드를 다 기억할 필요없이 코드를 읽기 쉽게 하기 위해 사용하지요. + +`name`이라는 새로운 변수를 만들어 보세요. : + + >>> name = "Ola" + + +봤죠? 간단해요. 매우 쉬어요! : name은 Ola와 같다. + +여러분도 알겠지만, 프로그램은 이전에 수행한 것을 보여주지 않아요. 그러면 실제 변수에 어떤 값이 들어있는지 알려면 어떻게 해야할까요? 간단하게 `name`를 입력하고 `엔터`를 입력하세요. : + + >>> name + 'Ola' + + +야호! 여러분이 만든 첫 변수입니다! :) 언제든지 여러분은 변수를 바꿀 수 있어요. : + + >>> name = "Sonja" + >>> name + 'Sonja' + + +또 함수 안에서 변수를 사용할 수 있습니다. : + + >>> len(name) + 5 + + +멋지죠? 물론 변수는 무엇이든지 담을 수 있으니, 당연히 숫자도 가능하죠! 해봅시다. : + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +그런데 만약 잘못된 이름을 사용했다면 어떻게 될까요? 해봅시다! + + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + + +에러가 나타났네요! 보다시피, 파이썬에는 많은 종류의 오류들이 있습니다. **NameError**는 그 중 하나입니다. 파이썬은 아직 정의하지 않은 변수를 사용하면 이 오류를 보여줍니다. 나중에 똑같은 오류를 보게 된다면, 이름에 오타가 없는지 확인해보세요. + +잠시동안 변수와 놀아봅시다. 그리고 어떤 것들을 할 수 있는지 살펴보아요! + +## print 함수 + +아래와 같이 따라해보세요: + + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + + +`name`을 쳤을 때, 파이썬 해석기는 'name' 변수의 문자열 *표현(representatio)*으로 응답하는데, 그 모양은 작은따옴표('') 로 둘러싸인 M-a-r-i-a 문자들 입니다. `print(name)`라고 치면, 파이썬은 화면에 따옴표 없이 더 깔끔한 변수를 "출력(print)"합니다. + +나중에 보겠지만, `print()`는 함수 안에 있는 어떤 것을 출력하거나, 이를 여러 줄로 출력할 때 유용하게 사용됩니다. + +## 리스트 (List) + +문자열과 정수 외에, 파이썬은 객체 정렬 위한 여러 방법들이 있어요. 이제 **리스트**라고 불리는 녀석에 대해서 알아보기로 하겠습니다. 리스트를 이렇게 생각하시면 됩니다. : 다른 객체들을 나열한 객체 + +이제 리스트를 만듭시다. : + + >>> [] + [] + + +네, 리스트가 비어있어요. 별로 유용해 보이지 않죠? 이제 로또 번호 목록을 만들어 봅시다. 매번 직접 우리가 반복하기는 귀찮으니, 리스트에 변수를 넣어봅시다. : + + >>> lottery = [3, 42, 12, 19, 30, 59] + + +좋아요, 리스트를 만들었네요! 어떻게 쓰면 될까요? 목록에 수 많은 로또 번호가 있다고 생각해봅시다. 함수를 사용할 수 있는 아이디어가 떠올랐나요? 여러분들은 이미 앞에서 해봤어요! + + >>> len(lottery) + 6 + + +네! `len()` 함수는 리스트 안에 있는 객체의 수를 알려줍니다. 편리하지 않나요? 이제 정렬을 해봅시다. : + + >>> lottery.sort() + + +아무것도 보여주지 않네요. 이 함수는 리스트 안의 숫자들을 오름차순으로 정렬합니다. 어떻게 변했는지 리스트를 출력해봅시다. : + + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + + +위에 나왔듯이, 리스트 안에 있는 숫자들은 오름차순으로 정렬되었습니다. 축하합니다! + +만약 반대로 내림차순으로 정렬하고 싶다면요? 하면 됩니다! + + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + + +참 쉽죠? 여러분이 리스트에 새로운 값을 추가하고 싶다면, 추가할 때마다 매번 다시 정렬 명령을 해줘야 합니다. : + + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + + +만약 첫 번째 숫자 하나만 보여주고 싶다면, **인덱스(index)**를 사용하세요. 인덱스는 리스트 안의 아이템 위치를 나타내는 숫자입니다. 프로그래머는 0부터 세는 것을 선호합니다. 따라서 리스트에 있는 첫 번째 객체는 인덱스 0부터 시작하고, 그 다음은 1, 그 다음은 2.. 가 됩니다. 해봅시다. : + + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + + +리스트의 이름이나 대괄호 안에 들어가는 객체의 인덱스를 사용해서, 리스트 안에 있는 다른 객체로도 접근이 가능합니다. + +리스트에서 뭔가 지우려면 **indexes** 위에서 이미 배운대로 `pop()` 문을 사용해야 합니다. (del은 delete의 약자에요) 이제 한번 해보고 이전에 배웠던 것을 다시 떠올려봅시다. ; 목록에서 첫 번째 숫자를 삭제할 것입니다. + + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + + +마법 같네요! + +재미로 몇 번 더 여러 인덱스를 테스트해보세요: 6, 7, 1000, -1, -6, -1000 등이요. 결과값을 보기 전에 미리 어떤 값이 나올지 예상할 수 있었나요? 생각했던 정답이 나왔나요? + +이번 장에 나온 리스트 메서드와 관련된 모든 내용은 파이썬 공식 문서에서 찾을 수 있습니다. : https://docs.python.org/3/tutorial/datastructures.html + +## 딕셔너리(Dictionary) + +딕셔너리는 리스트와 유사하지만, 인덱스가 아닌 키(key)로 값을 찾습니다. 키는 문자열이든, 숫자든지 상관없습니다. 빈 딕셔너리를 만드는 문법은 아래와 같습니다. : + + >>> {} + {} + + +방금 비어있는 딕셔너리를 하나 만들었답니다. 만세! + +자, 이제 아래 명령어를 따라 작성해 봅시다. (안에 있는 정보는 마음대로 바꿔도 됩니다): + + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + + +위 명령어로 `paticipant`라는 이름의 변수를 만들었습니다. 이 변수 안에는 3개의 키-값 쌍이 들어있습니다. + +* 키(key) 는 `name`이고, 값(value) 는 `'Ola'`를 가리킵니다. (`string(문자열)` 객체이지요), +* 키 `country`의 값은 `'Poland'`입니다. (또 다른 `string`입니다.), +* 그리고 키 `favorite_numbers`는 `[7, 42, 92]`를 가리킵니다. (`리스트`에는 세 개의 숫자가 있습니다) + +여러분은 아래와 같은 문법으로 개별 키의 값에 접근할 수 있습니다. + + >>> print(participant['name']) + Ola + + +리스트와 조금 비슷하죠. 다만 인덱스가 아닌, 이름을 사용해 값에 접근한다는 것을 기억하세요. + +만약 파이썬에 키에 대응하는 값이 없는 경우에는 어떻게 될까요? 예측할 수 있나요? 그럼 한 번 알아봅시다! + + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + + +보세요, 에러가 났네요! 이번에는 **KeyError**에러가 났습니다. 파이썬은 친절하게 키 `'age'`가 딕셔너리에 존재하지 않는다고 알려주네요. + +그렇다면 언제 딕셔너리를 쓰고, 언제 리스트를 사용해야할까요? 이를 위한 판단 기준은 다음과 같습니다. + +* 아이템을 나열할 때 정렬이 필요하나요? 그렇다면 리스트를 사용하세요. +* 키(key) 과 값(value) 이 서로 연관되어 있어야 하나요? 또는 보다 효과적으로 (키를 사용해서) 어떤 값을 찾아야 하나요? 그렇다면, 딕셔너리를 사용하세요. + +딕셔너리는 리스트와 유사하지만, *변경(mutable)*할 수 있습니다. 딕셔너리가 만들어진 후에도, 그 값을 마음대로 변경할 수 있다는 뜻이지요. 키/값 을 나중에 추가할 수 있답니다. 바로 이렇게요. : + + >>> participant['favorite_language'] = 'Python' + + +리스트처럼 딕셔너리도 `len()` 메서드를 사용하여 키-값 쌍의 수를 리턴합니다. 한 번 커맨드라인에서 확인합시다. : + + >>> len(participant) + 4 + + +다들 이해를 잘 하고 있으리라 믿어요 :) 딕셔너리로 좀 더 재미있는 것을 해볼까요? 좀더 흥미로운 내용이 다음에 있어요. + +`del` 명령어로 딕셔너리에 있는 아이템을 삭제할 수 있습니다. `'favorite_numbers'` 키를 삭제하고 싶으면, 아래와 같은 명령어를 입력하면 됩니다. : + + >>> participant.pop('favorite_numbers') + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + + +위에 보여지는 결과처럼 'favorite_numbers' 에 해당하는 키-값 쌍이 삭제되었네요. + +이뿐만 아니라 딕셔너리 안에 이미 만들어진 키에 해당하는 값도 변경할 수 있습니다. 다음 내용을 해보세요. : + + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + + +보셨듯이, `'country'` 키에 해당하는 값이 `'Poland'`에서 `'Germany'`로 변경되었네요. :) 재미있죠? 야호! 우리는 또 굉장한 것을 배웠네요. + +### 요약 + +훌륭하네요! 이제 모두가 프로그래밍에 대해서 많은 것을 알게 되었어요. 지금까지 우리가 배운 내용은 다음과 같아요. : + +* **에러** - 파이썬이 작성된 명령어를 이해하지 못할 때 발생하는 에러를 읽고 이해할 수 있습니다. +* **변수** - 객체에 이름을 붙여 코드를 가독성 좋게 작성할 수 있습니다. +* **리스트** - 특정한 순서로 정렬된 객체들이 저장된 목록임을 알고 있습니다. +* **딕셔너리** - 키(key)-값(value) 쌍으로 이루어진 객체들이 저장된 것임을 알고 있습니다. + +다음 내용이 기대되나요? :) + +## 비교하기 + +무엇인가 비교하는 것은 프로그래밍에서 매우 중요한 부분이에요. 비교를 할 때, 제일 쉬운 방법은 무엇일까요? 당연히, 숫자입니다. 어떻게 하는지 알아볼게요. : + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + + +파이썬이 숫자들을 비교했네요. 여러분도 보았듯이, 파이썬은 숫자 뿐만 아니라 메서드 결과도 비교 가능합니다. 멋지죠? + +두 숫자를 비교할 때 왜 등호 부호 `==`를 사용하는지 궁금했죠? 우리는 변수에 값을 넣을 때 한 개의 등호 기호 `=`를 사용하죠. 그렇기 때문에, 두 대상이 같은지 서로 비교하기 위해서는 **항상** 두 개의 등호 기호 `==`를 사용해야 합니다. 마찬가지로 두 대상이 서로 같지 않다라고 말할 수 있습니다. 위 예제에서 볼 수 있었듯이 서로 같은 대상이 아닐 때는 `!=` 기호를 사용합니다. + +두 번 더 테스트 해볼게요. : + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +`>`와 `<`는 알겠지만, `>=`와 `<=`는 무슨 뜻일까요? 아래 내용을 읽어보세요. : + +* x `>` y : x는 y보다 크다 +* x `<` : x는 y보다 작다 +* x `<=` : x가 y보다 작거나 같다 +* x `>=` : x가 y보다 크거나 같다 + +잘했어요! 좀 더 해볼까요? 이런 건 어떨까요. : + + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + + +파이썬은 얼마든지 원하는 만큼 숫자를 비교할 수 있고 답을 알려줄 거에요! 똑똑한 녀석이죠? + +* **and** - `and` 연산자는, 두 값 모두 참(True) 일 경우에만 결과가 True가 됩니다. +* **or** - `or` 연산자는, 둘 중 하나만 참(True) 일 경우에 True가 됩니다. + +"사과를 오렌지에 비교하기"라는 말을 들어본 적이 있나요? 파이썬에게 시켜봅시다. : + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +이처럼 파이썬은 숫자(`int`)와 문자열(`str`)을 비교할 수 없어요. 대신 **TypeError**를 보여줘 두 타입이 서로 비교 대상이 아니라는 것을 알려줍니다. + +## Boolean (불리언) + +방금 전 파이썬의 새로운 객체 종류를 배웠는데요. 바로 **Boolean**입니다. 여기 있는 것 중에 가장 쉬운 걸 거에요. + +Boolean 객체는 종류는 딱 두 가지 뿐이에요.: - 참(True) - 거짓(False) + +그런데 파이썬이 이해시키려면, 항상 'True'라고 써야 합니다. (즉 첫 글자가 대문자고 나머지는 소문자여야만, Boolean으로 이해하는 것이죠.) **true, TRUE, tRUE는 모두 틀린 표현이에요. -- True만 올바른 표현입니다.** (False도 마찬가지입니다.) + +Boolean도 변수로 사용할 수도 있습니다! 다음을 보세요. : + + >>> a = True + >>> a + True + + +이런 식으로도 쓸 수 있습니다. + + >>> a = 2 > 5 + >>> a + False + + +아래 명령어를 실행해보면서 Boolean을 가지고 놀아보세요. : + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +축하합니다! Boolean은 프로그래밍에 있어서 가장 멋진 기능 중 하나에요. 여러분은 Boolean을 앞으로 어떻게 사용해야 하는지 방금 배웠답니다! + +# 코드 저장하기! + +지금까지 우리는 인터프리터(interpreter)에서 파이썬 코드를 입력해 왔어요. 한 번에 코드 한 줄만 입력할 수 있었어요. 일반적으로 프로그램은 파일로 저장되어 프로그래밍 언어 **인터프리터(interpreter)** 또는 **컴파일러(complier)**로 실행됩니다. 지금까지 우리는 파이썬 **인터프리터**에서 한 줄씩 코드를 입력해 프로그램을 실행시켰어요. 이제 앞으로는 한 줄 이상 더 많은 코드를 작성해 실행해 볼 거에요. 빨리 해볼게요. : + +* 파이썬 인터프리터를 종료하세요. +* 선택한 코드 에디터를 실행하세요. +* 코드를 새 파이썬 파일로 저장하세요. +* 실행하세요! + +사용했던 파이썬 인터프리터를 종료하려면, exit()~~~ 함수를 입력하세요. : + + >>> exit() + $ + + +그러면 커맨드 프롬프트(또는 콘솔창) 가 초기화 됩니다. + +앞서 우리는 [코드 편집기][2] 섹션에서 어떤 코드 편집기를 사용할지 정했었습니다. 이제 편집기를 실행해서 새 코드를 작성하여 새 파일로 저장합니다: + + [2]: ../code_editor/README.md + +```python + print('Hello, Django girls!') +``` + +> **Note** 우리는 코드 에디터의 멋진 기능을 알고 있어야 해요. : 파이썬 콘솔에서는 모든 코드가 같은 색이였지만, 이제 `print` 함수와 그 안에 있는 문자열이 다른 색깔로 되어 구분할 수 있다는 것을 알게 되었을 거에요. 이를 "문법 하이라이팅(syntax highlighting)" 하는데, 코딩할 때 필요한 기능이죠. 이 기능은 여러분에게 색깔로 힌트를 알려줘요. 예를 들어, 문자열이 제대로 닫히지 않았다던가, 특정 키워드(함수에서 사용하는 `def` 같은 특별한 의미로 쓰이는 단어. 앞으로 다룰 거에요.)를 사용할 때, 다른 색으로 지정해서 바로 알 수 있게 해주죠. 그래서 우리는 코드 에디터를 사용한답니다. :) + +오늘 우리 모두가 파이썬 개발자가 되었답니다. 그러니 오늘 배운 코드를 가지고 놀아보세요. + +이제 파일을 저장하고 파일 이름을 바꾸세요. 바탕화면에 **python_intro.py** 파일로 저장하세요. 원하는 파일이름으로 저장할 수 있지만, 파일 이름이 반드시 **.py**로 끝나야 해요. **.py**파일 확장자는 운영체제에게 **파이썬 실행 파일**이니 파이썬을 실행하라고 지시합니다. + +파일을 저장했다면, 커맨드라인 장에서 배웠던 것을 써먹어야죠! 터미널에서 데스크탑으로 **디렉토리 변경**을 해보세요. + +맥이라면 명령어는 다음과 같을 것입니다. : + + cd /Users//Desktop + + +리눅스는 다음과 같아요. ("Desktop"이라는 문자는 해당 국어로 번역되어 있을 것에요. 한국어라면 "데스크탑" 또는 "바탕화면"으로 번역되어 있을 것입니다.) + + cd /home//Desktop + + 또는 "바탕화면"으로 번역되어 있다면 + cd /home//바탕화면 + + 또는 "데스크탑"으로 번역되어 있다면 + cd /home//데스크탑 + + +윈도우라면 다음과 같이 하세요. : + + > cd C:\Users\\Desktop + + +혹시 하다가 막히면, 코치에게 도움을 요청하세요. + +이제 파일 안에 있는 코드를 실행하기 위해 다음과 같이 파이썬을 실행해 봅시다. : + + $ python3 python_intro.py + Hello, Django girls! + + +잘했어요! 우리는 첫 파이썬 프로그램이 저장된 파일을 실행했어요. 내가 드디어 해냈다고 느껴지나요? + +다음으로 프로그래밍의 필수 도구를 알아볼 차례에요. : + +## If...elif...else + +코드의 많은 부분은 조건을 만났을 때 실행된답니다. 이를 위해 파이썬은 **if문**을 사용합니다. + +**python_intro.py** 파일을 다음과 같이 수정하세요: + +```python + if 3 > 2: +``` + +저장하고 실행하면 아래와 같은 에러를 보게 될 거에요. : + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +파이썬은 조건문 `3 > 2`가 참인 경우(또는 값이 `True`인 경우)에 어떤할 지 물어 보네요. 이 경우에 파이썬이 "It works!"를 출력하게 해봅시다. : **python_intro.py** 파일을 아래와 같이 수정하세요. : + +```python + if 3 > 2: + print('It works!') +``` + +두 번째 줄 들여쓰기 된 코드에 스페이스 4칸을 준 게 보이나요? 조건의 결과(여기서는 3>2) 가 참일 경우에, 실행할 코드에 들여쓰기를 해줘야 합니다. 물론 스페이스 한 칸만 띄울 수 있지만, 거의 모든 파이썬 프로그래머들은 코드를 깔끔하게 작성하기 위해 4칸을 사용해요. `탭(tab)` 한 번은 스페이스 4칸을 준 것과 같아요. + +이제 저장하고 실행해보세요. : + + $ python3 python_intro.py + It works! + + +### 조건이 참(True) 이 아니라면 어떻게 되나요? + +앞의 예제에서 코드가 조건이 True인 경우에만 실행되게 만들었어요. 하지만 파이썬은 `elif`문과 `else`문도 사용할 수 있습니다. + +```python + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') +``` + +실행하면 다음과 같이 출력됩니다. : + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +만약 2가 5보다 크다면 두번째 명령이 실행됩니다. 참 쉽죠? 이제 `elif`가 어떻게 작동하는지 봅시다. : + +```python + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') +``` + +그리고 실행해보세요. : + + $ python3 python_intro.py + Hey Sonja! + + +어떻게 됐나요? `elif`문은 맨 처음 조건이 아닐 경우 그 다음 조건을 처리하게 해줍니다. + +여러분은 `if` 문을 쓴 다음에 원하는 만큼 `elif` 문을 계속 추가할 수 있어요. 이렇게요. : + +```python + volume = 57 + if volume < 20: + print("It's kinda quiet.") + elif 20 <= volume < 40: + print("It's nice for background music") + elif 40 <= volume < 60: + print("Perfect, I can hear all the details") + elif 60 <= volume < 80: + print("Nice for parties") + elif 80 <= volume < 100: + print("A bit loud!") + else: + print("My ears are hurting! :(") +``` + +파이썬이 각 테스트를 순서대로 실행하고 출력합니다: + + $ python3 python_intro.py + Perfect, I can hear all the details + + +### 요약 + +지금까지 우리는 세 예제로 다음과 같은 것들을 배웠어요. : + +* **비교하기** - 파이썬에서 `>`, `>=`, `==`, `<=`, `<` 그리고 `and`, `or` 연산자를 사용해 비교합니다. +* **Boolean** -두 둘 중 하나의 값만 가질 수 있는 객체입니다. : `True` 또는 `False` +* **파일 저장하기** - 복잡한 프로그램을 실행할 수 있도록 코드를 파일로 저장합니다. +* **if...elif...else** - 조건문을 작성해 특정 조건이 주어졌을 때만 코드가 실행되도록 만듭니다. + +드디어 이번 장의 마지막 부분입니다! + +## 나만의 함수 만들기! + +앞에서 했던 파이썬 `len()` 같은 함수를 기억하나요? 네, 좋은 소식이에요. 지금부터는 함수를 만드는 법을 배울 거에요! + +함수는 파이썬이 실행해야하는 명령어의 나열이에요. 파이썬의 각 함수는 `def`로 시작해, 이름을 가지고, 몇 가지 매개 변수를 가집니다. 쉬운 것부터 시작할게요. **python_intro.py**파일을 열어 코드를 다음과 같이 고치세요. : + +```python + def hi(): + print('Hi there!') + print('How are you?') + + hi() +``` + +네, 우리가 만든 첫 번째 함수네요! + +파일 맨 밑에 왜 함수의 이름을 적는지 궁금할거에요. 왜냐하면 파이썬은 파일을 위에서 아래로 읽어 실행하기 때문이에요. 함수를 사용하기 위해서는 하단에 다시 적어야 합니다. + +이제 실행해서 어떻게 되는지 봅시다. : + + $ python3 python_intro.py + Hi there! + How are you? + + +정말 간단하네요! 매개 변수와 함께 첫 번째 함수를 만들어 볼게요. 전에 사용했던 예제를 다시 사용할 거에요. 함수를 실행하면, 사람들에게 이름과 함께 'hi'를 말하게요. + +```python + def hi(name): +``` + +함수에 매개변수인 `name`를 주었어요. + +```python + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() +``` + +기억하세요 : `if`문 안의 `print`함수는 4칸을 들여쓰기 했습니다. 조건문에 해당하는 경우에만 실행되게 만들기 위해서에요. 이제 어떻게 되는지 보세요. : + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' + + +이런, 에러가 나왔네요. 다행히도, 파이썬 에러는 유용한 오류 메세지를 보여주네요. 에러 메시지를 보면 함수 `hi()`가 한 개의 인자값(`name`) 을 필요로 하는데, 그 함수를 호출할 때 빼먹고 실행했다는 것을 알려주고 있어요. 이제 아래와 같이 코드를 수정해봅시다. : + +```python + hi("Ola") +``` + +그리고 다시 실행해보세요. : + + $ python3 python_intro.py + Hi Ola! + + +만약 이름을 바꾸면 어떻게 될까요? + +```python + hi("Sonja") +``` + +그리고 실행하세요. : + + $ python3 python_intro.py + Hi Sonja! + + +이제 다른 이름(Ola와 Sonja가 아닌) 을 넣는다면 어떻게 될까요? 한번 넣어서 실행해봅시다. 이렇게 나와야 해요. : + + Hi anonymous! + + +어때요, 정말 굉장하지 않나요? 이로써 인사 함수가 호출될 때마다, 사람 이름을 매번 반복할 필요가 없어요. 그래서 함수가 필요해요 - 매번 똑같은 코드를 반복해 작성하지 않아도 돼요! + +좀 더 똑똑한 것을 해볼게요. -- 2명 이상 이름이 있는 경우, 이름마다 조건문을 추가하는 건 꽤 귀찮은 일이 될거에요. 그렇죠? + +```python + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") +``` + +이제 코드를 실행해 봅시다: + + $ python3 python_intro.py + Hi Rachel! + + +축하합니다! 우리는 이제 함수를 작성하는 법을 알게 되었어요! :) + +## 반복하기 + +이제 마지막 부분입니다. 금방 했죠? :) + +프로그래머는 반복되는 일을 스스로 하기를 좋아하지 않아요. 프로그래밍이란 어떤 일들을 자동화하는 것이니까 반복적인 경우가 생기면 그걸 반복해서 해결하는 코드를 짜는 것이지요. 앞에서 했던 예제와 같이 인사해야 하는 사람이 수백명 있을 경우, 설마 각각 사람마다 인사하려고 hi('누구누구') 코드를 수백번 입력하고 싶지는 않겠지요? 이런 경우에 바로 반복문(loop)를 사용할 수 있어요. + +리스트 아직 기억하고 있어요? 아래 girls 리스트를 보세요. : + +```python + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + +우리는 여자 아이들 이름을 불러 인사를 하고 싶어요. 우리는 이미 `hi` 함수를 만들었으니 반복문을 사용해봅시다. : + +```python + for name in girls: +``` + +for~~~ 문은 if~~~ 문과 비슷하게 동작합니다. ; 두 경우 모두 다음에 오는 코드들을 4칸 들여쓰기 해야합니다. + +아래 완성된 코드입니다. : + +```python + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('Next girl') +``` + +실행하면 다음과 같습니다. : + + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl + + +`girls` 리스트의 요소마다 여러분이 `for`문에 넣은, 들여쓰기를 한 모든 코드들이 반복됩니다. + +`for`문에 `range` 함수로 숫자를 사용할 수 있어요. + +```python + for i in range(1, 6): + print(i) +``` + +이렇게 출력됩니다. : + + 1 + 2 + 3 + 4 + 5 + + +`range`는 매개 변수로 넘겨진 숫자부터 시작하는 숫자 리스트를 만들어주는 함수입니다. + +파이썬에서는 두 숫자 중 두 번째는 리스트에 포함되지 않는다는 것을 주의하세요. (즉 `range(1, 6)`는 1부터 5까지 카운트 하며 숫자 6은 리스트에 포함되지 않습니다.) "range"는 반만 열려 있기 때문에, 첫번째 숫자는 포함되지만 마지막 숫자는 포함되지 않아요. + +## 요약 + +이제 다 끝났어요. **모두 정말 대단해요!** 어려운 내용이었는데 잘 해낸 나 자신을 자랑스럽게 생각하세요. 여기까지 온 것이 자랑스럽습니다! + +다음 장으로 넘어가지 전에 좀 쉬고 와도 좋아요. 스트레칭을 하던가, 잠깐 산책을 하던가, 눈을 쉬게 한다던가 말이죠. :) + +![컵케이크][3] + + [3]: images/cupcake.png diff --git a/ko/python_introduction/images/cupcake.png b/ko/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/ko/python_introduction/images/cupcake.png differ diff --git a/ko/template_extending/README.md b/ko/template_extending/README.md new file mode 100755 index 00000000000..00af8a02eb3 --- /dev/null +++ b/ko/template_extending/README.md @@ -0,0 +1,123 @@ +# 템플릿 확장하기 + +장고의 또 다른 멋진 기능은 __템플릿 확장(template extending)__ 입니다. 무슨 뜻일까요? 바로 여러분의 웹사이트 안의 서로 다른 페이지에서 HTML의 일부를 동일하게 재사용 할 수 있다는 뜻이에요. + +이 방법을 사용하면 동일한 정보/레이아웃을 사용하고자 할 때, 모든 파일마다 같은 내용을 반복해서 입력 할 필요가 없게 됩니다. 또 뭔가 수정할 부분이 생겼을 때, 각각 모든 파일을 수정할 필요 없이 딱 한번만 수정하면 된답니다! + +## 기본 템플릿 생성하기 + +기본 템플릿은 웹사이트 내 모든 페이지에 확장되어 사용되는 가장 기본적인 템플릿입니다. + +`blog/templates/blog/`에 `base.html` 파일을 만들어 봅시다: + + blog + └───templates + └───blog + base.html + post_list.html + + +그 다음 파일을 열어 `post_list.html`에 있는 모든 내용을 `base.html`에 아래 내용을 복사해 붙여넣습니다. + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +그 다음 `base.html`에서 `` (``와 `` 사이에 있는 모든 내용)의 모든 내용을 아래와 같이 바꿉니다: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +`{% for post in posts %}{% endfor %}` 사이에 있는 모든 내용을 바꿨습니다. : + +```html +{% block content %} +{% endblock %} +``` + +무슨 의미일까요? 여러분이 만든 `block`은 템플릿 태그로 `base.html`을 확장한 이 블럭에 HTML을 추가할 수 있게 해줍니다. 어떻게 동작하는지 보여 드릴게요. + +이제 파일을 저장을 하고, `blog/templates/blog/post_list.html` 파일을 다시 엽니다. body 태그 안에 있는 모든 내용을 지우고, ``도 지웁니다. 그러면 파일은 아래처럼 될 거에요. : + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +파일 맨 윗 줄에 아래 내용을 추가합니다. + +```html + {% extends 'blog/base.html' %} +``` + +`post_list.html` 파일에 있는 {% raw %}는 이제 `base.html` 템플릿을 확장했음을 의미합니다. 이제 한 가지만 더 하면 되어요.: `{% block content %}`과 `{% endblock content %}` 사이에 (우리가 방금 추가한 행들을 빼고) 모든 것을 넣습니다. 아래 처럼요. :{% endraw %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +다 되었어요! 여러분의 웹사이트가 잘 작동하는지 확인해보세요. :) + +> 만약 `TemplateDoesNotExists` 에러가 난다면 `blog/base.html` 파일이 없어 콘솔에서 `runserver`가 작동되고 있는 경우 입니다. 이런 경우, (Ctrl+C)를 눌러서 멈춘 후 `python manage.py runserver`명령어로 재시작해 주세요. diff --git a/ko/whats_next/README.md b/ko/whats_next/README.md new file mode 100755 index 00000000000..0409a9d9ee7 --- /dev/null +++ b/ko/whats_next/README.md @@ -0,0 +1,40 @@ +# 더 나아가기 + +모두 축하합니다! **정말 멋져요!** 자신감을 가지세요! ^___^ + +### 이제 무엇을 해야하나요? + +잠시 휴식을 가지고 여유를 가지세요. 여러분은 이제 막 정말 큰 일 마쳤으니까요. + +잊지 말고 꼭 해보세요. : + +* [Facebook][1] 또는 [Twitter][2] 에서 Django Girls를 구독하셔서 최신 정보를 얻으세요! + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### 앞으로 해 볼만한 자료를 추천해주실래요? + +그럼요! [장고 걸스: 심화 (Django Girls Tutorial: Extensions)][3]를 읽어보세요. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +그 다음, 아래 추천 리스트를 참고해 공부해보세요. 모두 강력 추천합니다! + + - [Django 공식 튜터리얼(Django's official tutorial)][4] + - [초보 코더 튜터리얼(New Coder tutorials)][5] + - [코드 아카데미 파이썬 코스(Code Academy Python course)][6] + - [코드 아카데미 HTML & CSS 코스(Code Academy HTML & CSS course)][7] + - [Django Carrots tutorial][8] + - [Learn Python The Hard Way book][9] + - [Django 비디오 강좌로 시작하기(Getting Started With Django video lessons)][10] + - [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/pl/GLOSSARY.md b/pl/GLOSSARY.md new file mode 100755 index 00000000000..303cd4344e1 --- /dev/null +++ b/pl/GLOSSARY.md @@ -0,0 +1,3 @@ +# edytor kodu + +Edytor kodu to taka aplikacja, która pozwala Ci zapisać kod, byś mogła do niego wrócić w dowolnym późniejszym momencie. Możesz się dowiedzieć skąd go ściągnąć z [rozdziału o edytorach kodu](./code_editor/README.md). \ No newline at end of file diff --git a/pl/README.md b/pl/README.md index 239b6aeec62..d2bb1bf2e16 100755 --- a/pl/README.md +++ b/pl/README.md @@ -2,12 +2,11 @@ [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -> Niniejsza praca jest licencjonowana zgodnie z Creative Commons Attribution-ShareAlike License 4.0 International. Aby zobaczyć kopię niniejszej licencji, odwiedź http://creativecommons.org/licenses/by-sa/4.0/ +> Niniejsza praca jest licencjonowana zgodnie z Creative Commons Attribution-ShareAlike License 4.0 International. Aby zobaczyć kopię niniejszej licencji, odwiedź https://creativecommons.org/licenses/by-sa/4.0/ ## Tłumaczenie -Ten kurs został przetłumaczony z języka angielskiego przez grupę wolontariuszy. Specjalne podziękowania dla [Łukasza Wójcika](http://lukaszwojcik.net/), który poświęcił -ogromną ilość swojego wolnego czasu tłumacząc ponad 80% całego kursu. Dodatkowe podziękowania za pomoc dla: Oli Sitarskiej, Anny Warzechy, CrazyHorse, Kingi Kieczkowskiej, Maćka Zająca oraz Mariusza Zielińskiego. +Ten kurs został przetłumaczony z języka angielskiego przez grupę wolontariuszy. Specjalne podziękowania za pomoc dla: Łukasza Wójcika, Agaty Grdal, Oli Sitarskiej, Marysi Lowas-Rzechonek, Anny Warzechy, Maćka Zająca, CrazyHorse, Kingi Kieczkowskiej, Mariusza Zielińskiego, Beltuska, Bartka Dobrowolskiego, Oli Sendeckiej, Michała Krzysztofa Feilera, Kamila Gałuszki, Adriangit oraz Chrisa Warricka. <3 <3 ## Wprowadzenie @@ -15,7 +14,7 @@ Czy kiedykolwiek czułaś, że wokół jest coraz więcej nowych technologii, a No więc mamy dla Ciebie dobre nowiny! Programowanie nie jest tak trudne, jak się wydaje, a my chcemy Ci pokazać, że może być też niezłą zabawą. -Ten kurs nie zamieni Cię w zawodowego programistę. Jeżeli chcesz być w tym naprawdę dobra, musisz spędzić miesiące lub nawet lata na nauce i ćwiczeniach. Ale chcielibyśmy Ci pokazać, że programowanie i pisanie stron internetowych nie jest tak złożone, jak mogłoby się wydawać. Spróbujemy wyjaśnić to i owo jak tylko potrafimy w taki sposób, abyś nie czuła się przytłoczona nową technologią. +Ten kurs nie zamieni Cię w zawodowego programistę. Jeżeli chcesz być w tym naprawdę dobra, musisz spędzić miesiące lub nawet lata na nauce i ćwiczeniach. Ale chciałybyśmy Ci pokazać, że programowanie i pisanie stron internetowych nie jest tak trudne, jak mogłoby się wydawać. Spróbujemy wyjaśnić to i owo najprościej i najlepiej jak tylko potrafimy, abyś nie czuła się przytłoczona nową technologią. Mamy nadzieję sprawić, że pokochasz to tak jak my! @@ -25,21 +24,22 @@ Gdy skończysz kurs, będziesz mieć gotową prostą aplikacje internetową: sw Będzie to wyglądać mniej więcej tak: -![Rysunek 0.1](images/application.png) +![Rysunek 0.1][2] -> Jeżeli przerabiasz tutorial samodzielnie i nie masz w pobliżu osoby, która pomogłaby Ci w razie problemów, zapraszamy na czat: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -. Ustaliliśmy z naszymi mentorami oraz poprzednimi uczestniczkami, że od czasu do czasu będą się tam pojawiać i udzielać pomocy z tutorialem! Nie bój się pytać! + [2]: images/application.png + +> Jeżeli przerabiasz tutorial samodzielnie i nie masz w pobliżu osoby, która pomogłaby Ci w razie problemów, zapraszamy na czat: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Ustaliliśmy z naszymi mentorami oraz poprzednimi uczestniczkami, że od czasu do czasu będą się tam pojawiać i udzielać pomocy z tutorialem! Nie bój się pytać! Ok, [zacznijmy od początku...][3] -[3]: ./how_the_internet_works/README.md + [3]: ./how_the_internet_works/README.md ## Jak możesz pomóc? -Kurs jest prowadzony przez [DjangoGirls][4]. Jeżeli znajdziesz błąd lub chcesz dodać coś nowego, zapoznaj się z [tymi informacjami][5]. +Kurs jest prowadzony przez [DjangoGirls][4]. Jeżeli znajdziesz jakiś błąd lub chcesz dodać coś nowego, zapoznaj się proszę z [tymi informacjami][5]. -[4]: http://djangogirls.org/ -[5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md ## Pomożesz nam przetłumaczyć tutorial na inne języki? @@ -47,6 +47,6 @@ Obecnie przechowujemy wersje językowe na platformie Crowdin.com: https://crowdin.com/project/django-girls-tutorial -Jeżeli nie znajdziesz tam swojego języka, prosimy o [otwarcie nowego zgłoszenia][6] z brakującym językiem - postaramy się go dodać. +Jeżeli nie znajdziesz tam swojego języka, prosimy o [zgłoszenie][6] nowego, brakującego języka, abyśmy mogły go dodać. -[6]: https://github.com/DjangoGirls/tutorial/issues/new + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/pl/SUMMARY.md b/pl/SUMMARY.md index 12af9c7b640..e64dc1a1c79 100755 --- a/pl/SUMMARY.md +++ b/pl/SUMMARY.md @@ -1,14 +1,15 @@ # Podsumowanie * [Wprowadzenie](README.md) -* [Jak działa internet?](how_the_internet_works/README.md) +* [Instalacja](installation/README.md) +* [Jak działa internet](how_the_internet_works/README.md) * [Wprowadzenie do linii poleceń](intro_to_command_line/README.md) * [Instalowanie Pythona](python_installation/README.md) * [Edytor kodu](code_editor/README.md) * [Wprowadzenie do Pythona](python_introduction/README.md) * [Czym jest Django?](django/README.md) * [Instalowanie Django](django_installation/README.md) -* [Tworzenie projektu Django](django_start_project/README.md) +* [Twój pierwszy projekt w Django!](django_start_project/README.md) * [Modele w Django](django_models/README.md) * [Administracja Django (admin)](django_admin/README.md) * [Wdrażanie!](deploy/README.md) @@ -22,5 +23,4 @@ * [Rozbudowa szablonów](template_extending/README.md) * [Rozbudowa aplikacji](extend_your_application/README.md) * [Formularze Django](django_forms/README.md) -* [Domena](domain/README.md) * [Co dalej?](whats_next/README.md) diff --git a/pl/code_editor/README.md b/pl/code_editor/README.md index c06f19354ea..3a2d0024e7b 100755 --- a/pl/code_editor/README.md +++ b/pl/code_editor/README.md @@ -1,33 +1,7 @@ # Edytor kodu -Zaraz napiszesz swoją pierwszą linijkę kodu, czas na zainstalowanie edytora tekstu! +Zaraz napiszesz swoją pierwszą linijkę kodu, więc najwyższy czas zainstalować edytor kodu! -Tylko który wybrać? To nie takie proste, bo wybór zależy w dużej mierze od tego, co oczekujesz od swojego edytora. Większość programistów Pythona używa bardzo skomplikowanych i niezwykle bogatych w różne funkcjonalności IDE (z ang. zintegrowanych środowisk programistycznych - Integrated Development Environments), takich jak np. PyCharm. Jako osoba początkująca nie potrzebujesz jednak aż tak skomplikowanego edytora. Wystarczy coś prostszego, ale nadal dostatecznie użytecznego. +> **Uwaga** Jeśli zrobiłaś to już wcześniej w rozdziale 'Instalacja' - możesz przejść od razu do następnego rozdziału! -Poniżej znajdziesz nasze propozycje, ale jeżeli masz taką możliwość, możesz poprosić o rekomendację Twojego coacha -- będzie mu łatwiej pomagać Ci podczas warsztatów. - -## Gedit - -Gedit to open source'owy i darmowy edytor dostępny dla wszystkich systemów operacyjnych. Czasami nie jest jednak zbyt prosty w zainstalowaniu. - -[Pobierz tutaj][1] - - [1]: https://wiki.gnome.org/Apps/Gedit#Download - -## Sublime Text 2 - -Sublime Text to bardzo popularny edytor z darmowym okresem testowania. Jest bardzo prosty do zainstalowania i używania, dostępny na wszystkie systemy operacyjne. - -[Pobierz tutaj][2] - - [2]: http://www.sublimetext.com/2 - -## Atom - -Atom to nowy edytor kodu stworzony przez [GitHuba][3]. Jest darmowy, ma otwarte źródła, jest łatwy do zainstalowania i używania. Dostępny na Windowsa, OS X i Linuxa. - - [3]: http://github.com/ - -[Pobierz tutaj][4] - - [4]: https://atom.io/ +{% include "/code_editor/instructions.md" %} diff --git a/pl/code_editor/instructions.md b/pl/code_editor/instructions.md new file mode 100755 index 00000000000..c7659e8732f --- /dev/null +++ b/pl/code_editor/instructions.md @@ -0,0 +1,31 @@ +Tylko który wybrać? To nie takie proste, bo wybór zależy w dużej mierze od tego, czego oczekujesz od swojego edytora. Większość programistów Pythona używa bardzo skomplikowanych i niezwykle bogatych w różne funkcjonalności IDE (z ang. Integrated Development Environments - zintegrowane środowisko deweloperskie), takich jak: PyCharm. Jako osoba początkująca nie potrzebujesz jednak aż tak skomplikowanego edytora. Wystarczy coś prostszego, ale nadal dostatecznie użytecznego. + +Poniżej znajdziesz nasze propozycje, ale jeżeli masz taką możliwość, możesz poprosić o rekomendację Twojego coacha -- będzie mu łatwiej pomagać Ci podczas warsztatów. + +## Gedit + +Gedit to open source'owy i darmowy edytor dostępny dla wszystkich systemów operacyjnych. Czasami nie jest jednak zbyt prosty w zainstalowaniu. + +[Pobierz tutaj](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text to bardzo popularny edytor z darmowym okresem testowania. Jest bardzo prosty do zainstalowania i używania, dostępny na wszystkie systemy operacyjne. + +[Pobierz tutaj](https://www.sublimetext.com/3) + +## Atom + +Atom to nowy edytor kodu stworzony przez [GitHuba](https://github.com/). Jest darmowy, ma otwarte źródła, jest łatwy do zainstalowania i używania. Dostępny na Windowsa, OS X i Linuxa. + +[Pobierz tutaj](https://atom.io/) + +## Dlaczego instalujemy edytor kodu? + +Może się zastanawiasz dlaczego instalujemy specjalny edytor kodu zamiast używać Notatnika albo Notepada. + +Po pierwsze kod musi być napisany **zwykłym tekstem** (ang. "plain text"), a programy takie jak Word albo Textedit sprawiają, że wyrazy nie są tak naprawdę tylko tekstem - możesz zmieniać ich wielkość, czcionkę czy kolor. Jest to tak zwany sformatowany tekst (ang. rich text), używający różnych formatów, takich jak [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Po drugie, edytory kodu zostały specjalnie stworzone do tego, by pisać w nich kod, więc mają wiele przydatnych opcji, takich jak podświetlanie różnych elementów składni języka programowania czy automatyczne dodawanie zamykającego cudzysłowu. + +Wszystko to zobaczymy w akcji. Niedługo zaczniesz myśleć o swoim edytorze kodu jako o starym, dobrym przyjacielu :) \ No newline at end of file diff --git a/pl/css/README.md b/pl/css/README.md index 252cb2b9586..e45108a62a4 100755 --- a/pl/css/README.md +++ b/pl/css/README.md @@ -10,7 +10,7 @@ Ale nie chcemy znów zaczynać od samego początku, prawda? Użyjemy, raz jeszcz ## Użyjmy Bootstrap! -Bootstrap jest jednym z najpopularniejszych frameworków HTML i CSS do budowania pięknych stron: http://getbootstrap.com/ +Bootstrap jest jednym z najpopularniejszych frameworków HTML i CSS do budowania pięknych stron: https://getbootstrap.com/ Został stworzony przez programistów, którzy pracowali dla Twitter-a i w chwili obecnej jest rozwijany przez ochotników z całego świata. @@ -18,9 +18,10 @@ Został stworzony przez programistów, którzy pracowali dla Twitter-a i w chwil Aby zainstalować Bootstrap musisz dodać poniższe linijki do znacznika `` w Twoim pliku `.html` (`blog/templates/blog/post_list.html`): - - - +```html + + +``` Te linijki nie dodają żadnych plików do Twojego projektu. Wskazują one po prostu na pliki, które znajdują się w internecie. Otwórz teraz swoją przeglądarkę i odśwież stronę, a ujrzysz zmianę! @@ -45,10 +46,11 @@ Teraz musimy stworzyć katalog, w którym będziemy przetrzymywać nasze pliki s Otwórz plik z lokalizacji `mysite/settings.py` i dodaj na końcu następujące linie: - STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "static"), - ) - +```python +STATICFILES_DIRS = ( + os.path.join(BASE_DIR, "static"), +) +``` Tym sposobem Django będzie wiedziało gdzie szukać plików statycznych. @@ -65,7 +67,7 @@ Czas by napisać jakiś styl CSS! Otwórz plik `static/css/blog.css` w Twoim edy Nie będziemy się zanadto zagłębiać w style, ani uczyć się o arkuszach CSS, bo jest to całkiem łatwe i możesz nauczyć się tego samodzielnie po tym warsztacie. Naprawdę rekomendujemy spróbowanie [kursu Codeacademy HTML & CSS][2] by nauczyć się wszystkiego czego potrzebujesz o robieniu ładniejszych stron internetowych. - [2]: http://www.codecademy.com/tracks/web + [2]: https://www.codecademy.com/tracks/web Jednak zróbmy chociaż trochę. Może moglibyśmy zmienić kolor naszego nagłówka? Do rozpoznawania kolorów komputery używają specjalnych kodów. Kody te zaczynają się od znaku `#`, po którym następuje 6 znaków. Każdy znak to cyfra (0-9) lub litera (A-F). Możesz znaleźć kody kolorów na przykład tutaj: . Możesz również użyć uprzednio [zdefiniowanych kolorów][3], takich jak `red` (czerwony) czy `green ` (zielony).. @@ -73,17 +75,19 @@ Jednak zróbmy chociaż trochę. Może moglibyśmy zmienić kolor naszego nagł Do pliku `static/css/blog.css` dodaj następujący kod: - h1 a { - color: #FCA205; - } - +```css +h1 a { + color: #FCA205; +} +``` `h1` to selektor CSS. To oznacza, że nadajemy style do każdego elementu `a` znajdującego się w elemencie `h1` (np. kiedy w kodzie mamy coś takiego: `

link

`). W tym przypadku nadajemy mu kolor `#FCA205`, czyli pomarańczowy. Oczywiście kolor jest dowolny! W pliku CSS ustalamy styl dla elementów znajdujących się w pliku HTML. Elementy HTML identyfikujemy przez nazwę (n.p. `a`, `h1`, `body`), atrybut `class` lub atrybut `id`. Nazwę klasy lub id ustalasz sama dowolnie. Ta sama nazwa klasy może być przypisana do wielu elementów, ale id musi być unikalne dla całego kodu HTML. Przykładowo następujący tag możemy ostylować w CSS używając nazwy `a`, klasy `external_link` lub id `link_to_wiki_page`: - - +```html + +``` O selektorach CSS możesz przeczytać więcej tutaj: [CSS Selectors in w3schools][4]. @@ -101,7 +105,6 @@ Tym sposobem HTML załaduje nasze style CSS :) Następnie, pomiędzy `` i ``` - Właśnie pokazaliśmy naszemu szablonowi gdzie znajduje się nasz plik CSS. Twój plik powinien teraz wyglądać tak: @@ -124,7 +127,7 @@ Twój plik powinien teraz wyglądać tak:

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -137,10 +140,11 @@ Ok, teraz zapisz plik i odśwież stronę! Super! Niezła robota. Może damy teraz naszej stronie trochę świeżego powietrza i zwiększymy margines po lewej stronie? Spróbujmy! - body { - padding-left: 15px; - } - +```css +body { + padding-left: 15px; +} +``` Dodaj powyższy CSS do twojego pliku, zapisz go i sprawdź jak zadziałał! @@ -152,16 +156,16 @@ Może zmienimy też rodzaj czcionki w naszym nagłówku? Wklej to do sekcji ` ``` - Ta linia zaimportuje czcionkę zwaną *Lobster*, jedną z czcionek Google () Dodaj teraz linię `font-family: "Lobster";` do pliku CSS `static/css/blog.css` wewnątrz bloku deklaracji `h1` (kod deklaracji pomiędzy nawiasami klamrowymi `{` i `}`), a następnie odśwież stronę: - h1 a { - color: #FCA205; - font-family: 'Lobster'; - } - +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` ![Rysunek 14.3](images/font.png) @@ -171,9 +175,11 @@ Jak wspomniano wcześniej, arkusze stylów kaskadowe używają pojęcia klasy, k Śmiało! Nazwijmy kilka części Twojego kodu HTML. Dodaj klasę nazwaną `page-header` do Twojego `div` który zawiera nagłówek: - +```html + +``` Teraz dodaj klasę `post` do Twojego `div` zawierającego post bloga: @@ -182,72 +188,74 @@ Teraz dodaj klasę `post` do Twojego `div` zawierającego post bloga:

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

``` A teraz dodamy bloki deklaracji do selektorów. Selektory zaczynające się od `.` odnoszą się do klas. W internecie dostępnych jest mnóstwo świetnych samouczków i instrukcji poświęconych CSS, dzięki którym łatwiej będzie Ci zrozumieć poniższy kod. Póki co po prostu go skopiuj, a następnie wklej w pliku `djangogirls/static/css/blog.css`: - .page-header { - background-color: #ff9400; - margin-top: 0; - padding: 20px 20px 20px 40px; - } - - .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { - color: #ffffff; - font-size: 36pt; - text-decoration: none; - } - - .content { - margin-left: 40px; - } - - h1, h2, h3, h4 { - font-family: 'Lobster', cursive; - } - - .date { - float: right; - color: #828282; - } - - .save { - float: right; - } - - .post-form textarea, .post-form input { - width: 100%; - } - - .top-menu, .top-menu:hover, .top-menu:visited { - color: #ffffff; - float: right; - font-size: 26pt; - margin-right: 20px; - } - - .post { - margin-bottom: 70px; - } - - .post h1 a, .post h1 a:visited { - color: #000000; - } - +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` Teraz otocz kod HTML wyświetlający posty deklaracjami klas. Zamień to: - {% for post in posts %} -
-

published: {{ post.published_date }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

-
- {% endfor %} - +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` w pliku `blog/templates/blog/post_list.html` na to: @@ -261,7 +269,7 @@ w pliku `blog/templates/blog/post_list.html` na to: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -269,7 +277,6 @@ w pliku `blog/templates/blog/post_list.html` na to: ``` - Zapisz te pliki i odśwież swoją stronę. ![Rysunek 14.4](images/final.png) diff --git a/pl/deploy/README.md b/pl/deploy/README.md index 65999e59d31..59ebc02d30a 100755 --- a/pl/deploy/README.md +++ b/pl/deploy/README.md @@ -1,230 +1,313 @@ # Wdrażanie! -> **Uwaga**: Niniejszy rozdział może być miejscami dość trudny. Bądź dzielna i przestudiuj go do końca; wdrażanie jest ważną częścią pracy nad stroną. Celowo umieściłyśmy go tutaj, aby osoba prowadząca kurs była w stanie pomóc Ci przejść przez skomplikowany proces opublikowania Twojej strony w sieci. Oznacza to, że możesz wciąż ukończyć tutorial samodzielnie, jeśli zabraknie Ci czasu. +> **Uwaga:** Niniejszy rozdział może być miejscami dość trudny. Bądź dzielna i przestudiuj go do końca; wdrażanie jest ważną częścią pracy nad stroną. Celowo umieściłyśmy go tutaj, aby Twój mentor był w stanie pomóc Ci przejść przez skomplikowany proces opublikowania Twojej strony w sieci. Oznacza to, że możesz wciąż ukończyć tutorial samodzielnie, jeśli zabraknie Ci czasu. Do tej pory Twoja strona była dostępna tylko na Twoim komputerze. Teraz nauczysz się, jak ją wdrożyć! Wdrożenie to inaczej opublikowanie Twojej aplikacji w internecie, dzięki czemu możesz w końcu pokazać ją innym ludziom :). -Jak już wiesz, strona internetowa musi znajdować się na jakimś serwerze. Istnieje wiele firm udostępniających miejsce na serwerach, jednak my użyjemy takiej, która zapewnia najprostszy proces wdrażania: [Heroku][1]. Heroku jest darmowe dla aplikacji z niewielką liczbą odwiedzających i na tym etapie w zupełności Ci wystarczy. +Jak już wiesz, strona internetowa musi znajdować się na jakimś serwerze. Istnieje wielu dostawców serwerów w internecie (tzw. firm hostingowych). Skorzystamy z takiego, którego proces wdrażania jest stosunkowo prosty: [PythonAnywhere][1]. PythonAnywhere jest darmowy dla małych aplikacji, które nie mają zbyt dużo odwiedzających, więc na początek na pewno wystarczy. - [1]: http://heroku.com/ + [1]: https://pythonanywhere.com/ -Postępujemy według tego kursu: https://devcenter.heroku.com/articles/getting-started-with-django, jednak dla Twojej wygody wklejamy go poniżej. +Drugą zewnętrzną usługą, jakiej będziemy używać jest [GitHub][2], który przechowuje kod. Istnieją inne usługi, ale w dzisiejszych czasach prawie wszyscy programiści mają konto na GitHubie - i Ty dzisiaj do nich dołączysz! -## Plik `requirements.txt` + [2]: https://www.github.com -Musimy utworzyć plik `requirements.txt` aby poinformować Heroku, jakie pakiety muszą zostać zainstalowane na naszym serwerze. +GitHub będzie takim miejscem pośrednim, którego użyjemy, by przetransportować Twój kod między Twoim komputerem a serwerem PythonAnywhere i z powrotem. -Jednak na początku to Heroku wymaga od nas zainstalowania kilku pakietów. Przejdź do konsoli z uruchomionym `virtualenv` i wpisz: +# Git - (myvenv) $ pip install dj-database-url gunicorn whitenoise +Git jest "systemem kontroli wersji", którego używa wielu programistów. Program ten śledzi zmiany w plikach na przestrzeni czasu, dzięki czemu możesz później przywracać wybrane wersje tych plików. Działa trochę jak funkcja "śledź zmiany" w Microsoft Word, ale jest o wiele bardziej potężny. +## Instalacja Gita -Gdy instalacja się zakończy, przejdź do katalogu `djangogirls` i wykonaj polecenie: +> **Uwaga** Jeśli już wcześniej przeszłaś kroki instalacyjne, nie musisz ich powtarzać - przejdź od razu do następnego podrozdziału, żeby stworzyć repozytorium Git. - (myvenv) $ pip freeze > requirements.txt +{% include "/deploy/install_git.md" %} +## Tworzenie repozytorium Git -W ten sposób zostanie utworzony plik `requirements.txt` zawierający listę zainstalowanych przez Ciebie pakietów (czyli bibliotek Pythona, których używasz, na przykład Django :)). +Git śledzi zmiany dokonywane w zbiorze plików w czymś, co nazywamy repozytorium kodu (albo po prostu "repo", żeby było krócej). Stwórzmy takie repozytorium dla naszego projektu. Otwórz konsolę w katalogu `djangogirls` i wpisz następujące polecenia: -> **Note** Polecenie `pip freeze` wypisuje na ekranie listę wszystkich bibliotek Pythona zainstalowanych w Twoim środowisku virtualenv, zaś `>` pobiera treść wygenerowaną przez `pip freeze` i zapisuje ją w pliku. Spróbuj wykonać `pip freeze` bez `> requirements.txt` i sprawdź, co się stanie! +> **Uwaga** Zanim utworzysz repozytorium, sprawdź w jakim katalogu obecnie się znajdujesz, wpisujac `pwd` (OSX/Linux) lub `cd` (Windows). Powinnaś się znajdować w katalogu `djangogirls`. -Otwórz ten plik i dodaj na samym końcu następującą linijkę: + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Twoja Nazwa Uzytkownika" + $ git config --global user.email ty@adres.pl - psycopg2==2.5.4 +Inicjalizacja repozytorium to coś, co będziesz musiała zrobić tylko raz na dany projekt (i nie będziesz musiała już wpisywać swojej nazwy użytkownika i adresu email). -Jest ona niezbędna, aby Twoja aplikacja działa na Heroku. +Git będzie śledzić zmiany we wszyskich plikach i folderach w tym katalogu, ale zwróć uwagę, że znajdują się w nim pewne pliki, których zmiany chcemy ignorować. By to zrobić, musimy utworzyć w tym katalogu plik, który nazwiemy `.gitignore`. Otwórz swój edytor kodu i utwórz nowy plik o następującej treści: -## Procfile +``` +*.pyc +__pycache__ +myvenv +db.sqlite3 +.DS_Store +``` -Kolejną rzeczą, którą musimy stworzyć, jest Procfile. W ten sposób poinformujemy Heroku, jakie polecenia muszą zostać wykonane w celu uruchomienia naszej strony. Otwórz swój edytor, utwórz plik o nazwie `Procfile` w katalogu `djangogirls` i dodaj poniższy wiersz: +Zapisz go jako `.gitignore` w folderze najwyższego poziomu "djangogirls". - web: gunicorn mysite.wsgi +> **Uwaga** Ta kropka na początku nazwy pliku jest ważna! Jeśli masz jakieś problemy z utworzeniem tego pliku (na przykład, jeśli pracujesz na Macu to Finder broni się przed zapisywaniem plików, które zaczynają się od kropki) to użyj "Zapisz jako" w swoim edytorze, działa bezbłędnie. +Dobrym nawykiem jest wpisywanie polecenia `git status` zanim wpiszesz `git add` albo gdy nie jesteś pewna co się zmieniło. To powinno cię ustrzec przed nieprzyjemnymi niespodziankami, takimi jak dodanie lub zmienienie nieprawidłowych plików. Polecenie `git status` zwraca między innymi informacje o plikach, które zostały dodane/zmienione/usunięte. Po wpisaniu polecenia powinnaś zobaczyć coś podobnego do tego: -Ta linijka oznacza, że zamierzamy wdrożyć aplikację internetową (`web`); do wykonania tej operacji służy polecenie `gunicorn mysite.wsgi` (`gunicorn` jest programem przypominającym bardziej rozbudowaną wersję polecenia `runserver` w Django). + $ git status + On branch master -Zapisz zmiany w pliku. Gotowe! + Initial commit -## Plik `runtime.txt` + Untracked files: + (use "git add ..." to include in what will be committed) -Musimy poinformować Heroku, z której wersji Pythona chcemy korzystać. Odbywa się to poprzez utworzenie pliku `runtime.txt` w katalogu `djangogirls` (polecenie "Nowy plik" w Twoim edytorze kodu) i umieszczenie w nim następującej treści (tak, tylko tyle!): + .gitignore + blog/ + manage.py + mysite/ - python-3.4.2 + nothing added to commit but untracked files present (use "git add" to track) -## mysite/local_settings.py +I na końcu zapisujemy zmiany. Przejdź do konsoli i wykonaj poniższe polecenia: -Ustawienia, których używamy lokalnie (na naszym komputerze) są inne niż te, których używany dla naszego serwera. Heroku używa własnej bazy danych, nie tej samej, którą wykorzystuje Twój komputer. Dlatego musimy stworzyć osobny plik z ustawieniami, który będzie dostępny tylko dla naszego środowiska lokalnego. + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py -Zacznij od utworzenia pliku `mysite/local_settings.py`. Powinen on zawierać Twoją konfigurację `DATABASE` z pliku `mysite/settings.py`. Tak jak poniżej: - import os - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) +## Przesyłanie naszego kodu do GitHuba - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } - } +Wejdź na stronę [GitHub.com][2] i utwórz nowe darmowe konto. (Jeśli już to wcześniej zrobiłaś to super!) - DEBUG = True +Potem utwórz nowe repozytorium i nadaj mu nazwę "my-first-blog" (ang. "mój pierwszy blog") Nie zaznaczaj opcji "initialise with a README", nie zmieniaj nic przy polach .gitignore (powinno być None, same załatwiliśmy tę sprawę wcześniej). Licencja też powinna być ustawiona jako None. +![][3] -A potem po prostu go zapisz! :) + [3]: images/new_github_repo.png -## mysite/settings.py +> **Uwaga** Nazwa `my-first-blog` jest ważna -- mogłabyś wybrać jakąś inną, ale będziemy tej nazwy używać wiele razy i za każdym razem musiałabyś pamiętać, żeby zastępować "my-first-blog" swoją wybraną nazwą. Z tego powodu najłatwiej będzie jak użyjesz nazwy `my-first-blog`. -Kolejną rzeczą, którą musimy wykonać, to zmodyfikowanie pliku `settings.py` dla naszej strony. Otwórz plik `mysite/settings.py` w swoim edytorze i dodaj następujące wiersze na końcu tego pliku: +Na następnej stronie wyświetli Ci się adres URL do klonowania Twojego repozytorium. Wybierz wersję "HTTPS" i skopiuj ją. Niedługo będziemy tego adresu potrzebować. - import dj_database_url - DATABASES['default'] = dj_database_url.config() +![][4] - SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + [4]: images/github_get_repo_url_screenshot.png - ALLOWED_HOSTS = ['*'] +Teraz musimy podpiąć repozytorium Git na komputerze do tego na GitHubie. - STATIC_ROOT = 'staticfiles' +Wpisz następujące polecenie do konsoli (Zamień `` na swoją nazwę użytkownika, którą podałaś przy tworzeniu konta na GitHubie, ale bez nawiasów ostrokątnych, czyli "<" i ">"): - DEBUG = False + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master - try: - from .local_settings import * - except ImportError: - pass +Wpisz swoją nazwę użytkownika GitHub oraz hasło, a wtedy powinnaś zobaczyć coś takiego: -Dzięki temu Twoje lokalne ustawienia zostaną zaimportowane, jeżeli plik z nimi istnieje. + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. -Następnie zapisz zmiany w pliku. -## mysite/wsgi.py + -Otwórz plik `mysite/wsgi.py` i dodaj poniższy fragment na samym końcu: +Twój kod jest teraz na GitHubie. Możesz to sprawdzić! Zważ, że znajduje się w wyśmienitym towarzystwie - [Django][5], [kurs Django Girls][6] i wiele innych świetnych projektów open-source trzyma swój kod na GitHubie :) - from whitenoise.django import DjangoWhiteNoise - application = DjangoWhiteNoise(application) + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial +# Wdrażanie bloga na PythonAnywhere -Doskonale! +> **Uwaga** Możliwe, że już wcześniej utworzyłaś konto na PythonAnywhere, jeśli przeszłaś przez wszystkie kroki w rozdziale instalacyjnym - nie ma potrzeby, byś robiła to drugi raz. -## Konto Heroku +{% include "/deploy/signup_pythonanywhere.md" %} -Zainstaluj pakiet narzędziowy Heroku, który znajduje się tutaj (możesz pominąć ten krok, jeśli jeżeli zainstalowałaś go już wcześniej): https://toolbelt.heroku.com/ +## Umieszczanie naszego kodu na PythonAnywhere -> Jeżeli używasz pakietu narzędziowego Heroku pod Windows, pamiętaj, aby w trakcie wyboru składników do instalacji wybrać opcję "Custom installation". Z listy, która się pojawi, zaznacz pole wyboru przy pozycji "Git and SSH". -> -> Dodatkowo, w systemie Windows dodaj Gita i SSH do zmiennej `PATH` swojej ścieżki poleceń następującą instrukcją: `setx PATH "%PATH%;C:\Program Files\Git\bin"` lub `setx PATH "%PATH%;C:\Program Files (x86)\Git\bin"` - możesz sprawdzić w którym z katalogów zainstalował się Git przed wprowadzeniem tej komendy. Mentor na pewno Ci z tym pomoże. +Kiedy już zakończysz tworzenie konta na PythonAnywhere, zostaniesz przeniesiona do strony nawigacyjnej albo do strony "Konsole" (ang. "Consoles"). Wybierz opcję, by włączyć konsolę "Bash" -- to jest PythonAnywhere'owa wersja konsoli, którą masz na swoim komputerze. -> Zamknij wiersz poleceń i uruchom go ponownie, aby zmiana odniosła efekt. +> **Uwaga** PythonAnywhere jest oparty na Linuksie, więc jeśli pracujesz na Windowsie to konsola będzie wyglądać trochę inaczej niż na Twoim komputerze. -Utwórz proszę darmowe konto Heroku tutaj: https://id.heroku.com/signup/www-home-top +Umieśćmy nasz kod z GitHuba na PythonAnywhere. Zrobimy to "klonując" (ang. "clone") nasze repozytorium. Wpisz następujące polecenie do konsoli w PythonAnywhere (nie zapomnij zamienić `` na swoją nazwę użytkownika): -Następnie zaloguj się do konta Heroku na swoim komputerze za pomocą następującego polecenia: + $ git clone https://github.com//my-first-blog.git - $ heroku login +To polecenie ściągnie kopię twojego kodu na PythonAnywhere. By to sprawdzić, wpisz `tree my-first-blog`: -Jeżeli nie masz jeszcze klucza SSH, zostanie on utworzony automatycznie. Klucze SSH są niezbędne do publikowania kodu na Heroku. + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py -## Git -Git jest systemem kontroli wersji używanym przez wielu programistów. Program ten śledzi dokonywane zmiany w pliku lub zestawie plików na przestrzeni czasu, dzięki czemu możesz później przywracać wybrane wersje tych plików. Heroku wykorzystuje repozytorium Gita do zarządzania plikami Twojego projektu, więc my również musimy go używać. +### Tworzenie środowiska wirtualnego na PythonAnywhere -Utwórz w katalogu `djangogirls` plik `.gitignore` i wstaw w nim następującą treść: +Tak samo jak to robiłaś na swoim komputerze, możesz stworzyć środowisko wirtualne na PythonAnywhere. W konsoli Bash wpisz: - myvenv - __pycache__ - staticfiles - local_settings.py - db.sqlite3 - *.py[co] + $ cd my-first-blog -a następnie zapisz go. Kropka na początku nazwy pliku jest ważna! Jak widzisz, nakazujemy Heroku ignorować plik `local_settings.py` i nie pobierać go, dzięki czemu pozostaje on dostępny tylko i wyłącznie na Twoim komputerze (lokalnie). + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. -Następnie stwórzmy nowe repozytorium Gita i zapiszmy nasze zmiany. Przejdź do konsoli i uruchom poniższe polecenia: + $ source myvenv/bin/activate -> **Note** Zanim utworzysz repozytorium, za pomocą polecenia `pwd` (OSX/Linux) lub `cd` (Windows) sprawdź, w jakim folderze się znajdujesz. Powinnaś być w katalogu `djangogirls`. + (mvenv) $ pip install django whitenoise + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 - $ git init - Initialized empty Git repository in ~/djangogirls/.git/ - $ git add . - $ git commit -m "Moja aplikacja Django Girls" - [master (root-commit) 2943412] Moja aplikacja Django Girls - 7 files changed, 230 insertions(+) - create mode 100644 .gitignore - create mode 100644 Procfile - create mode 100644 mysite/__init__.py - create mode 100644 mysite/settings.py - create mode 100644 mysite/urls.py - create mode 100644 mysite/wsgi.py - create mode 100644 manage.py - create mode 100644 requirements.txt - create mode 100644 runtime.txt + +> **Uwaga** Polecenie `pip install` może trochę potrwać. Cierpliwości, cierpliwości! Jednak jeśli trwa to dłużej niż 5 min, coś jest nie tak. Spytaj swojego mentora. + + + +### Pobieranie plików statycznych. + +Zastanawiałaś się o co chodziło z "whitenoise"? Jest to narzędzie dla tak zwanych "plików statycznych". Pliki statyczne to pliki, które nie zmieniają się zbyt często, takie jak pliki HTML czy CSS. Zachowują się one inaczej na serwerach niż na naszych własych komputerach i dlatego potrzebujemy takich narzędzi jak "whitenoise", by je obsługiwać. + +Dowiemy się więcej o plikach statycznych później, kiedy będziemy zmieniać pliki CSS naszej strony. + +Na tę chwilę musimy tylko uruchomić polecenie `collectstatic` na serwerze. Polecenie to mówi Django, by zebrał wszystkie pliki statyczne, których potrzebuje na serwerze. W tym momencie chodzi głównie o pliki, które upiększają nam panel admina. + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +Wpisz "yes" i niech hula maszyna! Czy to nie piękne, jak komputer wypluwa z siebie dłuugie strony tekstu? Ja czasami wydaję ciche dźwięki, które mi się z tym kojarzą. Pip, pip, piiiip... + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### Tworzenie bazy danych na PythonAnywhere + +Oto kolejna różnica między Twoim komputerem a serwerem: serwer używa innej bazy danych. Tak więc możesz mieć inne konta użytkowników i posty na serwerze, a inne na swoim komputerze. + +Możemy zainicjować bazę danych na serwerze dokładnie w ten sam sposób, w jaki zrobiliśmy to na swoim komputerze, poleceniami `migrate` i `createsuperuser`: + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser -## Wybierz nazwę aplikacji +## Publikowanie naszego bloga jako aplikacji internetowej -Nasz blog będzie dostępny w internecie pod adresem `[nazwa Twojego bloga].herokuapp.com`, dlatego musimy wybrać taką nazwę, której ktoś już wcześniej nie zajął. Nazwa ta nie ma żadnego związku z naszą aplikacją `blog` w Django, `mysite` ani niczym innym, co utworzyłyśmy już wcześniej. Nazwa może wyglądać tak, jak Ci się podoba, ale Heroku posiada ścisłe reguły dotyczące zakresu dostępnych znaków: możesz używać wyłącznie małych liter alfabetu łacińskiego (bez wielkich liter i polskich znaków), cyfr oraz myślników (`-`). +Nasz kod znajduje się na PythonAnywhere, nasze środowisko wirtualne działa, mamy nasze pliki statyczne i zainicjowaliśmy bazę danych. Jesteśmy gotowi opublikować naszą aplikację internetową! -Gdy już wymyślisz nazwę (może coś związanego z Twoim imieniem albo pseudonimem?), uruchom poniższe polecenie, zastępując `djangogirlsblog` nazwą Twojej aplikacji: +Kliknij na logo PythonAnywhere, by wrócić do panelu nawigacyjnego, a potem kliknij na zakładkę **Web**. Następnie kliknij **Add a new web app** (czyli po polsku: "Dodaj nową aplikację internetową"). - $ heroku create djangogirlsblog +Po potwierdzeniu nazwy domeny, w oknie dialogowym wybierz konfigurację ręczną, czyli po angielsku **manual configuration** (*nie* opcję "Django"). Następnie wybierz **Python 3.4** i kliknij przycisk Dalej, aby zakończyć. +> **Uwaga** Upewnij się, że wybrałaś opcję "Ręczna konfiguracja", nie "Django". Jesteśmy zbyt fajne, aby używać domyślnej konfiguracji Django na PythonAnywhere ;-) -> **Uwaga**: Nie zapomnij zmienić `djangogirlsblog` na nazwę swojej aplikacji na Heroku. +### Ustawienie wirtualnego środowiska -Jeżeli masz problem z wymyśleniem nazwy, możesz po prostu wpisać +Zostaniesz przeniesiony do strony konfiguracji Twojej aplikacji internetowej, czyli do miejsca, gdzie musisz się udać, gdy chcesz zrobić zmiany w swojej aplikacji na serwerze. - $ heroku create +![][7] + [7]: images/pythonanywhere_web_tab_virtualenv.png -wówczas Heroku sam wybierze Ci wolną nazwę (pewnie coś w rodzaju `enigmatic-cove-2527`). +W sekcji dotyczącej środowiska wirtualnego ("Virtualenv") kliknij na czerwone pole z napisem "Enter the path to a virtualenv" i wpisz: `/home//my-first-blog/myvenv/`. Kliknij w niebieski prostokąt obok, aby zapisać ścieżkę przed przejściem do dalszej części. -Jeżeli kiedykolwiek zapragniesz zmienić nazwę swojej aplikacji na Heroku, możesz to zrobić w dowolnym momencie za pomocą poniższego polecenia (zastąp `nowa-nazwa` tą nazwą, której chcesz używać od tej pory): +> **Uwaga** Podmień nazwę użytkownika na właściwą. Jeśli się pomylisz, PythonAnywhere da Ci małe ostrzeżenie. - $ heroku apps:rename nowa-nazwa +### Konfiguracja pliku WSGI +Django używa "protokołu WSGI", standardu serwowania stron internetowych za pomocą Pythona, którego wspiera PythonAnywhere. Musimy zedytować plik konfiguracyjny WSGI tak, aby PythonAnywhere rozpoznawał naszego Django bloga. -> **Uwaga**: Pamiętaj, że po zmianie nazwy aplikacji zmieni się również jej adres. Aby zobaczyć swoją stronę po zmianie nazwy, przejdź pod adres `[nowa nazwa].herokuapp.com` . +Kliknij na link "WSGI configuration file" (w sekcji "Code" w górnej części strony - będzie nazywać się mniej więcej tak `/var/www/_pythonanywhere_com_wsgi.py`), a zostaniesz przeniesiona do edytora. -## Wdrażamy na Heroku! +Skasuj całą zawartość pliku i zastąp ją następującym tekstem: -Dużo zabawy z konfigurowaniem i instalowaniem, co? Na szczęście wystarczy zrobić to tylko raz! Teraz możesz rozpocząć wdrożenie! +```python +import os +import sys -Wykonanie polecenia `heroku create` sprawiło, że do naszego repozytorium zostało automatycznie dodane zdalne repozytorium Heroku. Teraz możemy posłużyć się prostym poleceniem git push, aby wdrożyć naszą aplikację: +path = '/home//my-first-blog' # use your own username here +if path not in sys.path: + sys.path.append(path) - $ git push heroku master +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` -> **Uwaga**: Za pierwszym razem zobaczysz zapewne *mnóstwo* treści, ponieważ Heroku musi skompilować i zainstalować psycopg. O tym, że proces został zakończony sukcesem, dowiesz się z komunikatu `https://twojanazwa.herokuapp.com/ deployed to Heroku` gdzieś na końcu treści wynikowej na ekranie. +> **Uwaga** Nie zapomnij zastąpić wszystkich wystąpień `` swoją nazwą użytkownika. -## Odwiedź swoją aplikację +Zadaniem tego pliku jest powiedzenie PythonAnywhere gdzie znajduje się nasza aplikacja i jaka jest nazwa naszego pliku z ustawieniami Django. Również zajmuje się poznanym wcześniej narzędziem "whitenoise", służącym do obsługi plików statycznych. -Opublikowałaś swój kod na Heroku oraz ustawiłaś typy procesów w pliku `Procfile` (wybrałyśmy wcześniej typ procesu `web`). Teraz możemy poinstruować Heroku, aby uruchomił ten `web process`. +Naciśnij **Zapisz** i potem wróć do karty **Web**. -Aby tego dokonać, wydaj następujące polecenie: +Mamy wszystko gotowe! Naciśnij duży zielony przycisk **Reload** ("Odśwież"), a będziesz mogła odwiedzić swoją aplikację. Znajdziesz do niej link na górze strony. - $ heroku ps:scale web=1 +## Porady dotyczące debugowania +Jeśli odwiedzając swoją stronę zobaczysz błąd, to pierwszym miejscem, w którym powinnaś poszukać informacji o tym, co się stało jest twój **dziennik błędów** (ang. "error log"). Znajdziesz do niego link na karcie [Web][8] w PythonAnywhere. Sprawdź czy znajdują się tam jakieś komunikaty o błędach; te najświeższe znajdują się na samym dole strony. Typowe problemy to: -Nakazuje ono Heroku uruchomienie tylko jednej instancji naszego procesu `web`. Nasz blog jest dość prosty, zatem nie potrzebujemy zbyt wiele mocy obliczeniowej i uruchomienie jednego procesu w zupełności wystarczy. Możemy poprosić Heroku o uruchomienie większej liczby procesów (nawiasem mówić, Heroku nazywa te procesy "Dynos", zatem nie bądź zdziwiona, gdy spotkasz się z tym terminem), ale to już nie jest darmowe. + [8]: https://www.pythonanywhere.com/web_app_setup/ -Teraz możemy otworzyć naszą aplikację w przeglądarce za pomocą polecenia `heroku open`. +* Pominięcie jednego z kroków, które powinnyśmy zrobić w konsoli: stworzenie środowiska wirtualnego, aktywowanie go, instalacja Django, pobranie plików statycznych, migracja bazy danych. - $ heroku open +* Pomyłka w ścieżce do środowiska wirtualnego w zakładce "Web" -- jeśli coś jest nie tak, wyświetli Ci się tam mały czerwony komunikat błędu. +* Zrobienie błędu w pliku konfiguracyjnym WSGI -- czy dobrze zapisałaś ścieżkę do katalogu my-first-blog? -> **Uwaga**: Zobaczysz stronę z komunikatem o błędzie. Zajmiemy się tym za momencik! +* Czy wybrałaś tę samą wersję Pythona dla Twojego środowiska wirtualnego, co dla aplikacji internetowej? Obie powinny być 3.4. -W Twojej przeglądarce otworzy się strona pod adresem zbliżonym do [https://djangogirlsblog.herokuapp.com/](), no i w tym momencie prawdopodobnie pojawi się błąd. Jak dotąd stworzyłyśmy w naszej aplikacji jedynie widok admina, więc dodaj do adresu `admin/` (np. [https://djangogirlsblog.herokuapp.com/admin/]()), aby zobaczyć działającą stronę Twojej aplikacji. +* Istnieje kilka [ogólnych porad dotyczących debugowania na PythonAnywhere wiki][9]. -Błąd, który widziałaś wcześniej, był spowodowany tym, że przy wdrażaniu strony na Heroku stworzyłyśmy nową bazę danych - i teraz jest ona pusta. Aby poprawnie przygotować naszą bazę danych do pracy, musimy wykonać polecenie `migrate` w taki sam sposób, jak wtedy, gdy zaczynałyśmy tworzyć nasz projekt: + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError - $ heroku run python manage.py migrate +I pamiętaj, Twój mentor jest tutaj, by Ci pomóc! - $ heroku run python manage.py createsuperuser +# Twoja strona jest w internecie! +Teraz na Twojej stronie w internecie powinny widniać słowa "Welcome to Django", dokładnie tak samo jak gdy otwierasz stronę znajdującą się na dysku lokalnym. Jeśli dodasz `/admin/` na koniec swojego adresu URL, powinnaś się przenieść do panelu admina. Zaloguj się swoim loginem i hasłem, a wtedy zobaczysz, że jesteś w stanie dodawać nowe posty na serwerze. -Teraz powinnaś być w stanie zobaczyć swoją stronę w przeglądarce. Gratulacje! :) +*Przybij piątkę!* Wdrażanie to jedna z najtrudniejszych i najbardziej skomplikowanych części projektowania stron internetowych. Często całemu zespołowi ludzi zajmuje to kilka dni zanim wszystko zacznie działać. Ale Tobie tak szybko udało się wdrożyć swoją stronę, jest ona w prawdziwym internecie! diff --git a/pl/deploy/images/github_get_repo_url_screenshot.png b/pl/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/pl/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/pl/deploy/images/new_github_repo.png b/pl/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/pl/deploy/images/new_github_repo.png differ diff --git a/pl/deploy/images/pythonanywhere_web_tab_virtualenv.png b/pl/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/pl/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/pl/deploy/install_git.md b/pl/deploy/install_git.md new file mode 100755 index 00000000000..005bdb365a0 --- /dev/null +++ b/pl/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows + +Możesz ściągnąć Gita z [git-scm.com](https://git-scm.com/). Możesz klikać "dalej dalej dalej" na każdym kroku oprócz jednego. W piątym kroku, który nazywa się "Adjusting your PATH environment", wybierz "Run Git and associated Unix tools from the Windows command-line" (opcję na samej górze). Poza tym domyślne ustawienia są w porządku. Upewnij się jeszcze, że w kroku "Configuring the line ending conversions" wybrana jest opcja "Checkout Windows-style, commit Unix-style line endings". + +### MacOS + +Ściągnij Gita z [git-scm.com](https://git-scm.com/) i postępuj zgodnie z instrukcją. + +### Linux + +Możliwe, że git jest już zainstalowany domyśle, ale jeśli tak nie jest, powinien być dostępny za pośrednictwem menedżera pakietów, więc spróbuj: + + sudo apt-get install git + # or + sudo yum install git + # or + sudo zypper install git diff --git a/pl/deploy/signup_pythonanywhere.md b/pl/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..412d8af33eb --- /dev/null +++ b/pl/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Czas utworzyć darmowe konto (opcja "Beginner" - dla początkujących) na PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Uwaga** Wybierając swoją nazwę użytkownika, weź pod uwagę, że twój adres na PythonAnywhere będzie z nią związany `twojanazwauzytkownika.pythonanywhere.com`. Dlatego polecamy wybrać nazwę, z którą się utożsamiasz albo która jest związana z tematyką Twojego bloga. \ No newline at end of file diff --git a/pl/django/README.md b/pl/django/README.md index cdc67c24c64..9e8ce479847 100755 --- a/pl/django/README.md +++ b/pl/django/README.md @@ -1,10 +1,10 @@ # Czym jest Django? -Django (czytaj: dżango) to darmowy, open-source'owy framework do tworzenia aplikacji webowych, napisany w Pythonie. To web framework – zestaw narzędzi ułatwiającyh szybsze i prostsze tworzenie stron internetowych. +Django (czytaj: dżango) to darmowy, open-source framework do tworzenia aplikacji webowych, napisany w Pythonie. To taki zbiór narzędzi, dzięki którym tworzenie stron internetowych jest szybsze i łatwiejsze. -Gdy budujesz stronę internetową, zawsze potrzebujesz podobnych rzeczy: sposobu do uporania się z uwierzytelnianiem (rejestracja, logowanie, wylogowywanie), panelu zarządzania stroną, formularzy, przesyłania plików, itd. +Gdy budujesz stronę internetową, często potrzebujesz tych samych rzeczy: uwierzytelnić użytkowników (rejestracja, logowanie, wylogowywanie), panel zarządzania stroną, formularzy, sposobu przesyłania plików itd. -Na szczęście dla nas, ktoś już kiedyś zauważył, że wszyscy web developerzy stają przed takimi samymi problemami, i stworzył framework (Django jest jednym z nich), które dostarczają nam gotowych do użycia komponentów. +Na szczęście pewni programiści już kiedyś zauważyli, że wszyscy web developerzy stają przed takimi samymi problemami i stworzyli frameworki (Django jest jednym z nich), które dostarczają nam gotowych do użycia komponentów. Frameworki istnieją, by oszczędzić Ci wyważania otwartych drzwi i ułatwić Ci proces tworzenia nowej strony. @@ -12,16 +12,16 @@ Frameworki istnieją, by oszczędzić Ci wyważania otwartych drzwi i ułatwić By zrozumieć do czego naprawdę służy Django, musimy lepiej przyjrzeć się serwerom. Pierwszą rzeczą którą musi wiedzieć serwer jest to, że chcesz, żeby wyświetlił Ci stronę. -Wyobraź sobie skrzynkę pocztową (port), która jest monitorowana pod kątem przychodzących listów (żądań). To właśnie rola serwera WWW. Serwer czyta list, i odsyła z powrotem odpowiedź w formie strony internetowej. Ale gdy chcesz coś wysłać, musisz mieć jakąś treść. Django jest właśnie tym, co pomoże Ci stworzyć tę treść. +Wyobraź sobie skrzynkę pocztową (port), która monitorowana pod kątem przychodzących listów (żądań). To właśnie rola serwera WWW. Serwer czyta list, i odsyła z powrotem odpowiedź w formie strony internetowej. Ale gdy chesz coś wysłać, musisz mieć jakąś treść. A Django jest właśnie tym, co pomoże Ci stworzyć tę treść. ## Co się dzieje, gdy ktoś chce otworzyć stronę z Twojego serwera? Kiedy serwer otrzymuje żądanie, przekazuje je dalej do Django, aby ten ustalił, czego właściwie ono dotyczy. Django sprawdza najpierw adres strony i decyduje, co zrobić dalej. Ta część jest wykonywana przez obecny w Django mechanizm rozpoznawania adresów (ang. **urlresolver** - zwróć uwagę, że adres strony to inaczej adres URL, czyli angielska nazwa tego modułu nie jest przypadkowa). Nie jest on zbyt inteligentny - jego działanie sprowadza się do porównania adresu URL z listą wzorców. Django sprawdza wzorce od góry do dołu i jeśli uda mu się znaleźć pasującą regułę, jest on przekazywana do odpowiedniej funkcji (zwanej *widokiem*). -Wyobraź sobie panią listonosz z listem w dłoni. Idzie przed siebie ulicą i patrzy na numery kolejnych domów, szukając tego, który jest napisany na kopercie. Gdy już go znajdzie, zostawia tam list. Tak właśnie działa mechanizm rozpoznawania adresów! +Wyobraź sobie listonosza niosącego list. Idzie ulicą i porównuje każdy numer domu z adresem na kopercie. List zostawia w skrzynce tego domu, którego adres pasuje. Tak samo działa urlresolver! -W funkcji *widoku* dzieje się wszystko to, co najciekawsze: tutaj możemy połączyć się z bazą danych i wyszukać potrzebne nam informacje. Może użytkownik poprosił o zmianę danych? To tak, jakbyś wysłała list o treści "proszę o zmianę opisu mojego stanowiska w pracy" - *widok* może sprawdzić, czy masz takie uprawnienie, a następnie dokona zmiany opisu i odeśle odpowiedź "Zrobione!". Wówczas *widok* generuje odpowiedź, a Django wysyła ją do przeglądarki użytkownika. +W funkcji *widoku* dzieje się wszystko to, co najciekawsze: tutaj możemy połączyć się z bazą danych i wyszukać potrzebne nam informacje. Może użytkownik poprosił o zmianę danych? To tak, jakbyś wysłała list o treści "proszę o zmianę opisu mojego stanowiska pracy" - *widok* może sprawdzić, czy masz takie uprawnienia, a następnie dokona zmiany opisu i odeśle odpowiedź "Zrobione!". Wówczas *widok* generuje odpowiedź, a Django wysyła ją do przeglądarki użytkownika. Oczywiście powyższy opis jest nieco uproszczony, ale znajomość niuansów technicznych nie jest Ci na razie potrzebna. Wystarczy, że zrozumiesz ogólną zasadę działania. -Dlatego nie będziemy się zbyt mocno zagłębiać w szczegóły i zaczniemy po prostu budować coś w Django. Wszystkich potrzebnych rzeczy nauczymy się po drodze! +Dlatego nie będziemy się zbyt mocno zagłębiać w szczegóły i zacznijmy po prostu budować coś w Django. Wszystkich potrzebnych rzeczy nauczymy się po drodze! \ No newline at end of file diff --git a/pl/django_admin/README.md b/pl/django_admin/README.md index 133ece8fe28..52cc8971419 100755 --- a/pl/django_admin/README.md +++ b/pl/django_admin/README.md @@ -4,19 +4,22 @@ Aby dodawać, modyfikować i usuwać wpisy, do których stworzyliśmy wcześniej Otwórzmy plik `blog/admin.py` i zastąpmy jego zawartość poniższym: - from django.contrib import admin - from .models import Post - - admin.site.register(Post) +```python +from django.contrib import admin +from .models import Post +admin.site.register(Post) +``` Jak widać, importujemy (dołączamy) model Post, który zdefiniowałyśmy w poprzednim rozdziale. Aby nasz model był widoczny w panelu admina, musimy go zarejestrować za pomocą polecenia `admin.site.register(Post)`. -OK, czas rzucić okiem na nasz model Post. Nie zapomnij uruchomić serwera za pomocą polecenia `python manage.py runserver` w swojej konsoli. Przejdź do swojej przeglądarki i wpisz adres: http://127.0.0.1:8000/admin/. Zobaczysz stronę logowania podobną do tej: +OK, czas rzucić okiem na nasz model Post. Pamiętaj, by wpisać `python manage.py runserver` w wierszu poleceń, by uruchomić serwer. Przejdź do przeglądarki i wpisz adres http://127.0.0.1:8000/admin/ Powinnaś zobaczyć taką stronę: + +![Strona logowania][1] -![Strona logowania](images/login_page2.png) + [1]: images/login_page2.png -Aby móc się zalogować, musisz utworzyć konto administratora (*superuser*) - czyli użytkownika, który posiada nieograniczony dostęp do całej strony. Wróć do wiersza poleceń i wpisz `python manage.py createsuperuser`. Zatwierdź klawiszem `enter`. Zostaniesz poproszona o wpisanie swojej nazwy użytkownika (małymi literami, bez spacji i polskich znaków), adresu e-mail oraz hasła. Gdy będziesz wpisywała hasło, litery nie będą widoczne - tak ma być, więc nie martw się, wpisz hasło i wciśnij `enter`. Treść widoczna na ekranie powinna wyglądać następująco (wpisz własną nazwę użytkownika i adres email): +By móc się zalogować, musisz stworzyć *konto administratora* (ang. "superuser") - użytkownika, który ma całkowitą kontrolę nad stroną. Wróć do wiersza poleceń, wpisz `python manage.py createsuperuser` i zatwierdź klawiszem enter. Zostaniesz poproszona o wpisanie swojej nazwy użytkownika (małymi literami, bez spacji i polskich znaków), adresu e-mail oraz hasła. Gdy będziesz wpisywała hasło, nie martw się, że nie widać żadnych znaków na ekranie. Tak ma być, wpisz hasło i wciśnij `enter`. Treść widoczna na ekranie powinna wyglądać następująco (wpisz własną nazwę użytkownika i adres email): (myvenv) ~/djangogirls$ python manage.py createsuperuser Username: admin @@ -28,14 +31,18 @@ Aby móc się zalogować, musisz utworzyć konto administratora (*superuser*) - Wróć do przeglądarki i zaloguj się danymi administratora, które wprowadziłaś wcześniej. Powinnaś zobaczyć panel admina Django. -![Administracja Django (admin)](images/django_admin3.png) +![Administracja Django (admin)][2] + + [2]: images/django_admin3.png Przejdź do sekcji Posts i poeksperymentuj trochę. Dodaj pięć - sześć wpisów. Nie przejmuj się ich treścią - możesz dla zaoszczędzenia czasu kopiować i wklejać treści z tego kursu :). -Postaraj się, aby przynajmniej dwa - trzy wpisy (ale nie wszystkie!) miały ustawioną datę publikacji. Przyda nam się to nieco później. +Postaraj się, aby przynajmniej dwa-trzy wpisy (ale nie wszystkie!) miały ustawioną datę publikacji. Przyda nam się nieco później. + +![Administracja Django (admin)][3] -![Administracja Django (admin)](images/edit_post3.png) + [3]: images/edit_post3.png -Jeśli chcesz dowiedzieć się więcej o panelu admina Django, powinnaś sprawdzić dokumentację Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ +Jeśli chcesz dowiedzieć się więcej o panelu admina Django, sprawdź dokumentację Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ To zdecydowanie dobra okazja na filiżankę kawy (lub herbaty) i schrupanie czegoś słodkiego. Stworzyłaś swój pierwszy model w Django - zasługujesz na małą nagrodę! diff --git a/pl/django_forms/README.md b/pl/django_forms/README.md index 883469e5669..c197853e272 100755 --- a/pl/django_forms/README.md +++ b/pl/django_forms/README.md @@ -16,20 +16,21 @@ Stwórzmy plik o takiej nazwie w katalogu `blog`. Dobrze, a teraz otwórzmy go i wprowadźmy następujący kod: - from django import forms +```python +from django import forms - from .models import Post +from .models import Post - class PostForm(forms.ModelForm): - - class Meta: - model = Post - fields = ('title', 'text',) +class PostForm(forms.ModelForm): + class Meta: + model = Post + fields = ('title', 'text',) +``` Musimy najpierw zaimportować formularze Django (`from django import forms`) oraz, naturalnie, nasz model wpisu (`from .models import Post`). -`PostForm`, jak zapewne podejrzewasz, to nazwa naszego formularza. Musimy poinformować Django, że ten formularz jest formularzem modelu (`ModelForm`), dzięki czemu Django wyręczy nas w pewnych czynnościach - właśnie za to odpowiada `forms.ModelForm`. +`PostForm`, jak zapewne podejrzewasz, to nazwa naszego formularza. Musimy poinformować Django, że ten formularz jest formularzem modelu (`ModelForm`), dzięki czemu Django wyręczy nas w pewnych czynnościach - właśnie za to odpowiada `forms.ModelForm`. Dalej mamy `class Meta`, gdzie przekazujemy Django informację o tym, jaki model powinien być wykorzystany do stworzenia tego formularza (`model = Post`). @@ -44,7 +45,7 @@ Oto, co za chwilę stworzymy: link do strony, adres URL, widok i szablon. Czas otworzyć plik `blog/templates/blog/base.html`. Wewnątrz `div`-a o nazwie `page-header` dodajmy odnośnik: ```html - + ``` Zauważ, że chcemy odwołać się do naszego nowego widoku `post_new`. @@ -63,7 +64,7 @@ Po dodaniu powyższej linii Twój plik HTML powinien wyglądać następująco:
@@ -78,27 +79,28 @@ Po dodaniu powyższej linii Twój plik HTML powinien wyglądać następująco: ``` - Po zapisaniu i odświeżeniu strony http://127.0.0.1:8000 zobaczyłaś oczywiście znajomo wyglądający błąd `NoReverseMatch`, zgadza się? ## URL Otwieramy plik `blog/urls.py` i dodajemy wiersz: +```python url(r'^post/new/$', views.post_new, name='post_new'), - +``` Ostatecznie kod będzie wyglądał tak: - from django.conf.urls import include, url - from . import views - - urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - url(r'^post/new/$', views.post_new, name='post_new'), - ] +```python +from django.conf.urls import url +from . import views +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` Po odświeżeniu strony zobaczymy błąd `AttributeError`, ponieważ nie mamy jeszcze zaimplementowanego widoku `post_new`. Dodajmy go teraz. @@ -106,15 +108,17 @@ Po odświeżeniu strony zobaczymy błąd `AttributeError`, ponieważ nie mamy je Czas otworzyć plik `blog/views.py` i dodać poniższe linijki obok innych wierszy z `from`: - from .forms import PostForm - +```python +from .forms import PostForm +``` no i nasz *widok*: - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` Aby stworzyć nowy formularz dla modelu `Post`, musimy wywołać funkcję `PostForm()` i przekazać ją do szablonu. Do tego *widoku* jeszcze wrócimy. Ale póki co, stwórzmy szybko szablon formularza. @@ -122,12 +126,14 @@ Aby stworzyć nowy formularz dla modelu `Post`, musimy wywołać funkcję `PostF Musimy utworzyć plik `post_edit.html` w katalogu `blog/templates/blog`. Aby nasz formularz zadziałał, niezbędne jest kilka rzeczy: -* musimy wyświetlić formularz. Możemy to zrobić np. za pomocą prostego polecenia `{{ form.as_p }}`. +* musimy wyświetlić formularz. Możemy to zrobić np. za pomocą prostego polecenia `{% raw %}{{ form.as_p }}{% endraw %}`. * powyższa linijka musi znajdować się wewnątrz znacznika formularza HTML: <`form method="POST">...` * potrzebny nam przycisk `Zapisz`. Tworzymy go jako przycisk w HTML: `` * i na koniec jeszcze, zaraz po znaczniku otwierającym `
`, musimy dodać `{% raw %}{% csrf_token %}{% endraw %}`. To bardzo ważne, gdyż ta linijka sprawia, że Twoje formularze są bezpieczne! Jeśli o tym zapomnisz i spróbujesz zapisać formularz, Django nie pozostawi tego bez komentarza: -![Strona CSRF Forbidden](images/csrf2.png) +![Strona CSRF Forbidden][1] + + [1]: images/csrf2.png OK. Podsumujmy, jak powinien wyglądać kod HTML w pliku `post_edit.html`: @@ -143,10 +149,11 @@ OK. Podsumujmy, jak powinien wyglądać kod HTML w pliku `post_edit.html`: {% endblock %} ``` - Czas odświeżyć stronę! Hura! Twój formularz został wyświetlony! -![Nowy formularz](images/new_form2.png) +![Nowy formularz][2] + + [2]: images/new_form2.png Ale zaraz zaraz! Co się stanie, gdy wpiszesz coś w pola z tytułem i treścią, a następnie spróbujesz to zapisać? @@ -158,68 +165,77 @@ Odpowiedź brzmi: nic. Mamy coś jeszcze do zrobienia w naszym *widoku*. Otwórz jeszcze raz plik `blog/views.py`. W tym momencie wszystko, co mamy w widoku `post_new` to: - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Gdy prześlemy formularz, wracamy do tego samego widoku, ale tym razem mamy nieco więcej danych w zapytaniu (zmiennej `request`) - a dokładnie w `request.POST`. Pamiętasz, że w pliku HTML nasza definicja formularza `` zawierała atrybut `method="POST"`? Wszystkie pola z formularza znajdują się teraz w `request.POST`. Nie zmieniaj nazwy `POST` na cokolwiek innego (inną prawidłową wartością dla `method` jest `GET`, ale nie mamy czasu na omawianie różnic). +Gdy prześlemy formularz, wracamy do tego samego widoku, ale tym razem mamy nieco więcej danych w zapytaniu (zmiennej `request`) - a dokładnie w `request.POST`. (Nazwa POST nie ma nic wspólnego z naszymi blogowymi postami. POST wzięło się od angielskiego czasownika "post", który oznacza wysłać, nadać). Pamiętasz, że w pliku HTML nasza definicja formularza `` zawierała atrybut `method="POST"`? Wszystkie pola z formularza znajdują się teraz w `request.POST`. Nie zmieniaj nazwy `POST` na cokolwiek innego (inną prawidłową wartością dla `method` jest `GET`, ale nie mamy czasu na omawianie różnic). A więc w naszym *widoku* mamy dwie oddzielne sytuacje do obsłużenia. Pierwsza: gdy wchodzimy na stronę po raz pierwszy i chcemy pusty formularz. Druga: gdy ponownie znajdziemy się w *widoku* wraz ze wszystkimi danymi wpisanymi przez nas w formularzu. Czyli musimy dodać wyrażenie warunkowe (użyjemy do tego `if`). - if request.method == "POST": - [...] - else: - form = PostForm() - +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` Teraz czas na uzupełnienie kropek `[...]`. Jeżeli zmienna `method` jest równa `POST`, to chcemy zbudować formularz `PostForm` z danymi wprowadzonymi w formularzu, zgadza się? Możemy zrobić to następująco: - form = PostForm(request.POST) - +```python +form = PostForm(request.POST) +``` Łatwizna! Następnie sprawdźmy, czy formularz jest wypełniony poprawnie (wszystkie wymagane pola są uzupełnione i żadna nieprawidłowa wartość nie zostanie zapisana). Użyjmy do tego `form.is_valid()`. Sprawdzamy, czy formularz jest wypełniony poprawnie. Jeśli tak, możemy go zapisać! - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` Tak właściwie robimy teraz dwie rzeczy: zapisujemy formularz przy pomocy `form.save` oraz dodajemy autora (jako że nasz `PostForm` nie zawierał pola `author`, a jest ono wymagane!). `commit=False` sygnalizuje, że jeszcze nie chcemy zapisywać modelu `Post` - najpierw chcemy dodać autora. Przez większość czasu będziesz używała `form.save()` bez `commit=False`, ale w tym przypadku musimy zrobić to w ten sposób. `post.save()` zachowa zmiany (razem z dodanym autorem) i nasz nowy wpis na blogu jest gotowy! Byłoby wreszcie wspaniale, gdybyśmy mogły przejdź od razu na stronę `post_detail` i zobaczyć nasz nowy wpis, prawda? Aby to było możliwe, musimy dodać parę importów: - from django.shortcuts import redirect - +```python +from django.shortcuts import redirect +``` Dodaj je na samym początku pliku. I teraz możemy powiedzieć: przejdź na stronę `post_detail`, żeby zobaczyć nowo utworzony wpis. - return redirect('blog.views.post_detail', pk=post.pk) - +```python +return redirect('post_detail', pk=post.pk) +``` `blog.views.post_detail` to nazwa widoku, do którego chcemy przejść. Pamiętasz, że ten *widok* potrzebuje zmiennej `pk`? Aby ją przekazać do widoków stosujemy `pk=post.pk`, gdzie `post` jest nowo utworzonym wpisem! No dobrze, pogadałyśmy sobie, to może teraz zobaczymy, jak wygląda cały nasz *widok*, co? - def post_new(request): - if request.method == "POST": - form = PostForm(request.POST) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Zobaczmy, czy zadziała. Przejdź na stronę http://127.0.0.1:8000/post/new/, dodaj tytuł i tekst, zapisz... i voilà! Nowy wpis został dodany, a my zostałyśmy przekierowane na stronę `post_detail`! +Zobaczmy, czy zadziała. Przejdź na stronę http://127.0.0.1:8000/post/new/, dodaj `tytuł` i `tekst`, zapisz... i voilà! Nowy wpis został dodany, a my zostałyśmy przekierowane na stronę `post_detail`! -Zapewne dostrzegłaś, że w ogóle nie zajęłyśmy się ustawianiem daty publikacji. Wprowadzimy *przycisk publikowania* w **Django Girls Tutorial: Rozszerzenia**. +Zapewne dostrzegłaś, że w ogóle nie zajęłyśmy się ustawianiem daty publikacji. Wprowadzimy przycisk publikacji *publish* w kursie **Django Girls: Rozszerzenia**. Wspaniale! @@ -229,13 +245,17 @@ Teraz pokażemy Ci, jak fajne potrafią być formularze w Django. Wpis na blogu Spróbuj zapisać formularz bez uzupełnionych pól `title` i `text`. Zgadnij, co się stanie! -![Walidacja formularza](images/form_validation2.png) +![Walidacja formularza][3] + + [3]: images/form_validation2.png Django dba o walidację pól w naszym formularzu, upewniając się, czy są uzupełnione poprawnie. Prawda że niesamowite? > Jako że niedawno używałyśmy interfejsu admina Django, system w tym momencie jest przekonany, że jesteśmy zalogowane. Niektóre sytuacje mogą doprowadzić do tego, że zostaniemy wylogowane (np. zamknięcie przeglądarki czy restart bazy danych). Jeżeli zauważysz, że przy tworzeniu wpisu pojawia się błąd związany z brakiem zalogowanego użytkownika, przejdź na stronę stronę panelu admina http://127.0.0.1:8000/admin i zaloguj się jeszcze raz. Na pewien czas problem się rozwiąże. W rozdziale **Praca domowa: zabezpiecz swoją stronę!** - zaraz po głównym kursie - czeka na Ciebie permanentne rozwiązanie tego problemu. -![Błąd logowania użytkownika](images/post_create_error.png) +![Błąd logowania użytkownika][4] + + [4]: images/post_create_error.png ## Edycja formularza @@ -243,9 +263,9 @@ Teraz już wiemy, jak dodać nowy formularz. Ale co w przypadku, gdy zapragniemy Otwórz `blog/templates/blog/post_detail.html` i dodaj poniższą linijkę: -```html +```python -```` +``` dzięki czemu nasz szablon będzie wyglądał tak: @@ -253,58 +273,68 @@ dzięki czemu nasz szablon będzie wyglądał tak: {% extends 'blog/base.html' %} {% block content %} -
- {% if post.published_date %} - {{ post.published_date }} - {% endif %} - +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

{% endblock %} ``` - W pliku `blog/urls.py` dodajmy wiersz: +```python url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), - +``` Wykorzystamy jeszcze raz szablon `blog/templates/blog/post_edit.html`, więc ostatnią rzeczą, której nam brakuje, jest *widok*. Otwórz `blog/views.py` i dodaj poniższy kod na samym końcu tego pliku: - def post_edit(request, pk): - post = get_object_or_404(Post, pk=pk) - if request.method == "POST": - form = PostForm(request.POST, instance=post) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm(instance=post) - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` To wygląda prawie tak samo, jak nasz widok `post_new`, nieprawdaż? Ale nie do końca. Po pierwsze: przekazujemy dodatkowy parametr `pk` z urls. Dalej - pobieramy model wpisu `Post` do edycji za pomocą `get_object_or_404(Post, pk=pk)`. Gdy tworzymy formularz, przekazujemy ten wpis pod zmienną `instance` zarówno w trakcie zapisywania formularza: - form = PostForm(request.POST, instance=post) - +```python +form = PostForm(request.POST, instance=post) +``` jak i zaraz po otwarciu formularza z wpisem do edycji: - form = PostForm(instance=post) - +```python +form = PostForm(instance=post) +``` OK. Przetestujmy, jak to działa! Przejdź na stronę `post_detail`. W górnym prawym rogu powinnaś znaleźć przycisk edycji: -![Przycisk edycji](images/edit_button2.png) +![Przycisk edycji][5] + + [5]: images/edit_button2.png Po kliknęciu w niego zobaczysz formularz z naszym wpisem: -![Edycja formularza](images/edit_form2.png) +![Edycja formularza][6] + + [6]: images/edit_form2.png Zmodyfikuj jego tytuł lub treść wedle uznania, a następnie zapisz zmiany! @@ -312,20 +342,55 @@ Gratulacje! Twoja aplikacja staje się coraz bardziej kompletna! Jeżeli potrzebujesz więcej informacji o formularzach Django, zajrzyj do dokumentacji: https://docs.djangoproject.com/en/1.8/topics/forms/ -## Jeszcze jedno: czas na wdrożenie! +## Bezpieczeństwo + +Super, że możemy tworzyć posty po prostu klikając w link! Jest niestety jeden problem - teraz każdy, kto odwiedzi Twoją stronę, może stworzyć nowy post. Dobrze by było, gdyby przycisk był widoczny tylko dla Ciebie. + +W `blog/templates/blog/base.html` znajdź `page-header` `div` i tag <0>a, który umieściliśmy tam wcześniej. Powinien wyglądać tak: -Dobrze byłoby wiedzieć, że nasza witryna nadal działa na Heroku, prawda? Spróbuj ponownie ją zaktualizować. Jeśli nie pamiętasz jak to zrobić, sprawdź na końcu rozdziału [Wdrażanie](../deploy/README.md): - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Dodano widoki do edycji i tworzenia blog postow" -... -$ git push heroku master +```html + +``` + +Dodamy kolejny tag `{% if %}`, który sprawi, że link będzie widoczny tylko dla użytkowników zalogowanych jako admin. W tej grupie na razie jesteś tylko Ty! Zmień `` tag, by wyglądał w ten sposób: + +```html +{% if user.is_authenticated %} + +{% endif %} ``` +Ten `{% if %}` spowoduje, że link zostanie wysłany do przeglądarki tylko jeśli to żądanie zostało wystosowane przez zalogowanego użytkownika. To nie chroni tworzenia wpisów w 100%, ale jest to dobry pierwszy krok. Zagadnieniu bezpieczeństwa poświęcimy więcej miejsca w rozszerzeniu do tego kursu. + +Pewnie jesteś teraz zalogowana, więc jak odświeżysz stronę to nie zobaczysz różnicy. Wejdź na tę stronę używając innej przeglądarki lub w trybie prywatnym, a wtedy zobaczysz, że link się już nie pokaże! + +## Jeszcze jedno: czas na wdrożenie! + +Dobrze byłoby wiedzieć, że nasza witryna nadal działa na PythonAnywhere, prawda? + +* Po pierwsze zapiszmy nasze zmiany i wyślijmy je na Githuba + + $ git status + $ git add --all . + $ git status + $ git commit -m "Dodano widok tworzenia/edytowania posta bezposrednio na stronie." + $ git push + + +* Potem, w konsoli [PythonAnywhere Bash][7]: + + [7]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Na koniec, przejdźmy do podstrony [Web tab][8] i wciśnijmy **Reload** (ang. odśwież). + + [8]: https://www.pythonanywhere.com/web_app_setup/ I to już wszystko! Gratulacje :) diff --git a/pl/django_installation/README.md b/pl/django_installation/README.md old mode 100755 new mode 100644 index 7d9eb7c5fce..2ca1433a389 --- a/pl/django_installation/README.md +++ b/pl/django_installation/README.md @@ -1,113 +1,5 @@ # Instalowanie Django -> Fragment tego rozdziału jest oparty na tutoriale Geek Girls Carrots (http://django.carrots.pl/). -> -> Fragmenty tego rozdziału są oparte o [tutorial django-marcador][1] na licencji Creative Commons Attribution-ShareAlike International 4.0. Tutorial django-marcador jest chroniony prawami autorskimi przez Markusa Zapke-Gründemanna i in. +> **Uwaga** Jeśli przerobiłaś rozdział "Instalacja" to wszystko masz zrobione - możesz przejść od razu do kolejnego rozdziału! - [1]: http://django-marcador.keimlink.de/ - -## Środowisko wirtualne - -Zanim zainstalujemy Django, zapoznamy się z niezwykle użytecznym narzędziem, które pomoże utrzymać porządek w środowisku pracy z kodem na Twoim komputerze. Można ten krok pominąć, ale jest to wysoce niewskazane - dobrze jest zacząć z możliwie najlepszą konfiguracją, gdyż zaoszczędzi Ci to wielu problemów w przyszłości! - -Stwórzmy zatem **środowisko wirtualne** (zwane też *virtualenv*). Jego zadaniem jest oddzielenie środowiska Pythona/Django dla każdego projektu z osobna. Oznacza to, że zmiany dokonane w obrębie jednej aplikacji nie wpłyną na działanie innych, nad którymi pracujesz. Sprytne, prawda? - -Jedyne, co potrzebujesz zrobić, to wybrać katalog, w którym chcesz utworzyć `virtualenv`; na przykład Twój katalog domowy. W systemie Windows może on wyglądać tak: `C:\Użytkownicy\Nazwa` (gdzie `Nazwa` to twoja nazwa użytkownika, której używasz przy logowaniu się do komputera). - -Na potrzeby kursu stwórzmy nowy katalog `djangogirls` w Twoim katalogu domowym: - - mkdir djangogirls - cd djangogirls - - -Stwórzmy nowe środowisko wirtualne o nazwie `myvenv`. Polecenie ma następujący format: - - python -m venv myvenv - - -### Windows - -Aby stworzyć nowego `virtualenv`'a, musisz otworzyć konsolę (wspominaliśmy o tym parę rozdziałów temu, pamiętasz?) i uruchom `C:\Python34\python -m venv venv`. Polecenie będzie wyglądać następująco: - - C:\Użytkownicy\Nazwa\djangogirls> C:\Python34\python -m venv myvenv - - -gdzie `C:\Python34\python` to katalog, w którym zainstalowałaś wcześniej Pythona, zaś `myvenv` to nazwa Twojego `virtualenv`'a. Nazwa środowiska może być dowolna, ale lepiej używać tylko małych liter, bez spacji i polskich znaków. Dobrze jest też trzymać się krótkich nazw - będziesz do nich często wracała! - -### Linux i OS X - -Stworzenie `virtualenv`'a w Linuksie i OS X ogranicza się jedynie do użycia polecenia `python3 -m venv myvenv`. Przyjmie ono następującą postać: - - ~/djangogirls$ python3 -m venv myvenv - - -`myvenv` to nazwa Twojego `virtualenv`'a. Nazwa środowiska może być dowolna, ale lepiej używać tylko małych liter, bez spacji i polskich znaków. Dobrze jest też trzymać się krótkich nazw - będziesz do nich często wracała! - -> **UWAGA:** Próba utworzenia w ten sposób środowiska wirtualnego w Ubuntu 14.04 skutkuje następującym błędem: -> -> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 -> -> -> Aby uniknąć tego problemu, użyj polecenia `virtualenv`. -> -> ~/djangogirls$ sudo apt-get install python-virtualenv -> ~/djangogirls$ virtualenv --python=python3.4 myvenv -> - -## Praca z virtualenv - -Powyższa instrukcja utworzy katalog o nazwie `myvenv` (albo o innej, którą wybrałaś) zawierający nasze środowisko wirtualne (czyli w zasadzie zbiór katalogów i plików). Pozostało nam już tylko uruchomienie go za pomocą polecenia: - - C:\Użytkownicy\Nazwa\djangogirls> myvenv\Scripts\activate - - -w Windows, albo: - - ~/djangogirls$ source myvenv/bin/activate - - -w OS X i Linuksie. - -Nie zapomnij zastąpić `myvenv` nazwą, którą wybrałaś dla Twojego `virtualenv`! - -> **UWAGA:** może się zdarzyć, że polecenie `source` nie będzie dostępne. W takim przypadku spróbuj użyć poniższego: -> -> ~/djangogirls$ . myvenv/bin/activate -> - -O tym, że Twój `virtualenv` jest uruchomiony, dowiesz się, gdy zobaczysz w swojej konsoli prompt podobny do tego: - - (myvenv) C:\Użytkownicy\Nazwa\djangogirls> - - -lub: - - (myvenv) ~/djangogirls$ - - -Zwróć uwagę, że pojawił się tam prefix `(myvenv)`! - -W trakcie pracy ze środowiskiem wirtualnym `python` będzie automatycznie odnosił się do właściwej wersji, dzięki czemu możesz używać polecenia `python` zamiast `python3`. - -Świetnie, wszystkie potrzebne elementy są już gotowe. Nareszcie możemy zainstalować Django! - -## Instalowanie Django - -Teraz, gdy Twój `virtualenv` jest już uruchomiony, możesz zainstalować django za pomocą narzędzia `pip`. W konsoli uruchom polecenie `pip install django==1.8` (zwróć uwagę, że używamy podwójnego znaku równości: `==`). - - (myvenv) ~$ pip install django==1.8 - Downloading/unpacking django==1.8 - Installing collected packages: django - Successfully installed django - Cleaning up... - - -w systemie Windows: - -> Jeżeli w trakcie wywoływania polecenia pip w Windows otrzymasz błąd, sprawdź czy ścieżka Twojego projektu nie zawiera spacji (np. `C:\Users\Imię Nazwisko\djangogirls`). Jeżeli tak, sugerujemy przeniesienie projektu do innego katalogu bez spacji w nazwie (proponujemy `C:\djangogirls`). Gdy już to zrobisz, spróbuj wykonać powyższe polecenie jeszcze raz. - -w systemie Linux: - -> Jeśli po użyciu polecenia pip w Ubuntu 12.04 otrzymasz błąd, użyj polecenia `python -m pip install -U --force-reinstall pip`, aby naprawić instalacją pip'a w środowisku wirtualnym. - -To wszystko! Teraz (nareszcie) jesteś gotowa do stworzenia aplikacji w Django! +{% include "/django_installation/instructions.md" %} diff --git a/pl/django_installation/instructions.md b/pl/django_installation/instructions.md new file mode 100755 index 00000000000..7d37f82c43b --- /dev/null +++ b/pl/django_installation/instructions.md @@ -0,0 +1,113 @@ +> Fragmenty tego rozdziału napisane są w oparciu o kurs Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Fragmenty tego rozdziału są oparte o tutorial [django-marcador](http://django-marcador.keimlink.de/) na licencji Creative Commons Attribution-ShareAlike 4.0 International. Tutorial django-marcador jest chroniony prawami autorskimi przez Markusa Zapke-Gründemanna i in. + +## Środowisko wirtualne + +Zanim zainstalujemy Django, zapoznamy się z niezwykle użytecznym narzędziem, które pomoże utrzymać porządek poczas pracy z kodem na Twoim komputerze. Można ten krok pominąć, ale zachęcamy, żebyś tego nie robiła. Dobrze jest zacząć z możliwie najlepszą konfiguracją, gdyż zaoszczędzi Ci to wielu problemów w przyszłości! + +Stwórzmy zatem **środowisko wirtualne** (zwane też *virtualenv*). Jego zadaniem jest oddzielenie środowiska Pythona/Django dla każdego projektu z osobna. Oznacza to, że zmiany dokonane w obrębie jednej aplikacji nie wpłyną na działanie innych, nad którymi pracujesz. Sprytne, prawda? + +Jedyne, co potrzebujesz zrobić, to wybrać katalog, w którym chcesz utworzyć `virtualenv`; na przykład Twój katalog domowy. W systemie Windows może on wyglądać tak: `C:\Użytkownicy\Nazwa` (gdzie `Nazwa` to twoja nazwa użytkownika, której używasz przy logowaniu się do komputera). + +Na potrzeby kursu będziemy stwórzmy nowy katalog `djangogirls` w Twoim katalogu domowym: + + mkdir djangogirls + cd djangogirls + + +Stwórzmy nowe środowisko wirtualne o nazwie `myvenv`. Polecenie ma następujący format: + + python3 -m venv myvenv + + +### Windows + +Aby stworzyć nowego `virtualenv`'a, musisz otworzyć konsolę (wspominaliśmy o tym parę rozdziałów temu, pamiętasz?) i uruchom `C:\ Python34\python -m venv venv`. Efekt będzie wyglądał tak: + + C:\Użytkownicy\Nazwa\djangogirls> C:\Python34\python -m venv myvenv + + +gdzie `C:\Python34\python` to katalog, w którym zainstalowałaś wcześniej Pythona, zaś `myvenv` to nazwa Twojego `virtualenv`'a. Nazwa może być dowolna, ale lepiej używać tylko małych liter, bez spacji i polskich znaków. Dobrze jest też trzymać się krótkich nazw - będziesz do nich często wracała! + +### Linux i OS X + +Stworzenie `virtualenv`'a w Linuksie i OS X ogranicza się jedynie do użycia polecenia `python3 -m venv myvenv`. Przyjmie ono następującą postać: + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` to nazwa Twojego `virtualenv`'a. Nazwa środowiska może być dowolna, ale lepiej używać tylko małych liter, bez spacji i polskich znaków. Dobrze jest też trzymać się krótkich nazw - będziesz do nich często wracała! + +> **UWAGA:** Próba utworzenia w ten sposób środowiska wirtualnego w Ubuntu 14.04 skutkuje następującym błędem: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Aby uniknąć tego problemu, użyj polecenia `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Praca z virtualenv + +Powyższa instrukcja utworzy katalog o nazwie `myvenv` (albo o nazwie, którą wybrałaś) zawierający nasze środowisko wirtualne (czyli w zasadzie zbiór katalogów i plików). + +#### Windows + +Uruchom wirtualne środowisko za pomocą polecenia: + + C:\Użytkownicy\Nazwa\djangogirls> myvenv\Scripts\activate + + +#### Linux i OS X + +Uruchom wirtualne środowisko za pomocą polecenia: + + ~/djangogirls$ source myvenv/bin/activate + + +Nie zapomnij zastąpić `myvenv` nazwą, którą wybrałaś dla Twojego `virtualenv`! + +> **UWAGA:** może się zdarzyć, że polecenie `source` nie będzie dostępne. W takim przypadku spróbuj użyć poniższego: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +O tym, że Twój `virtualenv` jest uruchomiony, dowiesz się, gdy zobaczysz w swojej konsoli prompt podobny do tego: + + (myvenv) C:\Użytkownicy\Nazwa\djangogirls> + + +lub: + + (myvenv) ~/djangogirls$ + + +Zwróć uwagę, że pojawił się tam prefix `(myvenv)`! + +W trakcie pracy ze środowiskiem wirtualnym `python` będzie automatycznie odnosił się do właściwej wersji, dzięki czemu możesz używać polecenia `python` zamiast `python3`. + +Świetnie, wszystkie potrzebne elementy są już gotowe. Nareszcie możemy zainstalować Django! + +## Instalowanie Django + +Teraz, gdy Twój `virtualenv` jest już uruchomiony, możesz zainstalować Django za pomocą narzędzia `pip`. W konsoli uruchom polecenie `pip install django==1.8` (zwróć uwagę, że używamy podwójnego znaku równości: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +w systemie Windows + +> Jeżeli w trakcie wywoływania polecenia pip otrzymasz błąd, sprawdź czy ścieżka Twojego projektu nie zawiera spacji (np. `C:\Users\Imie Nazwisko\djangogirls`). Jeżeli tak, sugerujemy przeniesienie projektu do innego katalogu bez spacji w nazwie (proponujemy `C:\djangogirls`). Gdy już to zrobisz, spróbuj wykonać powyższe polecenie jeszcze raz. + +w systemie Linux + +> Jeśli po użyciu polecenia pip w Ubuntu 12.04 otrzymasz błąd, użyj polecenia `python -m pip install -U --force-reinstall pip`, aby naprawić instalacją pip'a w środowisku wirtualnym. + +To wszystko! Teraz (nareszcie) jesteś gotowa do stworzenia aplikacji w Django! diff --git a/pl/django_models/README.md b/pl/django_models/README.md index f0c7f6112ee..f9c1af3c227 100755 --- a/pl/django_models/README.md +++ b/pl/django_models/README.md @@ -1,38 +1,38 @@ # Modele w Django -Teraz zajmiemy się stworzeniem czegoś, co będzie przechowywało wszystkie wpisy na naszym blogu. Ale zanim przystąpimy do tego, musimy poświęcić chwilę na przyjrzenie się tworom zwanym `obiektami`. +Teraz zajmiemy się tworzeniem czegoś, co będzie przechowywało wszystkie wpisy na naszym blogu. Ale zanim przystąpimy do tego, musimy poświęcić chwilę na przyjrzenie się tworom zwanym `obiektami`. ## Obiekty W programowaniu istnieje pojęcie `programowania zorientowanego obiektowo`. Chodzi o to, że zamiast wypisywania nudnych sekwencji poleceń, możemy tworzyć modele różnych rzeczy i definiować ich zachowania względem siebie. -Zatem czym są obiekty? To po prostu zbiór pewnych właściwości i czynności. Owszem, brzmi dziwnie, ale przyjrzyjmy się temu na konkretnym przykładzie. +Zatem czym są obiekty? To po prostu zbiór pewnych właściwości i czynności. Owszem, brzmi dziwnie, ale przyjrzyjmy się temu na przykładzie. -Jeśli chcemy stworzyć model kota, stworzymy obiekt o nazwie `Kot` posiadający jakieś właściwości, np. `kolor`, `wiek`, `nastrój` (np. dobry, zły, senny ;)), `posiadacz` (czyli obiekt typu `Person`, lub pozostawimy tę właściwość pustą w postaci kota-znajdy). +Jeśli chcemy stworzyć model kota, stworzymy obiekt o nazwie `Kot` posiadający jakieś właściwości, np. `kolor`, `wiek`, `nastrój` (np. dobry, zły, senny ;)), `właściciel` (czyli obiekt typu `Osoba` lub pozostawimy tę właściwość pustą, wtedy mamy bezpańskiego kota). -Nasz `Kot` ma określone czynności: `mrucz`, `podrap`, `jedz` (i tu przekażemy kotu oddzielny obiekt o nazwie `KociPrzysmak` ze swoimi własnymi właściwościami, np. `sprobuj`). +Nasz `Kot` ma określone czynności: `mrucz`, `podrap`, `jedz` (i tu przekażemy kotu oddzielny obiekt o nazwie `KociPrzysmak` ze swoimi własnymi właściwościami, np. `smak`). Kot -------- kolor wiek nastroj - posiadacz + wlasciciel mrucz() podrap() jedz(koci_przysmak) - - + + KociPrzysmak -------- - sprobuj - + smak + Czyli w zasadzie chodzi o to, że opisujemy prawdziwe rzeczy w kodzie za pomocą właściwości (zwanych `właściwościami obiektu`) oraz czynności (zwanych `metodami`). -W takim razie jak będzie wyglądał model naszego posta na blogu? Chcemy zbudować bloga, zgadza się? +W takim razie jak będzie wyglądał model naszego postu na blogu? Chcemy zbudować bloga, zgadza się? -Musimy odpowiedzieć sobie na pytanie: czym jest wpis na blogu? Jakie powinien mieć właściwości? +Musimy sobie odpowiedzieć na pytanie: Czym jest post na blogu? Jakie powinien mieć właściwości? Na pewno musi zawierać zawartość tekstową oraz tytuł, prawda? Fajnie byłoby też wiedzieć, kto go napisał - czyli potrzebujemy autora. No i chcemy także znać daty, kiedy wpis został utworzony i opublikowany. @@ -43,13 +43,13 @@ Na pewno musi zawierać zawartość tekstową oraz tytuł, prawda? Fajnie byłob author created_date published_date - + Co możemy zrobić z wpisem na blogu? Przydałaby nam się jakaś `metoda`, która opublikuje nasz wpis, zgadza się? -Czyli potrzebujemy metody `publish`. +Tak więc będziemy potrzebować metody `publish`. -Skoro już wiemy, co chcemy osiągnąć, możemy zacząć tworzyć model w Django! +Skoro już wiemy, co chcemy osiągnąć, pora zacząć tworzyć model w Django! ## Model w Django @@ -64,7 +64,7 @@ Możesz sobie wyobrazić model w bazie danych jako arkusz kalkulacyjny z kolumna Aby utrzymać wszystko w ładzie, stworzymy osobną aplikację wewnątrz naszego projektu. Przyjemnie jest mieć wszystko uporządkowane od samego początku. Aby stworzyć aplikację, musimy wykonać następujące polecenie w konsoli (z poziomu katalogu `djangogirls`, tam gdzie znajduje się plik `manage.py`): (myvenv) ~/djangogirls$ python manage.py startapp blog - + Z pewnością zauważysz, że pojawił się nowy folder `blog` zawierający kilka plików. Czyli foldery i pliki w naszym projekcie powinny wyglądać tak: @@ -83,20 +83,21 @@ Z pewnością zauważysz, że pojawił się nowy folder `blog` zawierający kilk ├── models.py ├── tests.py └── views.py - + Po stworzeniu aplikacji musimy dać znać Django, że powinien jej używać. Posługujemy się w tym celu plikiem `mysite/settings.py`. Musimy odnaleźć nagłówek `INSTALLED_APPS` i dodać wiersz o treści `'blog',` tuż przed nawiasem zamykającym `)`. Czyli efekt końcowy powinien wyglądać tak: - INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'blog', - ) - +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` ### Tworzymy model wpisu na blogu @@ -104,25 +105,27 @@ W pliku `blog/models.py` definiujemy wszystkie obiekty zwane `modelami` - to jes Otwórz plik `blog/models.py`, usuń z niego całą zawartość i napisz taki kod: - from django.db import models - from django.utils import timezone - - class Post(models.Model): - author = models.ForeignKey('auth.User') - title = models.CharField(max_length=200) - text = models.TextField() - created_date = models.DateTimeField( - default=timezone.now) - published_date = models.DateTimeField( - blank=True, null=True) - - def publish(self): - self.published_date = timezone.now() - self.save() - - def __str__(self): - return self.title - +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` > Upewnij się, czy na początku i końcu `str` używasz dokładnie dwóch znaków podkreślenia (`_`). W Pythonie używa się ich bardzo często i czasem nazywa się je "dunder" (skrót od angielskiej nazwy: "double-underscore"). @@ -136,38 +139,39 @@ Wszystkie wiersze zaczynające się od `from` lub `import` są wierszami dodają * `Post` to nazwa naszego modelu. Możemy nadać mu inną nazwę (bez polskich liter, znaków specjalnych i spacji). Zawsze zaczynaj nazwę modelu wielką literą. * `models.Model` oznacza, że nasz obiekt Post jest modelem Django. W ten sposób Django wie, że powinien go przechowywać w bazie danych. -Teraz dodamy właściwości, o których wspomniałyśmy już wcześniej: `title` (tytuł), `text` (treść wpisu), `created_date` (data utworzenia), `published_date` (data publikacji) oraz `author` (autor). Do tego celu potrzebujemy określić typ pola (czy jest to tekst? Liczba? Data? Odwołanie do innego obiektu, np. użytkownika?). +Teraz dodamy właściwości, o których wspomniałyśmy już wcześniej: `title` (tytuł), `text` (treść wpisu), `created_date` (data utworzenia), `published_date` (data publikacji) oraz `author` (autor). Do tego celu potrzebujemy określić typ pola (Czy jest to tekst? Liczba? Data? Odwołanie do innego obiektu, np. użytkownika?). * `models.CharField` - tak definiujemy tekst z ograniczoną liczbą znaków. * `models.TextField` - a to nadaje się do dłuższych tekstów bez ograniczeń w ilości znaków. Dla treści wpisu będzie idealne, prawda? * `models.DateTimeField` - to jest data i godzina. * `models.ForeignKey` - to jest odnośnik do innego modelu. -Nie będziemy tutaj wyjaśniać drobiazgowo każdego elementu kodu, gdyż zajęłoby to zbyt dużo czasu. Powinnaś zajrzeć do dokumentacji Django, jeżeli chcesz dowiedzieć się więcej o polach modelu oraz jak definiować typy inne niż opisywane powyżej (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). +Nie będziemy tutaj wyjaśniać drobiazgowo każdego elementu kodu, gdyż zajęłoby to zbyt dużo czasu. Zajrzyj do dokumentacji Django, jeżeli chcesz dowiedzieć się więcej o polach modelu oraz jak definiować typy inne niż opisywane powyżej (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). -A co to takiego `def publish(self):`? To nic innego, jak nasza metoda publikująca wpis, o której wspominałyśmy wcześniej. Słowo `def` oznacza, że mamy do czynienia z funkcją/metodą. Z kolei `publish` to nazwa metody. Możesz użyć innej, jeśli chcesz. Zasadą jest, że używamy małych liter oraz znaków podkreślenia zamiast spacji (czyli gdybyś chciała dodać metodę, która oblicza średnią cen, mogłabyś ją nazwać `calculate_average_price` lub `oblicz_srednia_cene`). +A co to takiego `def publish(self):`? To nic innego, jak nasza metoda publikująca wpis, o której wspominałyśmy wcześniej. Wyraz `def` oznacza, że mamy do czynienia z funkcją/metodą, a `publish` to nazwa metody. Możesz zmienić nazwę, jeśli chcesz. Zasadą jest, że używamy małych liter oraz znaków podkreślenia zamiast spacji. Na przykład, gdybyś chciała dodać metodę, która oblicza średnią cenę, mogłabyś ją nazwać `calculate_average_price` lub oblicz_srednia_cene. -Bardzo często metody coś zwracają (`return`). Przykład tego znajdziesz w metodzie `__str__`. W tym przypadku wywołując metodę `__str__()` otrzymamy tekst (**string**) zawierający tytuł wpisu. +Bardzo często metody coś zwracają (ang. `return`). Przykład tego znajdziesz w metodzie `__str__`. W tym przypadku wywołując metodę `__str__()` otrzymamy tekst (**string**) zawierający tytuł wpisu. -Jeżeli coś nadal nie jest jasne odnośnie modeli, nie bój się zapytać osoby prowadzącej kurs! Zdajemy sobie sprawę, że jest dość skomplikowane, zwłaszcza gdy poznajesz funkcje i obiekty w tym samym czasie. Mimo wszystko mamy nadzieję, że udało nam się chociaż odrobinę rozjaśnić temat! +Jeżeli coś nadal nie jest jasne odnośnie modeli, nie bój się zapytać osoby prowadzącej kurs! Zdajemy sobie sprawę, że jest to dość skomplikowane, zwłaszcza gdy poznajesz funkcje i obiekty w tym samym czasie. Mimo wszystko mamy nadzieję, że udało nam się chociaż odrobinę rozjaśnić temat! ### Tworzymy tabele dla modeli w bazie danych -Został nam ostatni krok, a mianowicie dodanie naszego nowego modelu do bazy danych. Najpierw musimy poinformować Django, że coś w naszym modelu zostało zmienione (właśnie go utworzyłyśmy). Wpisz `python manage.py makemigrations blog`. Efekt będzie wyglądał tak: +Został nam ostatni krok, a mianowicie dodanie naszego nowego modelu do bazy danych. Najpierw musimy poinformować Django, że coś w naszym modelu zostało zmienione (właśnie go utworzyłyśmy!). Wpisz `python manage.py makemigrations blog`. Efekt będzie wyglądał tak: (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': 0001_initial.py: - Create model Post - -Django przygotował za nas plik z migracjami, które musimy teraz wykonać w naszej bazie danych. Wpisz `python manage.py migrate blog`. Efekt powinien wyglądać tak: + +Django przygotował za nas plik z migracjami, które musimy teraz wykonać na naszej bazie danych. Wpisz `python manage.py migrate blog`. Powinnaś zobaczyć coś takiego: (myvenv) ~/djangogirls$ python manage.py migrate blog Operations to perform: Apply all migrations: blog Running migrations: + Rendering model states... DONE Applying blog.0001_initial... OK - -Hurra! Nasz model wpisu znalazł się w bazie danych. Fajnie byłoby go zobaczyć, co? Aby sprawdzić, jak wygląda nasz wpis, przeskocz do następnego rozdziału! + +Hurra! Nasz model wpisu na blogu znalazł się w bazie danych! Fajnie byłoby go zobaczyć, co? Aby sprawdzić jak wygląda nasz wpis, przejdź do następnego rozdziału! diff --git a/pl/django_orm/README.md b/pl/django_orm/README.md index 55fcfca04bf..d8d938141b4 100755 --- a/pl/django_orm/README.md +++ b/pl/django_orm/README.md @@ -10,16 +10,16 @@ Najłatwiej uczyć się na przykładach. To co, spróbujemy? ## Konsola Django -Otwórz konsolę i wpisz następujące polecenie: +Otwórz swoją lokalną konsolę Django (nie na PythonAnywhere) i wpisz następujące polecenie: (myvenv) ~/djangogirls$ python manage.py shell - + Efekt powinien wyglądać tak: (InteractiveConsole) >>> - + Jesteś teraz w intrektywnej konsoli Django. Przypomina ona nieco wiersz poleceń Pythona, z odrobiną dodatkowej magii Django :) Oczywiście możesz także używać w niej wszystkich poleceń Pythona. @@ -31,70 +31,60 @@ Na początek spróbujmy wyświetlić wszystkie nasze wpisy. Zrób to następują Traceback (most recent call last): File "", line 1, in NameError: name 'Post' is not defined - + Ups! Wyskoczył błąd. Mówi on nam, że nie istnieje coś takiego jak 'Post'. Oczywiście -- zapomniałyśmy go wcześniej zaimportować! >>> from blog.models import Post - + Nic skomplikowanego: importujemy model `Post` z `blog.models`. Spróbujmy jeszcze raz wyświetlić wszystkie wpisy: >>> Post.objects.all() - [, ] + [, ] + - -Pojawiła się lista wpisów, które dodałyśmy wcześniej przy pomocy panelu administracyjnego Django! Teraz jednak chciałybyśmy dodać nowy wpis używając interaktywnej konsoli. Jak to zrobimy? +Pojawiła się lista wpisów, które dodałyśmy wcześniej! Utworzyłyśmy je przy pomocy panelu administracyjnego Django. Teraz jednak chciałybyśmy dodać nowy wpis używając Pythona. Jak to zrobimy? ### Tworzenie obiektu -Obiekt Post w bazie danych tworzymy tak: - - >>> Post.objects.create(author=user, title='Sample title', text='Test') +W taki sposób tworzymy nowy obiekt Post w bazie danych: + >>> Post.objects.create(author=me, title='Sample title', text='Test') + -Ale brakuje nam jednego składnika: zmiennej `user`. Musimy przekazać instancję modelu `User` jako autora. Jak to zrobić? +Ale brakuje nam jednego składnika: `me`. Musimy przekazać instancję modelu `User` jako autora. Jak to zrobić? Najpierw zaimportujmy model User: >>> from django.contrib.auth.models import User - - -Jakich użytkowników mamy w bazie danych? Spróbuj tak: - - >>> User.objects.all() - [] - - -Żadnych użytkowników! No to stwórzmy jednego: - - >>> User.objects.create(username='ola') - - + Jakich użytkowników mamy w bazie danych? Spróbuj tak: >>> User.objects.all() [] + +To konto administratora, które stworzyłyśmy wcześniej! Teraz uzyskajmy dostęp do naszej instancji użytkownika: -Super! Teraz uzyskajmy dostęp do naszej instancji użytkownika: - - user = User.objects.get(username='ola') - + me = User.objects.get(username='ola') + Jak widzisz, za pomocą polecenia `get` pobrałyśmy z bazy obiekt użytkownika (`User`) z właściwością `username` o wartości 'ola'. Elegancko! Oczywiście musisz wprowadzić tam swoją nazwę użytkownika. -Teraz możemy wreszcie stworzyć nasz pierwszy wpis: - - >>> Post.objects.create(author = user, title = 'Sample title', text = 'Test') +Teraz możemy wreszcie stworzyć nasz post: + >>> Post.objects.create(author=me, title='Sample title', text='Test') + Hura! Chciałabyś sprawdzić, czy się udało? >>> Post.objects.all() - [] + [, , ] + +Jest! Kolejny post na liście! ### Dodajemy więcej wpisów @@ -102,42 +92,41 @@ Możesz teraz się pobawić i utworzyć więcej wpisów, żeby zobaczyć, jak to ### Filtrowanie obiektów -Niezmiernie istotną cechą QuerySetów jest możliwość ich filtrowania. Dajmy na to, że chciałybyśmy znaleźć wszystkie wpisy dodane przez użytkowniczkę (User) o nazwie ola. Skorzystamy z metody `filter` zamiast `all` w `Post.objects.all()`. W nawiasach wpiszemy jeden lub więcej warunków, które muszą zostać spełnione, żeby nasz wpis znalazł się w QuerySecie. W naszej sytuacji chodzi o to, aby `author` odpowiadał zmiennej `user`. W Django zapisujemy to tak: `author=user`. Teraz nasz kawałek kodu wygląda mniej-więcej tak: +Niezmiernie istotną cechą QuerySetów jest możliwość ich filtrowania. Dajmy na to, że chciałybyśmy znaleźć wszystkie wpisy dodane przez użytkowniczkę (User) o nazwie ola. Skorzystamy z metody `filter` zamiast `all` w `Post.objects.all()`. W nawiasach wpiszemy jeden lub więcej warunków, które muszą zostać spełnione, żeby nasz wpis znalazł się w QuerySecie. W naszej sytuacji chcemy, by `author` (autor) odpowiadał zmiennej `me`. W Django zapisujemy to tak: `author=me`. Teraz nasz kawałek kodu wygląda mniej-więcej tak: - >>> Post.objects.filter(author=user) + >>> Post.objects.filter(author=me) [, , , ] - + A gdybyśmy chciały wyświetlić wszystkie wpisy zawierające słowo 'title' w polu `title`? >>> Post.objects.filter(title__contains = 'title') [, ] - + > **Uwaga:** Pomiędzy `title` a `contains` znajdują się dwa znaki podkreślenia (`_`). ORM w Django używa takiej składni, aby oddzielić nazwy pól ("title") od operacji lub filtrów ("contains"). Jeśli użyjesz tylko jednego, zobaczysz błąd o treści "FieldError: Cannot resolve keyword title_contains". -Możemy także wyświetlić listę wszystkich opublikowanych wpisów. W tym celu odfiltrujmy wszystkie wpisy, które mają ustawioną datę publikacji (`published_date`) w przeszłości: +Możemy także wyświetlić listę wszystkich opublikowanych wpisów. W tym celu odfiltrujmy wszystkie wpisy, które mają ustawioną datę publikacji (`published_date`) na taką, która już minęła: >>> from django.utils import timezone >>> Post.objects.filter(published_date__lte=timezone.now()) [] +Niestety, żaden z naszych wpisów, które dodaliśmy przez konsolę, nie został jeszcze opublikowany. Zmieńmy to! Zacznij od pobrania wpisu, który chcesz opublikować: -Niestety, żaden z naszych wpisów nie został jeszcze opublikowany. Ale da się to zmienić! Zacznij od pobrania wpisu, który chcesz opublikować: - - >>> post = Post.objects.get(id = 1) - + >>> post = Post.objects.get(title="Sample title") + A następnie opublikuj go za pomocą metody `publish`! >>> post.publish() - + Teraz spróbujmy jeszcze raz wyświetlić listę opublikowanych wpisów (wciśnij trzykrotnie klawisz ze strzałką do góry, a następnie zatwierdź klawiszem `enter`): >>> Post.objects.filter(published_date__lte=timezone.now()) [] - + ### Kolejność obiektów @@ -145,13 +134,22 @@ QuerySety umożliwiają również porządkowanie list obiektów według określo >>> Post.objects.all().order_by('created_date') [, , , ] - + Możemy także odwrócić kolejność poprzez dodanie `-` na początku: >>> Post.objects.all().order_by('-created_date') [, , , ] + + +### Łączenie QuerySetów + +Możesz też połączyć QuerySety: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + +To naprawdę potężne narzędzie, które pozwala na pisanie bardzo złożonych zapytań. Doskonale! Jesteś teraz gotowa na następną część! Zamknij konsolę poleceniem: diff --git a/pl/django_start_project/README.md b/pl/django_start_project/README.md index 0c7cd3c82c7..662c09bb9ce 100755 --- a/pl/django_start_project/README.md +++ b/pl/django_start_project/README.md @@ -1,30 +1,32 @@ # Twój pierwszy projekt w Django! -> Fragment tego rozdziału jest oparty na tutorialu Geek Girls Carrots (http://django.carrots.pl/). +> Fragment tego rozdziału jest oparty o tutoriale Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > > Fragmenty tego rozdziału są oparte o [tutorial django-marcador][1] na licencji Creative Commons Attribution-ShareAlike International 4.0. Tutorial django-marcador jest chroniony prawami autorskimi przez Markusa Zapke-Gründemanna i in. -[1]: http://django-marcador.keimlink.de/ + [1]: http://django-marcador.keimlink.de/ Mamy zamiar stworzyć prostego bloga! -Pierwszym krokiem w stronę utworzenia go jest założenie nowego projektu w Django. To w zasadzie oznacza, że skorzystamy z dostarczonych przez Django skryptów, które za nas utworzą szkielet projektu Django: zbiór katalogów i plików, których będziemy używać później. +Pierwszy krok, który trzeba wykonać, to utworzenie nowego projektu Django. To oznacza, że skorzystamy z dostarczonych przez Django skryptów, które utworzą za nas szkielet projektu Django. Ten szkielet to zbiór katalogów i plików, których będziemy używać później. -Nazwy niektórych plików i katalogów są bardzo ważne dla Django. Nie powinnaś zmieniać nazw plików, które zostaną utworzone. Przenoszenie ich w inne miejsce też nie jest dobrym pomysłem. Django musi trzymać pewną strukturę, aby mieć łatwy dostęp do potrzebnych rzeczy. +Nazwy niektórych plików i katalogów są bardzo ważne dla Django. Nie powinnaś zmieniać nazw plików, które zostaną utworzone. Przenoszenie ich w inne miejsce też nie jest dobrym pomysłem. Django wymaga zachowania pewnej struktury, by móc szybko znaleźć potrzebne rzeczy. -Uruchom w konsoli (pamiętaj, że nie musisz pisać `(myvenv) ~/djangogirls$`, OK?): +> Pamiętaj, aby uruchamiać wszystko w virtualenv. Jeśli nie widzisz prefiksu `(myvenv)` w konsoli, to znaczy że musisz uruchomić swój virtualenv. Wyjaśniłyśmy, jak to zrobić w rozdziale **Instalacja Django** w części **Praca z virtualenv**. Wystarczy wpisać `myvenv\Scripts\activate` w systemie Windows lub `source myvenv/bin/activate`, jeśli używasz Mac OS / Linux. -> Pamiętaj, aby uruchamiać wszystko w virtualenv. Jeśli nie widzisz prefiksu `(myvenv)` w konsoli, to znaczy że musisz uruchomić swój virtualenv. Wyjaśniłyśmy, jak to zrobić w rozdziale **Instalowanie Django** w części **Praca z virtualenv**. - -Uruchom komendę: +Dla systemów MacOS lub Linux; wpisz teraz do swojej konsoli następującą komendę; ** nie zapomnij dodać kropki `.` na końcu**: (myvenv) ~/djangogirls$ django-admin startproject mysite . -Dla Windows: - (myvenv) C:\Users\Nazwa\djangogirls> python myvenv\Scripts\django-admin.py startproject mysite . +Dla Windows; **nie zapomnij dodać kropki `.` na końcu**: -> **Uwaga:** Pamiętaj koniecznie o kropce (`.`) na końcu polecenia, ona jest tam niezbędna. + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> Kropka `.` ma kluczowe znaczenie, ponieważ dzięki niej skrypt wie, że ma zainstalować Django w bieżącym katalogu (kropka `.` to taka skrócona nazwa bieżącego katalogu) +> +> **Uwaga** Kiedy będziesz przepisywać komedy, które zamieściliśmy wyżej, pamiętaj, że przepisujesz tylko tę część, która zaczyna się od `django-admin` lub `django-admin.py`. Te `(myvenv) ~/djangogirls$` i `(myvenv) C:\Users\Name\djangogirls>` (zwane z ang. promptem) są tutaj tylko po to, by pokazać Ci przykład linii poleceń i tego jak ona będzie wyglądała, gdy będziesz do niej wpisywać polecenia. `django-admin.py` jest skryptem, który utworzy katalogi i pliki za Ciebie. Powinnaś mieć teraz strukturę katalogów podobną do tej: @@ -49,37 +51,61 @@ Na razie zapomnijmy o innych plikach - nie będziemy ich modyfikować. Jedyne, o Wprowadźmy parę zmian w pliku `mysite/settings.py`. Otwórz go za pomocą edytora kodu, który zainstalowałaś wcześniej. -Fajnie byłoby posługiwać się poprawnym czasem na naszej stronie. Przejdź do http://en.wikipedia.org/wiki/List_of_tz_database_time_zones i skopiuj właściwą strefę czasową (TZ). (np. `Europe/Berlin`) +Fajnie byłoby posługiwać się na naszej stronie właściwą strefą czasową. Przejdź do [listy stref czasowych w wikipedii][2] i skopiuj właściwą strefę czasową (TZ). (np. `Europe/Berlin` ) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +W pliku settings.py znajdź linijkę, w której jest napisane `TIME_ZONE` i zmień ją według swoich potrzeb: + +```python +TIME_ZONE = 'Europe/Berlin' +``` -Znajdź linie zawierające `USE_TZ` i `TIME_ZONE` i zmodyfikuj je w następujący sposób, wstawiając w miejsce `Europe/Berlin` właściwą strefę czasową: +Gdzie odpowiednio zmienisz "Europe/Berlin" - USE_TZ = False - TIME_ZONE = 'Europe/Berlin' +Musimy także dodać ścieżkę do plików statycznych (dowiesz się więcej o plikach statycznych i CSS w dalszej części kursu). Przejdź do samego końca pliku i pod linijką zawierającą `STATIC_URL` dodaj nową zmienną `STATIC_ROOT`: +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'public', 'static') +``` ## Ustawienie bazy danych -Istnieje duży wybór baz danych, w których możemy przechowywać dane naszej strony. My użyjemy bazy domyślnej, czyli `sqlite3`. +Istnieje duży wybór baz danych, w których możemy trzymać dane naszej strony. My użyjemy bazy domyślnej, czyli `sqlite3`. Została ona już ustawiona w tej części pliku `mysite/settings.py`: - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } +} +``` - -Aby utworzyć bazę danych dla naszego bloga, wykonajmy następujące polecenie w konsoli: `python manage.py migrate` (musimy być w katalogu `djangogirls`, tam, gdzie znajduje się plik `manage.py`). Gdy to się uda, powinnaś zobaczyć coś takiego jak poniżej: +Aby utworzyć bazę danych dla naszego bloga, wykonajmy następujące polecenie w konsoli: `python manage.py migrate` (musimy być w katalogu `djangogirls`, tam gdzie znajduje się plik `manage.py`). Gdy to się uda, powinnaś zobaczyć coś takiego jak poniżej: (myvenv) ~/djangogirls$ python manage.py migrate Operations to perform: - Apply all migrations: admin, contenttypes, auth, sessions + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK Applying sessions.0001_initial... OK @@ -90,15 +116,22 @@ Musisz znajdować się w katalogu zawierającym plik `manage.py` (katalog `djang (myvenv) ~/djangogirls$ python manage.py runserver -Teraz pozostaje Ci jedynie przekonać się, czy Twoja strona działa - otwórz przeglądarkę (Firefox, Chrome, Safari, Internet Explorer lub inna, której używasz) i wpisz adres: +Jeśli pracujesz na Windowsie i zobaczysz w tym momencie `UnicodeDecodeError`, użyj następującej komendy: + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Teraz pozostaje Ci jedynie przekonać się, czy Twoja strona działa. Otwórz przeglądarkę (Firefox, Chrome, Safari, Internet Explorer czy inną, której używasz) i wpisz adres: http://127.0.0.1:8000/ -Serwer przejmie Twój wiersz poleceń i będzie go używał dopóty, dopóki go nie wyłączysz. Aby mieć możliwość wykonywania innych poleceń, możesz zrobić jedną z dwóch rzeczy: otwórz nowe okienko terminala (i nie zapomnij o uruchomieniu w nim środowiska virtualenv) albo zatrzymaj serwer - w tym celu wróć do okienka, w którym został on uruchomiony i wciśnij CTRL+C (klawisze Control i C jednocześnie; pod Windows działa skrót Ctrl+Break). +Serwer przejmie Twój wiersz poleceń i będzie go używał cały czas dopóki go nie wyłączysz. By móc wykonywać inne polecenia, otwórz nowe okienko terminala i uruchom w nim środowisko virtualenv. Aby zatrzymać serwer, wróć do okienka, w którym został on uruchomiony i wciśnij CTRL+C - klawisze Control i C jednocześnie (jeśli używasz systemu Windows to możesz też spróbować skrótu Ctrl+Break). Gratulacje! Właśnie stworzyłaś swoją pierwszą stronę i uruchomiłaś ją za pomocą serwera! Prawda, że wspaniale? -![Działa!](images/it_worked2.png) +![Działa!][3] + + [3]: images/it_worked2.png Gotowa na następny krok? Czas stworzyć treść! diff --git a/pl/django_templates/README.md b/pl/django_templates/README.md index eb2b20877fc..580431a0df1 100755 --- a/pl/django_templates/README.md +++ b/pl/django_templates/README.md @@ -1,10 +1,10 @@ # Szablony Django -Pora wyświetlić jakieś dane! Django udostępnia nam do tego celu przydatny zbiór wbudowanych **znaczników szablonu**. +Pora wyświetlić jakieś dane! Django udostępnia nam do tego celu przydatny zbiór wbudowanych **znaczników szablonu** (ang. template tags). ## Co to są znaczniki szablonu? -Widzisz, w HTML nie da się używać kodu w Pythonie, ponieważ przeglądarki go nie zrozumieją. Jedyne, co rozumieją przeglądarki, to HTML. Wiemy, że HTML jest raczej statyczny, podczas gdy Python jest znacznie bardziej dynamiczny. +Widzisz, w HTML nie da się używać kodu napisanego w Pythonie, ponieważ przeglądarki go nie zrozumieją. Jedyne, co rozumieją to HTML. Wiemy, że HTML jest raczej statyczny, podczas gdy Python jest znacznie bardziej dynamiczny. Za pomocą **znaczników szablonu Django** możemy przemycić elementy Pythona w naszym kodzie HTML, dzięki czemu budowanie dynamicznym stron jest szybsze i łatwiejsze. Hura! @@ -18,16 +18,18 @@ Aby wyświetlić zmienną w szablonie Django, używamy podwójnych nawiasów kla {{ posts }} ``` -Wypróbuj tego w szablonie `blog/templates/blog/post_list.html` (zastąp wszystko wewnątrz drugiego `
` wierszem `{{ posts }}`), zapisz plik i odśwież stronę, aby zobaczyć rezultat: +Spróbuj tak zrobić w szablonie` blog/templates/blog/post_list.html`. Zastąp wszystko od drugiego `
` do trzeciego `
` wierszem `{{ posts }}`. Zapisz plik i odśwież stronę, by zobaczyć rezultat: -![Rysunek 13.1](images/step1.png) +![Rysunek 13.1][1] + + [1]: images/step1.png Jak widzisz, dostaliśmy tylko tyle: [, ] -Oznacza to tyle, że Django rozumie to jako listę obiektów. Pamiętasz z rozdziału **Wprowadzenie do Pythona**, jak możemy wyświetlić zawartość listy? Tak, za pomocą pętli! W szablonie Django używamy ich w ten sposób: +Oznacza to tyle, że Django rozumie to jako listę obiektów. Pamiętasz z rozdziału **Wprowadzenie do Pythona**, jak możemy wyświetlić zawartość listy? Tak, za pomocą pętli for! W szablonie Django używamy ich w ten sposób: ```html {% for post in posts %} @@ -35,10 +37,11 @@ Oznacza to tyle, że Django rozumie to jako listę obiektów. Pamiętasz z rozdz {% endfor %} ``` - Wypróbuj tego w swoim szablonie. -![Rysunek 13.2](images/step2.png) +![Rysunek 13.2][2] + + [2]: images/step2.png Działa! Ale chcemy je wyświetlić tak samo, jak statyczne wpisy, które tworzyłyśmy wcześniej w rozdziale **Wprowadzenie do HTML**. Możliwe jest łączenie znaczników szablonu z kodem HTML. Nasza sekcja `body` będzie wyglądać tak: @@ -51,36 +54,52 @@ Działa! Ale chcemy je wyświetlić tak samo, jak statyczne wpisy, które tworzy

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` +{% raw %}Wszystko, co zawrzesz pomiędzy `{% for %}` a `{% endfor %}` zostanie powtórzone dla każdego obiektu z listy. Odśwież swoją stronę:{% endraw %} -Wszystko, co zawszesz pomiędzy `{% for %}` a `{% endfor %}` zostanie powtórzone dla każdego obiektu z listy. Odśwież stronę: +![Rysunek 13.3][3] -![Rysunek 13.3](images/step3.png) + [3]: images/step3.png -Zapewne zauważyłaś, że tym razem użyłyśmy nieco innej składni: `{{ post.title }}` i `{{ post.text }}`? W ten sposób uzyskujemy dostęp do danych zawartych w poszczególnych polach naszego modelu `Post`. Z kolei `|linebreaks` przepuszcza wpisy przez filtr, który zamienia znaczniki nowej linii na akapity. +Zapewne zauważyłaś, że tym razem użyłyśmy nieco innej składni: `{{ post.title }}` i `{{ post.text }}`? W ten sposób uzyskujemy dostęp do danych zawartych w poszczególnych polach naszego modelu `Post`. Z kolei `|linebreaksbr` przepuszcza wpisy przez filtr, który zamienia znaczniki nowej linii na akapity. ## Jeszcze jedno -Dobrze byłoby wiedzieć, że nasza witryna nadal działa na Heroku, prawda? Spróbuj ponownie wdrażania. Jeśli nie pamiętasz jak to zrobić, sprawdź na końcu rozdziału 15: - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Dodane szablony Django" -... -$ git push heroku master -``` +Dobrze byłoby sprawdzić, czy Twoja strona dalej działa w internecie, prawda? Ponownie wyślijmy kod na PythonAnywhere. Oto małe przypomnienie jak to zrobić... + +* Najpierw zapisz swój kod na Githubie + + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modyfikacja szablonu, by pokazywal posty z bazy danych" + [...] + $ git push + +* Teraz zaloguj się ponownie na [PythonAnywhere][4] i przejdź do konsoli **Bash** (albo uruchom nową) i wpisz: + + [4]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ git pull + [...] + + +* Na koniec przejdź do podstrony [Web tab][5] i naciśnij **Reload**. Twoja aktualizacja powinna być widoczna! + + [5]: https://www.pythonanywhere.com/web_app_setup/ Gratulacje! Teraz śmiało możesz dodać nowy wpis w swoim panelu administratora Django (nie zapomnij dodać published_date!). Następnie odśwież stronę, żeby sprawdzić, czy Twój wpis się tam pojawił. -Działa jak marzenie? Jesteśmy z Ciebie dumne! Zasłużyłaś na słodką nagrodę. :) +Poszło jak z płatka? Jesteśmy dumne! Odejdź na chwilkę od komputera, zasłużyłaś na przerwę. :) + +![Rysunek 13.4][6] -![Rysunek 13.4](images/donut.png) + [6]: images/donut.png diff --git a/pl/django_urls/README.md b/pl/django_urls/README.md index b8f2d33d8c8..f4bbb80e3f7 100755 --- a/pl/django_urls/README.md +++ b/pl/django_urls/README.md @@ -1,30 +1,33 @@ # Adresy URL w Django -Za chwilę zbudujemy naszą pierwszą stronę -- stronę główną Twojego bloga! Ale najpierw dowiedzmy się co nieco o adresach URL w Django. +Za chwilę zbudujemy naszą pierwszą stronę - stronę główną Twojego bloga! Ale najpierw dowiedzmy się co nieco o adresach URL w Django. ## Czym jest URL? -Adres URL to po prostu adres w internecie. Widzisz go za każdym razem, gdy odwiedzasz jakąkolwiek stronę - jest widoczny w pasku adresu Twojej przeglądarki (tak! 127.0.0.1:8000 jest adresem URL! http://djangogirls.com również): +Adres URL to po prostu adres w internecie. Widzisz go za każdym razem, gdy odwiedzasz jakąkolwiek stronę - jest widoczny w pasku adresu Twojej przeglądarki (tak! `127.0.0.1:8000` jest adresem URL! http://djangogirls.org również): -![Adres URL](images/url.png) +![Adres URL][1] -Każda strona w internecie potrzebuje własnego adresu URL. W ten sposób aplikacja wie, co wyświetlić użytkownikowi, który otworzy dany URL. W Django używamy tak zwanego `URLconf` (konfiguracji URL) -- zestawu wzorców, które Django stara się dopasować do otrzymanego adresu URL i znaleźć na tej podstawie właściwy widok. + [1]: images/url.png + +Każda strona w internecie potrzebuje własnego adresu URL. W ten sposób aplikacja wie, co wyświetlić użytkownikowi, który otworzy dany URL. W Django używamy tak zwanego `URLconf` (konfiguracji URL). Jest to zestaw wzorców, które Django stara się dopasować do otrzymanego adresu URL i na tej podstawie znaleźć właściwy widok. ## Jak działają adresy URL w Django? Otwórzmy plik `mysite/urls.py` i przyjrzyjmy się jego treści: - from django.conf.urls import include, url - from django.contrib import admin - - urlpatterns = [ - # Examples: - # url(r'^$', 'mysite.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), +```python +from django.conf.urls import include, url +from django.contrib import admin - url(r'^admin/', include(admin.site.urls)), - ] +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + url(r'^admin/', include(admin.site.urls)), +] +``` Jak zauważyłaś, Django coś nam już tu umieścił. @@ -32,20 +35,39 @@ Wiersze zaczynające się od `#` są komentarzami - co oznacza, że ich treść Adres URL panelu administracyjnego, który odwiedzałaś w poprzednim rozdziale, jest już tutaj dodany: - url(r'^admin/', include(admin.site.urls)), - +```python +url(r'^admin/', include(admin.site.urls)), +``` -To znaczy, że dla każdego adresu zaczynającego się od `admin/` Django spróbuje dopasować odpowiedni *widok*. W tym przypadku używamy wielu adresów URL panelu administracyjnego, dlatego nie wypisujemy ich wszystkich w tym jednym małym pliku - tak jak czytelniej i bardziej estetycznie. +To znaczy, że dla każdego adresu zaczynającego się od `admin/` Django spróbuje dopasować odpowiedni *widok*. W tym przypadku używamy wielu adresów URL panelu administracyjnego, dlatego nie wypisujemy ich wszystkich w tym jednym małym pliku - tak jest czytelniej i bardziej estetycznie. ## Regex, czyli wyrażenia regularne -Zastanawiałaś się, w jaki sposób Django kojarzy adresy URL z widokami? Cóż, ta część jest nieco bardziej złożona. Django wykorzystuje `regex` -- tzw. wyrażenia regularne. Regex posiada mnóstwo (naprawdę mnóstwo!) reguł, które tworzą wzorzec do wyszukania. To dość skomplikowany temat i na razie nie będziemy się nim zajmować. Z pewnością poznasz go bardziej szczegółowo w przyszłości. Dziś ograniczymy się do tego, co jest nam faktycznie potrzebne. +Zastanawiałaś się, w jaki sposób Django kojarzy adresy URL z widokami? Cóż, ta część jest nieco bardziej złożona. Django wykorzystuje `regex`, czyli tzw. wyrażenia regularne. Regex posiada mnóstwo (naprawdę mnóstwo!) reguł, które tworzą wzorzec do wyszukania. To dość skomplikowany temat i nie będziemy tutaj wchodzić w szczegóły. + +Do zrozumienia wzorców, które stworzyłyśmy powyżej, potrzebnych jest tylko kilka reguł: + + ^ oznacza początek tekstu + $ oznacza koniec tekstu + \d oznacza cyfrę + + oznacza, że poprzedni element powinien się powtórzyć przynajmniej raz + piszemy () aby uchwycić część wzorca + -Abyś jednak nie czuła zagubiona w tym miejscu, spójrzmy na prosty przykład. Wyobraź sobie, że masz stronę internetową z adresami w postaci `http://www.mojastrona.com/post/12345/`, gdzie `12345` to numer Twojego wpisu. Pisanie osobnych widoków dla każdego numeru z osobna byłoby frustrujące. Z Django jest dużo prościej, pozwala on bowiem na zapis `http://www.mojastrona.com/post//`. Django zajmie się resztą! +Inne znaki we wzorcu url będą rozumiane dosłownie. + +Wyobraź sobie, że masz stronę, której adres to: `http://www.mysite.com/post/12345/`, gdzie `12345` to numer Twojego posta. + +Pisanie osobnych widoków dla każdego numeru z osobna byłoby frustrujące. Z wyrażeniami regularnymi możemy stworzyć wzorzec, który dopasuje URL i znajdzie dla nas numer posta: `^post/(\d+)/$`. Rozbijmy go na mniejsze części, by zrozumieć, co tu się dzieje: + +* **^post/** mówi Django, by skupił się na każdym adresie URL, który zaczyna się od wyrazu `post` (zaraz po `^`) +* **(\d+)** oznacza, że szukamy numeru (jedna lub więcej cyfr) i że chcemy go wyodrębnić +* **/** mówi Django, że następny w kolejności powinien się pojawić znak `/` +* **$** informuje, że to jest koniec adresu URL, co oznacza, że Django będzie szukał adresów kończących się na `/` ## Twój pierwszy adres URL w Django! -Czas utworzyć nasz pierwszy adres URL! Chcemy, aby adres http://127.0.0.1:8000/ był stroną główną naszego bloga i wyświetlał listę wpisów. +Czas utworzyć nasz pierwszy adres URL! Chcemy, aby adres 'http://127.0.0.1:8000/' był stroną główną naszego bloga i wyświetlał listę wpisów. Zależy nam również, aby zachować porządek w pliku `mysite/urls.py`, dlatego zaimportujemy URLe z naszej aplikacji `blog` do głównego pliku `mysite/urls.py`. @@ -53,44 +75,51 @@ Zależy nam również, aby zachować porządek w pliku `mysite/urls.py`, dlatego Twój plik `mysite/urls.py` powinien teraz wyglądać tak: - from django.conf.urls import include, url - from django.contrib import admin +```python +from django.conf.urls import include, url +from django.contrib import admin - urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), - url(r'', include('blog.urls')), - ] +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` +Django przekieruje wszystkie reguły z adresu 'http://127.0.0.1:8000/' do `blog.urls` i tam będzie szukał dalszych wskazówek. -Od tej pory Django przekieruje wszystkie reguły z adresu http://127.0.0.1:8000/ do `blog.urls` i tam będzie szukał dalszych wskazówek. +Kiedy tworzymy wyrażenia regularne w Pythonie, zawsze piszemy `r` na początku ciągu znaków. To jest podpowiedź dla Pythona, że w tym ciągu znaków mogą się znajdować znaki specjalne, które nie są przeznaczone dla niego, ponieważ oznaczają wyrażenie regularne. ## blog.urls -Stwórz nowy pusty plik `blog/urls.py`. W porządku! Teraz dodaj dwie pierwsze linijki: - - from django.conf.urls import include, url - from . import views +Stwórz nowy pusty plik `blog/urls.py`. Super! Teraz dodaj dwie pierwsze linijki: +```python +from django.conf.urls import url +from . import views +``` Tutaj po prostu importujemy metody Django oraz wszystkie widoki (`views`) z naszej aplikacji `blog` (jeszcze nie mamy żadnych, ale dojdziemy do tego za chwilkę!) Potem możemy dodać nasz pierwszy wzorzec adresu URL: - urlpatterns = [ - url(r'^$', views.post_list), - ] - +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` -Jak widzisz, przyporządkowujemy widok (`view`) o nazwie `post_list` do adresu `^$`. A co oznacza `^$`? Tutaj kłania się magia wyrażeń regularnych. :) Rozłóżmy to na cześci: - `^` w wyrażeniu oznacza "początek"; od tego znaku rozpoczynamy poszukiwanie naszego wzorca - `$` oznacza "koniec" ciągu znaków, czyli tutaj kończymy poszukiwanie naszego wzorca +Jak widzisz, przyporządkowujemy widok (`view`) o nazwie `post_list` do adresu `^$`. To wyrażenie regularne będzie dopasowywać `^` (początek) i `$` (koniec) — połączenie tych dwóch znaków oznacza, że szukamy pustego ciągu znaków. I to się zgadza, ponieważ dla mechanizmów rozróżniających adresy w Django 'http://127.0.0.1:8000/' nie jest częścią adresu URL. Ten wzorzec będzie wskazówką dla Django, że `views.post_list` jest właściwym miejscem dla każdego, kto wejdzie na stronę poprzez adres 'http://127.0.0.1:8000/'. -Połączenie tych dwóch znaków oznaczałoby, że szukamy pustego ciągu znaków! I to się zgadza, ponieważ dla mechanizmów rozróżniających adresy w Django (ang. resolvers) http://127.0.0.1:8000/ nie jest częścią adresu URL. Wzorzec ten będzie wskazówką dla Django, że `views.post_list` jest właściwym kierunkiem dla każdego, kto wejdzie na stronę poprzez adres http://127.0.0.1:8000/. +Ostatni kawałek `name='post_list` jest nazwą adresu URL, która będzie używana do zidentyfikowania widoku. Nazwa może być taka sama jak nazwa widoku albo kompletnie inna. W naszym projekcie będziemy używać właśnie nazw URL-i, więc ważne jest nazwanie każdego URL-a w aplikacji. Nazwy powinny być unikalne i łatwe do zapamiętania. Wszystko gra? Otwórz http://127.0.0.1:8000/ w przeglądarce, żeby zobaczyć rezultat. -![Błąd](images/error1.png) +![Błąd][2] + + [2]: images/error1.png Gdzieś zniknęło "It works", zgadza się? Spokojnie, to tylko strona błędu, nic strasznego! Czasami ich treść okazuje się całkiem pomocna: -Jest napisane, iż **brakuje atrybutu 'post_list'**. Czy *post_list* czegoś Ci nie przypomina? Tak samo nazwaliśmy nasz widok! Czyli wszystko jest w porządku, po prostu nie stworzyliśmy jeszcze naszego *widoku*. Nie martw się, zajmiemy się tym. +Jest napisane, iż **brakuje atrybutu 'post_list'**. Czy *post_list* czegoś Ci nie przypomina? Tak samo nazwaliśmy nasz widok! To oznacza, że wszystko jest w porządku, po prostu nie stworzyliśmy jeszcze naszego *widoku*. Nie martw się, zajmiemy się tym. > Jeśli chciałabyś dowiedzieć się więcej na temat konfiguracji URL w Django, zajrzyj do oficjalnej dokumentacji: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/pl/django_views/README.md b/pl/django_views/README.md index 9fa1ea79e0e..061be55da30 100755 --- a/pl/django_views/README.md +++ b/pl/django_views/README.md @@ -2,7 +2,7 @@ Czas uporać się z błędem, który pozostawiłyśmy po poprzednim rozdziale. :) -*Widok* jest miejscem, w którym umieszczamy "logikę" naszej aplikacji. Zażąda on informacji od `modelu`, który wcześniej utworzyłaś, a następnie przekaże je do szablonu (`template`), który utworzysz w następnym rozdziale. Widoki to po prostu metody w Django, tylko nieco bardziej skomplikowane niż te, którymi zajmowałyśmy się w rozdziale **Wprowadzenie do Pythona**. +*Widok* jest miejscem, w którym umieszczamy "logikę" naszej aplikacji. Pobierze on informacje od modelu, który wcześniej utworzyłaś, a następnie przekaże je do szablonu (`template`). Nauczymy się tworzyć szablony w następnym rozdziale. Widoki to po prostu metody w Django, tylko nieco bardziej skomplikowane niż te, którymi zajmowałyśmy się w rozdziale **Wprowadzenie do Pythona**. Widoki (ang. views) są przechowywane w pliku `views.py`. Dodajmy *views* do naszego pliku `blog/views.py`. @@ -10,17 +10,18 @@ Widoki (ang. views) są przechowywane w pliku `views.py`. Dodajmy *views* do nas OK, otwórzmy ten plik i zobaczmy co siedzi w środku: - from django.shortcuts import render - - # Create your views here. +```python +from django.shortcuts import render +# Create your views here. +``` Póki co niewiele. Najprostszy *widok* może wyglądać tak. - def post_list(request): - - return render(request, 'blog/post_list.html', {}) - +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` Jak widzisz, stworzyłyśmy metodę (`def`) zwaną `post_list`, która przyjmuje zapytanie (`request`) i zwraca (`return`) metodę zwaną `render`, której zadaniem jest wyrenderowanie (złożenie w całość) naszego szablonu `blog/post_list.html`. @@ -28,8 +29,10 @@ Zapisz plik, przejdź do http://127.0.0.1:8000/ i sprawdź, co teraz się stanie Znowu błąd! Przeczytaj, o co chodzi tym razem: -![Błąd](images/error.png) +![Błąd][1] + + [1]: images/error.png Tym razem jest łatwo: *TemplateDoesNotExist*, Naprawmy ten błąd i stwórzmy szablon - ale to już w następnym rozdziale! -> Więcej na temat widoków Django dowiesz się czytając oficjalną dokumentację: https://docs.djangoproject.com/en/1.8/topics/http/views/ +> Więcej na temat widoków Django dowiesz się czytając oficjalną dokumentację: https://docs.djangoproject.com/en/1.7/topics/http/views/ diff --git a/pl/domain/README.md b/pl/domain/README.md index 391a5584559..220394c7e8c 100755 --- a/pl/domain/README.md +++ b/pl/domain/README.md @@ -16,33 +16,45 @@ Naszą ulubioną firmą jest [I want my name][2]. Reklamują się jako "bezboles ## Jak zarejestrować domenę w IWantMyName? -Przejdź do [iwantmyname][3] i wpisz nazwę domeny, którą chciałabyś mieć, w polu wyszukiwania. +Przejdź do [iwantmyname][3] i w polu wyszukiwania wpisz nazwę domeny, którą chciałabyś mieć. - [3]: http://iwantmyname.com + [3]: https://iwantmyname.com -![](images/1.png) +![][4] + + [4]: images/1.png Teraz powinnaś zobaczyć listę wszystkich domen zawierających nazwę, którą wpisałaś w polu wyszukiwania. Jak widzisz, uśmiechnięta buźka sygnalizuje, że dana domena jest wolna i można ją kupić, zaś smutna buźka oznacza, że dana domena należy już do kogoś innego. -![](images/2.png) +![][5] + + [5]: images/2.png Postanowiłyśmy kupić domenę `djangogirls.in`: -![](images/3.png) +![][6] + + [6]: images/3.png Przejdź do podsumowania transakcji. Jeżeli nie masz jeszcze konta w iwantmyname, załóż je teraz. Gdy już to zrobisz, wpisz dane swojej karty kredytowej i domena będzie Twoja! Następnie wybierz z menu opcję `Domains` i wybierz swoją nową domenę. Znajdź link `manage DNS records` i kliknij go: -![](images/4.png) +![][7] + + [7]: images/4.png Teraz musisz znaleźć taki formularz: -![](images/5.png) +![][8] + + [8]: images/5.png I wypełnić go w następujący sposób: - Hostname: www - Type: CNAME - Value: twoja domena w Heroku (na przykład djangogirls.herokuapp.com) - TTL: 3600 -![](images/6.png) +![][9] + + [9]: images/6.png Kliknij przycisk Add oraz Save changes na dole. diff --git a/pl/dynamic_data_in_templates/README.md b/pl/dynamic_data_in_templates/README.md index b453a8c5cf2..bef6743f09e 100755 --- a/pl/dynamic_data_in_templates/README.md +++ b/pl/dynamic_data_in_templates/README.md @@ -1,4 +1,4 @@ -# Obiekty Queryset w Django +# Dane dynamiczne w szablonach Django Sporo rzeczy jest już na swoim miejscu: model `Post` jest zdefiniowany w `models.py`, w `views.py` mamy `post_list`, szablon też już gotowy. Ale jak to zrobić, aby nasze wpisy pojawiały się w szablonie HTML? Bo to właśnie chcemy osiągnąć: pobrać treści (czyli modele zapisane w bazie) i ładnie je wyświetlić w szablonie, prawda? @@ -8,17 +8,19 @@ OK, zatem jak możemy to osiągnąć? Musimy otworzyć nasz plik `blog/views.py`. Jak dotąd *widok* `post_list` wygląda następująco: - from django.shortcuts import render - - def post_list(request): - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` Pamiętasz, jak rozmawiałyśmy o dołączaniu kodu zapisanego w odrębnych plikach? Teraz jest przyszedł czas na dołączenie modelu, który napisałyśmy wcześniej w `models.py`. Dodajmy wiersz `from .models import Post` w następujący sposób: - from django.shortcuts import render - from .models import Post - +```python +from django.shortcuts import render +from .models import Post +``` Kropka po `from` oznacza *bieżący katalog* lub *biężącą aplikację*. Jako że pliki `views.py` i `models.py` są w tym katalogu, możemy użyć po prostu `.` i nazwy pliku (bez `.py`). Następnie importujemy nazwę modelu (`Post`). @@ -33,36 +35,40 @@ Powinnaś być już zaznajomiona z zasadą działania obiektów typu QuerySet. R Więc teraz interesuje nas lista wpisów, które zostały opublikowane i posortowane według daty publikacji (`published_date`), zgadza się? Już to zrobiłyśmy w rozdziale o QuerySetach! Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - + Teraz umieśćmy ten kod wewnątrz pliku `blog/views.py` poprzez dodanie go do funkcji `def post_list(request)`: - from django.shortcuts import render - from django.utils import timezone - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` Zauważ, że tworzymy *zmienną* dla naszego QuerySetu: `posts`. Potraktuj ją jako nazwę naszego QuerySetu. Od tej pory będziemy odnosić się do niej tylko za pomocą tej nazwy. +Ponadto w kodzie mamy funkcję `timezone.now()`, więc musimy zaimportować `timezone`. + Ostatnią częścią, której nam brakuje, jest przekazanie QuerySetu `posts` do szablonu (jej wyświetlaniem w szablonie zajmiemy się w następnym rozdziale). -W funkcji `render` mamy już parametr `request` (czyli wszystko to, co odbieramy od użytkownika przez internet) oraz plik szablonu `'blog/post_list.html'`. Ostatni parametr, który wygląda tak: `{}` jest miejscem, w którym możemy dodać parę rzeczy do wykorzystania w szablonie. Musimy nadać im nazwy (ale póki co będziemy trzymać się nazwy `'posts'` :)). Powinno to wyglądać tak: `{'posts': posts}`. Zauważ, że część przed `:` jest zawarta w cudzysłowie `''`. +W funkcji `render` mamy już parametr `request` (czyli wszystko to, co odbieramy od użytkownika przez internet) oraz plik szablonu `'blog/post_list.html'`. Ostatni parametr, który wygląda tak: `{}` jest miejscem, w którym możemy dodać parę rzeczy do wykorzystania w szablonie. Musimy nadać im nazwy (ale póki co będziemy trzymać się nazwy `'posts'` :)). Powinno to wyglądać tak: `{'posts': posts}`. Zwróć uwagę, że ta część przed `:` jest stringiem - powinna być w środku znaków `''`. Zatem ostatecznie nasz plik `blog/views.py` powinien wyglądać następująco: - from django.shortcuts import render - from django.utils import timezone - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - return render(request, 'blog/post_list.html', {'posts': posts}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` I to wszystko! Czas, żebyśmy wróciły do naszego szablonu i wyświetliły ten QuerySet! -Jeżeli chciałabyś poczytać troszkę więcej na temat QuerySetów w Django, powinnaś rzucić okiem tutaj: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ +Jeżeli chciałabyś poczytać troszkę więcej na temat QuerySetów w Django, powinnaś rzucić okiem tutaj: https://docs.djangoproject.com/en/1.7/ref/models/querysets/ diff --git a/pl/extend_your_application/README.md b/pl/extend_your_application/README.md index bec3a9bbeff..845a606239d 100755 --- a/pl/extend_your_application/README.md +++ b/pl/extend_your_application/README.md @@ -22,59 +22,61 @@ Zaczniemy od dodania linku wewnątrz pliku `blog/templates/blog/post_list.html`. {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} ``` - -Chcemy, aby tytuł wpisu był linkiem prowadzącym do strony ze szczegółami wpisu. Zmieńmy `

{{ post.title }}

` w link: +{% raw %}Chcemy, aby tytuł wpisu był linkiem prowadzącym do strony ze szczegółami wpisu. Zmieńmy `

{{ post.title }}

` na link:{% endraw %} ```html -

{{ post.title }}

+

{{ post.title }}

``` - -Czas wyjaśnić, co oznacza to tajemnicze `{% url 'blog.views.post_detail' pk=post.pk %}`. Jak można podejrzewać, zapis `{% %}` oznacza, że używamy tagów szablonu Django. Tym razem używamy takiego, który generuje za nas adres strony! +{% raw %}Czas by wyjaśnić co oznacza tajemnicze `{% url 'post_detail' pk=post.pk %}`. Jak można podejrzewać, zapis `{% %}` oznacza, że używamy tagów szablonu Django. Tym razem używamy takiego, który generuje za nas adres strony.{% endraw %} `blog.views.post_detail` to ścieżka do *widoku* `post_detail`, który chcemy stworzyć. Zwróć uwagę: `blog` to nazwa Twojej aplikacji (folder `blog`), `views` pochodzi od nazwy pliku `views.py`, zaś ostatnia część - `post_detail` - to nazwa naszego *widoku*. -Teraz, gdy przejdziemy pod adres http://127.0.0.1:8000/ ujrzymy błąd (co było do przewidzenia, bo nie mamy jeszcze ustawionego adresu URL ani *widoku* dla `post_detail`). Będzie to wyglądać tak: +Teraz, gdy wejdziemy na adres http://127.0.0.1:8000/ ujrzymy błąd (co było do przewidzenia, bo nie mamy jeszcze ustawionego adresu URL ani *widoku* dla `post_detail`). Będzie to wyglądać tak: -![Błąd NoReverseMatch](images/no_reverse_match2.png) +![Błąd NoReverseMatch][1] -Dodajmy adres URL w pliku `urls.py` dla naszego *widoku* `post_detail`! + [1]: images/no_reverse_match2.png + +## Utwórzmy URL dla poszczególnego wpisu -### URL: http://127.0.0.1:8000/post/1/ +Dodajmy adres URL w pliku `urls.py` dla naszego *widoku* `post_detail`! -Potrzebujemy stworzyć adres URL wskazujący na *widok* o nazwie `post_detail`, który wyświetli nam cały wpis. Dodaj wiersz `url(r'^post/(?P[0-9]+)/$', views.post_detail),` w pliku `blog/urls.py`. Powinna wyglądać tak: +Chcemy, aby nasz wpis i wszystkie informacje o nim, były widoczne pod tym adresem **URL**: http://127.0.0.1:8000/post/1/ - from django.conf.urls import include, url - from . import views +W pliku `blog/urls.py` stwórzmy adres URL wskazujący na *widok* o nazwie `post_detail`, który wyświetli nam cały wpis. Dodaj wiersz `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` w pliku `blog/urls.py`. Jego zawartość powinna wyglądać tak: - urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - ] +```python +from django.conf.urls import url +from . import views +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` -Strasznie to wygląda, ale spokojnie - wyjaśniamy: - zaczyna się od `^` again -- "początek" - `post/` oznacza tylko, że zaraz po początku adres URL powinien zawierać słowo **post** i **/**. Na razie nie jest źle. - `(?P[0-9]+)` - ta część jest trudniejsza. Oznacza ona, że Django pobierze wszystko, co umieścisz w tym miejscu i przekaże to do widoku w zmiennej o nazwie `pk`. `[0-9]` dodatkowo mówi nam, że może to być tylko cyfra, nie litera (czyli wszystko pomiędzy 0 a 9). `+` oznacza, że to musi być jedna lub więcej cyfr. Czyli coś takiego: `http://127.0.0.1:8000/post//` nie jest poprawne, ale już `http://127.0.0.1:8000/post/1234567890/` jest jak najbardziej w porządku! - `/` - znów potrzebujemy **/** - `$` - "koniec"! +Ten fragment `^post/(?P[0-9]+)/$` wygląda trochę przerażająco, ale spokojnie - wyjaśnijmy wszystko krok po kroku: - znów zaczyna się od `^` -- "początek" - `post/` oznacza tylko, że zaraz po początku adres URL powinien zawierać słowo **post** i **/**. Na razie nie jest źle. - `(?P[0-9]+)` - ta część jest trudniejsza. Oznacza ona, że Django pobierze wszystko, co umieścisz w tym miejscu i przekaże to do widoku w zmiennej o nazwie `pk`. `[0-9]` dodatkowo mówi nam, że może to być tylko cyfra, nie litera (czyli wszystko pomiędzy 0 a 9). `+` oznacza, że to musi być jedna lub więcej cyfr. Czyli coś takiego: `http://127.0.0.1:8000/post//` nie jest poprawne, ale już `http://127.0.0.1:8000/post/1234567890/` jest jak najbardziej w porządku! - `/` - znów potrzebujemy **/** - `$` - "koniec"! To oznacza, że gdy wpiszesz w przeglądarce adres `http://127.0.0.1:8000/post/5/`, Django zrozumie, że potrzebujesz *widoku* zwanego `post_detail` i przekaże temu *widokowi* informację, że `pk` jest równe `5`. `pk` to skrót od `primary key` (ang. klucz główny). Nazwa ta jest często używana w projektach Django. Ale możesz nazwać tę zmienną jak Ci się żywnie podoba (tylko pamiętaj: same małe litery i znak `_` zamiast spacji!). Dla przykładu, zamiast `(?P[0-9]+)` możemy mieć zmienną `post_id`. Wówczas ten fragment wyglądałby tak: `(?P[0-9]+)`. -OK! No to odświeżmy stronę http://127.0.0.1:8000/ +OK, dodałyśmy nowy wzorzec URL do `blog/urls.py`! Odświeżmy stronę: http://127.0.0.1:8000/ Bum! Znowu błąd! Tak jak myślałyśmy! +![AttributeError][2] -Bum! Znowu błąd! Tak jak myślałyśmy! - -![AttributeError](images/attribute_error2.png) + [2]: images/attribute_error2.png Pamiętasz, jaki jest następny krok? Oczywiście: dodanie widoku! -## Widok post_detail +## Dodajmy widok dla poszczególnego wpisu Tym razem nasz *widok* otrzymuje dodatkowy parametr `pk`. Nasz *widok* musi go "złapać", zgadza się? A więc zdefiniujmy funkcję tak: `def post_detail(request, pk):`. Zwróć uwagę, że musimy użyć dokładnie tej samej nazwy jak ta, której użyłyśmy w pliku urls (`pk`). Pominięcie tej zmiennej jest niepoprawne i spowoduje błąd! @@ -85,11 +87,15 @@ Teraz chcemy wyświetlić jeden i tylko jeden wpis na blogu. Aby to zrobić, mo Ale jest jeden problem. Jeśli nie istnieje żaden wpis (`Post`) zawierający przekazany `klucz główny` (`pk`) , to ujrzymy przepaskudny błąd! -![Błąd DoesNotExist](images/does_not_exist2.png) +![Błąd DoesNotExist][3] + + [3]: images/does_not_exist2.png Tak nie może być! Ale oczywiście Django ma dla nas coś, co rozwiąże ten problem za nas: `get_object_or_404`. W sytuacji, gdy nie istnieje żaden wpis (`Post`) z przekazaną wartością `pk`, wyświetli znacznie przyjemniejszą stronę (zwaną `Page Not Found 404` albo stroną błędu 404 - informującą, że dana strona nie została znaleziona). -![Nie znaleziono strony](images/404_2.png) +![Nie znaleziono strony][4] + + [4]: images/404_2.png Dobra wiadomość - możesz stworzyć własną stronę błędu 404 i upiększyć ją tak, jak tylko Ci się podoba. Ale teraz nie jest to super ważne, więc na razie pominiemy ten temat. @@ -97,70 +103,91 @@ OK, czas dodać nasz *widok* do naszego pliku `views.py`! Musimy otworzyć plik `blog/views.py` i dodać następujący kod: - from django.shortcuts import render, get_object_or_404 - +```python +from django.shortcuts import render, get_object_or_404 +``` w pobliżu innych linii zawierających `from`. Z kolei na końcu pliku dodajemy nasz *widok*: - def post_detail(request, pk): - post = get_object_or_404(Post, pk=pk) - return render(request, 'blog/post_detail.html', {'post': post}) - +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` -Właśnie tak. Czas na odświeżenie strony: http://127.0.0.1:8000/ +Czas na odświeżenie strony: http://127.0.0.1:8000/ +![Widok listy wpisów][5] -![Widok listy wpisów](images/post_list2.png) + [5]: images/post_list2.png Działa! Ale co się stanie, gdy klikniesz na link w tytule wpisu? -![Błąd TemplateDoesNotExist](images/template_does_not_exist2.png) +![Błąd TemplateDoesNotExist][6] + + [6]: images/template_does_not_exist2.png O nie! Kolejny błąd! Ale wiemy już, jak sobie z nim poradzić, prawda? Musimy dodać szablon! +## Stwórzmy szablon dla poszczególnego wpisu + W folderze `blog/templates/blog` stwórzmy plik o nazwie `post_detail.html`. -Jego treść będzie wyglądać tak: +Efekt będzie wyglądał tak: ```html {% extends 'blog/base.html' %} {% block content %} - {% if post.published_date %} -
- {{ post.published_date }} -
- {% endif %} -

{{ post.title }}

-

{{ post.text|linebreaks }}

+
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
{% endblock %} ``` - Znów rozszerzamy `base.html`. W bloku `content` chcemy wyświetlić datę opublikowania wpisu (o ile istnieje), tytuł oraz treść. Ale jest kilka ważnych rzeczy do omówienia, nieprawdaż? -`{% if ... %} ... {% endif %}` jest znacznikiem szablonu, którego możemy użyć do sprawdzenia jakiegoś warunku (pamiętasz `if... else ..` z rozdziału **Wprowadzenie do Pythona**?). W naszym scenariuszu chcemy sprawdzić, czy data publikacji wpisu (`published_date`) nie jest pusta. +{% raw %}`{% if ... %} ... {% endif %}` jest znacznikiem szablonu, którego możemy użyć do sprawdzenia jakiegoś warunku (pamiętasz `if... else ..` z rozdziału **Wprowadzenie do Pythona**?). W naszym scenariuszu chcemy sprawdzić, czy data publikacji wpisu (`published_date`) nie jest pusta.{% endraw %} OK, możemy teraz odświeżyć naszą stronę i sprawdzić, czy strona `Page not found` już znikła. -![Strona ze szczegółami wpisu](images/post_detail2.png) +![Strona ze szczegółami wpisu][7] + + [7]: images/post_detail2.png Hura! Działa! ## Jeszcze jedno: czas na wdrożenie! -Byłoby dobrze, aby zobaczyć, jeśli witryna nadal będzie nad Heroku, prawa? Spróbuj ponownie wdrażania. Jeśli nie pamiętasz jak to zrobić, sprawdź na końcu rozdziału [Wdrażanie](../deploy/README.md): - -```bash -$ git status -... -$ git add -A . -$ git status -... -$ git commit -m "Dodane widoki do strony" -... -$ git push heroku master -``` +Dobrze byłoby sprawdzić czy nasza strona dalej będzie dobrze działać na PythonAnywhere, prawda? Spróbuj ponownie wdrożyć projekt. + + $ git status + $ git add --all . + $ git status + $ git commit -m "Dodano widok i szablon dla poszczegolnego wpisu na stronie." + $ git push + + +* Potem, w konsoli [PythonAnywhere Bash][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +* Na koniec, przejdźmy do podstrony [Web tab][9] i wciśnijmy **Reload** (ang. odśwież). + [9]: https://www.pythonanywhere.com/web_app_setup/ I to już wszystko! Gratulacje :) diff --git a/pl/how_the_internet_works/README.md b/pl/how_the_internet_works/README.md index f97a7e7a3a2..a56317fac43 100755 --- a/pl/how_the_internet_works/README.md +++ b/pl/how_the_internet_works/README.md @@ -2,11 +2,11 @@ > Niniejszy rozdział został zainspirowany prelekcją "Jak działa internet" Jessiki McKellar (http://web.mit.edu/jesstess/www/). -Założymy się, że używasz internetu codziennie. Ale czy wiesz co dzieje się kiedy wpisujesz w oknie przeglądarki adres taki jak http://djangogirls.org i naciskasz `enter`? +Możemy się założyć, że używasz go każdego dnia. Ale czy naprawdę wiesz co się dzieje, gdy wpisujesz w przeglądarce adres https://djangogirls.org i wciskasz `enter`? -Aby zrozumieć jak działa internet powinnaś najpierw dowiedzieć się czym tak naprawdę jest strona internetowa, a jest ona tylko zbiorem plików zapisanych na dysku twardym. Dokładnie tak samo jak filmy, muzyka czy zdjęcia na Twoim komputerze. Aczkolwiek strony internetowe różnią się od nich tym, że zawierają kod komputerowy zwany HTML. +Aby zrozumieć jak działa internet powinnaś najpierw dowiedzieć się czym tak naprawdę jest strona internetowa, a jest ona tylko zbiorem plików zapisanych na dysku twardym. Tak samo jak twoje zdjęcia, muzyka czy filmy. Aczkolwiek strony internetowe różnią się od nich tym, że zawierają kod komputerowy zwany HTML. -Jeśli do tej pory nie miałaś styczności z programowaniem, na początku może być Ci trudno zrozumieć czym jest HTML, ale Twoje przeglądarki (takie jak Chrome, Safari, Firefox itp.) go uwielbiają. Przeglądarki internetowe są zaprojektowane i stworzone tak, aby rozumieć ten kod, wykonywać zawarte w nim instrukcje i wyświetlać wszystkie pliki składające się na stronę internetową w taki sposób jak Ty tego chcesz. +Jeśli nie miałaś wcześniej do czynienia z programowaniem, może być Ci na początku trudno zrozumieć HTML, ale przeglądarki internetowe (takie jak Chrome, Safari, Firefox itd.) uwielbiają go. Zostały one zaprojektowane po to, by czytać ten kod, przetwarzać go i postępować zgodnie z jego instrukcjami. Prezentują pliki, z których składa się Twoja strona - by wyglądała dokładnie tak jak Ty chcesz. Tak jak w przypadku każdego innego pliku, musimy umiejscowić pliki HTML na dysku twardym. Do przechowywania plików HTML używamy specjalnych, potężnych komputerów zwanych *serwerami (ang. servers)*. Serwery nie posiadają monitorów, myszy ani klawiatur, ponieważ ich głownym celem jest przechowywanie danych i serwowanie ich. Dlatego są one nazywane *serwerami* -- ponieważ służą do *serwowania* danych. @@ -14,32 +14,40 @@ Ok, ale pewnie chciałabyś wiedzieć jak wygląda internet? Narysowaliśmy Ci schemat Internetu! Wygląda tak: -![Rysunek 1.1](images/internet_1.png) +![Rysunek 1.1][1] -Wygląda dość chaotycznie, prawda? W rzeczywistości jest to sieć połączonych między sobą maszyn (wspomnianych wyżej *serwerów*). Setki tysięcy maszyn! Wiele, wiele kilometrów kabli na całym świecie! Możesz odwiedzić stronę mapy podwodnych kabli (http://submarinecablemap.com/) aby zobaczyć, jak skomplikowana jest to sieć. Oto zrzut ekranu ze strony internetowej: + [1]: images/internet_1.png -![Rysunek 1.2](images/internet_3.png) +Wygląda dość chaotycznie, prawda? W rzeczywistości jest to sieć połączonych między sobą maszyn (wspomnianych wyżej *serverów*). Setki tysięcy maszyn! Wiele, wiele kilometrów kabli na całym świecie! Możesz wejść na stronę Submarine Cable Map (http://submarinecablemap.com) i sama zobaczyć jak skomplikowana jest ta sieć. Oto zrzut ekranu ze strony internetowej: -To fascynujące, prawda? Ale oczywiście niemożliwe jest stworzenie bezpośredniego połączenia kablowego między każdym komputerem w internecie. Więc aby dostać się do maszyny dostępnej w internecie (na przykład tej, na której zapisane jest http://djangogirls.org) potrzebujemy wykonać zapytanie przez wiele, wiele różnych maszyn. +![Rysunek 1.2][2] + + [2]: images/internet_3.png + +To fascynujące, prawda? Ale oczywiście niemożliwe jest stworzenie bezpośredniego połączenia kablowego między każdym komputerem w internecie. Więc aby dostać się do maszyny dostępnej w internecie (na przykład tej, na której zapisane jest https://djangogirls.org) potrzebujemy wykonać zapytanie przechodzące przez wiele, wiele różnych maszyn. Wygląda to tak: -![Rysunek 1.3](images/internet_2.png) +![Rysunek 1.3][3] + + [3]: images/internet_2.png + +Wyobraź sobie, że po wpisaniu https://djangogirls.org, wysyłasz list o treści: "Drogie Django Girls, chcę zobaczyć stronę djangogirls.org. Wyślijcie ją do mnie, proszę! " -Wyobraź sobie, że po wpisaniu http://djangogirls.org, wysyłasz list o treści: "Drogie Django Girls, chcę zobaczyć stronę djangogirls.org. Wyślijcie ją do mnie, proszę! " +List trafia do urzędu pocztowego najbliżej Ciebie. Potem idzie do drugiego urzędu, który znajduje się trochę bliżej Twojego adresata. Potem do kolejnego, kolejnego, kolejnego, aż w końcu zostanie doręczony do miejsca przeznaczenia. Ciekawa rzecz - jeśli wyślesz wiele listów (*pakietów danych*) do tego samego adresata, mogą przejść przez zupełnie inne urzędy pocztowe (*routery*). To zależy od tego w jaki sposób zostaną rozdzielone w każdym urzędzie. -List trafia do urzędu pocztowego najbliżej Ciebie. Następnie trafia do kolejnego urzędu bliżej adresata, i do następnego, i następnego, aż zostanie doręczony do miejsca przeznaczenia. Jeśli chodzi o strony internetowe, sytuacja jest bardzo podobna. Różnica polega na tym, że nawet jeśli wysyłasz listy (*pakiety danych*) do tego samego miejsca, to każdy z nich może "przejść" przez zupełnie inne pośrednie urzędy pocztowe (*routery*). +![Rysunek 1.4][4] -![Rysunek 1.4](images/internet_4.png) + [4]: images/internet_4.png -Tak, to jest tak proste. Wysyłasz wiadomości i oczekujesz jakiejś odpowiedzi. Oczywiście, zamiast papieru i długopisu używasz bitów danych, ale koncepcja jest dokładnie ta sama! +Tak, to takie proste. Wysyłasz wiadomości i oczekujesz jakiejś odpowiedzi. Oczywście, zamiast papieru i długopisu używasz bitów danych, ale koncepcja jest dokładnie taka sama! -Zamiast adresów z nazwą ulicy, miastem, kodem pocztowym oraz nazwą kraju, używa się adresów IP. Twój komputer najpierw prosi serwer DNS (system nazw domenowych, ang. DNS - Domain Name System) o przetłumaczenie djangogirls.org na adres IP. Działa to trochę jak stare książki telefoniczne, gdzie można było poszukać nazwiska i imienia w celu znalezienia konkretnej osoby, jej numeru telefonu i adresu. +Zamiast adresów z nazwą ulicy, miastem, kodem pocztowym oraz nazwą kraju, używa się adresów IP. Twój komputer najpierw pyta serwera DNS (system nazw domenowych, ang. DNS - Domain Name System) o przetłumaczenie djangogirls.org na adres IP. Działa to podobnie do dawnych książek telefonicznych, w których mogłaś poszukać adresu czy numeru po nazwisku osoby, z którą chciałaś się skontaktować. -Listy muszą spełniać konkretne warunki, żeby zostały poprawnie doręczone: muszą posiadać adres, znaczek itd. Muszą one też być napisane językiem zrozumiałym dla odbiorcy. Tak samo jest z *pakietami danych*, które wysyłasz w celu obejrzenia strony internetowej: używasz protokołu zwanego HTTP (Hypertext Transfer Protocol). +Listy muszą spełniać konkretne warunki, żeby zostały poprawnie doręczone: muszą posiadać adres, znaczek itd. Muszą być też napisane językiem zrozumiałym dla odbiorcy. To samo dotyczy *pakietów danych*, które wysyłasz, by zobaczyć jakąś stronę. Używany jest protokół HTTP (Hypertext Transfer Protocol). -Ogólnie rzecz ujmując, aby mieć stronę internetową musisz mieć *serwer* (komputer) gdzie będzie ona funkcjonować. *Serwer* oczekuje na nadchodzące *żądania* (listy, które proszą o wysłanie Twojej strony) i odsyła odpowiedź z Twoją stroną internetową (jako kolejny list). +Tak więc, ogólnie rzecz ujmując, jeśli chcesz mieć swoją stronę internetową musisz mieć *serwer* (komputer), gdzie będzie ona funkcjonować. Gdy *serwer* odbiera przychodzące *żądania* (Twój list), wysyła Ci w odpowiedzi Twoją stronę (kolejny list). -Zapytasz pewnie co robi Django, skoro masz przed sobą tutorial Django. Kiedy odpowiadasz na żądanie, nie chcesz aby każdy dostawał tę samą odpowiedź, prawda? Zdecydowanie lepiej jest, jeśli listy są spersonalizowane i skierowane do konkretnej osoby - konkretnie do tej, która napisała do Ciebie. Django pomaga Ci w tworzeniu tych spersonalizowanych, interesujących listów. :) +Zapytasz pewnie co robi Django, skoro masz przed sobą tutorial Django. Kiedy odpowiadasz na żądanie, nie chcesz aby każdy dostawał tę samą odpowiedź, prawda? Zdecydowanie lepiej jest jeśli listy są spersonalizowane i skierowane do konkretnej osoby, do tej, która napisała do Ciebie. Django pomaga Ci w tworzeniu tych spersonalizowanych, interesujących listów :). -Wystarczy teorii, zabieramy się za tworzenie! +Wystarczy teorii, zabieramy się za tworzenie! \ No newline at end of file diff --git a/pl/how_the_internet_works/images/internet_4.png b/pl/how_the_internet_works/images/internet_4.png index 05f1aed562f..2661cec1b61 100644 Binary files a/pl/how_the_internet_works/images/internet_4.png and b/pl/how_the_internet_works/images/internet_4.png differ diff --git a/pl/html/README.md b/pl/html/README.md index 9f5b4a5c41c..16cc9c71083 100755 --- a/pl/html/README.md +++ b/pl/html/README.md @@ -10,7 +10,7 @@ Format szablonów Django wykorzystuje język HTML (ten sam, o którym wspominali HTML to prosty kod interpretowany przez Twoją przeglarkę - taką jak Chrome, Firefox czy Safari - w celu wyświetlenia strony dla użytkownika. -HTML to skrót od "HyperText Markup Language". **HyperText** oznacza typ tekstu, który umożliwia łączenie stron za pomocą łączy (hyperlinków, albo po prostu linków). **Markup** oznacza, że używamy tego kodu w dokumencie, żeby przekazać komuś informację (w naszym przypadku przeglądarce), jak zinterpretować daną stronę. Kod HTML składa się ze **znaczników ** (tagów), a każdy z nich zaczyna się od `<` i kończy na`>`. Za pomocą znaczników oznaczamy **elementy**. +HTML to skrót od "HyperText Markup Language". **HyperText** oznacza, że jest to tekst, który wspiera hyperlinki - czyli po prostu linki między stronami. **Markup** oznacza, że używamy tego kodu w dokumencie, żeby przekazać komuś informacje (w naszym przypadku przeglądarce), jak zinterpretować daną stronę. Kod HTML składa się ze **znaczników ** (tagów), a każdy z nich zaczyna się od `<` i kończy na`>`. Za pomocą znaczników oznaczamy **elementy**. ## Twój pierwszy szablon! @@ -31,21 +31,26 @@ Popatrz, jak Twoja strona wygląda teraz: http://127.0.0.1:8000/ > Jeżeli nadal otrzymujesz błąd `TemplateDoesNotExists`, spróbuj uruchomić serwer ponownie. Przejdź do wiersza poleceń, zatrzymaj serwer wciskając Ctrl+C (klawisze Control i C równocześnie), a następnie uruchom go jeszcze raz poleceniem `python manage.py runserver`. -![Rysunek 11.1](images/step1.png) +![Rysunek 11.1][1] + + [1]: images/step1.png Nie ma błędu! Gratulacje :) Niestety, twoja aplikacja nie wyświetla niczego poza pustą stroną, ponieważ Twój szablon również jest pusty. Naprawmy to. Dodaj następującą treść w pliku z szablonem: - -

Hej!

-

Działa!

- - +```html + +

Hej!

+

Działa!

+ +``` I jak twoja strona wygląda teraz? Kliknij, żeby się dowiedzieć: http://127.0.0.1:8000/ -![Rysunek 11.2](images/step3.png) +![Rysunek 11.2][2] + + [2]: images/step3.png Zadziałało! Dobra robota :) @@ -64,20 +69,23 @@ Używamy znacznika ``, aby poinformować przeglądarkę o konfiguracji str Przykładowo, element tytułu strony możesz umieścić wewnątrz ``, o tak: - - - Ola's blog - - -

Hi there!

-

It works!

- - - +```html + + + Blog Oli + + +

Hej!

+

Działa!

+ + +``` Zapisz plik i odśwież swoją stronę. -![Rysunek 11.3](images/step4.png) +![Rysunek 11.3][3] + + [3]: images/step4.png Zauważyłaś, że przeglądarka zrozumiała, że "Ola's blog" jest tytułem Twojej strony? Zinterpretowała ona `Ola's blog` i umieściła tekst w pasku tytułu twojej przeglądarki (będzie on również używany m.in. w zakładkach). @@ -97,61 +105,66 @@ Teraz nieco się pobawmy i spróbujmy dostosować nasz szablon! Oto kilka znaczn * `tekst` dodaje wyróżnienie twojego tekstu * `text` jeszcze mocniej wyróżnia twój tekst * `
` to przejście do nowej linii (wewnątrz br nie wstawiamy niczego) -* `link` tworzy link +* `link` tworzy link * `
  • pierwsza pozycja
  • druga pozycja
` tworzy listę, taką samą jak ta! * `
` tworzy sekcję na stronie Poniżej przykład pełnego szablonu: - - - Django Girls blog - - - - -
-

published: 14.06.2014, 12:14

-

My first post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

-
- -
-

published: 14.06.2014, 12:14

-

My second post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

-
- - - +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` Stworzyliśmy tutaj trzy sekcje `div`. -* Pierwszy `div` zawiera tytuł naszego wpisu na blogu - tworzy go nagłówek wraz z linkiem +* Pierwszy `div` zawiera w sobie tytuł naszego bloga - jest to nagłówek i link. * Kolejne dwa elementy `div` zawierają nasze wpisy wraz z opublikowaną datą, `h2` z klikalnym tytułem wpisu oraz dwa elementy `p` (akapity) z tekstem, jeden z datą i drugi z treścią naszego wpisu. Daje nam to taki efekt: -![Rysunek 11.4](images/step6.png) +![Rysunek 11.4][4] + + [4]: images/step6.png Hura! Ale jak do tej pory, nasz szablon wyświetla dokładnie **tą samą treść**. Tymczasem wspominałyśmy wcześniej, że szablony umożliwiają nam wyświetlenie **różnych** treści w **takim samym formacie**. Chcemy wyświetlić prawdziwe wpisy dodane w naszym panelu admina Django - i tym się teraz zajmiemy. -## Jeszcze jedno +## Jeszcze jedna rzecz: wdrożenie na serwer! + +Byłoby fajnie, gdybyśmy mogli to wszystko zobaczyć "na żywo" w Internecie, a nie tylko u siebie w komputerze. Czas na wdrożenie na serwer PythonAnywhere: -Byłoby dobrze zobaczyć, czy Twoja strona będzie nadal dobrze działała na Heroku, prawda? Spróbujmy zaktualizować naszą stronę na serwerze. +### Zapisz zmiany w historii i wrzuć swój kod na GitHuba -Po pierwsze, zobaczmy, jakie pliki zostały zmienione od ostatniej aktualizacji: +Po pierwsze, zobaczmy, jakie pliki zostały zmienione od ostatniej aktualizacji (wpisz następujące polecenie lokalnie w wierszu poleceń, nie na PythonAnywhere): $ git status -Teraz powiedzmy `git`owi aby dodał wszystkie zmiany z aktualnego folderu: +Upewnij się, że jesteś w folderze `djangogirls` i powiedz `git`owi aby dodał wszystkie zmiany z aktualnego folderu: - $ git add -A . + $ git add --all . > **Uwaga:** `-A` (skrót od "all", czyli "wszystko") oznacza, że `git` weźmie pod uwagę pliki, które usunęłaś (domyślnie rozpoznaje zmiany tylko w nowych lub już istniejących plikach). Pamiętaj również (vide rozdział 3), że `.` oznacza aktualny katalog. @@ -168,9 +181,29 @@ Już blisko do końca. Teraz czas poprosić gita, aby zapisał te zmiany w histo > **Uwaga:** Nie zapomnij umieścić informacji o zmianach w cudzysłowie (" "). -Gdy już to zrobimy, możemy wreszcie zapisać zmiany (zrobić tzw. push) na naszej stronie na Heroku: +Jak już wszystko to zrobimy, możemy wysłać (push) nasze zmiany na Githuba: + + git push + + +### Prześlij nową wersję kodu do PythonAnywhere i ponownie załaduj swoją stronę + +* Otwórz [stronę konsol na PythonAnywhere][5] i przejdź do swojej **Bash console** (czyli po polsku "konsoli Bash") albo otwórz nową. Wpisz do niej: + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +I obserwuj jak Twój kod się ściąga. Jeśli chcesz sprawdzić czy już się pobrał, możesz przejść do zakładki **Files tab** i przeglądnąć swój kod na PythonAnywhere. - $ git push heroku master +* Na koniec przeskocz do zakładki [Web tab][6] i naciśnij **Reload**. + [6]: https://www.pythonanywhere.com/web_app_setup/ -I to powinno wystarczyć! Gdy Heroku skończy, możesz śmiało odświeżyć swoją stronę w przeglądarce. Zmiany powinny być widoczne! +I to powinno wystarczyć! Możesz śmiało odświeżyć swoją stronę w przeglądarce! Zmiany powinny być widoczne :) diff --git a/pl/installation/README.md b/pl/installation/README.md new file mode 100755 index 00000000000..8180aa6cdec --- /dev/null +++ b/pl/installation/README.md @@ -0,0 +1,49 @@ +# Jeśli robisz ten kurs w domu + +Jeśli robisz ten kurs w domu, a nie w trakcie jednego z [warsztatów Django Girls](https://djangogirls.org/events/), możesz pominąć ten rozdział i przejść od razu do [Jak działa internet?](../how_the_internet_works/README.md) + +Informacje, które się tutaj znajdują, napotkasz również w kolejnych rozdziałach. W trakcie warsztatów Django Girls, instalujemy wszystko w trakcie jednego wieczoru, żeby następnego dnia nie musieć się o to martwić, więc zebraliśmy wszystkie potrzebne informacje w jedno miejsce. + +Jeśli chcesz, też możesz zainstalować wszystko od razu. Ale jeśli wolisz zacząć naukę już teraz bez instalowania najpierw kilku nowych rzeczy na swoim komputerze, pomiń ten rozdział. Wszystko wytłumaczymy później. + +Powodzenia! + +# Instalacja + +Podczas warsztatów będziesz budować bloga, ale abyś mogła zacząć programować, musimy najpierw zainstalować kilka rzeczy. + +# Zainstaluj Pythona + +{% include "/python_installation/instructions.md" %} + +# Utwórz środowisko wirtualne i zainstaluj Django + +{% include "/django_installation/instructions.md" %} + +# Zainstaluj edytor kodu + +{% include "/code_editor/instructions.md" %} + +# Zainstaluj Gita + +{% include "/deploy/install_git.md" %} + +# Utwórz konto na GitHubie + +Wejdź na stronę [GitHub.com](https://www.github.com) i załóż darmowe konto użytkownika. + +# Utwórz konto na PythonAnywhere + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Zacznij czytać + +Gratulacje, jesteś gotowa, by zacząć pracę! Jeśli masz trochę czasu przed warsztatami, możesz przeczytać początkowe rozdziały: + + * [Jak działa internet](../how_the_internet_works/README.md) + + * [Wprowadzenie do wiersza poleceń](../intro_to_command_line/README.md) + + * [Wprowadzenie do Pythona](../intro_to_command_line/README.md) + + * [Czym jest Django?](../django/README.md) diff --git a/pl/intro_to_command_line/README.md b/pl/intro_to_command_line/README.md index ddad0dbb0aa..8e045bc91e6 100755 --- a/pl/intro_to_command_line/README.md +++ b/pl/intro_to_command_line/README.md @@ -2,13 +2,15 @@ Za chwilę napiszesz swoją pierwszą linijkę kodu. Jesteś już podekscytowana? :) -**Pozwól, że przedstawimy Ci Twojego pierwszego przyjaciela: wiersz poleceń!** +**Pozwól, że przedstawimy Ci, Twojego pierwszego przyjaciela: wiersz poleceń!** -Następujące kroki pokażą Ci, jak wykorzystać tajemnicze czarne okno, którego używają wszyscy hakerzy. Na początku może to wyglądać nieco przerażająco, ale tak naprawdę to tylko zachęta do wpisywania komend. +Następujące kroki pokażą Ci, jak wykorzystać tajemnicze czarne okno, które używają wszyscy hakerzy. Na początku może to wyglądać nieco przerażająco ale tak naprawdę to tylko zachęta do wpisywania komend. + +> **Uwaga** Podczas tego kursu będziemy używać terminów "katalog" i "folder" zamiennie, ponieważ oznaczają one tę samą rzecz. ## Czym jest wiersz poleceń? -Okno zwane zazwyczaj **wierszem poleceń** lub **interfejsem wiersza poleceń** jest aplikacją tekstową służącą do przeglądania, obsługi i operowania plikami na Twoim komputerze (podobnie jak np. Eksplorator Windows lub Finder na Macu, ale bez interfejsu graficznego). Inne nazwy dla wiersza poleceń to *cmd*, *CLI*, *prompt*, *konsola* lub *terminal*. +Okno zwane **wierszem poleceń** lub **interfejsem wiersza poleceń** jest aplikacją tekstową służącą do przeglądania, obsługi i operowania plikami na Twoim komputerze. Podobnie jak np. Eksplorator Windows lub Finder na Macu, ale bez interfejsu graficznego. Inne nazwy dla wiersza poleceń to *cmd*, *CLI*, *prompt*, *konsola* lub *terminal*. ## Uruchamiamy interfejs wiersza poleceń @@ -33,36 +35,36 @@ Teraz powinnaś zobaczyć białe lub czarne okno, które czeka na Twoje poleceni Jeżeli używasz Maca lub Linuksa, powinnaś zobaczyć `$`, tak jak poniżej: $ - + W systemie Windows ujrzysz znak `>`, o tak: > - + Każde polecenie będzie poprzedzone tym znakiem oraz jedną spacją, ale nie musisz ich przepisywać. Twój komputer zrobi to za Ciebie :) > Jedna mała uwaga: w Twoim przypadku prompt może być poprzedzony czymś jeszcze, np. `C:\Users\ola>` lub `Olas-MacBook-Air:~ ola$` i jest to w 100% poprawne. W tym tutorialu uprościmy sposób zapisu do minimum. -## Twoja pierwsza komenda! +## Twoja pierwsza komenda! Zacznijmy od czegoś łatwego. Wpisz to polecenie: $ whoami - + lub > whoami - + A następnie wciśnij `enter`. Oto rezultat: $ whoami olasitarska + - -Jak widzisz, komputer właśnie wyświetlił Twoją nazwę użytkownika. Prawda, że sprytne? :) +Jak widzisz, komputer właśnie wyświetlił Twoją nazwę użytkownika. Prawda, że sprytne?:) > Staraj się zawsze przepisywać polecenia zamiast je kopiować i wklejać. W ten sposób zapamiętasz więcej! @@ -72,99 +74,92 @@ Każdy system operacyjny ma nieco inny zestaw komend dostępnych w wierszu polec ### Bieżący katalog -Byłoby miło dowiedzieć się, gdzie teraz jesteśmy, co? No to sprawdźmy. Wpisz poniższe polecenie i wciśnij `enter`: +Miło byłoby dowiedzieć się, gdzie teraz jesteśmy, co? No to sprawdźmy. Wpisz poniższe polecenie i wciśnij `enter`: $ pwd /Users/olasitarska - + Jeżeli używasz Windows: > cd C:\Users\olasitarska + +Prawdopodobnie ujrzysz coś podobnego na swoim komputerze. Kiedy otwierasz wiersz poleceń, zwykle jest on uruchamiany w folderze głównym Twojego konta użytkownika. -Prawdopodobnie ujrzysz coś podobnego na swoim komputerze. Kiedy otwierasz wiersz poleceń, zwykle jest on uruchamiany w miejscu folderu głównego Twojego konta użytkownika. - -> Ciekawostka: `pwd` oznacza print working directory czyli w wolnym tłumaczeniu "wypisz folder roboczy" +> Uwaga: 'pwd' pochodzi od angielskiego skrótu 'print working directory', czyli wyświetl katalog roboczy - ten, w którym się aktualnie znajdujemy. * * * ### Lista plików i folderów Co znajduje się w środku? Fajnie byłoby się tego dowiedzieć. Sprawdźmy: -``` -$ ls -Applications -Desktop -Downloads -Music -... -``` + $ ls + Applications + Desktop + Downloads + Music + ... + Windows: -``` -> dir -Directory of C:\Users\olasitarska -05/08/2014 07:28 PM
Applications -05/08/2014 07:28 PM Desktop -05/08/2014 07:28 PM Downloads -05/08/2014 07:28 PM Music -... -``` + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + * * * ### Zmiana katalogu bieżącego -A może by tak przejść do naszego folderu Pulpitu? - -$ cd Desktop +Przejdźmy teraz do naszego folderu Pulpit: + $ cd Desktop + Windows: -``` -> cd Desktop -``` + > cd Desktop + Sprawdźmy, czy coś się faktycznie zmieniło: -``` -$ pwd -/Users/olasitarska/Desktop -``` + $ pwd + /Users/olasitarska/Desktop + Windows: -``` -> cd -C:\Users\olasitarska\Desktop -``` + > cd + C:\Users\olasitarska\Desktop + Tak, to tutaj! -> PRO tip: gdy wpiszesz `cd D` i wciśniesz przycisk `tab` na klawiaturze, wiersz poleceń automatycznie uzupełni resztę nazwy, dzięki czemu będziesz mogła nawigować szybciej. Jeżeli istnieje więcej niż jeden folder o nazwie zaczynającej się na "D", wciśnij `tab` dwukrotnie, aby wyświetlić listę możliwości. +> PRO tip: gdy wpiszesz `cd D` i wciśniesz przycisk `Tab` na klawiaturze, wiersz poleceń automatycznie uzupełni resztę nazwy, dzięki czemu będziesz mogła nawigować szybciej. Jeżeli istnieje więcej niż jeden folder o nazwie zaczynającej się na "D", wciśnij `Tab` dwukrotnie, aby wyświetlić listę możliwości. * * * ### Tworzenie folderu -Co powiesz na stworzenie folderu Django Girls na swoim pulpicie? Zrób to w ten sposób: +Co powiesz na stworzenie folderu cwiczenie na swoim pulpicie? Zrób to w ten sposób: -``` -$ mkdir djangogirls -``` + $ mkdir cwiczenie + Windows: -``` -> mkdir djangogirls -``` + > mkdir cwiczenie + -To niepozorne polecenie doda do twojego pulpitu folder o nazwie `djangogirls`. Możesz sprawdzić, czy na pewno został tam dodany - spójrz na swój pulpit albo uruchom polecenie `ls`/`dir`! Spróbuj :) +To niepozorne polecenie doda do Twojego pulpitu folder o nazwie `cwiczenie`. Możesz sprawdzić, czy na pewno został tam dodany - spójrz na swój pulpit albo uruchom polecenie `ls` lub `dir`! Spróbuj :) > PRO tip: Jeżeli nie chcesz w kółko wpisywać tych samych poleceń, wciśnij na klawiaturze klawisz ze `strzałką w górę` i `strzałką w dół` aby przewinąć listę poprzednio użytych poleceń. @@ -172,25 +167,23 @@ To niepozorne polecenie doda do twojego pulpitu folder o nazwie `djangogirls`. M ### Ćwiczenie! -Małe wyzwanie dla Ciebie: wewnątrz świeżo utworzonego katalogu `djangogirls` stwórz katalog o nazwie `test`. Użyj poleceń `cd` i `mkdir`. +Małe wyzwanie dla Ciebie: wewnątrz świeżo utworzonego katalogu `cwiczenie` stwórz katalog o nazwie `test`. Użyj poleceń `cd` i `mkdir`. #### Rozwiązanie: -``` -$ cd djangogirls -$ mkdir test -$ ls -test -``` + $ cd cwiczenie + $ mkdir test + $ ls + test + Windows: -``` -> cd djangogirls -> mkdir test -> dir -05/08/2014 07:28 PM test -``` + > cd cwiczenie + > mkdir test + > dir + 05/08/2014 07:28 PM test + Gratulacje! :) @@ -202,70 +195,62 @@ Nie chcemy zostawić bałaganu, a zatem wyrzućmy wszystko, co do tej pory zrobi Najpierw musimy wrócić do Pulpitu: -``` -$ cd .. -``` + $ cd .. + Windows: -``` -> cd .. -``` + > cd .. + Wykonanie `cd` wraz z `..` przeniesie Cię do katalogu nadrzędnego (czyli tego, w którym znajduje się Twój aktualny katalog). Sprawdź, gdzie jesteś: -``` -$ pwd -/Users/olasitarska/Desktop -``` + $ pwd + /Users/olasitarska/Desktop + Windows: -``` -> cd -C:\Users\olasitarska\Desktop -``` -A teraz czas na usunięcie katalogu `djangogirls`. + > cd + C:\Users\olasitarska\Desktop + + +Teraz czas usunąć katalog `cwiczenie`: > **Uwaga**: Usuwanie plików za pomocą `del`, `rmdir` lub `rm` jest nieodwracalne. To znaczy, że *Twoje pliki zostaną bezpowrotnie utracone*! Tak więc bądź ostrożna z tymi poleceniami. -``` -$ rm -r djangogirls -``` + $ rm -r cwiczenie + Windows: -``` -> rmdir /S djangogirls -djangogirls, Are you sure ? Y -``` + > rmdir /S cwiczenie + cwiczenie, Are you sure ? Y + Gotowe! Dla pewności, że został on naprawdę usunięty, sprawdźmy to: -``` -$ ls -``` + $ ls + Windows: -``` -> dir -``` + + > dir + ### Wyjście -To na razie tyle! Możesz teraz spokojnie zamknąć wiersz poleceń. To co, zrobimy to po hakersku? :) +To na razie tyle! Możesz teraz spokojnie zamknąć wiersz poleceń. To co, zrobimy to jak prawdziwy haker?:) -``` -$ exit -``` + $ exit + Windows: -``` -> exit -``` + > exit + Fajnie, nie? :) @@ -287,8 +272,8 @@ To tylko garstka wszystkich poleceń, z których możesz skorzystać w wierszu p Jeżeli temat Cię zainteresował, to [ss64.com][1] zawiera kompletny spis poleceń dla wszystkich systemów operacyjnych. -[1]: http://ss64.com + [1]: http://ss64.com ## Gotowa? -No to poznajmy Pythona! +No to poznajmy Pythona! \ No newline at end of file diff --git a/pl/python_installation/README.md b/pl/python_installation/README.md index 6c69bd4ded3..da17c58b8d4 100755 --- a/pl/python_installation/README.md +++ b/pl/python_installation/README.md @@ -4,63 +4,10 @@ Nareszcie tutaj! Ale najpierw porozmawiajmy o tym, czym jest Python. Python jest niezwykle popularnym językiem programowania, który może służyć do tworzenia stron internetowych, gier, oprogramowania naukowego, grafiki i wielu, wielu innych rzeczy. -Początki Pythona sięgają późnych lat 80., a jego głównym założeniem jest czytelność, dzięki której kod jest łatwy do zrozumienia przez ludzi (a nie tylko maszyny!). Z tego powodu Python jest uważany za znacznie prostszy od innych języków programowania. Dzięki temu łatwo się go nauczyć, ale niech Cię to nie zmyli - Python jest naprawdę potężnym językiem! +Początki Pythona sięgają późnych lat 80., a jego głównym założeniem jest czytelność, dzięki której kod jest łatwy do zrozumienia przez ludzi (a nie tylko przez komputery!). Z tego powodu Python jest uważany za znacznie prostszy od innych języków programowania. Dzięki temu łatwo się go nauczyć, ale niech Cię to nie zmyli - Python jest naprawdę potężnym językiem! # Instalowanie Pythona -> Niniejszy podrozdział powstał w oparciu o kurs Geek Girls Carrots (http://django.carrots.pl/) +> **Uwaga** Jeśli zrobiłaś to już wcześniej w rozdziale 'Instalacja', nie ma potrzeby instalować Pythona po raz drugi - przejdź od razu do następnego rozdziału! -Django został w napisany w Pythonie. Potrzebujemy Pythona, żeby móc zrobić cokolwiek w Django. Zacznijmy zatem od zainstalowania go! Potrzebujemy zainstalować Pythona 3.4, dlatego jeżeli masz już zainstalowaną jakąkolwiek starszą wersję, będziesz musiała ją uaktualnić. - -### Windows - -Możesz ściągnąć Pythona dla Windowsa z tej strony: https://www.python.org/downloads/release/python-343/. Po pobraniu pliku ***.msi**, uruchom go (klikając dwukrotnie na niego) i postępuj według wyświetlanych instrukcji. Koniecznie zapamiętaj katalog (ścieżkę), w którym zainstalowałaś Pythona. Będzie Ci niebawem potrzebna! - -### Linux - -Jest bardzo prawdopodobne, że masz już zainstalowanego Pythona wraz z systemem. Aby się upewnić (a także sprawdzić jego wersję), otwórz konsolę i wpisz następujące polecenie: - - $ python3 --version - Python 3.4.2 - - -Jeżeli nie masz zainstalowanego Pythona, lub chciałabyś zainstalować go w innej wersji, skorzystaj z jednego z poniższych sposobów: - -#### Debian lub Ubuntu - -Wpisz w konsoli poniższe polecenie: - - $ sudo apt-get install python3.4 - - -#### Fedora (<=21) - -Użyj następującego polecenia w konsoli: - - $ sudo yum install python3.4 - - -#### Fedora (22+) - -Użyj następującego polecenia w konsoli: - - $ sudo dnf install python3.4 - - -### OS X - -Przejdź na stronę https://www.python.org/downloads/release/python-342/ i pobierz instalator Pythona: - -* pobierz plik *DMG* o nazwie *Mac OS X 64-bit/32-bit installer*, -* kliknij dwukrotnie, aby go otworzyć, -* kliknij dwukrotnie *Python.mpkg*. aby uruchomić instalator. - -Sprawdź, czy instalacja zakończyła się pomyślnie - otwórz aplikację *Terminal* i uruchom polecenie `python3`: - - $ python3 --version - Python 3.4.2 - - -* * * - -W razie jakichkolwiek wątpliwości, lub jeśli coś poszło nie tak i nie wiesz, co zrobić dalej - zapytaj osobę prowadzącą kurs! Czasami nie wszystko idzie tak, jak powinno i lepszym wyjściem z sytuacji jest prośba o pomoc bardziej doświadczonej osoby. +{% include "/python_installation/instructions.md" %} diff --git a/pl/python_installation/images/add_python_to_windows_path.png b/pl/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/pl/python_installation/images/add_python_to_windows_path.png differ diff --git a/pl/python_installation/instructions.md b/pl/python_installation/instructions.md new file mode 100755 index 00000000000..e259941cc27 --- /dev/null +++ b/pl/python_installation/instructions.md @@ -0,0 +1,66 @@ +> Niniejszy podrozdział powstał w oparciu o kurs Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django został w napisany w Pythonie. Potrzebujemy Pythona, żeby móc zrobić cokolwiek w Django. Zacznijmy zatem od zainstalowania go! Potrzebujemy zainstalować Pythona 3.4, dlatego jeżeli masz już zainstalowaną jakąkolwiek starszą wersję, będziesz musiała ją uaktualnić. + +### Windows + +Możesz ściągnąć Pythona pod Windows z tej strony: https://www.python.org/downloads/release/python-343/. Po pobraniu pliku ***.msi**, uruchom go (klikając dwukrotnie na niego) i postępuj według wyświetlanych instrukcji. Koniecznie zapamiętaj ścieżkę (katalog), w którym zainstalowałaś Pythona. Będzie Ci niebawem potrzebna! + +Na jedno trzeba zwrócić uwagę: na drugiej stronie instalatora nazwanej "Customize" ("Dostosuj do potrzeb") przewiń na sam dół i wybierz "Add python.exe to the Path" ("Dodaj python.exe do ścieżki systemowej"), tak jak to zostało pokazane na poniższym obrazku: + +![Nie zapomnij dodać Pythona do ścieżki systemowej (ang. Path)](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Jest bardzo prawdopodobne, że masz już zainstalowanego Pythona wraz z systemem. Aby się upewnić (a także sprawdzić jego wersję) otwórz konsolę i wpisz następujące polecenie: + + $ python3 --version + Python 3.4.3 + + +Jeżeli nie masz zainstalowanego Pythona lub chciałabyś zainstalować go w innej wersji, skorzystaj z jednego z poniższych sposobów: + +#### Debian lub Ubuntu + +Wpisz w konsoli poniższe polecenie: + + $ sudo apt-get install python3.4 + + +#### Fedora (do 21) + +Użyj następującego polecenia w konsoli: + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +Użyj następującego polecenia w konsoli: + + $ sudo dnf install python3.4 + + +#### openSUSE + +Użyj następującego polecenia w konsoli: + + $ sudo zypper install python3 + + +### OS X + +Przejdź na stronę https://www.python.org/downloads/release/python-343/ i pobierz instalator Pythona: + + * Pobierz plik o nazwie *Mac OS X 64-bit/32-bit installer*, + * Kliknij dwukrotnie na *python-3.4.3-macosx10.6.pkg*, by uruchomić instalator. + +Sprawdź, czy instalacja zakończyła się pomyślnie - otwórz aplikację *Terminal* i uruchom polecenie `python3`: + + $ python3 --version + Python 3.4.3 + + +* * * + +W razie jakichkolwiek wątpliwości albo jeśli coś poszło nie tak i nie wiesz, co dalej robić - zapytaj mentora lub osobę prowadzącą kurs! Czasami nie wszystko idzie tak, jak powinno i najlepszym wyjściem z sytuacji jest poprosić o pomoc kogoś bardziej doświadczonego. diff --git a/pl/python_introduction/README.md b/pl/python_introduction/README.md index 7e99bde6b99..a18624ee1e7 100755 --- a/pl/python_introduction/README.md +++ b/pl/python_introduction/README.md @@ -1,29 +1,24 @@ # Wprowadzenie do Pythona -> Fragment tego rozdziału jest oparty o tutoriale Geek Girls Carrots (http://django.carrots.pl/). +> Fragment tego rozdziału jest oparty o tutoriale Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Napiszmy jakiś kod! ## Wiersz poleceń Pythona -Aby rozpocząć zabawę z Pythonem, musisz otworzyć jego *wiersz poleceń* na swoim komputerze. Już umiesz to robić -- nauczyłaś się tego w rozdziale [Wprowadzenie do interfejsu wiersza poleceń](../intro_to_command_line/README.md). - +Aby rozpocząć zabawę z Pythonem, musisz otworzyć jego *wiersz poleceń* na swoim komputerze. Już umiesz to robić - nauczyłaś się tego w rozdziale [Wprowadzenie do interfejsu wiersza poleceń][1]. + [1]: ../intro_to_command_line/README.md Gdy już będziesz gotowa, postępuj według instrukcji poniżej. -Musimy otworzyć konsolę Pythona. Wpisz `python3` i wciśnij `enter`. +Chcemy otworzyć konsolę Pythona. Wpisz `python`, jeśli pracujesz na Windowsie, lub `python3`, jeśli pracujesz na MacOS/Linuxie. Wciśnij `enter`. $ python3 - Python 3.4.2 (...) - Type "copyright", "credits" or "license" for more information. + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. >>> -Dla Windowsa: - -``` -C:\Python34\python -``` ## Twoje pierwsze polecenie w Pythonie! @@ -31,13 +26,13 @@ Po uruchomieniu Pythona wiersz poleceń wygląda tak: `>>>`. Jest to sygnał dla Jeśli w którymkolwiek momencie zechcesz wyjść z konsoli Pythona, po prostu wpisz polecenie `exit()` albo użyj kombinacji klawiszy `Ctrl + Z` w Windows lub `Ctrl + D` w Macu/Linuksie. Nie będziesz już więcej widzieć promptu `>>>`. -Teraz jednak nie chcemy wychodzić z konsoli Pythona. Chcemy za jej pomocą nauczyć się czegoś nowego. Zaczniemy od czegoś bardzo prostego. Spróbuj wpisać jakieś działanie matematyczne, jak `2 + 3`, i wciśnij `enter`. +Teraz jednak nie chcemy wychodzić z konsoli Pythona. Chcemy za jej pomocą nauczyć się czegoś nowego. Zaczniemy od czegoś bardzo prostego. Spróbuj wpisać jakieś działanie matematyczne, np. `2 + 3`, i wciśnij `enter`. >>> 2 + 3 5 -Świetnie! Zauważyłaś, że na ekranie pojawiła się odpowiedź? Python umie liczyć! Spróbuj użyć innych poleceń takich jak: - `4 * 5` - `5 - 1` - `40 / 2` +Świetnie! Zauważyłaś, że na ekranie pojawiła się podpowiedź? Python umie liczyć! Spróbuj użyć innych poleceń takich jak: - `4 * 5` - `5 - 1` - `40 / 2` Pobaw się tym przez chwilę, a potem wróć tutaj :). @@ -51,7 +46,7 @@ A jakby tak wpisać swoje własne imię? Wpisz swoje imię używając cudzysłow 'Ola' -Właśnie stworzyłaś swój pierwszy string! Jest to po prostu ciąg znaków, który może być przetwarzany przez komputer. String musi zawsze zaczynać się i kończyć tym samym znakiem. Może to być apostrof (`'`) lub cudzysłów (`"`) - sygnalizują one Pythonowi, że wszystko, co znajduje się pomiędzy nimi, jest stringiem. +Właśnie stworzyłaś swój pierwszy string! Jest to ciąg znaków, który może być przetwarzany przez komputer. String musi zawsze zaczynać się i kończyć tym samym znakiem. Może to być apostrof (`'`) lub cudzysłów (`"`) - nie ma różnicy! Sygnalizują one Pythonowi, że wszystko, co znajduje się pomiędzy nimi, jest stringiem. Stringi mogą być łączone. Spróbuj tak: @@ -73,7 +68,7 @@ Za pomocą cudzysłowu: "Runnin' down the hill" -lub poprzedzając apostrof odwróconym ukośnikiem (`\`): +lub poprzedzając apostrof odwróconym ukośnikiem (\'): >>> 'Runnin\' down the hill' "Runnin' down the hill" @@ -85,9 +80,9 @@ Fajnie, co? Możesz także wyświetlić swoje imię wielkimi literami. Wpisz po 'OLA' -Właśnie użyłaś **funkcji** `upper` na swoim stringu! Funkcja (na przykład `upper()`) jest zestawem poleceń, które Python musi wykonać na danym obiekcie (`"Ola"`) gdy tylko ją wywołasz. +Właśnie użyłaś **funkcji** `upper` na swoim stringu! Funkcja (na przykład taka jak `upper()`) jest zestawem poleceń, które Python musi wykonać na danym obiekcie (`"Ola"`) gdy tylko ją wywołasz. -A gdybyś chciała sprawdzić, z ilu liter składa się Twoje imię, to również możesz skorzystać z funkcji! +A gdybyś chciała sprawdzić z ilu liter składa się Twoje imię to również możesz skorzystać z funkcji! >>> len("Ola") 3 @@ -101,14 +96,14 @@ OK, wystarczy już stringów. Jak dotąd nauczyłaś się o: * **wierszu poleceń** - wpisywanie instrukcji (kodu) w wierszu poleceń Pythona powoduje wyświetlenie odpowiedzi przez Pythona * **liczbach i stringach** - Python używa liczb w działaniach matematycznych oraz stringów dla obiektów tekstowych -* **operatorach** - takich jak + czy \*, które tworzą nową wartość z tych już istniejących +* **operatorach** - takich jak + czy *, które tworzą nową wartość z tych już istniejących * **funkcjach** - takich jak upper() czy len(), wykonywania działań na obiektach. Są to podstawy każdego języka programowania, jakiego przyjdzie Ci się uczyć. Gotowa na coś trudniejszego? Mamy nadzieję, że tak! ## Błędy -Spróbujmy czegoś nowego. Czy możemy sprawdzić długość liczby w taki sam sposób, jak długość naszego imienia? Wpisz `len(304023)` i wciśnij `enter`: +Spróbujmy czegoś nowego. Czy możemy sprawdzić długość liczby w taki sam sposób jak długość naszego imienia? Wpisz `len(304023)` i wciśnij `enter`: >>> len(304023) Traceback (most recent call last): @@ -140,7 +135,7 @@ Przypuśćmy, że chcemy stworzyć nową zmienną zwaną `imie`: Widzisz? Nietrudne! Po prostu: "imie" równa się Ola. -Jak już zauważyłaś, Twój program nie wyświetlił niczego tak, jak to robił poprzednio. Zatem skąd wiemy, że zmienna faktycznie istnieje? Po prostu wpisz `imie` i wciśnij `enter`: +Jak już zauważyłaś, Twój program nie wyświetlił niczego tak, jak to robił wcześniej. Zatem skąd wiemy, że zmienna faktycznie istnieje? Po prostu wpisz `imie` i wciśnij `enter`: >>> imie 'Ola' @@ -153,7 +148,7 @@ Jupi! Twoja pierwsza zmienna :)! Zawsze masz możliwość zmiany tego, do czego 'Sonja' -Możesz także używać jej w funkcjach: +Mozesz także używać jej w funkcjach: >>> len(imie) 5 @@ -169,20 +164,20 @@ Ekstra, co? Oczywiście zmienne mogą reprezentować cokolwiek, także liczby! S Ale co by było, gdybyśmy użyły złej nazwy? Masz pomysł, co mogłoby się stać? Sprawdźmy! - >>> city = "Tokyo" - >>> ctiy + >>> miasto = "Tokyo" + >>> masto Traceback (most recent call last): File "", line 1, in - NameError: name 'ctiy' is not defined + NameError: name 'masto' is not defined -Błąd! Jak widzisz, Python ma różne rodzaje błędów, a ten nosi nazwę **NameError**. Python zwróci (wyświetli) Ci taki błąd, gdy będziesz próbowała używać nazwy, która nie została jeszcze utworzona. Gdybyś w przyszłości natrafiła na niego, sprawdź w swoim kodzie czy nie masz literówek w nazwach zmiennych. +Błąd! Jak widzisz, Python ma różne rodzaje błędów, a ten nosi nazwę **NameError**. Python zwróci Ci taki błąd, gdy będziesz próbowała używać nazwy, która nie została jeszcze utworzona. Gdybyś w przyszłości natrafiła na niego, sprawdź w swoim kodzie czy nie popełniłaś literówek w nazwach zmiennych. -Poświęć chwilę na zabawę i przekonaj się, co możesz z tym zrobić! +Poświęć chwilę czasu na zabawę i przekonaj się co możesz z tym zrobić! ## Funkcja print -Spróbuj tak: +Spróbuj tego: >>> imie = 'Maria' >>> imie @@ -243,7 +238,7 @@ Proste, prawda? Jeśli chcesz dodać coś do swojej listy, możesz to zrobić wp [59, 42, 30, 19, 12, 3, 199] -Jeśli chcesz wyświetlić tylko pierwszą liczbę, możesz to uczynić używając **indeksów**. Indeks jest numerem mówiącym nam, w którym miejscu listy znajduje się dany element. Ludzie związani z komputerami często zaczynają liczenie od zera, zatem pierwszy element Twojej listy znajduje się w miejscu oznaczonym indeksem 0, następny z indeksem 1, i tak dalej. Spróbuj tak: +Jeśli chcesz wyświetlić tylko pierwszą liczbę, możesz to uczynić używając **indeksów**. Indeks jest numerem mówiącym nam, w którym miejscu listy znajduje się dany element. Programiści zaczynają liczenie od zera, zatem pierwszy element Twojej listy znajduje się w miejscu oznaczonym indeksem 0, następny z indeksem 1, i tak dalej. Spróbuj tego: >>> print(wyniki[0]) 59 @@ -253,7 +248,20 @@ Jeśli chcesz wyświetlić tylko pierwszą liczbę, możesz to uczynić używaj Jak widzisz, możesz uzyskać dostęp do każdego z elementów Twojej listy za pomocą jej nazwy oraz numeru indeksu wewnątrz nawiasów kwadratowych. -Żeby było zabawniej, sprawdź inne indeksy: 6, 7, 1000, -1, -6 czy -1000. Sprawdź, czy jesteś w stanie przewidzieć rezultat przed użyciem instrukcji. Czy otrzymane rezultaty mają sens? +Aby skasować coś ze swojej listy, będziesz musiała użyć **indeksów**, których nauczyłyśmy się wyżej oraz polecenia `pop()`. Spróbujmy zobaczyć jak to działa na przykładzie i powtórzmy sobie to, czego się nauczyłyśmy wyżej. Usuńmy pierwszy element z naszej listy. + + >>> print(wyniki) + [59, 42, 30, 19, 12, 3, 199] + >>> print(wyniki[0]) + 59 + >>> wyniki.pop(0) + >>> print(wyniki) + [42, 30, 19, 12, 3, 199] + + +Wszystko zadziałało zgodnie z planem! + +Żeby było zabawniej, sprawdź inne indeksy: 6, 7, 1000, -1, -6 czy -1000. Sprawdż, czy jesteś w stanie przewidzieć rezultat przed użyciem instrukcji. Czy otrzymane rezultaty mają sens? Wykaz wszystkich metod dostępnych dla list znajdziesz w odpowiednim rozdziale dokumentacji Pythona: https://docs.python.org/3/tutorial/datastructures.html @@ -267,12 +275,11 @@ Słownik przypomina nieco listę, jednak różni się tym, że dostęp do warto To pokazuje, że właśnie stworzyłaś pusty słownik. Hura! -A teraz spróbuj wpisać poniższą instrukcję (możesz użyć własnych danych): - - >>> uczestniczka = {'imie' : 'Ola', - 'kraj' : 'Polska', - 'ulubione_liczby' : [7, 42, 92]} +A teraz spróbuj wpisać poniższą instrukcję (spróbuj użyć własnych danych): +```python +>>> uczestniczka = {'imie' : 'Ola', 'kraj' : 'Polska', 'ulubione_liczby' : [7, 42, 92]} +``` Za pomocą tej instrukcji stworzyłaś właśnie zmienną o nazwie `uczestniczka` zawierającą trzy pary klucz-wartość: @@ -298,7 +305,7 @@ A co się stanie, gdy poprosimy Pythona o wartość klucza, który nie istnieje? Spójrz, kolejny błąd! Tym razem **KeyError**. Python próbuje Ci pomóc i wskazuje, że klucz `'wiek'` nie istnieje w tym słowniku. -Kiedy należy używać słownika, a kiedy listy? Coż, bardzo dobre pytanie. Zastanów się nad rozwiązaniem, zanim spojrzysz na odpowiedź poniżej. +Kiedy powinniśmy używać słownika, a kiedy listy? To bardzo dobre pytanie! Zastanów się nad rozwiązaniem, zanim spojrzysz na odpowiedź poniżej. * Potrzebujesz ułożyć elementy w określonej kolejności? Wybierz listę. * Potrzebujesz powiązać wartości z kluczami, żeby mieć później łatwiejszy dostęp do nich (używając klucza)? Użyj słownika. @@ -316,9 +323,9 @@ Podobnie jak w przypadku list, metoda `len()` zwraca liczbę par klucz-wartość Mam nadzieję, że jak dotąd jest to zrozumiałe. :) Gotowa na dalszą zabawę ze słownikami? W następnej linijce czeka nas jeszcze więcej niesamowitości. -Za pomocą polecenia `del` możesz usunąć element ze słownika. Załóżmy, że chciałabyś usunąć wpis oznaczony kluczem `'ulubione_liczby'`. Po prostu wpisz następującą instrukcję: +Za pomocą polecenia `pop()` możesz usunąć element ze słownika. Założmy, że chciałabyś usunąć wpis oznaczony kluczem `'ulubione_liczby'`. Po prostu wpisz następującą instrukcję: - >>> del uczestniczka['ulubione_liczby'] + >>> uczestniczka.pop('ulubione_liczby') >>> uczestniczka {'kraj': 'Polska', 'ulubiony_jezyk': 'Python', 'imie': 'Ola'} @@ -341,13 +348,13 @@ Doskonale! Wiesz już sporo o programowaniu. W tej części nauczyłaś się o: * **błędach** - umiesz już czytać ze zrozumieniem błędy pojawiające się, gdy Python nie rozumie polecenia, które mu wydałaś * **zmiennych** - nazwach dla obiektów, dzięki którym programuje się łatwiej, a Twój kod jest czytelniejszy * **listach** - listach obiektów uporządkowanych w określonej kolejności -* **słownikach** - obiektach przechowywanych w postaci par klucz-wartość +* **słownikach** - zbiorach obiektów przechowywanych w postaci par klucz-wartość Gotowa na następną część? :) ## Porównywanie rzeczy -Istotną częścią programowania jest porównywanie różnych rzeczy. Co najłatwiej porównać? Liczby, oczywiście. Zobaczmy, jak to działa: +Istotną częścią programowania jest porównywanie różnych rzeczy. Co najłatwiej porównać? Liczby oczywiście. Zobaczmy, jak to działa: >>> 5 > 2 True @@ -357,11 +364,13 @@ Istotną częścią programowania jest porównywanie różnych rzeczy. Co najła True >>> 1 == 1 True + >>> 5 != 2 + True -Dałyśmy Pythonowi różne liczby do porównania. Jak widać, potrafi on nie tylko porównywać liczby, ale również wyniki działań. Fajnie, nie? +Dałyśmy Pythonowi różne liczby do porównania. Jak widać, potrafi on nie tylko porównywać listy, ale również wyniki działań. Fajnie, nie? -Zastanawiasz się, dlaczego stawiamy dwa znaki równości `==` obok siebie, gdy sprawdzamy, czy liczby są równe? Pojedynczego znaku równości `=` używamy do nadawania wartości zmiennym. **Zawsze, ale to zawsze** musisz używać dwóch znaków równości `==`, gdy chcesz sprawdzić, czy dane elementy są sobie równe. +Zastanawiasz się, dlaczego stawiamy dwa znaki równości `==` obok siebie, gdy sprawdzamy, czy liczby są równe? Pojedynczego znaku równości `=` używamy do nadawania wartości zmiennym. **Zawsze, ale to zawsze** musisz używać dwóch znaków równości `==`, gdy chcesz sprawdzić, czy dane elementy są równe. Możemy również stwierdzić, że dwie rzeczy nie są sobie równe. Aby to zrobić, używamy symbolu `!=`, tak jak to zostało pokazane na przykładzie powyżej. Użyjmy Pythona do wykonania dwóch innych zadań: @@ -390,8 +399,8 @@ Użyjmy Pythona do wykonania dwóch innych zadań: Możesz przekazać Pythonowi tyle liczb, ile Ci się podoba, a on zawsze zwróci Ci wynik! Prawda, że sprytne? -* **and** - gdy używasz operatora `and` (z ang. 'oraz'), oba porównania muszą być prawdziwe (True), żeby całe wyrażenie było prawdziwe -* **or** - gdy używasz operatora `or` (z ang. 'lub'), tylko jedno z obu porównań musi być prawdziwe, aby całe wyrażenie było prawdziwe +* **and** - gdy używasz operatora `and` , oba porównania muszą być prawdziwe (True), żeby całe wyrażenie było prawdziwe +* **or** - gdy używasz operatora `or`, tylko jedno z obu porównań musi być prawdziwe, aby całe wyrażenie było prawdziwe Znasz powiedzenie "porównywać jabłka z gruszkami"? Zobaczmy, jak działa jego odpowiednik w Pythonie: @@ -405,11 +414,9 @@ Widać, że podobnie jak w powiedzeniu, Python nie jest w stanie porównać licz ## Obiekt logiczny (Boolean) -Przez przypadek poznałaś nowy typ obiektu w Pythonie. Nazywa się: **obiekt logiczny (Boolean)** -- i jest chyba najprostszym typem jaki istnieje. +Przez przypadek poznałaś nowy typ obiektu w Pythonie. Nazywa się **obiektem logicznym (Boolean)** -- i jest chyba najprostszym typem jaki istnieje. -Są tylko dwa obiekty logiczne: -* **True** - prawda -* **False** - fałsz +Są tylko dwa obiekty logiczne: - True (prawda) - False (fałsz) Jednak żeby Python mógł to zrozumieć, powinnaś zawsze zapisywać je tak: True (pierwsza litera wielka, reszta to małe litery). **true, TRUE, tRUE nie zadziałają -- tylko True jest poprawne.** (oczywiście to samo dotyczy False.) @@ -434,7 +441,7 @@ Poćwicz i pobaw się wartościami logicznymi wpisując następujące instrukcje * `True or 1 == 1` * `1 != 2` -Gratulacje! Wartości logiczne są jedną z najfajniejszych możliwości w programowaniu, a Ty właśnie nauczyłaś się ich używać! +Gratulacje! Wartości logiczne są jedną z najfajniejszych możliwości w programaniu, a Ty właśnie nauczyłaś się ich używać! # Zapisujemy! @@ -445,7 +452,7 @@ Do tej pory pisałyśmy cały nasz kod Pythona w interpreterze, co zmusza nas do * Zapisać kod do nowego pliku Pythona * Uruchomić go! -Aby wyjść z używanego przez nas interpretera Pythona, użyj po prostu funkcji ```exit()``` : +Aby wyjść z używanego przez nas interpretera Pythona, użyj po prostu funkcji ~~~ exit()~~~ : >>> exit() $ @@ -457,39 +464,42 @@ Nieco wcześniej, w sekcji [Edytor kodu][2], dokonałyśmy wyboru programu używ [2]: ../code_editor/README.md - print('Hello, Django girls!') +```python +print('Hello, Django girls!') +``` +> **Uwaga** Powinnaś zauważyć jedną z najfajniejszych rzeczy, jeśli chodzi o edytor kodu: kolory! Gdy pisałaś w konsoli Pythona, wszystko miało ten sam kolor. Teraz powinnaś zobaczyć, że funkcja `print` jest innego koloru niż string. Nazywa się to "podświetlanie składni" i jest naprawdę użyteczne podczas kodowania. Kolor wyrazów w edytorze będzie dla Ciebie wskazówką, np. łatwo rozpoznasz dzięki temu niezamknięty string albo literówkę w słowie kluczowym (tak jak `def` w funkcji). To jeden z powodów, dla których używamy edytora kodu :) -Oczywiście jest już całkiem kompetentną programistką Pythona, więc śmiało - dodaj tam więcej kodu, który poznałaś wcześniej. +Oczywiście jesteś już całkiem kompetentną programistką Pythona, więc śmiało - dodaj tam więcej kodu, który poznałaś wcześniej. -Teraz musimy zapisać plik i nadać mu wymowną nazwę. Nazwijmy go **python_intro.py** i zapiszmy na Pulpicie. Możemy nazwać plik jak tylko nam się podoba, ale jedna rzecz jest istotna: na końcu nazwy musi być **.py**. W ten sposób informujemy nasz komputer, że to jest **plik wykonywalny Pythona** i Python może go uruchomić. +Teraz musimy zapisać plik i nadać mu wymowną nazwę. Nazwijmy go **python_intro.py** i zapiszmy na Pulpicie. Możemy nazwać plik jak tylko nam się podoba, ale jedna rzecz jest istotna: na końcu nazwy musi być **.py**. Rozszerzenie **.py** informuje nasz komputer, że to jest **plik wykonywalny Pythona** i Python może go uruchomić. Mamy już zapisany plik, a więc czas go uruchomić! Wykorzystując wiadomości poznane w sekcji poświęconej wierszowi poleceń, użyj terminala, aby **zmienić aktualny katalog** na katalog Pulpitu. Na Macu polecenie będzie wyglądać mniej-więcej tak: - cd /Users//Desktop + $ cd /Users//Desktop W Linuksie będzie tak (słowo "Desktop" może zostać przetłumaczone na polski jako "Pulpit"): - cd /home//Desktop + $ cd /home//Desktop A w systemie Windows będzie to wyglądać tak: - cd C:\Users\\Desktop + > cd C:\Users\\Desktop Jeżeli coś jest dla Ciebie niejasne, nie wahaj się poprosić o pomoc. -A następnie użyć Pythona do uruchomienia kod z pliku w następujący sposób: +Teraz użyj Pythona do uruchomienia kodu z pliku w następujący sposób: $ python3 python_intro.py Hello, Django girls! -W porządku. Właśnie uruchomiłaś swój pierwszy program w Pythonie, do tego zapisany w pliku. Wspaniałe uczucie, co? +Super! Właśnie uruchomiłaś z pliku swój pierwszy program w Pythonie. Wspaniałe uczucie, co? Teraz możemy przejść do niezwykle istotnego narzędzia w programowaniu: @@ -499,10 +509,11 @@ Dużo różnych rzeczy w kodzie powinno być uruchamiane tylko wtedy, kiedy zost Zastąp kod w pliku **python_intro.py** następującym: - if 3 > 2: +```python +if 3 > 2: +``` - -Gdybyśmy ten plik teraz zapisały i uruchomiły, pojawiłby się błąd podobny do poniższego: +Gdybyśmy to teraz zapisały i uruchomiły, pojawił się błąd podobny do poniższego: $ python3 python_intro.py File "python_intro.py", line 2 @@ -510,31 +521,33 @@ Gdybyśmy ten plik teraz zapisały i uruchomiły, pojawiłby się błąd podobny SyntaxError: unexpected EOF while parsing -Python oczekuje od nas dalszych instrukcji, które mają zostać wykonane w przypadku, gdy warunek `3 > 2` okaże się prawdziwy (czyli przyjmie wartość `True` w tym przypadku). Sprawmy, żeby Python wypisał na ekranie "To działa!". Zmień kod w pliku **python_intro.py** na poniższy: - - if 3 > 2: - print('To działa!') +Python oczekuje od nas dalszych instrukcji, które mają zostać wykonane w przypadku, gdy warunek `3 > 2` okaże się prawdziwy (czyli przyjmie wartość `True`). Sprawmy, żeby Python wypisał na ekranie "To działa!". Zmień kod w pliku **python_intro.py** na poniższy: +```python +if 3 > 2: + print('To dziala!') +``` -Zauważyłaś, że w kolejnym wierszu nasz kod posiada wcięcie 4 spacji? Musimy tak robić, aby Python wiedział, co ma uruchomić w przypadku, gdy warunek okaże się prawdą. Możesz używać jednej spacji, ale prawie każdy programista Pythona stosuje 4 spacje, aby kod wyglądał czytelniej. Pojedynczy tabulator również będzie liczył się jako 4 spacje. +Zauważyłaś, że w kolejnym wierszu nasz kod posiada wcięcie 4 spacji? Musimy tak robić, aby Python wiedział, co ma uruchomić, gdy warunek jest prawdziwy. Możesz używać jednej spacji, ale prawie każdy programista Pythona stosuje 4 spacje, aby kod wyglądał czytelniej. Pojedynczy `tabulator` również będzie liczył się jako 4 spacje. Zapisz plik i uruchom go jeszcze raz: $ python3 python_intro.py - To działa! + To dziala! -### A co jeśli nie? +### A co jeśli warunek nie jest prawdziwy? W poprzednich przykładach kod był wykonywany wtedy, gdy warunki okazywały się prawdziwe (True). Ale Python posiada również wyrażenia `elif` i `else`: - if 5 > 2: - print('5 jest jednak większe od 2') - else: - print('5 nie jest większe od 2') - +```python +if 5 > 2: + print('5 jest jednak większe od 2') +else: + print('5 nie jest większe od 2') +``` -Po uruchomieniu wyświetliłoby się: +Po uruchomieniu wyświetli się: $ python3 python_intro.py 5 jest jednak większe od 2 @@ -542,14 +555,15 @@ Po uruchomieniu wyświetliłoby się: Gdyby 2 było większą liczbą niż 5, wtedy zostałaby wykonana druga instrukcja. Proste, nie? Zobaczmy, jak działa `elif`: - name = 'Sonja' - if name == 'Ola': - print('Hej Ola!') - elif name == 'Sonja': - print('Hej Sonja!') - else: - print('Hej anonimie!') - +```python +name = 'Sonja' +if name == 'Ola': + print('Hej Ola!') +elif name == 'Sonja': + print('Hej Sonja!') +else: + print('Hej nieznajoma!') +``` i uruchommy go: @@ -557,16 +571,40 @@ i uruchommy go: Hej Sonja! -Widziałaś, co się stało? +Widzisz co się tutaj wydarzyło? `elif` pozwala Ci na dodanie dodatkowego warunku, jeśli poprzedni warunek nie został spełniony. + +Po początkowej instrukcji `if` możesz dodać tyle instrukcji `elif` ile tylko Ci się podoba. Na przykład: + +```python +glosnosc = 57 +if glosnosc < 20: + print("Prawie nic nie slychac.") +elif 20 <= glosnosc < 40: + print("O, muzyka leci w tle.") +elif 40 <= glosnosc < 60: + print("Idealnie, moge uslyszec wszystkie detale") +elif 60 <= glosnosc < 80: + print("Dobre na imprezy") +elif 80 <= glosnosc < 100: + print("Troszeczke za glosno!") +else: + print("Ojoj! Moje uszy! :(") +``` + +Python zbada każdy warunek i wyświetli: + + $ python3 python_intro.py + Idealnie, moge uslyszec wszystkie detale + ### Podsumowanie -W ostatnich trzech ćwiczeniach nauczyłaś się o: +W ostatnich trzech ćwiczeniach nauczyłaś się: -* **porównywaniu rzeczy** - w Pythonie do porównywania rzeczy możesz używać operatorów `>`, `>=`, `==`, `<=`, `<` oraz `and`, `or` +* **porównywać rzeczy** - w Pythonie do porównywania rzeczy możesz używać operatorów `>`, `>=`, `==`, `<=`, `<` oraz `and`, `or` * **Boolean** - typ obiektu, który może przyjmować jedną z dwóch wartości: `True` (prawda) lub `False` (fałsz) -* **Zapisywaniu plików** - przechowywaniu kodu w plikach, co pozwala nam uruchamiać bardziej rozbudowane programy. -* **if...elif...else** - wyrażeniach, które pozwalają Ci uruchamiać kod tylko wtedy, gdy zostaną spełnione określone warunki. +* **zapisywać pliki** - przechowywać kod w plikach, co pozwala nam uruchamiać bardziej rozbudowane programy. +* **if...elif...else** - wyrażenia, które pozwalają Ci uruchamiać kod tylko wtedy, gdy zostaną spełnione określone warunki. Czas na ostatnią część tego rozdziału! @@ -576,12 +614,13 @@ Pamiętasz funkcje takie jak `len()`, które możesz uruchamiać w Pythonie? Dob Funkcja jest zestawem poleceń, które Python ma wykonać. Każda funkcja w Pythonie zaczyna się słowem `def`, posiada nazwę i może przyjmować parametry. Zacznijmy od prostej funkcji. Zastąp kod w pliku **python_intro.py** następującym: - def hi(): - print('Hej!') - print('Jak się masz?') - - hi() +```python +def hej(): + print('Hej!') + print('Jak się masz?') +hej() +``` OK, nasza pierwsza funkcja gotowa! @@ -596,37 +635,40 @@ Uruchommy to teraz i sprawdźmy, co się stanie: To nie było trudne! Zbudujmy naszą pierwszą funkcję z parametrami. Posłużymy się wcześniejszym przykładem - funkcją, która wita każdego, kto ją uruchomi, wraz z imieniem: - def hi(name): - +```python +def hej(imie): +``` Jak widać, teraz nasza funkcja przyjmuje parametr, który nazwałyśmy `name`: - def hi(name): - if name == 'Ola': - print('Hej Ola!') - elif name == 'Sonja': - print('Hej Sonja!') - else: - print('Hej anonimie!') - - hi() +```python +def hej(imie): + if imie == 'Ola': + print('Hej Ola!') + elif imie == 'Sonja': + print('Hej Sonja!') + else: + print('Hej nieznajoma!') +hej() +``` -Jak zauważyłaś, musiałyśmy dodać osiem spacji przed funkcją `print`, ponieważ `if` musi dostać informację o tym, co powinno się wydarzyć, gdy warunek zostanie spełniony. Zobaczmy teraz, jak to działa: +Pamiętaj: Musiałyśmy dodać cztery dodatkowe spacje (razem osiem) przed funkcją `print`, ponieważ `if` musi dostać informację o tym, co powinno się wydarzyć, gdy warunek zostanie spełniony. Zobaczmy teraz jak to działa: $ python3 python_intro.py Traceback (most recent call last): File "python_intro.py", line 10, in - hi() - TypeError: hi() missing 1 required positional argument: 'name' + hej() + TypeError: hej() missing 1 required positional argument: 'imie' -Ups, błąd. Na szczęście Python zwrócił nam dość przydatny komunikat. Mówi nam, że funkcja `witaj()` (ta, którą stworzyłyśmy) posiada jeden wymagany argument (zwany `name`) i że zapomniałyśmy go przekazać przy wywoływaniu funkcji. Naprawmy to na końcu naszego pliku: - - hi("Ola") +Ups, błąd. Na szczęście Python zwrócił nam dość przydatny komunikat. Mówi nam, że funkcja `hej()` (ta, którą stworzyliśmy) posiada jeden wymagany argument (zwany `imie`) i że zapomniałyśmy go przekazać przy wywoływaniu funkcji. Naprawmy to na końcu naszego pliku: +```python +hej("Ola") +``` -i wykonajmy ponownie: +I wykonajmy ponownie: $ python3 python_intro.py Hej Ola! @@ -634,10 +676,11 @@ i wykonajmy ponownie: A gdybyśmy zmieniły imię? - hi("Sonja") - +```python +hej("Sonja") +``` -i wykonajmy: +I wykonajmy: $ python3 python_intro.py Hej Sonja! @@ -645,18 +688,19 @@ i wykonajmy: A jak myślisz - co się stanie, jak wprowadzimy tam inne imię (jeszcze inne niż Ola i Sonja)? Spróbuj i przekonaj się, czy miałaś rację. Powinno sie wyświetlić coś takiego: - Hej anonimie! + Hej nieznajoma! Prawda, że fajnie? W ten sposób nie musisz powtarzać się za każdym razem, gdy zechcesz zmienić imię osoby, która ma zostać powitana. To właśnie dlatego funkcje są nam potrzebne - żeby nie powtarzać kodu! Zróbmy coś sprytniejszego -- istnieje znacznie więcej niż dwa imiona i raczej ciężko byłoby pisać warunek dla każdego, co? - def hi(name): - print('Hej ' + name + '!') - - hi("Rachel") +```python +def hej(imie): + print('Hej ' + imie + '!') +hej("Rachel") +``` Teraz wywołajmy ten kod: @@ -664,59 +708,63 @@ Teraz wywołajmy ten kod: Hej Rachel! -Gratulacje! Właśnie nauczyłaś się pisać funkcje :)! +Gratulacje! Właśnie nauczyłaś się pisać funkcje :) ## Pętle -To już ostatnia część. Prawda, że szybko poszło? :) +To już ostatnia cześć. Prawda, że szybko poszło? :) Jak już wspomniałyśmy, programiści są leniwi i nie lubią się powtarzać. W programowaniu chodzi o automatyzowanie różnych rzeczy, więc nie chcemy witać ręcznie każdej osoby po imieniu, prawda? I tu właśnie przydają nam się pętle. Pamiętasz jeszcze listy? Zróbmy listę dziewczyn: - dziewczyny = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Ty'] - - -Chcemy powitać po imieniu każdą z nich. Mamy do tego funkcję `witaj`, zatem użyjmy jej wewnątrz pętli: +```python +dziewczyny = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Ty'] +``` - for imie in dziewczyny: +Chcemy powitać po imieniu każdą z nich. Mamy do tego funkcję `hej`, zatem użyjmy jej wewnątrz pętli: +```python +for imie in dziewczyny: +``` -Wyrażenie `for` zachowuje się podobnie jak `if`, a więc kod pod nimi musi być wcięty 4 spacjami. +Wyrażenie for zachowuje się podobnie jak if, a więc kod pod nimi musi być wcięty 4 spacjami. Oto kompletny kod, który umieścimy w pliku: - def hi(name): - print('Witaj ' + name + '!') - - dziewczyny = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Ty'] - for imie in dziewczyny: - hi(imie) - print('Kolejna dziewczyna') +```python +def hej(imie): + print('Hej ' + imie + '!') +dziewczyny = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'Ty'] +for imie in dziewczyny: + hej(imie) + print('Kolejna dziewczyna') +``` a gdy go uruchomimy: $ python3 python_intro.py - Witaj Rachel! + Hej Rachel! Kolejna dziewczyna - Witaj Monica! + Hej Monica! Kolejna dziewczyna - Witaj Phoebe! + Hej Phoebe! Kolejna dziewczyna - Witaj Ola! + Hej Ola! Kolejna dziewczyna - Witaj Ty! + Hej Ty! Kolejna dziewczyna Jak widzisz, cokolwiek umieścisz wewnątrz wyrażenia `for` wraz z wcięciem - zostanie powtórzone dla każdego elementu listy `dziewczyny`. -Możesz także użyć `for` na liczbach, używając funkcji `range`: - - for i in range(1, 6): - print(i) +Możesz także użyć `for` na liczbach, używając metody `range`: +```python +for i in range(1, 6): + print(i) +``` Co wypisze nam na ekranie: @@ -729,12 +777,14 @@ Co wypisze nam na ekranie: `range` jest funkcją, która tworzy listę liczb jedna po drugiej (liczby te podajesz jako parametry). -Zwróć uwagę, że druga z tych liczb nie jest częścią listy stworzonej przez Pythona (to znaczy, że `range(1, 6)` liczy od 1 do 5, ale nie zawiera liczby 6). +Zwróć uwagę, że druga z tych liczb nie jest częścią listy stworzonej przez Pythona (to znaczy, że `range(1, 6)` liczy od 1 do 5, ale nie zawiera liczby 6). Dzieje się tak, bo "range" ma przedział jednostronnie otwarty, co oznacza, że zawiera pierwszą wartość z przedziału, ale nie zawiera ostatniej. ## Podsumowanie -To już wszystko. **Wspaniale Ci idzie!** To nie było wcale takie łatwe, możesz zatem być z siebie dumna. My zdecydowanie jesteśmy dumne z Ciebie, że dotarłaś do tego miejsca! +To już wszystko. **Wspaniale Ci idzie!** To nie było wcale takie łatwe, możesz zatem być z siebie dumna. My zdecydowanie jesteśmy z Ciebie dumne, że dotarłaś do tego miejsca! + +Jak myślisz, może czas na małą przerwę? Rozciągnij się, rozprostuj nogi, daj odpocząć oczom zanim przejdziesz do kolejnego rozdziału. :) -Poczęstuj się babeczką i przejdź do następnego rozdziału :) +![Babeczka][3] -![Babeczka](images/cupcake.png) + [3]: images/cupcake.png diff --git a/pl/template_extending/README.md b/pl/template_extending/README.md index baca698d215..89a8cf87e2e 100755 --- a/pl/template_extending/README.md +++ b/pl/template_extending/README.md @@ -2,7 +2,7 @@ Kolejną fajną rzeczą, którą Django daje Ci do dyspozycji, jest możliwość **rozszerzania szablonów**. Co to oznacza? To znaczy, że możesz używać tych samych części Twojego kodu HTML na różnych stronach Twojej aplikacji. -Dzięki temu, gdy zechcesz użyć tych samych informacji/układu w kilku plikach, nie musisz go za każdym razem powtarzać. Ponadto, gdy zechcesz coś zmienić, nie będziesz musiała robić tego we wszystkich plikach szablonu -- tylko raz w jednym miejscu! +Dzięki temu, jeśli chcesz mieć te same informacje albo ten sam layout to nie musisz się powtarzać w każdym pliku. Tak samo jeśli chcesz coś zmienić - nie musisz edytować kilku plików, robisz to tylko raz! ## Tworzenie szablonu bazowego @@ -15,7 +15,7 @@ Stwórzmy plik `base.html` w `blog/templates/blog/`: └───blog base.html post_list.html - + Następnie otwórz go i skopiuj całą zawartość pliku `post_list.html` do pliku `base.html`, w taki sposób: @@ -43,7 +43,7 @@ Następnie otwórz go i skopiuj całą zawartość pliku `post_list.html` do pli {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -51,7 +51,7 @@ Następnie otwórz go i skopiuj całą zawartość pliku `post_list.html` do pli -``` +``` Następnie, w `base.html`, zamień całą zawartość `` (wszystko, co znajduje się pomiędzy `` a ``) na to: @@ -70,7 +70,6 @@ Następnie, w `base.html`, zamień całą zawartość `` (wszystko, co zna ``` - W zasadzie zastąpiłyśmy całą treść wewnątrz `{% for post in posts %}{% endfor %}` tym: @@ -78,7 +77,6 @@ W zasadzie zastąpiłyśmy całą treść wewnątrz `{% for post in posts %}{% e {% block content %} {% endblock %} ``` - Co to znaczy? Stworzyłaś właśnie `block` (blok), który jest znacznikiem szablonu umożliwiającym Ci wstawienie HTML wewnątrz tego bloku w innych szablonach, które rozszerzają `base.html`. Za chwilę pokażemy Ci, jak to się robi. @@ -91,20 +89,18 @@ Teraz zapisz zmiany, a potem otwórz jeszcze raz plik `blog/templates/blog/post_ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - A teraz dodaj ten wiersz na początku pliku: ```html {% extends 'blog/base.html' %} -``` - +``` -To znaczy, że teraz rozszerzamy szablon `base.html` w pliku `post_list.html`. Zostało już tylko jedno: wstaw całą treść (pomijając wiersz, który właśnie dodałyśmy) pomiędzy `{% block content %}` a `{% endblock content %}`. O tak: +{% raw %}To znaczy, że rozszerzamy szablon `base.html` w pliku `post_list.html`. Zostało już tylko jedno: wstaw całą treść (pomijając wiersz, który właśnie dodałyśmy) pomiędzy `{% block content %}` a `{% endblock content %}`. O tak:{% endraw %} ```html {% extends 'blog/base.html' %} @@ -116,12 +112,11 @@ To znaczy, że teraz rozszerzamy szablon `base.html` w pliku `post_list.html`. Z {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} -``` - +``` I już! Sprawdź, czy twoja strona nadal działa poprawnie. :) diff --git a/pl/whats_next/README.md b/pl/whats_next/README.md index a1856002b10..08b29ae8a65 100755 --- a/pl/whats_next/README.md +++ b/pl/whats_next/README.md @@ -1,40 +1,40 @@ # Co dalej? -Możesz być z siebie zadowolona! **Jesteś absolutnie świetna**. Jesteśmy takie dumne! <3 +Możesz być z siebie dumna! **Jesteś absolutnie świetna**. Jesteśmy takie dumne! <3 ### Co teraz? Zrób sobie przerwę i zrelaksuj się. Odwaliłaś kawał dobrej roboty! -Zaraz po tym, upewnij się że: +Zaraz po tym, upewnij się, że: * Obserwujesz Django Girls na [Facebooku][1] lub [Twitterze][2], żeby być na bieżąco [1]: http://facebook.com/djangogirls - [2]: http://twitter.com/djangogirls + [2]: https://twitter.com/djangogirls ### Czy możesz polecić kolejne materiały? -Tak! Najpierw możesz spróbować naszej kolejnej książki: [Django Girls Tutorial: Extensions][3] - zawiera rozszerzenia i dodatkowe zadania związane z tym, co już tutaj przerobiłaś. +Tak! Najpierw możesz spróbować naszej kolejnej książki: [Django Girls Tutorial: Extensions][3] -- zawiera rozszerzenia i dodatkowe zadania związane z tym, co już tutaj przerobiłaś. [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ -Możesz też spróbować któregoś z materiałów poniżej. Wszystkie bardzo polecamy! +Możesz też wypróbować materiały, które wypisałyśmy poniżej. Wszystkie bardzo polecamy! - [Oficjalna dokumentacja Django][4] - [instrukcje New Coder][5] -- [Code Academy Python kurs][6] -- [Code Academy HTML & CSS kurs][7] +- [kurs Code Academy Python][6] +- [kurs Code Academy HTML & CSS][7] - [tutorial Django Carrots][8] - [książka Learn Python The Hard Way][9] - [video lekcje Getting Started With Django][10] -- [książka Two Scoops of Django: Best Practices for Django][11] +- [książka Two Scoops of Django: Best Practices for Django 1.8][11] [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ [5]: http://newcoder.io/tutorials/ - [6]: http://www.codecademy.com/en/tracks/python - [7]: http://www.codecademy.com/tracks/web - [8]: http://django.carrots.pl/en/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ [9]: http://learnpythonthehardway.org/book/ [10]: http://gettingstartedwithdjango.com/ - [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6 + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/pt/README.md b/pt/README.md index 8647b77f75c..889484670d9 100755 --- a/pt/README.md +++ b/pt/README.md @@ -4,11 +4,48 @@ [1]: https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -> Este trabalho é licenciado sob a licença Creative Commons Attribution-ShareAlike 4.0. Para ver uma cópia desta licença, visite http://creativecommons.org/licenses/by-sa/4.0/ +> Este trabalho é licenciado sob a licença Creative Commons Attribution-ShareAlike 4.0. Para ver uma cópia desta licença, visite https://creativecommons.org/licenses/by-sa/4.0/ ## Translation -This tutorial has been translated from English to Portuguese by a group of awesome volunteers. Special thanks for help goes out to Willie Lawrence, Vivian Macedo, Cleiton Lima, danieltex, Leandro Silva Araujo, Adailton do Nascimento, Pablo Palacios, Paulo Alem, Eric Hidecki, Joao Luiz Lorencetti, clemente.jnr, Leonardo Alves dos Santos, joepreludian, Gabriela Cavalcante da Silve, Rafael Biagioni de Fazio, Fabio C. Barrionuevo da Luz, ffabiorj, Lucas Magnum, 1pedro, Adjamilton Junior, Leandro Barbosa, Kleber C Pinheiro, Katyanna Moura, Annanda Sousa, Flavio Barros, Marcel Ribeiro Dantas, Adam Victor Nazareth Brandizzi, Bernardo Fontes, Antonio Luis, Raony Guimares Correo do Carmo Lisboa Cardenas, Camilla Achutti and Carla Suarez. Wow! <3 <3 +This tutorial has been translated from English to Portuguese by a group of awesome volunteers. + +Special thanks for help goes out to: + +*Adailton do Nascimento +*Adam Victor Nazareth Brandizzi +*Antonio Luis +*Annanda Sousa +*Adjamilton Junior +*Bernardo Fontes +*Camilla Achutti +*Carla Suarez +*Cleiton Lima +*clemente.jnr +*danieltex +*Eric Hideki +*Flavio Barros +*Fabio C. Barrionuevo da Luz +*ffabiorj +*Gabriela Cavalcante da Silva +*Leandro Silva Araujo +*Lucas Magnum +*1pedro +*Joao Luiz Lorencetti +*Katyanna Moura +*Kleber C Pinheiro +*Leandro Barbosa +*Leonardo Alves dos Santos +*Marcel Ribeiro Dantas +*joepreludian +*Rafael Biagioni de Fazio +*Pablo Palacios +*Paulo Alem +*Raony Guimares Correo do Carmo Lisboa Cardenas +*Vivian Macedo +*Willie Lawrence +*Ricardo Manhães Savii +Wow! <3 <3 ## Introdução @@ -40,8 +77,8 @@ OK, [vamos pelo começo...][3] Este tutorial é mantido por [DjangoGirls][4]. Se você encontrar quaisquer erros ou quiser atualizar o tutorial, por favor [siga as orientações de contribuição][5]. - [4]: http://djangogirls.org/ - [5]: https://github.com/DjangoGirls/tutorial/blob/master/CONTRIBUTING.md + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md ## Gostaria de nos ajudar a traduzir o tutorial para outros idiomas? diff --git a/pt/code_editor/README.md b/pt/code_editor/README.md index 126011cdf87..edb60626441 100755 --- a/pt/code_editor/README.md +++ b/pt/code_editor/README.md @@ -14,19 +14,19 @@ Gedit é um editor open-source, gratuito, disponível para todos os sistemas ope [1]: https://wiki.gnome.org/Apps/Gedit#Download -## Sublime Text 2 +## Sublime Text 3 -Sublime Text 2 é um editor muito popular com um período de avaliação gratuita. É fácil de instalar e usar, e está disponível para todos os sistemas operacionais. +Sublime Text 3 é um editor muito popular com um período de avaliação gratuita. É fácil de instalar e usar, e está disponível para todos os sistemas operacionais. [Baixe aqui][2] - [2]: http://www.sublimetext.com/2 + [2]: https://www.sublimetext.com/3 ## Atom Atom é um novo editor de código criado pelo [GitHub][3]. Ele é gratuito, open-source, fácil de instalar e fácil de usar. Está disponível para Windows, OSX e Linux. - [3]: http://github.com/ + [3]: https://github.com/ [Baixe aqui][4] diff --git a/pt/css/README.md b/pt/css/README.md index 247b3de987b..2a9f538143c 100755 --- a/pt/css/README.md +++ b/pt/css/README.md @@ -10,7 +10,7 @@ Mas nós não queremos iniciar do zero de novo, certo? Nós tentaremos, mais uma ## Vamos usar o Bootstrap! -Bootstrap é um dos mais famosos e populares frameworks de HTML e CSS para desenvolver sites bonitos: http://getbootstrap.com/ +Bootstrap é um dos mais famosos e populares frameworks de HTML e CSS para desenvolver sites bonitos: https://getbootstrap.com/ Foi escrito por programadores que trabalharam no Twitter e agora é desenvolvido por voluntários de todo o mundo. @@ -66,7 +66,7 @@ Hora de escrever CSS! Abra o arquivo `static/css/blog.css` no seu editor de cód Não vamos nos aprofundar muito em customizar e aprender sobre CSS aqui, porque é bem fácil e você pode aprender no seu próprio após este workshop. Recomendamos fortemente fazer este [Codeacademy HTML & CSS couse][2] para aprender tudo o que você precisa saber sobre como tornar seus sites mais bonitos com CSS. - [2]: http://www.codecademy.com/tracks/web + [2]: https://www.codecademy.com/tracks/web Mas vamos fazer pelo menos um pouco. Talvez possamos mudar a cor do nosso cabeçalho? Para entender as cores, computadores usam códigos especiais. Eles começam com `#` e são seguidos por 6 letras (A-F) e números (0-9). Você pode encontrar exemplos de códigos de cores aqui: http://www.colorpicker.com/. Você pode também usar [cores predefinidas][3], como `red` e `green`. @@ -86,7 +86,7 @@ h1 a { Em um arquivo CSS podemos determinar estilos para elementos no arquivo HTML. Os elementos são identificados pelo nome do elemento (ou seja, `a`, `h1`, `body`), o atributo de `class` ou o atributo `id`. Classe e id são nomes que você mesmo dá ao elemento. Classes definem grupos de elementos, e ids apontam para elementos específicos. Por exemplo, a seguinte tag pode ser identificada por CSS usando a tag de nome `a`, a classe `link_externo` ou a identificação de `link_para_a_pagina_wiki`: ```html - + ``` @@ -130,7 +130,7 @@ Agora, seu arquivo deve ficar assim:

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -162,7 +162,7 @@ Adicione isto ao seu arquivo CSS, salve e veja como ele funciona! Talvez a gente possa customizar a fonte no nosso cabeçalho? Cole na seção `` do arquivo `blog/templates/blog/post_list.html` o seguinte: ```html - + ``` @@ -201,7 +201,7 @@ E agora, adicione uma classe `post` em sua `div` que contém um post de blog.

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

``` @@ -266,7 +266,7 @@ Então envolva o código HTML que exibe as mensagens com declarações de classe

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` @@ -284,7 +284,7 @@ no arquivo `blog/templates/blog/post_list.html` por isto: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} diff --git a/pt/deploy/README.md b/pt/deploy/README.md index 14d227f3a46..8ea47ba590e 100755 --- a/pt/deploy/README.md +++ b/pt/deploy/README.md @@ -4,13 +4,13 @@ Até agora nosso site só estava disponível no seu computador, agora você vai aprender como publicar ele na internet! A implantação é o processo de publicação do seu aplicativo na Internet de tal forma que as pessoas possam, finalmente, ver seu aplicativo :). -Como você aprendeu, um website precisa estar localizado num servidor. Existem muitos provedores, mas iremos utilizar o que tem um processo de deploy relativamente simples: [Python Anywhere][1] PythonAnywhere é gratuito para aplicações pequenas que não possuem muitos visitantes, então será suficiente para você por enquanto. +Como você aprendeu, um website precisa estar localizado num servidor. Existem muitos provedores, mas iremos utilizar o que tem um processo de deploy relativamente simples: [PythonAnywhere][1]. PythonAnywhere é gratuito para aplicações pequenas que não possuem muitos visitantes, então será suficiente para você por enquanto. - [1]: http://pythonanywhere.com/ + [1]: https://pythonanywhere.com/ O outro serviço externo que usaremos é [GitHub][2], que é um serviço de hospedagem de código. Existem outros, mas quase todos os programadores possuem uma conta no GitHub atualmente e agora você também! - [2]: http://www.github.com + [2]: https://www.github.com Usaremos o GitHub como um trampolim para transportar nosso código para o PythinAnywhere. @@ -24,7 +24,7 @@ Git é "sistema de controle de versão" usado por muitos programadores - um soft Você pode baixar Git em [git-scm.com][3]. Você pode apertar "next next next" em todos os passos exceto um; no quinto passo chamado "Adjusting your PATH environment", escolha "Run Git and associated Unix tools from the Windows command-line" (a opção de baixo). Além disso, o padrão está ótimo. Checkout estilo Windows, commit Unix-style linhas de confirmação está bom. - [3]: http://git-scm.com/ + [3]: https://git-scm.com/ ### MacOS @@ -37,7 +37,7 @@ Se ele já não estiver instalado, Git deve estar disponível através de seu ge sudo apt-get install git # or sudo yum install git - + ## Começando nosso repositório no Git @@ -49,7 +49,7 @@ Git controla as alterações para um determinado conjunto de arquivos no que cha Initialized empty Git repository in ~/djangogirls/.git/ $ git config user.name "Your Name" $ git config user.email you@example.com - + Inicializar o repositório git é algo que só precisamos fazer uma vez por projeto (e você não terá que re-introduzir o nome de usuário e e-mail nunca mais) @@ -60,7 +60,7 @@ Git irá controlar as alterações para todos os arquivos e pastas neste diretó myvenv db.sqlite3 .DS_Store - + E salve como `.gitignore` na pasta de nível superior "djangogirls". @@ -70,36 +70,36 @@ E salve como `.gitignore` na pasta de nível superior "djangogirls". $ git status On branch master - + Initial commit - + Untracked files: (use "git add ..." to include in what will be committed) - + .gitignore blog/ manage.py mysite/ - + nothing added to commit but untracked files present (use "git add" to track) - + E finalmente nós salvamos nossas alterações, Vá para o seu console e execute estes comandos: - $ git add -A . + $ git add --all . $ git commit -m "My Django Girls app, first commit" [...] 13 files changed, 200 insertions(+) create mode 100644 .gitignore [...] create mode 100644 mysite/wsgi.py - + ## Empurrando o nosso código para GitHub Vá para [GitHub.com][4] e cadastre uma nova e gratuita conta de usuário. Em seguida, crie um novo repositório, e dê o nome "my-first-blog". Deixe o "initialise with a README" desmarcado, deixe a opção .gitignore em branco (já fizemos isso manualmente) e a licença como None. - [4]: http://www.github.com' + [4]: https://www.github.com' ![][5] @@ -117,7 +117,7 @@ Agora precisamos ligar o repositório Git no seu computador com o no GitHub. $ git remote add origin https://github.com//my-first-blog.git $ git push -u origin master - + Digite seu GitHub username e senha, e você deve ver algo como isto: @@ -129,7 +129,7 @@ Digite seu GitHub username e senha, e você deve ver algo como isto: To https://github.com/hjwp/my-first-blog.git * [new branch] master -> master Branch master set up to track remote branch master from origin. - + @@ -157,7 +157,7 @@ Quando você se inscreve para PythonAnywhere, você é levado ao seu painel de c Vamos puxar nosso código de GitHub em PythonAnywhere através da criação de um "clone" do repo. Digite o seguinte para o console na PythonAnywhere: $ git clone https://github.com//my-first-blog.git - + Isto puxará uma cópia do seu código para PythonAnywhere. Confira digitando: @@ -178,26 +178,26 @@ Isto puxará uma cópia do seu código para PythonAnywhere. Confira digitando: ├── settings.py ├── urls.py └── wsgi.py - + ### Criando um virtualenv na PythonAnywhere Assim como fez em seu próprio computador, você pode criar um virtualenv na PythonAnywhere. No console Bash, digite: 20:20 ~ $ cd my-first-blog - + 20:20 ~ $ virtualenv --python=python3.4 myvenv Running virtualenv with interpreter /usr/bin/python3.4 [...] Installing setuptools, pip...done. - - 20:20 ~ $ source myenv/bin/activate - + + 20:20 ~ $ source myvenv/bin/activate + (mvenv)20:20 ~ $ pip install django whitenoise Collecting django [...] - Successfully installed django-1.8.2 whitenoise-2.0 - + Successfully installed django-1.8.5 whitenoise-2.0 + @@ -210,17 +210,17 @@ Vamos descobrir um pouco mais sobre arquivos estáticos mais tarde no tutorial, Por enaunto só precisamos executar um comando extra chamado "collectstatic" no servidor. Isso diz pro Django reunir todos os arquivos estáticos que ele precisa no servidor. Em sua maioria, estes são os arquivos estáticos que fazem o site do admin bonito no momento. 20:20 ~ $ python manage.py collectstatic - + You have requested to collect static files at the destination location as specified in your settings: - + /home/edith/my-first-blog/static - + This will overwrite existing files! Are you sure you want to do this? - + Type 'yes' to continue, or 'no' to cancel: yes - + Digite "Sim" e vai embora! Você não adora fazer computadores imprimir páginas e páginas de texto? Sempre faço pequenos ruídos para acompanhá-lo. Brp, brp brp... @@ -230,7 +230,7 @@ Digite "Sim" e vai embora! Você não adora fazer computadores imprimir páginas Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' 62 static files copied to '/home/edith/my-first-blog/static'. - + ### Criando o banco de dados em PythonAnywhere @@ -242,10 +242,10 @@ Então nós vamos inicializar o banco de dados no servidor tal como fizemos no s Operations to perform: [...] Applying sessions.0001_initial... OK - - + + (mvenv)20:20 ~ $ python manage.py createsuperuser - + ## Publicação do nosso blog como um aplicativo web @@ -265,7 +265,7 @@ Você será levado para a tela de configuração de PythonAnywhere para seu weba [10]: images/pythonanywhere_web_tab_virtualenv.png -Na seção "Virtualenv", clique no texto vermelho que diz "Enter the path to a virtualenv" e digite: */home//my-first-blog/myvenv/* +Na seção "Virtualenv", clique no texto vermelho que diz "Enter the path to a virtualenv" e digite: `/home//my-first-blog/myvenv/` > **Nota**: substitua seu próprio nome de usuário conforme apropriado. Se você cometer um erro, PythonAnywhere irá mostrar um pequeno aviso. @@ -314,4 +314,4 @@ O treinador está aqui para ajudar! A página padrão para seu site deve dizer "Bem-vindo ao Django", como acontece no seu PC local. Tente adicionar `/admin/` para o final da URL, e você será levado ao site admin. Fazer login com o nome de usuário e senha, e você verá que você pode adicionar novas mensagens no servidor. -Dë em você mesma um *enorme* tapinha nas costas - implantações de servidor são uma das partes mais difíceis do desenvolvimento web, e muitas vezes leva as pessoas vários dias antes de fazer funcionar. Mas você tem seu site publicado, na internet, assim! \ No newline at end of file +Dë em você mesma um *enorme* tapinha nas costas - implantações de servidor são uma das partes mais difíceis do desenvolvimento web, e muitas vezes leva as pessoas vários dias antes de fazer funcionar. Mas você tem seu site publicado, na internet, assim! diff --git a/pt/django/README.md b/pt/django/README.md index 31a9d998ac6..d7d1904c403 100755 --- a/pt/django/README.md +++ b/pt/django/README.md @@ -4,13 +4,13 @@ Django é um framework gratuito e de código aberto para a criação de aplicaç Veja, quando você está construindo um site, você sempre precisa um conjunto similar de componentes: uma maneira de lidar com a autenticação do usuário (inscrever-se, realizar login, realizar logout), painel de gerenciamento para o seu site, formulários, upload de arquivos, etc. -Felizmente para você, há muito tempo, outras pessoas notaram varias semelhanças nos problemas enfrentados pelos desenvolvedores web quando estão criando um novo site, então eles uniram-se e criaram os frameworks (Django é um deles) que lhe dão componentes prontos, que você pode usar. +Felizmente para você, há muito tempo, outras pessoas notaram várias semelhanças nos problemas enfrentados pelos desenvolvedores web quando estão criando um novo site, então eles uniram-se e criaram os frameworks (Django é um deles) que lhe dão componentes prontos, que você pode usar. Frameworks existem para salvá-lo de ter que reinventar a roda e ajudam a aliviar a sobrecarga quando você está construindo um novo site. ## Por que você precisa de um framework? -Para entender o que Django é na verdade, precisamos olhar mais de perto os servidores. A primeira coisa é que o servidor precisa saber que você quer para servi-lo uma página da Web. +Para entender o que Django é na verdade, precisamos olhar mais de perto os servidores. A primeira coisa é que o servidor precisa saber o que você quer para servi-lo uma página da Web. Imagine uma caixa de correio (porta) que é monitorada por cartas recebidas (requisição). Isso é feito por um servidor web. O servidor web lê a carta e envia uma resposta com uma página web. Mas, quando você quer enviar alguma coisa você precisa ter um conteúdo. E o Django é aquilo que vai lhe ajudar a criar esse conteúdo. @@ -24,4 +24,4 @@ Todas as coisas interessantes são feitas dentro da *view*: podemos dar uma olha Claro, a descrição acima é muito simplificada, mas você não precisa saber detalhes técnicos ainda. Ter uma ideia geral já é suficiente. -Então em vez de mergulhar em muitos detalhes, nós simplesmente vamos começar criando algo com o Django e aprenderemos toda as partes importantes ao longo do caminho! \ No newline at end of file +Então em vez de mergulhar em muitos detalhes, nós simplesmente vamos começar criando algo com o Django e aprenderemos todas as partes importantes ao longo do caminho! diff --git a/pt/django_admin/README.md b/pt/django_admin/README.md index 1ada6b1bc63..9281a7d8afb 100755 --- a/pt/django_admin/README.md +++ b/pt/django_admin/README.md @@ -43,6 +43,6 @@ Certifique-se que pelo menos duas ou três postagens (mas não todas) têm a dat [3]: images/edit_post3.png -Se você quiser saber mais sobre o Django admin, você deve conferir a documentação do Django: https://docs.djangoproject.com/en/1.6/ref/contrib/admin/ +Se você quiser saber mais sobre o Django admin, você deve conferir a documentação do Django: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ -Este é provavelmente um bom momento para tomar um café (ou chocolate) ou algo para comer para repora as energias. Você criou seu primeiro modelo de Django - você merece um pouco de descanso! +Este é provavelmente um bom momento para tomar um café (ou chocolate) ou algo para comer para repor as energias. Você criou seu primeiro modelo de Django - você merece um pouco de descanso! diff --git a/pt/django_forms/README.md b/pt/django_forms/README.md index 393144908b9..af4c937e580 100755 --- a/pt/django_forms/README.md +++ b/pt/django_forms/README.md @@ -93,8 +93,8 @@ url(r'^post/new/$', views.post_new, name='post_new'), O código final deve se parecer com isso: ``` python -from django.conf.urls import include, url -from . mport views +from django.conf.urls import url +from . import views urlpatterns = [ url(r'^$', views.post_list), @@ -197,6 +197,7 @@ Verificamos se o formulário é válido e se estiver tudo certo, podemos salvá- if form.is_valid(): post = form.save(commit=False) post.author = request.user + post.published_date = timezone.now() post.save() ``` @@ -225,6 +226,7 @@ def post_new(request): if form.is_valid(): post = form.save(commit=False) post.author = request.user + post.published_date = timezone.now() post.save() return redirect('blog.views.post_detail', pk=post.pk) else: @@ -232,7 +234,7 @@ def post_new(request): return render(request, 'blog/post_edit.html', {'form': form}) ``` -Vamos ver se funciona. Vá para o página http://127.0.0.1:8000/post/novo /, adicione um `title` e o `text`, salve... e voilà! O novo blog post é adicionado e nós somos redirecionados para a página de `post_detail`! +Vamos ver se funciona. Vá para o página http://127.0.0.1:8000/post/new/, adicione um `title` e o `text`, salve... e voilà! O novo blog post é adicionado e nós somos redirecionados para a página de `post_detail`! Você provavelmente notou que nós não estamos definindo a data de publicação em tudo. Vamos introduzir um *botão de publicação* em **Django Girls Tutorial: Extensões**. @@ -280,7 +282,7 @@ Agora o modelo estará parecido com:

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endblock %} ``` @@ -303,6 +305,7 @@ def post_edit(request, pk): if form.is_valid(): post = form.save(commit=False) post.author = request.user + post.published_date = timezone.now() post.save() return redirect('blog.views.post_detail', pk=post.pk) else: @@ -338,7 +341,7 @@ Sinta-se livre para mudar o título ou o texto e salvar as mudanças! Parabéns! Sua aplicação está ficando cada vez mais completa! -Se você precisar de mais informações sobre formulários do Django você deve ler a documentação: https://docs.djangoproject.com/en/1.6/topics/forms/ +Se você precisar de mais informações sobre formulários do Django você deve ler a documentação: https://docs.djangoproject.com/en/1.8/topics/forms/ ## Mais uma coisa: hora de implantar! @@ -348,7 +351,7 @@ Vamos ver se tudo isso funciona na PythonAnywhere. Tempo para outro deploy! ```bash $ git status -$ git add -A . +$ git add --all . $ git status $ git commit -m "Added views to create/edit blog post inside the site." $ git push diff --git a/pt/django_installation/README.md b/pt/django_installation/README.md index 9ca44a1747e..34f22f79e98 100755 --- a/pt/django_installation/README.md +++ b/pt/django_installation/README.md @@ -1,6 +1,6 @@ # Instalação do Django -> Parte deste capítulo é baseado nos tutoriais do Geek Girls Carrots (http://django.carrots.pl/). +> Parte deste capítulo é baseado nos tutoriais do Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > > Parte deste capítulo é baseado no [django-marcador tutorial][1] licenciado sobre Creative Commons Attribution-ShareAlike 4.0 International License. O tutorial do django-marcador é protegido por direitos autorais por Markus Zapke-Gründemann et al. @@ -8,7 +8,7 @@ ## Ambiente virtual -Antes de instalarmos o Django, nós iremos instalar uma ferramenta extremamente útil que irá ajudar a manter seu ambiente de desenvolvimento arrumado em seu computador. É possível ignorar este passo, mas é altamente recomendado não começar com a melhor configuração, evitando problemas adiante! +Antes de instalarmos o Django, nós iremos instalar uma ferramenta extremamente útil que irá ajudar a manter seu ambiente de desenvolvimento arrumado em seu computador. É possível ignorar este passo, mas ele é altamente recomendado. Começar com a melhor configuração possível te salvará de muitos problemas no futuro! Então, vamos criar um **ambiente virtual**(também chamado um *virtualenv*). Isso isolará sua configuração Python/Django em uma base por projeto, significa que quaisquer mudanças que fizer em um website não afetará quaisquer outras aplicações que estiver desenvolvendo a parte. Arrumado, certo? @@ -20,7 +20,7 @@ Para este tutorial usaremos um novo diretório`djangogirls` do seu diretório ho cd djangogirls -Nós vamos fazer um virtualenv chamado `meuenv`. O formato geral desse comando é: +Nós vamos fazer um virtualenv chamado `myvenv`. O formato geral desse comando é: python3 -m venv myvenv @@ -70,7 +70,7 @@ no OS X e no Linux. Lembre-se de substituir `myvenv` com seu nome escolhido do `virtualenv`! -> **NOTE:** às vezes `source(fonte)` pode não estar disponível. Nesses casos, tente fazer isso em vez disso: +> **NOTE:** às vezes `source(fonte)` pode não estar disponível. Nesses casos, tente fazer isso: > > ~/djangogirls$ . myvenv/bin/activate > @@ -93,10 +93,10 @@ Ok, nós temos todas as dependências importantes no lugar. Finalmente podemos i ## Instalando o Django -Agora que você tem a sua `virtualenv` iniciado, você pode instalar Django usando `pip`. No console, execute `pip install django==1.7.1` (Perceba que usamos um duplo sinal de igual: `==`). +Agora que você tem a sua `virtualenv` iniciado, você pode instalar Django usando `pip`. No console, execute `pip install django==1.8.5` (Perceba que usamos um duplo sinal de igual: `==`). - (myvenv) ~$ pip install django==1.8 - Downloading/unpacking django==1.8 + (myvenv) ~$ pip install django==1.8.5 + Downloading/unpacking django==1.8.5 Installing collected packages: django Successfully installed django Cleaning up... @@ -110,4 +110,4 @@ No Linux > Se você receber um erro ao chamar pip no Ubuntu 12.04 por favor execute `python -m pip install -U --force-reinstall pip` para corrigir a instalação do pip no virtualenv. -É isso! Agora você está (finalmente) pronto para criar uma aplicação Django! \ No newline at end of file +É isso! Agora você está (finalmente) pronto para criar uma aplicação Django! diff --git a/pt/django_orm/README.md b/pt/django_orm/README.md index df530bdd23d..2503cc047f1 100755 --- a/pt/django_orm/README.md +++ b/pt/django_orm/README.md @@ -106,7 +106,8 @@ Ou talvez nós queremos ver todos os posts que contenham a palavra 'title' no ca Você também pode obter uma lista de todos os posts publicados. Fazemos isso filtrando todos os posts com `published_date` definido no passado: -> > > from django.utils import timezone Post.objects.filter(published_date__lte=timezone.now()) [] +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) [] Infelizmente, nenhum dos nossos posts estão publicados ainda. Nós podemos mudar isso! Primeiro obtenha uma instância de um post que queremos publicar: @@ -141,4 +142,4 @@ Você também pode inverter a ordem adicionando `-` no início: Legal! Você já está pronto para a próxima parte! Para fechar o terminal digite: >>> exit() - $ \ No newline at end of file + $ diff --git a/pt/django_start_project/README.md b/pt/django_start_project/README.md index 0c6f3b9ba96..cb4caab2eaf 100755 --- a/pt/django_start_project/README.md +++ b/pt/django_start_project/README.md @@ -1,6 +1,6 @@ # Seu primeiro projeto Django! -> Parte deste capítulo é baseado nos tutoriais do Geek Girls Carrots (http://django.carrots.pl/). +> Parte deste capítulo é baseado nos tutoriais do Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). > > Parte deste capítulo é baseado no [django-marcador tutorial][1] licenciado sobre Creative Commons Attribution-ShareAlike 4.0 International License. O tutorial do django-marcador é protegido por direitos autorais por Markus Zapke-Gründemann et al. @@ -23,7 +23,7 @@ No console, você deve executar (Lembre-se de que você não pode digitar `~/dja no Windows: - (myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . + (myvenv) C:\Users\Name\djangogirls> python myvenv\Scripts\django-admin.py startproject mysite . `Django-admin` é um script que irá criar os diretórios e arquivos para você. Agora, você deve ter um diretório estrutura que se parece com isso: @@ -49,17 +49,17 @@ Vamos ignorar os outros arquivos por agora - nós não vamos mudá-los. A única Vamos fazer algumas alterações no `mysite/settings.py`. Abra o arquivo usando o editor de código que você instalou anteriormente. -Seria bom ter a hora correta no nosso site. Vá para a <[wikipedia timezones list][2] e copie seu fuso horário. (por exemplo. `Europa/Berlim`) +Seria bom ter a hora correta no nosso site. Vá para a <[wikipedia timezones list][2] e copie seu fuso horário. (por exemplo. `America/Sao_Paulo`) - [2]: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones Em settings.py, localize a linha que contém `TIME_ZONE` e modifique para escolher seu próprio fuso horário: ```python -TIME_ZONE = 'Europe/Berlin' +TIME_ZONE = 'America/Sao_Paulo' ``` -Modifique "Europa/Berlim", conforme o caso +Modifique "America/Sao_Paulo", conforme o caso Nós também precisaramos adicionar um caminho para arquivos estáticos (nós vamos descobrir tudo sobre arquivos estáticos e CSS mais tarde no tutorial). Desça até o *final* do arquivo e logo abaixo da entrada `STATIC_URL`, adicione um novo um chamado `STATIC_ROOT`: @@ -70,7 +70,7 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'static') ## Instalação de um banco de dados -Há um monte de software de banco de dados diferente que pode armazenar dados para o seu site. Nós vamos usar o padrão, `sqlite3`. +Há vários softwares de banco de dados diferentes que pode armazenar dados para o seu site. Nós vamos usar o padrão, `sqlite3`. Isto já está configurado nesta parte do seu arquivo `mysite/settings.py`: @@ -115,4 +115,4 @@ Parabéns! Você criou seu primeiro site e o executou usando um servidor de web! [3]: images/it_worked2.png -Pronto para o próximo passo? Está na hora de criar algum conteúdo! \ No newline at end of file +Pronto para o próximo passo? Está na hora de criar algum conteúdo! diff --git a/pt/django_templates/README.md b/pt/django_templates/README.md index 1e493a39986..90b994f72dc 100755 --- a/pt/django_templates/README.md +++ b/pt/django_templates/README.md @@ -54,7 +54,7 @@ Funciona! Mas nós queremos que eles sejam exibidos como os posts estáticos, co

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` @@ -65,7 +65,7 @@ Tudo que você põe enrte `{% for %}` e `{% endfor %}` será repetido para cada [3]: images/step3.png -Você notou que dessa vez nós usamos uma notação um pouco diferente `{{ post.title }}` ou `{{ post.text }}`? Nós estamos acessando os dados em cada um dos campos que definimos no model do `Post`. Além disso, `|linebreaks` está passando o texto do post por um filtro, convertendo quebras de linha em parágrafos. +Você notou que dessa vez nós usamos uma notação um pouco diferente `{{ post.title }}` ou `{{ post.text }}`? Nós estamos acessando os dados em cada um dos campos que definimos no model do `Post`. Além disso, `|linebreaksbr` está passando o texto do post por um filtro, convertendo quebras de linha em parágrafos. ## Mais uma coisa @@ -75,7 +75,7 @@ Seria bom ver se seu site ainda estará funcionando na internet, certo? Vamos te ``` $ git status - $ git add -A . + $ git add --all . $ git status $ git commit -m "Added views to create/edit blog post inside the site." $ git push diff --git a/pt/django_urls/README.md b/pt/django_urls/README.md index b1aefe8ee4c..a63fbe1105c 100755 --- a/pt/django_urls/README.md +++ b/pt/django_urls/README.md @@ -4,7 +4,7 @@ Estamos prestes a construir nossa primeira Web page - uma página inicial para o ## O que é uma URL? -Uma URL é simplesmente um endereço da web, você pode ver uma URL toda vez que você visita qualquer site - é visível na barra de endereços do seu navegador (Sim! `127.0.0.1:8000` é uma URL! E http://djangogirls.com também é uma URL): +Uma URL é simplesmente um endereço da web, você pode ver uma URL toda vez que você visita qualquer site - é visível na barra de endereços do seu navegador (Sim! `127.0.0.1:8000` é uma URL! E http://djangogirls.org também é uma URL): ![URL][1] @@ -120,4 +120,4 @@ Não tem mais "It Works!' mais ein? Não se preocupe, é só uma página de erro Você pode ler que não há **no attribute 'post_list'**. O *post_list* te lembra alguma coisa? Isto é como chamamos o nosso view! Isso significa que está tudo no lugar, só não criamos nossa *view* ainda. Não se preocupe, nós chegaremos lá. -> Se você quer saber mais sobre Django URLconfs, veja a documentação oficial: https://docs.djangoproject.com/en/1.7/topics/http/urls/ +> Se você quer saber mais sobre Django URLconfs, veja a documentação oficial: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/pt/django_views/README.md b/pt/django_views/README.md index 39c5c325b44..077726964df 100755 --- a/pt/django_views/README.md +++ b/pt/django_views/README.md @@ -35,4 +35,4 @@ Outro erro! Leia o que está acontecendo agora: Esta é fácil: *TemplateDoesNotExist*. Vamos corrigir este bug e criar um modelo no próximo capítulo! -> Aprenda mais sobre as views do Django lendo a documentação oficial: https://docs.djangoproject.com/en/1.6/topics/http/views/ +> Aprenda mais sobre as views do Django lendo a documentação oficial: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/pt/dynamic_data_in_templates/README.md b/pt/dynamic_data_in_templates/README.md index 979da6ef255..ae15a38fe96 100755 --- a/pt/dynamic_data_in_templates/README.md +++ b/pt/dynamic_data_in_templates/README.md @@ -28,7 +28,7 @@ E o que vem agora? Para pegar os posts reais do model `Post` nós precisamos de ## QuerySet -Você já deve estar familiarizado com o modo que os QuerySets funcionam. Nós conversamos sobre isso no [capítulo ORM do Django (QuerySets)][2].

+Você já deve estar familiarizado com o modo que os QuerySets funcionam. Nós conversamos sobre isso no [capítulo ORM do Django (QuerySets)][2]. Agora nós estamos interessados em uma lista de posts que são publicados e classificados por `published_date`, certo? Nós já fizemos isso no capítulo QuerySets! ```python @@ -67,6 +67,6 @@ def post_list(request): Feito! Hora de voltar para o nosso template e exibir essa QuerySet! -Se quiser ler mais sobre QuerySets no Django você deve dar uma olhada aqui: https://docs.djangoproject.com/en/1.7/ref/models/querysets/ +Se quiser ler mais sobre QuerySets no Django você deve dar uma olhada aqui: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ [2]: /django_orm/README.html diff --git a/pt/extend_your_application/README.md b/pt/extend_your_application/README.md index 5a01024d8e9..7def24c838c 100755 --- a/pt/extend_your_application/README.md +++ b/pt/extend_your_application/README.md @@ -4,7 +4,7 @@ Já concluímos todos os passos necessários para a criação do nosso site: sab Hora de praticar! -A primeira que precisamos no nosso blog é, obviamente, uma página para mostrar uma postagem, certo? +A primeira coisa que precisamos no nosso blog é, obviamente, uma página para mostrar uma postagem, certo? Já temos um modelo de `Post`, então não precisamos adicionar nada ao `models.py`. @@ -22,7 +22,7 @@ Vamos começar com a adição de um link dentro do arquivo `blog/templates/blog/ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} @@ -51,7 +51,7 @@ Vamos criar a URL em `urls.py` para a nossa`post_detail` *view*! Queremos criar uma URL para guiar o Django para a *view* chamada `post_detail`, que irá mostrar um post completo do blog. Adicione a linha `url(r'^post/(?P[0-9]+)/$', views.post_detail),` ao arquivo `blog/urls.py`. Deve ficar assim: ```python -from django.conf.urls import include, url +from django.conf.urls import url from . import views urlpatterns = [ @@ -140,7 +140,7 @@ Será algo parecido com isto: {% endif %}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endblock %} ``` @@ -162,7 +162,7 @@ Yay! Funciona! Seria bom ver se seu site ainda estará trabalhando em PythonAnywhere, certo? Vamos tentar fazer deploy novamente. ```bash $ git status -$ git add -A . +$ git add --all . $ git status $ git commit -m "Added views to create/edit blog post inside the site." $ git push diff --git a/pt/how_the_internet_works/README.md b/pt/how_the_internet_works/README.md index a5202a3e4cd..c4ee064691f 100755 --- a/pt/how_the_internet_works/README.md +++ b/pt/how_the_internet_works/README.md @@ -2,7 +2,7 @@ > Este capítulo é inspirado na palestra "Como a Internet funciona" de Jessica McKellar (http://web.mit.edu/jesstess/www/). -Apostamos que você usa a Internet todos os dias. Mas você sabe realmente o que acontece quando você digita um endereço como http://djangogirls.org em seu navegador e pressiona 'Enter'? +Apostamos que você usa a Internet todos os dias. Mas você sabe realmente o que acontece quando você digita um endereço como https://djangogirls.org em seu navegador e pressiona 'Enter'? A primeira coisa que você precisa entender é que um site é só um monte de arquivos salvos em um disco rígido. Assim como seus filmes, músicas ou fotos. No entanto, há uma parte que é exclusiva para sites: essa parte inclui códigos de computador chamado HTML. @@ -20,13 +20,13 @@ Que bagunça né? Na verdade é uma rede de máquinas conectadas (os *servidores ![Figura 1.2](images/internet_3.png) -Fascinante, não? Mas, obviamente, não é possível ter um fio conectado a toda máquina ligada na internet. Logo, para chegar em uma máquina (por exemplo aquela onde http://djangogirls.org está salva) nós precisamos passar uma requisição por muitas máquinas diferentes. +Fascinante, não? Mas, obviamente, não é possível ter um fio conectado a toda máquina ligada na internet. Logo, para chegar em uma máquina (por exemplo aquela onde https://djangogirls.org está salva) nós precisamos passar uma requisição por muitas máquinas diferentes. Se parece com isso: ![Figura 1.3](images/internet_2.png) -Imagine que quando você digita http://djangogirls.org você envia uma carta que diz: "Querido Django Girls, eu desejo ver o site djangogirls.org. Envie ele pra mim, por favor!" +Imagine que quando você digita https://djangogirls.org você envia uma carta que diz: "Querido Django Girls, eu desejo ver o site djangogirls.org. Envie ele pra mim, por favor!" Sua carta vai para a agência dos correios mais próxima de você. Depois vai para outra que é um pouco mais perto do seu destinatário, depois para outra e outra até que seja entregue ao seu destino. O único diferencial é que se você enviar cartas (*pacotes de dados*) com freqüência para o mesmo lugar, cada carta pode passar por diferentes agências de correios (*roteadores*), dependendo de como elas são distribuídas em cada agência. diff --git a/pt/how_the_internet_works/images/internet_1.png b/pt/how_the_internet_works/images/internet_1.png index 9c5bcf0b003..21bf592af8e 100644 Binary files a/pt/how_the_internet_works/images/internet_1.png and b/pt/how_the_internet_works/images/internet_1.png differ diff --git a/pt/how_the_internet_works/images/internet_2.png b/pt/how_the_internet_works/images/internet_2.png index dd5861f376f..726d432fc03 100644 Binary files a/pt/how_the_internet_works/images/internet_2.png and b/pt/how_the_internet_works/images/internet_2.png differ diff --git a/pt/how_the_internet_works/images/internet_4.png b/pt/how_the_internet_works/images/internet_4.png index 05f1aed562f..ddadf75d984 100644 Binary files a/pt/how_the_internet_works/images/internet_4.png and b/pt/how_the_internet_works/images/internet_4.png differ diff --git a/pt/html/README.md b/pt/html/README.md index ff79e0645b8..fb788da123f 100755 --- a/pt/html/README.md +++ b/pt/html/README.md @@ -105,7 +105,7 @@ Agora você pode se divertir um pouco tentando customizar o seu template! Aqui e * `texto` enfatiza seu texto * `text` enfatiza fortemente seu texto * `
` pula para a próxima linha (você não pode colocar nada dentro de br) -* `link` cria um link +* `link` cria um link * `
  • primeiro item
  • segundo item
` cria uma lista, exatamente como essa! * `
` define uma seção da página @@ -164,7 +164,7 @@ Primeiro de tudo, vejamos quais arquivos foram alterados desde a última implant Verifique se você está no diretório `djangogirls` e vamos dizer ao `git` para incluir todas as mudanças dentro deste diretório: - $ git add -A . + $ git add --all . > **Nota** `-A` (abreviação de "all", tudo em inglês) significa que o `git` também reconhecerá se você deletou algum arquivo (por padrão, o git apenas reconhece arquivos criados/modificados). Lembre-se também (do capítulo 3) que `.` significa o diretório atual. @@ -190,7 +190,14 @@ Quando fizermos isso, nós fazemos upload (envio) das nossas mudanças para o Py * Abra a [página de consoles de PythonAnywhere][5] e vá para o seu **console Bash** (ou começar um novo). Em seguida, execute: - $ cd ~/my-first-blog $ git pull [...] +``` + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` [5]: https://www.pythonanywhere.com/consoles/ diff --git a/pt/intro_to_command_line/README.md b/pt/intro_to_command_line/README.md index 54f54920e95..002553086da 100755 --- a/pt/intro_to_command_line/README.md +++ b/pt/intro_to_command_line/README.md @@ -157,7 +157,7 @@ Windows: > mkdir djangogirls -Este comando vai criar uma pasta com o nome `djangogirls` no nosso desktop. Você pode verificar se ele está lá, só de olhar na sua área de trabalho ou executando um comando `ls`/`dir`! Experimente :) +Este comando vai criar uma pasta com o nome `djangogirls` no nosso desktop. Você pode verificar se ele está lá, só de olhar na sua área de trabalho ou executando um comando `ls` (Mac ou Linux) ou `dir` (Windows)! Experimente :) > Dica de profissional: Se você não quiser digitar o mesmo comando várias vezes, tente pressionar `seta para cima` e `seta para baixo` no teclado para percorrer comandos usados recentemente. diff --git a/pt/python_installation/README.md b/pt/python_installation/README.md index cec6d2c9dcc..465ef8a0713 100755 --- a/pt/python_installation/README.md +++ b/pt/python_installation/README.md @@ -8,9 +8,9 @@ O Python é originário da década de 1980 e seu principal objetivo é ser legí # Instalação do Python -> Este subcapítulo é baseado em um tutorial criado por Geek Girls Carrots (http://django.carrots.pl/) +> Este subcapítulo é baseado em um tutorial criado por Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) -Django é escrito em Python. Nó precisamos dele para fazer qualquer coisa em Django. Vamos começar com sua instalação! Nós queremos que você instale o Python 3.4, então se você tem qualquer versão anterior, você vai precisar atualizá-la. +Django é escrito em Python. Nós precisamos dele para fazer qualquer coisa em Django. Vamos começar com sua instalação! Nós queremos que você instale o Python 3.4, então se você tem qualquer versão anterior, você vai precisar atualizá-la. ### Windows @@ -46,6 +46,13 @@ Use o seguinte comando no terminal: sudo yum install python3.4 +#### openSUSE + +Use o seguinte comando no terminal: + + sudo zypper install python3 + + ### OS X Você precisa acessar o site https://www.python.org/downloads/release/python-342/ e baixar o instalador do Python: @@ -62,4 +69,4 @@ Verifique se a instalação foi bem sucedida abrindo o *Terminal* e digitando o * * * -Se você tiver qualquer dúvida ou se alguma coisa deu errado e você não sabe o que fazer - por favor pergunte ao seu instrutor! Às vezes, as coisas não estão indo bem e é melhor pedir ajuda a alguém com mais experiência. \ No newline at end of file +Se você tiver qualquer dúvida ou se alguma coisa deu errado e você não sabe o que fazer - por favor pergunte ao seu instrutor! Às vezes, as coisas não estão indo bem e é melhor pedir ajuda a alguém com mais experiência. diff --git a/pt/python_installation/images/add_python_to_windows_path.png b/pt/python_installation/images/add_python_to_windows_path.png index 7946019bc29..9510d6f2176 100644 Binary files a/pt/python_installation/images/add_python_to_windows_path.png and b/pt/python_installation/images/add_python_to_windows_path.png differ diff --git a/pt/python_introduction/README.md b/pt/python_introduction/README.md index a0affe89863..899a5e5e428 100755 --- a/pt/python_introduction/README.md +++ b/pt/python_introduction/README.md @@ -1,12 +1,12 @@ # Introdução ao Python -> Parte deste capítulo é baseado nos Tutoriais de Geek Girls Carrots (http://django.carrots.pl/). +> Parte deste capítulo é baseado nos Tutoriais de Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Vamos escrever um pouco de código! ## Interpretador Python -Para começar a brincar com Python nós precisamos abrir uma *linha de comando* no seu computador. Você já sabe dever como fazer isso -- você aprendeu isso no capítulo [Introdução à Linha de Comando][2].

+Para começar a brincar com Python nós precisamos abrir uma *linha de comando* no seu computador. Você já deve saber como fazer isso -- você aprendeu isso no capítulo [Introdução à Linha de Comando][2]. Assim que estiver pronto, siga as instruções abaixo. Nós queremos abrir o Python num terminal, então digite `python3` e tecle Enter. @@ -127,27 +127,27 @@ Um conceito importante na programação é o conceito de variáveis. Uma variáv Digamos que queremos criar uma nova variável chamada `nome`: - >>> name = "Ola" + >>> nome = "Ola" Vê? É fácil! É só fazer: nome igual a Ola. Como você percebeu, seu programa não retornou nada como fez anteriormente. Então como sabemos que a variável realmente existe? Simplesmente digite `nome` e tecle Enter: - >>> name + >>> nome 'Ola' -Yippee! Sua primeira variável:)! Você sempre pode mudar o seu valor: +Yippee! Sua primeira variável! :) Você sempre pode mudar o seu valor: - >>> name = "Sonja" - >>> name + >>> nome = "Sonja" + >>> nome 'Sonja' Você pode usá-la também em funções: - >>> len(name) + >>> len(nome) 5 @@ -176,14 +176,14 @@ Brinque com isso por um tempo e veja o que você consegue fazer! Tente isso: - >>> name = 'Maria' - >>> name + >>> nome = 'Maria' + >>> nome 'Maria' - >>> print(name) + >>> print(nome) Maria -Quando você apenas digita `name`, o interpretador Python responde com a *representação* como string da variável 'name', que são as letras M-a-r-i-a, entre aspas simples. Quando você diz `print(name)`, Python vai "imprimir" o conteúdo da variável na tela, sem as aspas, o que é mais puro. +Quando você apenas digita `nome`, o interpretador Python responde com a *representação* como string da variável 'name', que são as letras M-a-r-i-a, entre aspas simples. Quando você diz `print(nome)`, Python vai "imprimir" o conteúdo da variável na tela, sem as aspas, o que é mais puro. Como veremos mais tarde, `print()` também é útil quando queremos imprimir algo dentro de funções, ou quando queremos imprimir algo em várias linhas. @@ -199,23 +199,23 @@ Vá em frente e crie uma lista: Sim, esta é uma lista vazia. Não é muito, não é? Vamos criar uma lista dos números da loteria. Como não queremos ficar repetindo o código todo o tempo vamos criar uma variável para ela: - >>> lottery = [3, 42, 12, 19, 30, 59] + >>> loteria = [3, 42, 12, 19, 30, 59] Tudo certo, nós temos uma lista! O que podemos fazer com isso? Vamos ver quantos números de loteria existem nesta lista. Você tem ideia de qual função deve usar para isso? Você já sabe disso! - >>> len(lottery) + >>> len(loteria) 6 Sim! `len()` pode te dar o número de objetos que fazem parte de uma lista. Uma mão na roda, não? Vamos organizar isso agora: - >>> lottery.sort() + >>> loteria.sort() Isso não retorna nada, apenas troca a ordem em que os números aparecem na lista. Vamos imprimir isso outra vez e ver o que acontece: - >>> print(lottery) + >>> print(loteria) [3, 12, 19, 30, 42, 59] @@ -223,23 +223,23 @@ Como você pode ver, os números na nossa lista estão ordenados do menor para o Talvez a gente queira inverter essa ordem? Vamos fazer isso! - >>> lottery.reverse() - >>> print(lottery) + >>> loteria.reverse() + >>> print(loteria) [59, 42, 30, 19, 12, 3] Moleza né? Se você quiser adicionar alguma coisa à sua lista, você pode fazer isto digitando o seguinte comando: - >>> lottery.append(199) - >>> print(lottery) + >>> loteria.append(199) + >>> print(loteria) [59, 42, 30, 19, 12, 3, 199] -Se você quiser mostrar apenas o primeiro número você pode usar **indices**. Um índice é um número que diz onde um item da lista está. Os computadores gostam de iniciar a contagem por 0, então o primeiro objeto tem índice 0, o próximo tem índice 1 e por aí vai. Tente isso: +Se você quiser mostrar apenas o primeiro número você pode usar **índices**. Um índice é um número que diz onde um item da lista está. Os computadores gostam de iniciar a contagem por 0, então o primeiro objeto tem índice 0, o próximo tem índice 1 e por aí vai. Tente isso: - >>> print(lottery[0]) + >>> print(loteria[0]) 59 - >>> print(lottery[1]) + >>> print(loteria[1]) 42 @@ -261,7 +261,7 @@ Isso mostra que você acabou de criar um dicionário vazio. Hurra! Agora, tente escrever o seguinte comando (tente substituir com as suas próprias informações também): - >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + >>> participante = {'nome': 'Ola', 'pais': 'Polonia', 'numeros_favoritos': [7, 42, 92]} Com esse comando, você acabou de criar uma variável chamada `participant` com três pares de chave-valor: @@ -272,7 +272,7 @@ Com esse comando, você acabou de criar uma variável chamada `participant` com Você pode checar o conteúdo de chaves individuais com a sintaxe: - >>> print(participant['name']) + >>> print(participante['nome']) Ola @@ -280,13 +280,13 @@ Veja, é similar a uma lista. Mas você não precisa lembrar o índice - apenas O que acontece se pedirmos ao Python o valor de uma chave que não existe? Você consegue adivinhar? Vamos tentar e descobrir! - >>> participant['age'] + >>> participante['idade'] Traceback (most recent call last): File "", line 1, in - KeyError: 'age' + KeyError: 'idade' -Olha, outro erro! Esse é um **KeyError**. Python é bastante prestativo e te diz que a chave `'age'` não existe no nesse dicionário. +Olha, outro erro! Esse é um **KeyError**. Python é bastante prestativo e te diz que a chave `'idade'` não existe nesse dicionário. Quando usar um dicionario ou uma lista? Bem, um bom ponto para refletir. Pense em uma solução antes de olhar a resposta na próxima linha. @@ -295,34 +295,32 @@ Quando usar um dicionario ou uma lista? Bem, um bom ponto para refletir. Pense e Dicionários, como listas, são *mutáveis*, ou seja, que podem ser mudados depois que são criados. Você pode adicionar novos pares de chave/valor para o dicionário após sua criação, como: - >>> participant['favorite_language'] = 'Python' + >>> participante['linguagem_favorita'] = 'Python' Como as lists, usar o método `len()` em dicionários retorna o número de pares chave-valor no dicionario. Vá em frente e digite o comando: - >>> len(participant) + >>> len(participante) 4 Espero que agora faça sentido até agora. :) Pronta para mais diversão com dicionários? Pule na próxima linha para coisas incríveis. -Você pode usar o comando `del` para deletar um item no dicionario. Digamos, se você quer excluir a entrada correspondente a chave `'favorite_numbers'`, basta digitar o seguinte comando: +Você pode usar o comando `pop()` para deletar um item no dicionario. Digamos, se você quer excluir a entrada correspondente a chave `'numeros_favoritos'`, basta digitar o seguinte comando: - >>> del participant['favorite_numbers'] - >>> participant - {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} - + >>> participante.pop('numeros_favoritos') + >>> participante + {'pais': 'Polonia', 'linguagem_favorita': 'Python', 'nome': 'Ola'} -Como você pode ver no retorno, o par chave-valor correspondente à chave 'favorite_numbers' foi excluído. +Como você pode ver no retorno, o par chave-valor correspondente à chave 'numeros_favoritos' foi excluído. Além disso você pode mudar o valor associado com uma chave já criada no dicionário. Digite: - >>> participant['country'] = 'Germany' - >>> participant - {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} - + >>> participante['pais'] = 'Alemanha' + >>> participante + {'pais': 'Alemanha', 'linguagem_favorita': 'Python', 'nome': 'Ola'} -Como você pode ver, o valor da chave `'country'` foi alterado de `'Poland'` para `'Germany'`. :) Emocionante? Hurra! Você acabou de aprender outra coisa incrível. +Como você pode ver, o valor da chave `'pais'` foi alterado de `'Polonia'` para `'Alemanha'`. :) Emocionante? Hurra! Você acabou de aprender outra coisa incrível. ### Sumário @@ -393,7 +391,7 @@ Já ouviu a expressão "comparar maçãs com laranjas"? Vamos tentar o equivalen TypeError: unorderable types: int() > str() -Aqui vemos que assim como na expressão, Python não é capaz de comparar um número (`int`) e uma string (`str. +Aqui vemos que assim como na expressão, Python não é capaz de comparar um número (`int`) e uma string (`str`). Em vez disso, ele mostrou um TypeError e nos disse que os dois tipos não podem ser comparados juntos.

Booleano

@@ -433,20 +431,20 @@ Parabéns! Booleanos são um dos recursos mais interessantes na programação, e Até agora nós escrevemos todo nosso código em um interpretador python, que nos limita a uma linha de código em um momento. Programas normais são salvos em arquivos e executados pelo nosso **interpretador** de linguagem de programação ou **compilador**. Até agora já corremos nossos programas de uma linha de cada vez no **interpretador** Python. Nós vamos precisar de mais de uma linha de código para as próximas tarefas, então precisaremos rapidamente: -* Saída do interpretador Python -* Abra seu editor de código de sua escolha -* Salvar algum código em um novo arquivo de python +* Sair do interpretador Python +* Abrir o editor de código de sua escolha +* Salvar algum código em um novo arquivo python * Executá-lo! -Para sair do interpretador Python que estamos usando, simplesmente digite o ~~~ exit() ~~~ função: +Para sair do interpretador Python que estamos usando, simplesmente digite a função `exit()`: >>> exit() $ -Isso vai colocá-lo no prompt de comando. +Isso vai colocá-la no prompt de comando. -Anteriormente, nós escolhemos um editor de código da seção do [editor de código][4]. Nós precisamos abrir o editor agora e escrever algum código em um novo arquivo:

+Anteriormente, nós escolhemos um editor de código da seção do [editor de código][4]. Nós precisamos abrir o editor agora e escrever algum código em um novo arquivo: ```python print('Hello, Django girls!') ``` @@ -476,13 +474,13 @@ E no windows, vai ser assim: Se você ficar preso, só pedir ajuda. -e, em seguida, usar o Python para executar o código no arquivo assim: +Em seguida, usar o Python para executar o código no arquivo assim: $ python3 python_intro.py Hello, Django girls! -Tudo bem! Você acabou de seu primeiro programa em python que foi salvo em um arquivo. Me sinto ótimo? +Tudo bem! Você acabou de executar seu primeiro programa em python que foi salvo em um arquivo. Se sente ótima? Você pode agora passar para uma ferramenta essencial na programação: @@ -504,14 +502,13 @@ Se salvou este e ele foi executado, nós veríamos um erro como este: SyntaxError: unexpected EOF while parsing -Python espera que fornecemos mais instruções que serão supostamente executadas caso a condição `3 > 2` venha a ser verdadeira (ou `True` nesse caso). Vamos tentar fazer o Python imprimir "It works!". Altere o seu código no seu arquivo **python_intro.py** para isto: +Python espera que nós forneçamos mais instruções que serão supostamente executadas caso a condição `3 > 2` venha a ser verdadeira (ou `True` nesse caso). Vamos tentar fazer o Python imprimir "It works!". Altere o seu código no seu arquivo **python_intro.py** para isto: ```python if 3 > 2: print('It works!') ``` - -Observe como podemos ter recuado a próxima linha de código por 4 espaços? Precisamos fazer isso para que Python sabe que código a ser executado se o código resulta em true. Você pode fazer um espaço, mas quase todos os programadores Python fazem com 4 para tornar as coisas um olhar puro. Um único tab também vai contar como 4 espaços. +Você percebeu que identamos a próxima linha com 4 espaços? Precisamos fazer isso para que o Python saiba qual código será executado se o resultado for True. Você pode fazer com 1 espaço, mas quase todos os programadores Python fazem com 4 para deixar as coisas arrumadas. Um único tab também vai contar como 4 espaços. Salvá-lo e execute novamente: @@ -525,15 +522,15 @@ Nos exemplos anteriores, o código foi executado somente quando as condições e ```python if 5 > 2: - print('5 is indeed greater than 2') + print('5 é realmente maior que 2') else: - print('5 is not greater than 2') + print('5 não é maior que 2') ``` Quando for executado irá imprimir: $ python3 python_intro.py - 5 e maior que 2 + 5 é realmente maior que 2 Se 2 for um número maior do que 5, então o segundo comando será executado. Fácil, né? Vamos ver como funciona o `elif`: @@ -563,7 +560,7 @@ Nos últimos três exercícios você aprendeu: * **comparar as coisas** - em Python, você pode comparar as coisas usando os operadores `>`, `>=`, `==`, `<=`, `<` e o `and`, `or` * **Booleano** - um tipo de objeto que só tem um dos dois valores: `True` ou `False` * **Salvando arquivos** - armazenamento de código em arquivos assim você pode executar programas maiores. -* **if... elif... else**-instruções que permitem que você execute o código somente se determinadas condições forem atendidas. +* **if... elif... else** - instruções que permitem que você execute o código somente se determinadas condições forem atendidas. É hora da última parte deste capítulo! @@ -571,7 +568,7 @@ Nos últimos três exercícios você aprendeu: Se lembra de funções como `len()` que você pode executar no Python? Bem, boas notícias, agora você vai aprender a escrever suas próprias funções! -Uma função é um sequência de instruções que o Python deve executar. Cada função em Python começa com a palavra-chave `def`, seguido de um nome para a função e opcionalmente uma lista de parâmetros. Vamos começar com uma função simples. Substitua o código no **python_intro.py** com o seguinte: +Uma função é uma sequência de instruções que o Python deve executar. Cada função em Python começa com a palavra-chave `def`, seguido de um nome para a função e opcionalmente uma lista de parâmetros. Vamos começar com uma função simples. Substitua o código no **python_intro.py** com o seguinte: ```python def hi(): @@ -583,7 +580,7 @@ hi() Ok, nossa primeira função está pronta! -Você pode se perguntar por que escrevemos o nome da função na parte inferior do arquivo. Isto é porque Python lê o arquivo e executa-lo de cima para baixo. Então, para usar a nossa função, temos re-escrevê-lo na parte inferior. +Você pode se perguntar por que escrevemos o nome da função na parte inferior do arquivo. Isto é porque Python lê o arquivo e executa de cima para baixo. Então, para usar a nossa função, temos de escrevê-lo na parte inferior. Vamos executa-lo agora e ver o que acontece: @@ -645,12 +642,12 @@ e executá-lo: Hi Sonja! -Agora, o que acha que vai acontecer se você escrever outro nome lá? (Não Ola ou Sonja) Experimentá-lo e ver se você está certo. Ele deve imprimir isto: +Agora, o que acha que vai acontecer se você escrever outro nome lá? (Sem ser Ola ou Sonja) Experimentá-lo e ver se você está certo. Ele deve imprimir isto: Hi anonymous! -Isto é incrível, não? Dessa maneira você não precisa se repetir (DRY - don't repeat yourself) cada vez que for mudar o nome da pessoa que a função pretende cumprimentar. E é exatamente por isso que precisamos de funções - você nunca quer repetir seu código! +Isto é incrível, não? Dessa maneira você não precisa se repetir (DRY - don't repeat yourself, ou em português, não se repita) cada vez que for mudar o nome da pessoa que a função pretende cumprimentar. E é exatamente por isso que precisamos de funções - você nunca quer repetir seu código! Vamos fazer algo mais inteligente..--existem mais que dois nomes, e escrever uma condição para cada um seria difícil, certo? @@ -687,7 +684,7 @@ Queremos cumprimentar todas elas pelos seus nomes. Temos a função `hi` para fa for name in girls: ``` -O ~~~ for ~~~ declaração se comporta da mesma forma para o ~~~ if ~~~ declaração, código abaixo esses dois precisam ser recuados quatro espaços. +O `for` se comporta da mesma forma que o `if`, o código abaixo esses dois precisam ser recuados quatro espaços. Aqui está o código completo que será salvo no arquivo: @@ -740,11 +737,11 @@ Note que o segundo desses dois números não está incluído na lista que o Pyth ## Sumário -É isso. **Você é totalmente demais!** Não é tão fácil, então você deve se sentir orgulhoso de si mesmo. Estamos definitivamente orgulhosos de você por ter chegado até aqui! +É isso. **Você é totalmente demais!** Não é tão fácil, então você deve se sentir orgulhosa de si mesma. Estamos definitivamente orgulhosas de você por ter chegado até aqui! Talvez você queira brevemente fazer algo mais - espreguiçar, andar um pouco, descansar os olhos - antes de ir para o próximo capítulo. :) ![Cupcake](images/cupcake.png) [2]: /intro_to_command_line/README.html - [4]: code_editor/README.md + [4]: ../code_editor/README.md diff --git a/pt/template_extending/README.md b/pt/template_extending/README.md index 11554ff4f16..a888a3ec111 100755 --- a/pt/template_extending/README.md +++ b/pt/template_extending/README.md @@ -43,7 +43,7 @@ Abra-o e copie tudo que está no arquivo `post_list.html` para `base.html`, dess {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -89,7 +89,7 @@ Salve e abra o arquivo `blog/templates/blog/post_list.html` novamente. Apague ex {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` @@ -112,7 +112,7 @@ Isso significa que, agora, nós estamos estendendo o template `base.html` em `po {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} diff --git a/pt/whats_next/README.md b/pt/whats_next/README.md index 94a0c512a13..fb97dbb3627 100755 --- a/pt/whats_next/README.md +++ b/pt/whats_next/README.md @@ -11,7 +11,7 @@ Depois disso: * Siga Django girls no [Facebook][1] ou [Twitter][2] para ficar atualizada [1]: http://facebook.com/djangogirls - [2]: http://twitter.com/djangogirls + [2]: https://twitter.com/djangogirls ### Você pode recomendar outras fontes? @@ -31,9 +31,9 @@ Depois você pode tentar as fontes listadas abaixo. Todas elas são recomendadas [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ [5]: http://newcoder.io/tutorials/ - [6]: http://www.codecademy.com/en/tracks/python - [7]: http://www.codecademy.com/tracks/web - [8]: http://django.carrots.pl/en/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ [9]: http://learnpythonthehardway.org/book/ [10]: http://gettingstartedwithdjango.com/ - [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6 + [11]: https://twoscoopspress.org/products/two-scoops-of-django-1-6 diff --git a/ru/GLOSSARY.md b/ru/GLOSSARY.md new file mode 100755 index 00000000000..86fce21027d --- /dev/null +++ b/ru/GLOSSARY.md @@ -0,0 +1,3 @@ +# Текстовый редактор + +Текстовый редактор - это приложение, которое позволяет тебе сохранить свой код, чтобы вернуться к нему позднее. Информацию о том, где можно таким обзавестись, можно найти в главе [Текстовый редактор](./code_editor/README.md) \ No newline at end of file diff --git a/ru/README.md b/ru/README.md new file mode 100755 index 00000000000..434fc3b8ab2 --- /dev/null +++ b/ru/README.md @@ -0,0 +1,46 @@ +# Руководство Django Girls + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Это руководство распространяется под международной лицензией Creative Commons Attribution-ShareAlike 4.0 Чтобы ознакомиться с содержанием этой лицензии, посети: https://creativecommons.org/licenses/by-sa/4.0/ + +## Введение + +Ты когда-нибудь чувствовала, что мир становится все более и более технологичным, в то время как ты остаёшься где-то позади? Ты задумывалась о том, как создать веб-сайт, но мотивации начать никогда не хватало? Приходило ли тебе в голову, что мир программного обеспечения слишком сложен, чтобы пробовать сделать что-то самой? + +Тогда у нас есть для тебя хорошие новости! Программирование – не такая уж сложная задача, как кажется, и мы покажем тебе, как весело это может быть. + +Это руководство не превратит тебя волшебным образом в программиста. Если ты хочешь добиться мастерства, то потребуются месяцы, а может быть и годы обучения и практики. Однако, мы хотим показать тебе, что программирование или создание веб-сайтов не настолько сложная задача как может показаться. Мы постараемся объяснить все настолько хорошо, насколько сможем, чтобы ты не чувствовала себя запуганной техническими деталями. + +Надеемся, что ты полюбишь информационные технологии также, как мы любим их! + +## Что ты узнаешь из этого руководства? + +После прохождения руководства у тебя будет простое работающее веб-приложение: свой собственный блог. Мы покажем, как разместить его онлайн, чтобы другие увидели твою работу! + +Он будет выглядеть следующим образом (более или менее): + +![Рисунок 0.1](images/application.png) + +> Если ты будешь работать над учебником самостоятельно и без тренера, который смог бы помочь при необходимости, то у нас есть для тебя чат: [!\[Gitter\](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Мы попросили наших тренеров и успешно прошедших обучение участников заглядывать туда время от времени и помогать остальным! Не стесняйся задавать там свои вопросы! + +Хорошо, [давай начнем с начала...][3] + + [3]: ./how_the_internet_works/README.md + +## Сотрудничество и дополнительная информация + +Это руководство поддерживается [DjangoGirls][4]. Если ты нашла ошибки или хочешь обновить информацию, пожалуйста, [следуй этим рекомендациям][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Хочешь помочь с переводом руководства на другие языки? + +В настоящее время перевод координируется через платформу crowdin.com: + +https://crowdin.com/project/django-girls-tutorial + +Если твоего языка нет в списке на crowdin, пожалуйста, [дай нам знать][6], чтобы мы могли его добавить. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/ru/SUMMARY.md b/ru/SUMMARY.md new file mode 100755 index 00000000000..9fc224ba38a --- /dev/null +++ b/ru/SUMMARY.md @@ -0,0 +1,26 @@ +# Содержание + +* [Введение](README.md) +* [Установка](installation/README.md) +* [Как работает Интернет](how_the_internet_works/README.md) +* [Знакомство с командной строкой](intro_to_command_line/README.md) +* [Установка Python](python_installation/README.md) +* [Текстовый редактор](code_editor/README.md) +* [Введение в Python](python_introduction/README.md) +* [Что же представляет из себя Django?](django/README.md) +* [Установка Django](django_installation/README.md) +* [Твой первый проект на Django!](django_start_project/README.md) +* [Модели Django](django_models/README.md) +* [Администрирование Django](django_admin/README.md) +* [Публикация!](deploy/README.md) +* [URL-адреса Django](django_urls/README.md) +* [Представления в Django – время создавать!](django_views/README.md) +* [Введение в HTML](html/README.md) +* [Django ORM (Querysets)](django_orm/README.md) +* [Динамически изменяющиеся данные в шаблонах](dynamic_data_in_templates/README.md) +* [Шаблоны Django](django_templates/README.md) +* [CSS - сделай это красивым](css/README.md) +* [Расширение шаблона](template_extending/README.md) +* [Расширяем свое приложение](extend_your_application/README.md) +* [Формы в Django](django_forms/README.md) +* [Что дальше?](whats_next/README.md) diff --git a/ru/code_editor/README.md b/ru/code_editor/README.md new file mode 100755 index 00000000000..5a63261e934 --- /dev/null +++ b/ru/code_editor/README.md @@ -0,0 +1,7 @@ +# Текстовый редактор + +Приступаем к написанию первых строк кода - пора загрузить текстовый редактор! + +> **Примечание**: Если ты уже все сделала в главе, посвященной установке, то можешь смело переходить к следующей главе! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/ru/code_editor/instructions.md b/ru/code_editor/instructions.md new file mode 100755 index 00000000000..e37368ddbb4 --- /dev/null +++ b/ru/code_editor/instructions.md @@ -0,0 +1,31 @@ +Существует много различных редакторов и в основном все сводится к личным предпочтениям. Большинство Python программистов используют сложные, но чрезвычайно мощные IDE (англ. Integrated Development Environments - Интегрированные среды разработки), такие как PyCharm. Однако они, вероятно, не очень подходят для начинающих; мы предлагаем столь же мощные, но куда более простые варианты. + +Ниже приведен перечень наших предпочтений, но также можешь попросить совета у своего тренера - будет проще получить помощь от него. + +## Gedit + +Gedit является открытым, бесплатным редактором, доступным для всех операционных систем. + +[Скачать его можно здесь](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text - это очень популярный текстовый редактор с бесплатным пробным периодом. Он легко устанавливается и прост в использовании, а также доступен для всех операционных систем. + +[Скачать его можно здесь](https://www.sublimetext.com/3) + +## Atom + +Atom - это новейший текстовый редактор от [GitHub](https://github.com/). Он является бесплатным, открытым, легко устанавливается и прост в использовании. Доступен для Windows, OSX и Linux. + +[Скачать его можно здесь](https://atom.io/) + +## Зачем нам нужен редактор кода? + +Ты можешь спросить - зачем устанавливать отдельную программу для редактирования кода, если можно использовать Word или Notepad. + +Во-первых, код должен должен храниться в виде **простого текста**, а проблема таких программ, как Word или Textedit в том, что они не сохраняют файлы в этом виде, а используют "обогащенный" текст (с форматированием и шрифтами), например, [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Вторая причина в том, что специализированные редакторы предоставляют множество полезных для программирования возможностей, такие как цветную подсветку кода в зависимости от его смысла и автоматически закрывающиеся кавычки. + +Позже мы увидим все это в действии. Скоро ты начнешь думать о своем редакторе кода как о проверенном любимом инструменте :) \ No newline at end of file diff --git a/ru/css/README.md b/ru/css/README.md new file mode 100755 index 00000000000..64fc384a1fe --- /dev/null +++ b/ru/css/README.md @@ -0,0 +1,296 @@ +# CSS - сделай это красиво! + +Наш блог все еще выглядит довольно скверно, не так ли? Пора сделать его красивым! Для этого будем использовать CSS. + +## Что такое CSS? + +Каскадные таблицы стилей (англ. Cascading Style Sheets или сокращенно CSS) - специальный язык, используемый для описания внешнего вида и форматирования сайта, написанного на языке разметки (как HTML). Воспринимай это, как своего рода макияж для нашей веб-страницы ;). + +Но мы же не хотим начинать все с нуля, правда? Мы просто снова возьмем что-то, что уже было создано программистами и опубликовано в Интернете для свободного пользования. Ты же знаешь, заново изобретать велосипед совсем не весело. + +## Давай использовать Bootstrap! + +Bootstrap - один из наиболее популярных HTML и CSS фреймворков для разработки красивых сайтов: https://getbootstrap.com/ + +Он был написан программистами, которые работали в Twitter, а сейчас совершенствуется волонтерами со всего мира. + +## Установка Bootstrap + +Для установки Bootstrap тебе нужно добавить следующие строки в `` твоего `.html` файла (`blog/templates/blog/post_list.html`): + +```html + + +``` + +Это не добавит ни одного файла к твоему проекту. Эти строки просто указывают на файлы, опубликованные в Интернете. Просто продолжай, открой свой веб-сайт и обнови страницу. Вот и результат! + +![Рисунок 14.1][1] + + [1]: images/bootstrap1.png + +Выглядит уже лучше! + +## Статические файлы в Django + +Теперь мы ближе познакомимся с теми таинственными **статическими файлами**. Статическими файлами называются все файлы CSS и изображения, т.е. файлы, которые не изменяются динамически, их содержание не зависит от контекста запроса и будет одинаково для всех пользователей. + +### Куда поместить статические файлы в Django + +Как ты видела при выполнении команды `collectstatic` на сервере, Django уже знает где искать статические файлы для встроенного приложения "admin". Теперь нам нужно добавить статические файлы для своего приложения `blog`. + +Мы сделаем это, создав папку `static` внутри каталога с нашим приложением: + +``` + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite +``` + +Django будет автоматически находить папки "static" внутри всех каталогов твоих приложений и сможет использовать их содержимое в качестве статических файлов. + +## Твой первый CSS файл! + +Давай создадим CSS файл, чтобы добавить свой собственный стиль для твоей web-страницы. Создай новую папку под названием `css` внутри твоей папки `static`. Затем создайте новый файл под названием `blog.css` внутри папки `css`. Готова? + +``` + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css +``` + +Пришло время написать несколько строк CSS! Открой файл `blog/static/css/blog.css` в своем редакторе кода. + +Мы не будем здесь погружаться слишком глубоко в процесс настройки и изучения CSS, поскольку это так просто, что ты сможешь изучить этот материал самостоятельно после этого руководства. Мы настоятельно рекомендуем пройти этот курс [Codeacademy HTML & CSS course][2], чтобы изучить все, что тебе нужно знать об оформлении веб-сайтов с помощью CSS. + + [2]: https://www.codecademy.com/tracks/web + +Но давай сделаем хотя бы немного. Возможно, мы могли бы изменить цвет заголовка? Чтобы понимать цвета, компьютеры используют специальные коды. Они начинаются с `#` и далее следуют 6 букв (A-F) и цифр (0-9). Ты можешь найти коды цветов, например, здесь: http://www.colorpicker.com/. Также можешь пользоваться [предопределенными цветами][3], такими как `red` и `green`. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +В файле `blog/static/css/blog.css` тебе нужно добавить следующий код: + +```css + h1 a { + color: #FCA205; + } +``` + +`h1 a` это CSS селектор. Это означает, что мы применяем наши стили к каждому элементу `a` внутри элемента `h1` (например, когда мы имеем в коде что-то вроде: `

link

`). В этом случае мы говорим о том, что нужно изменить цвет элемента на `#FCA205`, то есть на оранжевый. Конечно, ты можешь указать свой собственный цвет! + +В CSS файле мы определяем стили для элементов файла HTML. Элементы идентифицируются именами (то есть `a`, `h1`, `body`), атрибутом `class` или атрибутом `id`. Class и id – это имена, которые ты сама присваиваешь элементам. Классы (сlass) определяют группы элементов, а идентификаторы (id) указывают на конкретные элементы. Например, следующий тег может быть идентифицирован CSS с использованием имени тега `a`, класса `external_link` или идентификатора `link_to_wiki_page`: + +```html + +``` + +Почитай про CSS селекторы в [CSS Selectors in w3schools][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Затем нам также нужно сообщить нашему HTML-шаблону о том, что мы добавили CSS. Открой файл `blog/templates/blog/post_list.html` и добавь эту строку в самом начале: + +```html + {% load staticfiles %} +``` + +Мы просто загружаем здесь статические файлы :). Далее между `` и ``, после ссылок на файлы Bootstrap CSS (браузер читает файлы в порядке их следования, поэтому код нашего файла может переопределить код в файлах Bootstrap) добавь эту строку: + +```html + +``` + +Мы только что сказали нашему шаблону, где находится наш CSS файл. + +Твой файл должен теперь выглядеть следующим образом: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +ОК, сохрани файл и обнови страницу! + +![Рисунок 14.2][5] + + [5]: images/color2.png + +Отличная работа! Может быть, мы также хотели бы добавить нашему веб-сайту немного пространства и увеличить отступ слева? Давай попробуем! + +```css + body { + padding-left: 15px; + } +``` + +Добавь это к твоему CSS, сохрани файл и посмотри, как это работает! + +![Рисунок 14.3][6] + + [6]: images/margin2.png + +Возможно, мы можем настроить шрифт нашего заголовка? Вставь это внутрь тега `` в файле `blog/templates/blog/post_list.html`: + +```html + +``` + +Эта строка импортирует шрифт под названием *Lobster* из шрифтов Google (https://www.google.com/fonts). + +Теперь добавь строку `font-family: 'Lobster';` в CSS файле `blog/static/css/blog.css` внутри блока определения стиля `h1 a` (код помещается между скобками `{` и `}`) и обнови страницу: + +```css + h1 a { + color: #FCA205; + font-family: 'Lobster'; + } +``` + +![Рисунок 14.3][7] + + [7]: images/font.png + +Отлично! + +Как было указано выше, CSS имеет концепцию классов, которая позволяет назвать часть HTML кода и применять стили только для этой части без всякого эффекта для других. Это очень полезно если у вас есть скажем два блока div, но они выполняют совершенно разные функции (как ваш заголовок и пост), следовательно, вы не хотите, чтобы они выглядели одинаково. + +Дайте имена определенным частям HTML кода. Добавьте класс под названием `page-header` в блок `div`, содержащий ваш заголовок, как это сделано здесь: + +```html + +``` + +А теперь добавьте класс `post` в ваш `div`, содержащий сообщение в блоге. + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +А теперь добавим определения блоков для различных селекторов. Селекторы, которые начинают с символа `.` относятся к классам. Существует много хороших справочников о CSS в Интернете, которые могут помочь вам понять следующий код. А теперь, просто скопируй и вставь код в файл `djangogirls/static/css/blog.css`: + +```css + .page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; + } + + .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; + } + + .content { + margin-left: 40px; + } + + h1, h2, h3, h4 { + font-family: 'Lobster', cursive; + } + + .date { + float: right; + color: #828282; + } + + .save { + float: right; + } + + .post-form textarea, .post-form input { + width: 100%; + } + + .top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; + } + + .post { + margin-bottom: 70px; + } + + .post h1 a, .post h1 a:visited { + color: #000000; + } +``` + +Далее переделайте HTML код, отображающий посты. замените: + +```html + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +в `blog/templates/blog/post_list.html` этим кодом: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Сохраните эти файлы и обновить свой веб-сайт. + +![Рисунок 14.4][8] + + [8]: images/final.png + +Юхууу! Выглядит прекрасно, не так ли? Код, который мы только что вставили в действительности не является сложным для понимания и вы должны быть в состоянии понять большую его часть просто прочитав. + +Не бойтесь немного повозиться с этим CSS файлом и попробуйте поменять некоторые вещи. Если что-то сломается, не волнуйтесь, вы всегда можете отменить предыдущее действие! + +В любом случае, мы настоятельно рекомендуем пройти этот бесплатный онлайн курс [Codeacademy HTML & CSS course ][2] как своеобразную домашнюю работу после воркшопа чтобы изучить все, что нужно знать об оформлении ваших веб-сайтов с CSS. + +Готовы к следующей главе?! :) diff --git a/ru/css/images/bootstrap1.png b/ru/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/ru/css/images/bootstrap1.png differ diff --git a/ru/css/images/color2.png b/ru/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/ru/css/images/color2.png differ diff --git a/ru/css/images/final.png b/ru/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/ru/css/images/final.png differ diff --git a/ru/css/images/font.png b/ru/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/ru/css/images/font.png differ diff --git a/ru/css/images/images/bootstrap1.png b/ru/css/images/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/ru/css/images/images/bootstrap1.png differ diff --git a/ru/css/images/images/color2.png b/ru/css/images/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/ru/css/images/images/color2.png differ diff --git a/ru/css/images/images/final.png b/ru/css/images/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/ru/css/images/images/final.png differ diff --git a/ru/css/images/images/font.png b/ru/css/images/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/ru/css/images/images/font.png differ diff --git a/ru/css/images/images/margin2.png b/ru/css/images/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/ru/css/images/images/margin2.png differ diff --git a/ru/css/images/margin2.png b/ru/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/ru/css/images/margin2.png differ diff --git a/ru/deploy/README.md b/ru/deploy/README.md new file mode 100755 index 00000000000..27d374a1ccd --- /dev/null +++ b/ru/deploy/README.md @@ -0,0 +1,314 @@ +# Разверните! + +> **Примечание**: Эта глава может показаться сложной. Будь упорна, развертывание сайта на сервере является важной частью веб-разработки. Данная глава намеренно расположена в середине учебника для того, чтобы твой наставник смог помочь с таким мудреным процессом, как публикация сайта. Так ты сможешь самостоятельно закончить все главы, даже если время будет поджимать. + +До настоящего момента твой сайт был доступен только для локального просмотра, теперь же ты узнаешь как развернуть его на удаленном сервере! Развертывание (deploy) — это процесс публикации приложения в интернете, чтобы люди могли наконец увидеть твое творение :). + +Как ты уже знаешь, веб-сайт должен располагаться на сервере. Есть много компаний, предоставляющих сервера в интернете. Мы воспользуемся услугами одной из них, с довольно простым процессом публикации: [PythonAnywhere][1]. PythonAnywhere бесплатен для маленьких приложений с небольшим числом посетителей, и этого будет более чем достаточно для нас. + + [1]: https://pythonanywhere.com/ + +Другим внешним сервисом, которым мы будем пользоваться, является [GitHub][2] — сервис хостинга кода. Существуют и другие похожие сервисы, но практически у каждого программиста есть GitHub аккаунт, теперь будет и у тебя! + + [2]: https://www.github.com + +Мы будем использовать GitHub для передачи нашего кода PythonAnywhere и обратно. + +# Git + +Git — это "система управления версиями", используемая множеством программистов. Эта программа отслеживает изменения, происходящие с файлами, чтобы впоследствии можно было восстановить состояние кода на нужный момент времени. Это немного похоже на функцию отслеживания изменений в Microsoft Word, но куда мощнее. + +## Установка Git + +> **Примечание** Если вы уже выполнили установку, незачем повторять её вновь — вы можете сразу переходить к следующему разделу и начать создание собственного Git репозитория. + +{% include "/deploy/install_git.md" %} + +## Создаём Git-репозиторий + +Git отслеживает изменения определенного набора файлов, который называется репозиторием (сокращенно "репо"). Давайте создадим один для нашего проекта. Откройте консоль и запустите эти команды в папке `djangogirls`: + +> **Заметка**: Проверь текущий рабочий каталог с помощью команд `pwd` (OSX/Linux) или `cd` (Windows) прежде чем инициализировать новый репозиторий. Ты должна находиться в директории `djangogirls`. + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +Инициализировать git-репозиторий придется только один раз за проект (и тебе больше не придется вводить имя пользователя и адрес электронной почты). + +Git будет отслеживать изменения всех файлов и каталогов в заданной директории, однако некоторые из них мы предпочли бы игнорировать. Для этого нам нужно создать файл `.gitignore` в корневом каталоге репозитория. Открой редактор и создай новый файл со следующим содержанием: + + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store + + +И сохрани его как `.gitignore` в корневом каталоге "djangogirls". + +> **Примечание**: Точка в начале имени файла имеет важное значение! Если у тебя есть проблемы с созданием таких файлов (Mac не позволит создать файл с названием, начинающимся с точки, через Finder, например), тогда используй кнопку "Сохранить как" в меню своего редактора кода, это точно поможет. + +Используй команду `git status` перед `git add` или в любой другой момент, когда ты не уверена, что изменения — хорошая идея. Это убережёт тебя от таких неприятных сюрпризов как добавление неправильных файлов. Команда `git status` возвращает информацию обо всех ранее неотслеживаемых/изменённых/добавленных в git файлах, а также статус ветки и многое другое. Результат должен быть похож на: + + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) + + +И, наконец, мы сохраним наши изменения. Переключись на консоль и набери: + + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## Загружаем код в репозиторий GitHub + +Зайди на [GitHub.com][2] и создай новую бесплатную учётную запись. (если это уже сделано во время подготовки к воркшопу — здорово!) + +Затем создай новый репозиторий и назови его "my-first-blog". Не выбирай опцию "initialise with a README", не создавай файл .gitignore (мы сделаем это локально сами) и оставь Лицензию None. + +![][3] + + [3]: images/new_github_repo.png + +> **Примечание**: Имя репозитория `my-first-blog` имеет для нас большую важность -- ты можешь, конечно, придумать другое название, но оно будет встречаться множество раз в руководстве и тебе придется заменять его каждый раз на свое. Будет проще для начала остановиться на нашем варианте `my-first-blog`. + +На следующем экране ты можешь найти URL для клонирования репозитория. Выбери вариант "HTTPS", копируй команду и вставь в окно терминала: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Теперь нужно связать локальный репозиторий с репозиторием на GitHub. + +Напечатай у себя в консоли следующую команду (Замени `` именем, указанным при создании аккаунта на GitHub, но без угловых скобок): + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +Введи свое имя пользователя и пароль от аккаунта GitHub, и ты должна увидеть что-то подобное: + + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +Твой код теперь на GitHub. Зайди на сайт и проверь! Ты найдешь его в хорошей компании: [фреймворк Django][5], [этот учебник][6], а также многие другие великолепные проекты с исходным кодом размещены на GitHub :) + + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Настройка нашего блога на PythonAnywhere + +> **Примечание** Возможно, ты уже завела учётную запись на PythonAnywhere ранее — если так, нет нужды повторять это вновь. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Загружаем код на PythonAnywhere + +После регистрации на PythonAnywhere ты будешь перемещена на страницу "Consoles". Выбери опцию старта "Bash" консоли -- это версия консоли PythonAnywhere, аналогичная твоему локальному терминалу. + +> **Примечание**: PythonAnywhere использует Linux, так что если ты используешь Windows, то терминал и команды могут немного отличаться от того, к чему ты привыкла на своем компьютере. + +Давай загрузим наш код из GitHub на PythonAnywhere, создав "клон" репозитория. Введи следующую команду в консоли на PythonAnywhere (не забудь заменить `` на свою учётку GitHub): + + $ git clone https://github.com//my-first-blog.git + + +Эта команда загрузит копию твоего кода на PythonAnywhere. Проверь это, набрав `tree my-first-blog`: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### Создаём виртуальное окружение на PythonAnywhere + +Также как ты делала на своем компьютере, ты можешь создать виртуальное окружение на PythonAnywhere. В Bash консоли введи следующую команду: + + $ cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + (myvenv) $ pip install django whitenoise + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 + + +> **Примечание** Выполнение команды `pip install` может занять несколько минут. Терпение, терпение! Однако, если это занимает больше 5 минут, что-то не так. Спроси своего инструктора. + + + +### Сбор статических файлов. + +Задаешься вопросом "что это за whitenoise такой"? Это утилита для работы с так называемыми "статическими файлами". Статические файлы — это файлы, не содержащие программного кода, такие как файлы HTML или CSS. Статические файлы работают на серверах не так как на твоем локальном компьютере, и нам потребуется инструмент, такой как "whitenoise", чтобы управляться с ними. + +Мы ближе познакомимся со статическими файлами в дальнейшем, когда начнем писать CSS для нашего сайта. + +А пока нам просто нужно запускать дополнительную команду под названием `collectstatic`, на сервере. Это даст Django знать, что он должен собрать все статические файлы, которые потребуются серверу. На данный момент эти файлы главным образом позволят админке хорошо выглядеть. + + (myvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +Набери "yes" и жди! Как тебе нравятся страницы непонятного текста, которые выводятся в терминале? Я всегда сопровождаю их звуками. Брп, брп, брп... + + Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/.virtualenvs/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### Создаем базу данных на PythonAnywhere + +Есть еще одно отличие твоего локального компьютера и сервера - они используют разные базы данных. Таким образом, пользовательские аккаунты и записи в блоге на сервере и локальном компьютере могут отличаться друг от друга. + +Нам нужно инициализировать базу данных на сервере, также как мы это сделали на твоем компьютере, с помощью команд `migrate` и `createsuperuser`: + + (myvenv)20:20 ~ $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv)20:20 ~ $ python manage.py createsuperuser + + +## Публикация нашего блога как веб-приложения + +Теперь наш код загружен на PythonAnywhere, виртуальное окружение готово, статические файлы собраны и база данных инициализирована -- мы готовы опубликовать блог как веб-приложение! + +Вернись в панель управления PythonAnywhere нажав на лого в верхнем левом углу, затем переключись на вкладку **Web** и нажми кнопку **Add a new web app**. + +После подтверждения доменного имени, выбери **manual configuration** (NB *не* «Django»!) в диалоговом окне. Затем выбери **Python 3.4** и заверши работу мастера. + +> **Примечание**: убедись, что ты выбрала опцию "Manual configuration", а не "Django". Мы слишком круты для стандартного настройщика PythonAnywhere для Django ;-) + +### Настройка виртуального окружения + +Ты будешь перенесена на страницу настройки веб-приложения PythonAnywhere, куда тебе будет нужно заходить каждый раз, когда потребуется внести изменения в приложении на сервере. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +В секции "Virtualenv" кликни по красному тексту "Enter the path to a virtualenv" и набери `/home//my-first-blog/myvenv/`. Нажми на синий прямоугольник с галочкой, чтобы сохранить изменения, прежде чем двигаться дальше. + +> **Примечание**: замени имя пользователя на свое. Если ты допустишь ошибку, PythonAnywhere выдаст предупреждение. + +### Настройка файла WSGI + +Django использует протокол WSGI, стандартный протокол для обслуживания веб-сайтов, используя Python, который поддерживается PythonAnywhere. Используя файл настроек WSGI мы позволим PythonAnywhere распознать наш Django блог. + +Кликни по ссылке "WSGI configuration file" (в секции "Code" наверху страницы -- она будет выглядеть следующим образом: `/var/www/_pythonanywhere_com_wsgi.py`) и ты будешь переключена на редактор. + +Удали все содержимое и замени его чем-то вроде этого: + +```python +import os +import sys + +path = '/home//my-first-blog' # use your own username here +if path not in sys.path: + sys.path.append(path) + +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` + + +> **Примечание**: не забудь заменить имя пользователя на свое там, где указано `` + +Задача данного файла сказать PythonAnywhere где находится наше веб-приложение и как называется файл настроек Django. Он также загружает "whitenoise" для работы со статическими файлами. + +Нажми **Save** и переключись на вкладку **Web**. + +Мы все сделали! Нажми на большую зеленую кнопку **Reload** и можешь проверять свое приложение. Ссылку можно найти в верхней части страницы. + +## Советы по отладке + +Если видишь ошибку при попытке посетить свой сайт, для отладочной информации первым делом смотри **журнал ошибок**. Ссылку на него ты найдёшь на [вкладке Web][8] на PythonAnywhere. Посмотри, нет ли там сообщений о каких-нибудь ошибках; самые последние из них приведены ниже. Они включают: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* пропуск одного из шагов в консоли: создание virtualenv, её активация, установка Django в виртуальное окружение, запуск collectstatic, инициализация базы данных. + +* ошибка в пути к virtualenv -- рядом должно появляться небольшое предупреждение, если PythonAnywhere не может найти виртуальное окружение по указанному адресу. + +* ошибка в файле настроек WSGI -- ты правильно указала путь к директории my-first-blog? + +* Ты выбрала одну и ту же версию Python для virtualenv и для веб-приложения? Обе должны быть 3.4. + +* Также можешь посмотреть [общие советы по отладке на вики PythonAnywhere][9]. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +И помни: твой инструктор здесь, чтобы помогать! + +# Ты в сети! + +Стандартная страница твоего сайта должна включать приветствие "Welcome to Django", точно также как было на локальном компьютере. Попробуй добавить `/admin/` к концу адреса сайта и перейдешь к панели администратора сайта. Войди под своим именем и паролем и увидишь форму для добавления новых записей в блог. + +Ты заслужила *огромную* похвалу! Развертывание сервера — одна из самых каверзных частей веб-разработки, и не редко уходит несколько дней, прежде чем заставишь всё работать. А у нас уже есть работающий в сети веб-сайт, вот так вот! diff --git a/ru/deploy/images/github_get_repo_url_screenshot.png b/ru/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/ru/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/ru/deploy/images/new_github_repo.png b/ru/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/ru/deploy/images/new_github_repo.png differ diff --git a/ru/deploy/images/pythonanywhere_web_tab_virtualenv.png b/ru/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/ru/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/ru/deploy/install_git.md b/ru/deploy/install_git.md new file mode 100755 index 00000000000..1ddef84127a --- /dev/null +++ b/ru/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows + +Ты можешь загрузить Git с официального сайта [git-scm.com](https://git-scm.com/). Ты можешь нажимать "дальше дальше дальше" на всех этапах установки за исключением одного: на пятом шаге, который называется "Adjusting your PATH environment" (Настройка системной переменной Path), выберите "Run Git and associated Unix tools from the Windows command-line" (Запуск Git и соответствующих Unix утилит через командную строку Windows, нижняя опция). Все остальные настройки можно оставить по умолчанию. Опция "Checkout Windows-style, commit Unix-style line endings" будет неплохим выбором. + +### MacOS + +Загрузи Git с официального сайта [git-scm.com](https://git-scm.com/) и просто следуйте инструкциям по установке. + +### Linux + +Если git ещё не установлен, то он будет доступен через менеджер пакетов, попробуй следующую команду: + + sudo apt-get install git + # or + sudo yum install git + # or + sudo zypper install git diff --git a/ru/deploy/signup_pythonanywhere.md b/ru/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..e98cd6e1b7b --- /dev/null +++ b/ru/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Теперь нам потребуется создать бесплатный аккаунт уровня "Beginner" на PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Примечание**: При выборе имени пользователя, помни что URL блога примет вид `yourusername.pythonanywhere.com`, так что остановись либо на своём нике, либо на имени, связанном с тематикой блога. \ No newline at end of file diff --git a/ru/django/README.md b/ru/django/README.md new file mode 100755 index 00000000000..ce3fb13b6f8 --- /dev/null +++ b/ru/django/README.md @@ -0,0 +1,27 @@ +# Что такое Django? + +Django (*/ˈdʒæŋɡoʊ/ джанго*) -- бесплатный и свободный фреймворк для веб-приложений, написанный на Python. Фреймворк - это набор компонентов, которые помогают разрабатывать веб-сайты быстро и просто. + +Каждый раз при разработке веб-сайтов требуются похожие компоненты: способ аутентифицировать пользователей (вход, выход, регистрация), панель управления сайтом, формы, инструменты для загрузки файлов и т. д. + +К счастью для нас, другие люди обратили внимание на возникновение однотипных проблем при веб-разработке, так что они объединились и создали фреймворки (Django и другие), которые предлагают нам готовые шаблоны для использования. + +Фреймворки существуют, чтобы облегчить процесс разработки и позволить нам не изобретать колесо. + +## Зачем нам нужен фреймворк? + +Чтобы понять, для чего же нам нужен Django, нам нужно ближе познакомиться с серверами. Во-первых, сервер должен узнать о том, что мы ждем от него веб-страницу. + +Представь себе почтовый ящик (порт), который проверяется на наличие новых писем (запросов). Это делает веб-сервер. Когда письмо приходит, сервер читает его и отправляет ответ с веб-страничкой. Однако, чтобы что-то отправить нам надо это что-то иметь. И Django как раз и отвечает за создание контента, который будет отправлен в ответе. + +## Что происходит, когда кто-то запрашивает веб-сайт у твоего сервера? + +Когда на сервер приходит запрос, он переадресуется Django, который пытается сообразить что же конкретно от него просят. Для начала он берет адрес веб-страницы и пробует понять -- что же нужно сделать. Эту часть процесса в Django выполняет **urlresolver** (адрес веб-сайта называется URL - Uniform Resource Locator - Единый указатель ресурсов, так что название *urlresolver*, resolver == определитель, имеет определенный смысл). Он не слишком умен, поэтому просто берет список шаблонов и пытается сопоставить их с URL. Django сверяет шаблоны сверху вниз и, если что-то совпадает, он переправляет запрос соответствующей функции (которая называется *view*). + +Представь себе почтальона с письмом. Она идет вниз по улице и сверяет номера домов с адресом на письме. Если они совпадают, то она оставляет письмо. Так же работает и urlresolver! + +Но самые интересные вещи происходят в функции *view*: мы, например, можем обращаться к базе данных за определенной информацией. Может быть пользователь попросил изменить какую-нибудь информацию? Как будто в письме написано: "Пожалуйста, поменяйте описание моей работы." Функция *view* может проверить имеете ли вы разрешение делать это, а затем обновит описание работы и отправит обратно ответ: "Готово!". Затем функция *view* сгенерирует ответ и Django сможет отправить его веб-браузеру пользователя. + +В реальности все немного сложнее, однако тебе не обязательно знать все технические навороты прямо сейчас. Достаточно основной концепции. + +Так что вместо погружения в пучины нюансов, мы просто начнем работать с Django и познакомимся со всеми важными особенностями по мере продвижения! diff --git a/ru/django_admin/README.md b/ru/django_admin/README.md new file mode 100755 index 00000000000..0a13a0ca8b7 --- /dev/null +++ b/ru/django_admin/README.md @@ -0,0 +1,49 @@ +# Администрирование Django + +Чтобы добавлять, редактировать и удалять записи, для которых мы только сделали модель, нам потребуется использовать права администратора в Django. + +Давай откроем файл `blog/admin.py` и заменим его содержимое на: + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + + +Как ты можешь заметить, мы импортировали (включили) модель Post, которая была определена в предыдущей главе. Чтобы наша модель стала доступна на странице администрирования, нам нужно зарегистрировать её при помощи `admin.site.register(Post)`. + +Хорошо, теперь нам нужно взглянуть на модель Post. Не забудь запустить веб-сервер командой `python manage.py runserver`. Перейди в браузер и набери адрес http://127.0.0.1:8000/admin/ Ты увидишь страницу авторизации: + +![Страница авторизации][1] + + [1]: images/login_page2.png + +Чтобы залогиниться, тебе сначала нужно создать *суперпользователя (англ. superuser)* - пользователя, который имеет полный доступ к управлению сайтом. Вернись к командной строке, набери `python manage.py createsuperuser`, и нажми Enter. При появлении запроса введи имя пользователя (строчными буквами, без пробелов), адрес электронной почты и пароль. Не беспокойся, если пароль не появляется на экране по мере ввода, так и задумано. Просто напечатай его и нажмите `Enter`, чтобы продолжить. Результат должен выглядеть следующим образом (имя пользователя и почта соответственно будут твоими): + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Вернись в браузер и войди в систему при помощи имени пользователя и пароля, которые ты только что выбрала. Ты должна попасть в панель управления Django. + +![Администрирование Django][2] + + [2]: images/django_admin3.png + +Перейди к разделу Posts и немного поэкспериментируй с ним. Добавь пять или шесть постов. Не беспокойся о содержании - можешь просто скопировать и вставить текст из этого учебника, чтобы сэкономить время :). + +Убедись, что выбрала для двух или трех записей (но не больше) дату публикации. Это пригодится позднее. + +![Администрирование Django][3] + + [3]: images/edit_post3.png + +Если ты хочешь узнать больше об администрировании Django, то ознакомься с этим разделом официальной документации: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +Сейчас, вероятно, подходящий момент, чтобы порадовать себя кружечкой кофе (или чая), а также съесть чего-нибудь для пополнения энергии. Ты только что создала свою первую Django модель и заслужила перерыв! diff --git a/ru/django_admin/images/django_admin3.png b/ru/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/ru/django_admin/images/django_admin3.png differ diff --git a/ru/django_admin/images/edit_post3.png b/ru/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/ru/django_admin/images/edit_post3.png differ diff --git a/ru/django_admin/images/images/django_admin3.png b/ru/django_admin/images/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/ru/django_admin/images/images/django_admin3.png differ diff --git a/ru/django_admin/images/images/edit_post3.png b/ru/django_admin/images/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/ru/django_admin/images/images/edit_post3.png differ diff --git a/ru/django_admin/images/images/login_page2.png b/ru/django_admin/images/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/ru/django_admin/images/images/login_page2.png differ diff --git a/ru/django_admin/images/login_page2.png b/ru/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/ru/django_admin/images/login_page2.png differ diff --git a/ru/django_forms/README.md b/ru/django_forms/README.md new file mode 100755 index 00000000000..2989e67cbe5 --- /dev/null +++ b/ru/django_forms/README.md @@ -0,0 +1,398 @@ +# Формы в Django + +Последним, что нам стоит сделать для нашего веб-сайта является удобный способ добавления и редактирования записей. Django `admin`-панель удобна, но её дизайн сложно изменять. С `forms` (формами) у нас будем иметь абсолютную власть над интерфейсом блога - мы сможем сделать практически все что только можно придумать! + +В формах Django удобно то, что мы можем создать новую форму с нуля или воспользоваться `ModelForm` для сохранения содержимого форм в модель. + +Это как раз то, что нам нужно сделать: мы создадим форму для модели `Post`. + +Как и любая важная часть Django, формы имеют свой собственный: `forms.py`. + +Нам нужно создать файл с таким именем в директории `blog`. + +``` + blog +    └── forms.py +``` + +Теперь открой его и набери следующее: + +```python + from django import forms + from .models import Post + + class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Для начала нам нужно импортировать формы Django (`from django import forms`) и, разумеется, нашу модель `Post` (`from .models import Post`). + +`PostForm`, как ты, вероятно, подозреваешь, это имя для нашей формы. Нам нужно также сообщить Django, что эта форма относится к `ModelForm` (чтобы он смог поколдовать для нас) - `forms.ModelForm` поможет с этим. + +Дальше к нас `class Meta`, где мы определяем какая модель будет использоваться для создания формы (`model = Post`). + +В завершении мы можем указать, какие поля должны присутствовать в нашей форме. Сейчас нам требуются только поля `title` и `text` - `author` будет автоматически выбран в зависимости от авторизованного пользователя (тебя) и `created_date` должна автоматически проставляться в момент создания записи (т.е. через код), верно? + +Вот и все! Теперь мы можем использовать форму в *представлении* и отобразить её в шаблоне. + +Таким образом, мы создали: ссылку на страницу, URL-адрес, представление и шаблон. + +## Ссылка на страницу с формой + +Пришло время открыть файл `blog/templates/blog/base.html`. Мы добавим ссылку в элемент `div` с именем `page-header`: + +```html + +``` + +Обрати внимание, что мы назвали новое представление `post_new`. + +После добавления строки, твой html-файл должен выглядеть следующим образом: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Сохрани файл и перезагрузи страницу по адресу http://127.0.0.1:8000, ты должна увидеть знакомую ошибку `NoReverseMatch`, все верно? + +## URL + +Нам нужно открыть файл `blog/urls.py` и добавить строку: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + +Окончательная версия файла будет выглядеть следующим образом: + +```python + from django.conf.urls import url + from . import views + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), + ] +``` + +После перезагрузки веб-сайта, мы увидим ошибку `AttributeError`, поскольку представление `post_new` не реализовано. Давай добавим его прямо сейчас. + +## Представление post_new + +Самое время открыть файл `blog/views.py` и добавить следующую строку к остальным, начинающимся с `from`: + +```python + from .forms import PostForm +``` + +и наше *представление*: + +```python + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Чтобы создать новую форму `Post`, нам потребуется вызвать `PostForm()` и передать её шаблону. Мы еще вернемся к этому *представлению*, а пока, давай быстро создадим шаблон под форму. + +## Шаблон + +Нам нужно создать файл `post_edit.html` в директории `blog/templates/blog`. Чтобы заставить её работать, нам потребуется несколько вещей: + +* нам нужно отобразить форму. Мы можем сделать это к примеру простым `{% raw %}{{ form.as_p }}{% endraw %}`. +* строка выше должна быть обернута в HTML-теги `...` +* нам потребуется кнопка `Save`. Мы реализуем при помощи HTML-кнопки: `` +* и наконец сразу после открытия тега `< form... >` мы должны добавить `{% raw %}{% csrf_token %}{% endraw %}`. Это очень важно, поскольку так мы делаем форму защищенной! Django будет ругаться, если ты забудешь добавить этот код: + +![Страница CSFR Forbidden][1] + + [1]: images/csrf2.png + +Хорошо, давай посмотрим как должен выглядеть HTML-код в файле `post_edit.html`: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+ {% endblock %} +``` + +Время обновить страницу! Ура! Форма отображается! + +![Новая форма][2] + + [2]: images/new_form2.png + +Но подожди минутку! Если ты наберешь что-нибудь в полях `title` и `text` и попробуешь сохранить - что произойдет? + +Ничего! Мы снова на той же странице и наш текст пропал... и новая запись не была добавлена. Так что же пошло не так? + +Ответ прост: ничего. Нам нужно сделать кое-что еще, чтобы новое *представление* заработало. + +## Сохраняем данные из формы + +Снова открой файл `blog/views.py`. Все что у нас есть в представлении `post_new` выглядит пока следующим образом: + +```python + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +После отправки формы мы возвращаемся к тому же представлению, но в этот раз с новыми данными в `request`, а точнее в `request.POST` (имя POST не имеет ничего общего с "постом" в блоге, оно связано с тем, что мы "публикуем" данные). Помнишь, что в HTML-файле, определение `
` имеет параметр `method="POST"`? Все поля формы теперь находятся в `request.POST`. Ты не должна переименовывать `POST` во что-то другое (другое доступное значение параметра `method` - `GET`, но у нас нет времени объяснять разницу сейчас). + +Получается, что в представлении *view* нам нужно обработать две разные ситуации. Первая: когда мы только зашли на страницу и хотим получить пустую форму. Вторая: когда мы возвращаемся к *представлению* со всей информацией, которую мы ввели в форму. Таким образом, нам потребуется ввести условие (мы будем использовать условный оператор `if` для этой цели). + +```python + if request.method == "POST": + [...] + else: + form = PostForm() +``` + +Теперь заполним строку, занятую `[...]`. Если `method` - `POST`, тогда мы хотим построить `PostForm` с данными из формы, верно? Мы добьемся этого следующим образом: + +```python + form = PostForm(request.POST) +``` + +Легко! Дальше мы проверим корректна ли форма (все необходимые поля заполнены и неверные значения не будут сохранены). Мы сделаем это при помощи `form.is_valid()`. + +Мы проверяем допустимо ли содержание формы и, если все в порядке, сохраняем её! + +```python + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +Практически мы выполняем две операции: сохраняем форму `form.save` и добавляем автора (поскольку обязательного поля `author` нет в `PostForm`!). `commit=False` означает, что мы пока не хотим сохранять модель `Post` - сначала нужно добавить автора. В основном ты будешь использовать `form.save()`, без `commit=False`, но в данном случае нам это пригодится. `post.save()` сохранит изменения (после добавления автора) и новая запись будет создана! + +Наконец, будет прекрасно, если мы сможем сразу переходить к странице `post_detail` после добавления новой записи, согласна? Для этого нам понадобится еще один импорт: + +```python + from django.shortcuts import redirect +``` + +Добавь эту строку в начало файла. Теперь мы можем сделать переадресацию на страницу `post_detail` для созданной записи. + +```python + return redirect('blog.views.post_detail', pk=post.pk) +``` + +`blog.views.post_detail`это имя представления, которое нам необходимо. Помнишь, что это *представление* требует переменную `pk`? Чтобы передать её представлению мы используем аргумент `pk=post.pk`, где `post` - это новая запись в блоге! + +Хорошо, мы многое обсудили, пора взглянуть на *представление* полностью, верно? + +```python + def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Проверим, все ли работает. Перейди по адресу http://127.0.0.1:8000/post/new/, добавь текст в поля `title` и `text`, затем сохрани... и вуаля! Новая запись создана и мы перешли на страницу `post_detail`! + +Возможно, ты заметила, что мы устанавливаем дату публикации перед сохранением поста. В последствии мы сделаем *кнопку публикации* в **Django Girls Tutorial: Extensions**. + +Это круто! + +## Валидация формы + +Теперь мы покажем тебе насколько круты формы в Django. Запись в блоге должна иметь поля `title` и `text`. В нашей модели `Post` мы не указываем, что эти поля необязательны (в отличии от `published_date`), так Django по умолчанию будет ожидать их заполнение пользователем. + +Попробуй сохранить форму без с незаполненными полями `title` и `text`. Угадай, что произойдет! + +![Валидация формы][3] + + [3]: images/form_validation2.png + +Django заботится о проверке всех полей в нашей форме на корректность. Разве не шикарно? + +> Поскольку мы недавно использовали панель администратора Django, системы до сих пор думает, что мы авторизованы. Существует несколько случаев, когда мы можем случайно выйти из аккаунта (закрытие браузера, перезапуск базы данных и т.д.). Если ты получаешь ошибку при попытке сохранения записи, то потребуется перейти на страницу http://127.0.0.1:8000/admin и авторизоваться в системе снова. Это решит проблему. В главе **Домашнее задание: добавляем безопасность нашему веб-сайту!** после основного учебника приводится перманентное исправление. + +![Ошибка при выходе из аккаунта][4] + + [4]: images/post_create_error.png + +## Редактирование формы + +Теперь мы знаем как добавить новую форму. Но что, если мы хотим внести исправления в уже существующую запись? По сути это схожая с предыдущей задача. Давай быстро создадим пару важных вещей (если ты чего-то не понимаешь, спроси своего тренера или загляни в предыдущие главы, поскольку мы уже объясняли все необходимые шаги). + +Открой `blog/templates/blog/post_detail.html` и добавь следующую строку: + +```python + +``` + +так, чтобы шаблон выглядел следующим образом: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + +В файле `blog/urls.py` добавь: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Мы будем использовать повторно шаблон `blog/templates/blog/post_edit.html`, так что осталось лишь отсутствующее *представление*. + +Let's open a `blog/views.py` and add at the very end of the file: + +```python + def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Выглядит практически идентично представлению `post_new`, верно? Но не совсем. Первое: мы передаем параметр `pk` из URL-адреса. Следующее: мы получаем модель `Post` для редактирования при помощи `get_object_or_404(Post, pk=pk)` и передаем экземпляр post в качестве `instance` форме для сохранения: + +```python + form = PostForm(request.POST, instance=post) +``` + +и когда мы открываем форму для редактирования: + +```python + form = PostForm(instance=post) +``` + +Хорошо, давай проверим что все работает! Перейди на страницу `post_detail`. Ты должна увидеть кнопку редактирования в правом верхнем углу: + +![Кнопка Редактировать (Edit)][5] + + [5]: images/edit_button2.png + +Когда ты её нажмешь, то увидишь форму с выбранной записью: + +![Форма редактирования][6] + + [6]: images/edit_form2.png + +Поменяй заголовок и текст, а затем сохрани запись! + +Поздравляем! Твое приложение становится все более сложным! + +Если тебе нужно больше информации о формах в Django, то обратись к официальной документации: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## Безопасность + +Круто иметь возможность создавать новые посты просто нажав на ссылку! Однако, сейчас кто угодно из посетителей вашего сайта может создать новую запись в блоге, а это, скорее всего, совсем не то, чего бы вам хотелось. Давай сделаем так, чтобы кнопка показывалась для нас, а не кого-либо еще. + +В файле `blog/templates/blog/base.html`, найди `page-header` `div` и тег <a> который мы добавили ранее. Должно выглядеть примерно так: + +```html + +``` + +Мы добавим сюда ещё один тэг `{% if %}` чтобы ссылка показывалась только пользователям, вошедшим в админку. То есть, пока что только тебе! Измени тег `< >`, чтобы получилось так: + +```html + {% if user.is_authenticated %} + + {% endif %} +``` + +Из-за этого `{% if %}` ссылка будет отправлена в браузер только если запрашивающий страницу пользователь вошёл в систему. Это не обезопасит создание новых постов полностью, но для начала и это неплохо. Мы подробнее рассмотрим вопросы безопасности в дополнении к учебнику. + +Поскольку ты авторизована, никаких изменений после обновления страницы ты не увидишь. Но попробуй загрузить страницу в другом браузере или в режиме инкогнито, и увидишь что ссылка не отобразится! + +## Еще одна вещь: развертывание! + +Теперь давай посмотрим как это будет работать на PythonAnywhere. Пришло время для очередного развертывания! + +* Сначала нам нужно сделать commit и push нового кода в репозиторий Github + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push +``` + +* Затем набери в [Bash консоли PythonAnywhere][7]: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +* И нажми **Reload** на вкладке [Web tab][8]. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +Вот и все! Поздравляем :) diff --git a/ru/django_forms/images/csrf2.png b/ru/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/ru/django_forms/images/csrf2.png differ diff --git a/ru/django_forms/images/drafts.png b/ru/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/ru/django_forms/images/drafts.png differ diff --git a/ru/django_forms/images/edit_button2.png b/ru/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/ru/django_forms/images/edit_button2.png differ diff --git a/ru/django_forms/images/edit_form2.png b/ru/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/ru/django_forms/images/edit_form2.png differ diff --git a/ru/django_forms/images/form_validation2.png b/ru/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/ru/django_forms/images/form_validation2.png differ diff --git a/ru/django_forms/images/images/csrf2.png b/ru/django_forms/images/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/ru/django_forms/images/images/csrf2.png differ diff --git a/ru/django_forms/images/images/drafts.png b/ru/django_forms/images/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/ru/django_forms/images/images/drafts.png differ diff --git a/ru/django_forms/images/images/edit_button2.png b/ru/django_forms/images/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/ru/django_forms/images/images/edit_button2.png differ diff --git a/ru/django_forms/images/images/edit_form2.png b/ru/django_forms/images/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/ru/django_forms/images/images/edit_form2.png differ diff --git a/ru/django_forms/images/images/form_validation2.png b/ru/django_forms/images/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/ru/django_forms/images/images/form_validation2.png differ diff --git a/ru/django_forms/images/images/new_form2.png b/ru/django_forms/images/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/ru/django_forms/images/images/new_form2.png differ diff --git a/ru/django_forms/images/images/post_create_error.png b/ru/django_forms/images/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/ru/django_forms/images/images/post_create_error.png differ diff --git a/ru/django_forms/images/new_form2.png b/ru/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/ru/django_forms/images/new_form2.png differ diff --git a/ru/django_forms/images/post_create_error.png b/ru/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/ru/django_forms/images/post_create_error.png differ diff --git a/ru/django_installation/README.md b/ru/django_installation/README.md new file mode 100755 index 00000000000..39ef9a7241d --- /dev/null +++ b/ru/django_installation/README.md @@ -0,0 +1,5 @@ +# Установка Django + +> **Примечание** Если ты уже выполнила установку — можешь пропустить эту часть и сразу перейти к следующей главе! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/ru/django_installation/instructions.md b/ru/django_installation/instructions.md new file mode 100755 index 00000000000..0adda7ffec7 --- /dev/null +++ b/ru/django_installation/instructions.md @@ -0,0 +1,113 @@ +> Отдельные части этой главы основаны на учебных пособиях Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Отдельные части этой главы основаны на [учебном пособии django-marcador](http://django-marcador.keimlink.de/), лицензированном под Creative Commons Attribution-ShareAlike 4.0 International License. Руководство django-marcador защищено авторским правом Markus Zapke-Gründemann et al. + +## Виртуальное окружение + +Перед установкой Django мы попросим тебя установить крайне полезный инструмент, который поможет тебе содержать среду разработки в чистоте. Можно пропустить этот шаг, но мы очень советуем этого не делать. Использование лучших рекомендаций с самого начала убережёт от многих проблем в будущем! + +Итак, давай создадим **виртуальное окружение** (оно также называется *virtualenv*). Virtualenv будет изолировать зависимости Python/Django для каждого отдельного проекта. Это значит, что изменения одного сайта никогда не затронут другие сайты, которые вы разрабатываете. Удобно, правда? + +Все что тебе нужно сделать -- найти директорию, в которой мы создадим `virtualenv`; домашний каталог вполне подойдет. Для Windows адрес будет выглядеть так: `C:\Users\Name` (где `Name` твое имя пользователя). + +Мы будем использовать отдельную директорию `djangogirls` в домашнем каталоге: + + mkdir djangogirls + cd djangogirls + + +Мы создадим виртуальное окружение под именем `myvenv`. В общем случаем команда будет выглядеть так: + + python3 -m venv myvenv + + +### Windows + +Чтобы создать новое `virtualenv`, тебе нужно открыть командную строку (мы рассказывали про неё в одной из прошлых глав - помнишь?) и набрать `C:\Python34\python -m venv myvenv`. Он должен содержать следующее: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + +где `C:\Python34\python` это директория, где ты установила Python и `myvenv` имя твоего `virtualenv`. Ты можешь выбрать любое имя, использовать можно только прописные буквы, без пробелов и специальных символов. Имя виртуального окружения выбирай покороче! + +### Linux and OS X + +Для Linux и OS X достаточно набрать `python3 -m venv myvenv`, чтобы создать `virtualenv`: + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` -- имя виртуального окружения `virtualenv`. Опять же, только строчные буквы и никаких пробелов. Имя виртуального окружения лучше выбирать покороче — его набирать его предстоит не раз! + +> **ПРИМЕЧАНИЕ:** создание виртуального окружения данной командой на Ubuntu 14.04 приведет к следующей ошибке: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Чтобы обойти эту проблему используй команду `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Работаем с virtualenv + +Вышеуказанная команда создаст директорию `myvenv` (или другую, в зависимости от выбранного имени), которая будет содержать виртуальное окружение (по сути -- набор файлов и папок). + +#### Windows + +Запусти виртуальное окружение, выполнив: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +#### Linux and OS X + +Запусти виртуальное окружение, выполнив: + + ~/djangogirls$ source myvenv/bin/activate + + +Не забудь поменять `myvenv` на выбранное для `virtualenv` имя! + +> **ПРИМЕЧАНИЕ:** иногда команда `source` может быть недоступна. В таком случае, используй следующий метод: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Ты поймешь, что `virtualenv` запущено, когда увидишь приписку в командной строке: + + (myvenv) C:\Users\Name\djangogirls> + + +или: + + (myvenv) ~/djangogirls$ + + +Обрати внимание на появление префикса `(myvenv)`! + +При работе с виртуальным окружением, команда `python` будет автоматически обращаться к правильной версии языка, так что тебе не обязательно использовать `python3`. + +Отлично, теперь мы будем хранить все важные зависимости в одном месте. Наконец можно установить Django! + +## Установка Django + +После запуска `virtualenv` ты можешь установить Django используя `pip`. Набери в командной строке строке `pip install django==1.8` (обрати внимание на двойной знак равенства: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +для Windows + +> Если ты получаешь сообщение об ошибке при запуске pip, проверь что путь к директории с проектом не содержит пробелы или специальные символы (`C:\Users\User Name\djangogirls`). Если проблема в этом, то, пожалуйста, перенеси свой проект в другое место, адрес которого не будет содержать пробелы и специальные символы (предложение: `C:\djangogirls`). После этого еще раз попробуй запустить pip. + +для Linux + +> При возникновении ошибки при вызове pip под Ubuntu 12.04, пожалуйста, запусти `python -m pip install -U --force-reinstall pip`, чтобы исправить установку pip в virtualenv. + +Вот и оно! Теперь ты (наконец то) готова создать свое Django приложение! diff --git a/ru/django_models/README.md b/ru/django_models/README.md new file mode 100755 index 00000000000..0a2daf7ed1f --- /dev/null +++ b/ru/django_models/README.md @@ -0,0 +1,179 @@ +# Модели Django + +Нам нужно что-то, что будет хранить все записи нашего блога. Но прежде, давай поговорим о вещах, называемых `объектами`. + +## Объекты + +В программировании существует особая концепция, она называется -- `объектно-ориентированным программированием`. Идея заключается в том, что вместо скучной последовательности инструкций мы моделируем вещи и описываем как они взаимодействуют друг с другом. + +Так что же такое объект? Это совокупность поведения и свойств. Звучит странно, но мы приведем пример. + +Если мы хотим смоделировать кошку, то создадим объект `Cat`, который обладает определенными свойствами, например `color` (цвет), `age` (возраст), `mood` (настроение: плохое, хорошее, сонное ;)), `owner` (хозяин, например другой объект -- `Person` или, если кошка дикая, это свойство будет пустым). + +Объект `Cat` будет иметь набор определенных действий: `purr` (мурчать), `scratch` (царапаться) или `feed` (кормить, где мы дадим кошке немного `CatFood` (кошачьей еды), которая так же может быть отдельным объектом со своими свойствами, например `taste` (вкусом)). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +Основная идея, таким образом, заключается в описании объекта в коде, используя его параметры (`свойства объекта`) и доступные ему действия (`методы`). + +Так как же мы смоделируем запись в блоге? Нам же нужен блог, верно? + +Для начала стоит ответить на вопрос: что такое запись в блоге? Какие свойства она имеет? + +Ну, запись содержит какой-то текст и заголовок, это наверняка, верно? Было бы неплохо также знать кто её написал -- так что нам нужен автор. Ну и в заключении, нам нужно знать когда запись создана и когда опубликована. + + Post + -------- + title + text + author + created_date + published_date + + +Какие вещи можно сделать с записью в блоге? Было бы неплохо иметь `метод` для её публикации, согласна? + +Так что нам пригодится метод `publish`. + +Ну и раз уж мы определились с тем, что хотим получить, давай начнем моделирование в Django! + +## Модель в Django + +Зная, что представляет из себя объект, мы можем создать Django модель для записи в блоге. + +Модель в Django это объект определенного свойства - он хранится в `базе данных`. База данных представляет собой совокупность различных данных. Это то место, где ты будешь хранить информацию о своих пользователях, записях в блоге и т.д. Мы будем использовать базу данных SQLite для хранения информации. Это стандартная база данных в Django -- её вполне хватит для наших нужд сейчас. + +Ты можешь представить модель в базе данных как электронную таблицу с колонками (полями) и строками (данными). + +### Создание приложения + +Для аккуратности мы создадим отдельное приложение в нашем проекте. Очень удобно иметь хорошо организованное рабочее место с самого начала. Для создания приложения нам понадобиться набрать следующую инструкцию в командной строке (из директории `djangogirls`, где находится файл `manage.py`): + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +Обрати внимание, что в нашем проекте появилась новая папка `blog`, которая содержит некоторые файлы. Структура нашего проекта, таким образом, будет выглядеть так: + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +После того как приложение создано, нам нужно сообщить Django, что теперь он должен его использовать. Мы сделаем это через файл `mysite/settings.py`. Нам нужно найти `INSTALLED_APPS` и добавить к списку `'blog',` прямо перед `)`. Конечный результат должен выглядеть следующим образом: + +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` + + +### Создание модели записи в блоге + +В файле `blog/models.py` мы определяем все `Модели` - модель записи для блога также пойдет сюда. + +Открой файл `blog/models.py`, удали весь текст и вставь на его место следующий код: + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + + +> Убедись, что использовала два символа нижнего подчеркивания (`_`) с обоих сторон от метода `str`. Это соглашение часто используется при программировании на Python, и иногда его называют "dunder" (сокращение от англ. "double-underscore"). + +Смотрится страшно, да? Но не волнуйся, мы объясним, что значит каждая строка кода! + +Строки, начинающиеся с `from` или `import`, открывают доступ к коду из других файлов. Так что, вместо того, чтобы копировать и вставлять один и тот же код во все файлы, ты можешь сослаться на него при помощи `from ... import ...`. + +`class Post(models.Model):` -- эта строка определяет нашу модель (`объект`). + +* `class` это специальное ключевое слово для определения объектов. +* `Post` это имя нашей модели, мы можем поменять его при желании (специальные знаки и пробелы использовать нельзя). Всегда начинай имена классов с прописной буквы. +* `models.Model` означает, что объект Post является моделью Django, так Django поймет, что он должен сохранить его в базу данных. + +Дальше мы задаем свойства, о которых уже говорили: `title`, `text`, `created_date`, `published_date` и `author`. Чтобы это сделать нам нужно определиться с типом полей (это текст? число? дата? ссылка на другой объект? например, на пользователя?). + +* `models.CharField` -- так мы определяем текстовое поле с ограничением на количество символов. +* `models.TextField` -- так определяется поле для неограниченно длинного текста. Выглядит подходящим для содержимого поста, верно? +* `models.DateTimeField` -- дата и время. +* `models.ForeignKey` -- ссылка на другую модель. + +Мы не будем объяснять каждую запятую, поскольку на это уйдет слишком много времени. Ознакомься с официальной документаций Django — если хочешь узнать больше о полях моделей и о том как определять разные объекты, то эта ссылка может помочь: (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +Что насчет `def publish(self):`? Это как раз метод `публикации` для записи, о котором мы говорили. `def` означает, что создаётся функция/метод, а `publish` — это название этого метода. Можно изменить имя метода, если хочешь. Существует правило для имён функций: нужно использовать строчные буквы, а пробелы заменять на подчёркивания. Например метод, вычисляющий среднюю цену может называться `calculate_average_price`. + +Методы часто `возвращают` что-то. Например, метод `__str__`. В наше случае, после вызова метода `__str__()` мы получим текст (**строку**) с заголовком записи. + +Если тема моделей тебе до сих пор непонятна -- не стесняйся обратиться к тренеру! Мы знаем, что она действительно сложна, особенно когда ты изучаешь параллельно объекты и функции. Но мы надеемся, что все это кажется тебе теперь не магией! + +### Создаем таблицы моделей в базе данных + +Последним шагом будет добавление нашей модели в базу данных. Сначала мы должны дать Django знать, что сделали изменения в нашей модели (мы её только что создали!). Набери `python manage.py makemigrations blog`. Должно получиться примерно так: + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +Django создал для нас файл с миграцией для базы данных. Набери `python manage.py migrate blog`, результат должен быть следующим: + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK + + +Ура! Модель записи для блога теперь в базе данных, было бы неплохо посмотреть на неё, верно? Тогда переходи к следующей главе! diff --git a/ru/django_orm/README.md b/ru/django_orm/README.md new file mode 100755 index 00000000000..cd367d8af36 --- /dev/null +++ b/ru/django_orm/README.md @@ -0,0 +1,157 @@ +# Django ORM и QuerySet + +В этой главе ты узнаешь как Django подключается к базе данных и сохраняет в неё информацию. Давай начнем! + +## Что такое QuerySet? + +QuerySet, по сути, список объектов заданной Модели. QuerySet позволяет читать данные из базы данных, фильтровать и изменять их порядок. + +Проще научиться на примере. Давай попробуем, согласна? + +## Интерактивная консоль Django + +Открой свой локальный терминал (не на PythonAnywhere), и набери следующую команду: + + (myvenv) ~/djangogirls$ python manage.py shell + + +Результат должен быть таким: + + (InteractiveConsole) + >>> + + +Ты находишься в интерактивной консоли Django. По сути, это та же интерактивная консоль Python, но с магией Django :). Ты можешь использовать весь синтаксис Python, разумеется. + +### Все объекты + +Давай попробуем вывести на экран все записи в нашем блоге. Ты можешь сделать это следующей командой: + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +Упс! Ошибка. Она говорит, что не существует объекта с именем Post. И это верно -- мы забыли импортировать его! + + >>> from blog.models import Post + + +Все просто: мы импортируем модель `Post` из `blog.models`. Давай попробуем получить все записи блога еще раз: + + >>> Post.objects.all() + [, ] + + +Это список записей, с которыми мы работали до этого! Мы создали их через панель администратора Django. Теперь же, мы хотим создавать записи через Python, так как же мы этого добьемся? + +### Создаем объект + +Создать объект Post в базе данных можно следующим образом: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Но у нас есть один недочет: `me`. Мы должны передать этой переменной экземпляр модели `User`, который будет отвечать за автора записи. Как это сделать? + +Давай импортируем модель user для начала: + + >>> from django.contrib.auth.models import User + + +Какие пользователи есть в нашей базе данных? Попробуй эту команду: + + >>> User.objects.all() + [] + + +Это суперпользователь, которого мы создали ранее! Нам нужен его экземпляр: + + me = User.objects.get(username='ola') + + +Как ты можешь заметить, мы получили (`get`) пользователя (`User`) с именем `username` 'ola'. Шикарно! В твоем случае, имя, конечно, может отличаться. + +Теперь мы наконец можем создать наш пост: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Ура! Хочешь проверить, что все работает? + + >>> Post.objects.all() + [, , ] + + +Есть, еще один пост в списке! + +### Добавляем записи + +Можешь повеселиться и добавить еще записей. 2-3 будет достаточно. + +### Фильтрация объектов + +Важной особенностью QuerySets является возможность фильтровать объекты. Предположим, нам нужно найти все записи пользователя ola. Мы используем метод `filter` вместо метода `all` в `Post.objects.all()`. В кавычках мы укажем условия, по которым будет построена выборка записей. В нашей ситуации условием будет являться равенство поля `author` переменной `me`. В Django мы можем написать это следующим образом: `author=me`. Теперь наш код выглядит следующим образом: + + >>> Post.objects.filter(author=me) + [, , , ] + + +А может быть мы хотим получить все записи со словом 'title' в поле `title`? + + >>> Post.objects.filter(title__contains='title') + [, ] + + +> **Примечание**: Обрати внимание на два символа нижнего подчеркивания (`_`) между `title` и `contains`. Django's ORM использует этот синтаксис для разделения имен полей ("title") и операций или фильтров ("contains"). Если ты используешь только один символ нижнего подчеркивания, то получишь ошибку "FieldError: Cannot resolve keyword title_contains". + +Ты также можешь получить список всех опубликованных записей. Мы просто отфильтруем записи по полю `published_date`: + + >>> from django.utils import timezone + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + +К сожалению, пост, который мы добавили в консоли Python еще не опубликован. Мы можем изменить это! Сначала выберем запись, которую мы хотим опубликовать: + + >>> post = Post.objects.get(title="Sample title") + + +Дальше мы опубликуем её с помощью метода `publish`! + + >>> post.publish() + + +Теперь попробуй получить список опубликованных сообщений снова (нажмите стрелку вверх 3 раза и затем `enter`): + + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + + +### Сортировка объектов + +QuerySets позволяет сортировать объекты. Давай попробуем сортировку по полю `created_date`: + + >>> Post.objects.order_by('created_date') + [, , , ] + + +Мы также можем изменить порядок на противоположный, добавив `-` в начало условия: + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +### Соединение QuerySets + +QuerySets можно **сцеплять**, создавая цепочки: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +Это — мощный и удобный инструмент, позволяющий писать сложные запросы. + +Отлично! Теперь ты готова к следующей части! Чтобы закрыть интерактивную консоль, набери: + + >>> exit() + $ diff --git a/ru/django_start_project/README.md b/ru/django_start_project/README.md new file mode 100755 index 00000000000..22f008d8c7c --- /dev/null +++ b/ru/django_start_project/README.md @@ -0,0 +1,140 @@ +# Твой первый проект на Django! + +> Часть этой главы основана на учебных пособиях Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). +> +> Отдельные части этой главы основаны на учебном пособии [django-marcador ][1], лицензированном под Creative Commons Attribution-ShareAlike 4.0 International License. Руководство django-marcador защищено авторским правом Markus Zapke-Gründemann et al. + + [1]: http://django-marcador.keimlink.de/ + +Мы собираемся создать простой блог! + +Первый шаг — создать новый проект Django. Попросту, это значит что мы запустим несколько стандартных скриптов из поставки Django, которые создадут для нас скелет проекта. Это просто куча каталогов и файлов, которые мы будем использовать позже. + +Имена этих каталог и файлов очень важны для Django. Ты не должна переименовывать их. Перемещать их в другое место тоже не самая удачная идея. Django необходима определенная структура, чтобы иметь возможность найти важные вещи. + +> Не забудь: ты должна запускать все команды в virtualenv. Если ты не видишь в командной строке префикса `(myvenv)`, то необходимо активировать virtualenv. Мы объясняли как это сделать в разделе **Работаем с virtualenv** главы **Установка Django**. Для этого нужно набрать `myvenv\Scripts\activate` в Windows или `source myvenv/bin/activate` в Mac OS / Linux. + +В консоли Mac OS или Linux нужно запустить следующую команду; **не забудьте добавить точку `.` в конце**: + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +В Windows; **не забудьте добавить точку `.` в конце**: + + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> `.` Точка крайне важна, потому что говорит скрипту устанавливать Django в вашем текущем каталоге (который и обозначается сокращённо точкой `.`) +> +> **Примечание** При вводе команд выше, помните что вам нужно набирать только часть, начинающуюся с `django-admin` или `django-admin.py`. `(myvenv) ~/djangogirls$` и `(myvenv) C:\Users\Name\djangogirls>` — это просто примеры строк-приглашений терминала. + +`django-admin.py` это скрипт, который создаст необходимую структуру директорий и файлы для нас. Ты должна теперь иметь следующую структуру проекта: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +`manage.py` это другой скрипт, который помогает с управлением сайтом. С помощью него мы сможем запустить веб-сервер на твоем компьютере без установки дополнительных программ. + +Файл `settings.py` содержит настройки для твоего веб-сайта. + +Помнишь нашу аналогию с почтальоном? Файл `urls.py` содержит список шаблонов, по которым ориентируется `urlresolver`. + +Давай пока забудем про остальные файлы - мы не будем их изменять. Только не удали их случайно! + +## Изменяем настройки + +Давай внесем изменения в `mysite/settings.py`. Открой файл в текстовом редакторе, который ты выбрала ранее. + +Было бы неплохо установить корректный часовой пояс на нашем сайте. Перейди к [списку часовых поясов википедии][2] и скопируй название своего часового пояса (TZ). (например, `Europe/Moscow`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +В файле settings.py найди строку, содержащую `TIME_ZONE`, и модифицируй её в соответствии со своим часовым поясом: + +```python +TIME_ZONE = 'Europe/Moscow' +``` + + +Замени "Europe/Moscow" на соответствующий часовой пояс + +Нам также необходимо добавить в настройки информацию о расположении статических файлов (мы познакомимся со статичными файлами и CSS в следующих главах). Спустись в *конец* файла и после переменной `STATIC_URL` добавь новую - `STATIC_ROOT`: + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + + +## Настройка базы данных + +Существует множество различных баз данных, которые могут хранить данные для твоего сайта. Мы будем использовать стандартную -- `sqlite3`. + +Она уже выбрана по умолчанию в файле `mysite/settings.py`: + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + + +Чтобы создать базу данных для нашего блога, набери в командной строке следующее: `python manage.py migrate` (мы должны быть в директории `djangogirls`, где расположен файл `manage.py`). Если все прошло успешно, то ты увидишь следующий результат: + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK + + +И мы закончили! Пришло время запустить веб-сервер и посмотреть работает ли наш веб-сайт! + +Ты должна быть в директории, где расположен файл `manage.py` (в нашем случае -- `djangogirls`). Запустим веб-сервер из командной строки: `python manage.py runserver`: + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Если вы используете Windows, и команда падает с ошибкой `UnicodeDecodeError`, используйте вместо неё другую: + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +Теперь тебе нужно проверить работает ли веб-сайт - открой браузер (Firefox, Chrome, Safari, Internet Explorer или любой другой) и набери следующий адрес: + + http://127.0.0.1:8000/ + + +Веб-сервер займёт командную строку, пока вы его не остановите. Чтобы и дальше иметь возможность набирать команды, откройте ещё одно окно терминала и активируйте в нём виртуальное окружение. Чтобы остановить веб-сервер, перейдите обратно в окно, в котором он работает и нажмите CTRL + C - кнопки Control и C вместе (в Windows, может потребоваться нажать клавиши Ctrl + Break). + +Поздравляем! Ты только что создала свой первый веб-сайт и запустила его на веб-сервере! Ну не круто ли? + +![Сработало!][3] + + [3]: images/it_worked2.png + +Готова к следующему шагу? Пришло время создать наполнение для нашего блога! diff --git a/ru/django_start_project/images/images/it_worked2.png b/ru/django_start_project/images/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/ru/django_start_project/images/images/it_worked2.png differ diff --git a/ru/django_start_project/images/it_worked2.png b/ru/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/ru/django_start_project/images/it_worked2.png differ diff --git a/ru/django_templates/README.md b/ru/django_templates/README.md new file mode 100755 index 00000000000..22e7b6e85ac --- /dev/null +++ b/ru/django_templates/README.md @@ -0,0 +1,108 @@ +# Шаблоны Django + +Пришло время отобразить данные на сайте! Django поможет нам с этим при помощи встроенных **тегов шаблонов**. + +## Что представляют из себя теги шаблонов? + +Как видишь, в HTML нельзя помещать код Python, поскольку браузеры не понимают его. Они знают только HTML. Мы помним, что HTML статичен, в то время как Python позволяет динамические изменения. + +**Теги шаблонов Django** позволяют нам вставлять Python в HTML, так что ты можешь создавать динамические веб-сайты быстрее и проще. То что надо! + +## Отображаем шаблон списка записей + +В предыдущей главе мы передали нашему шаблону список записей в переменной `posts`. Теперь мы отобразим его в HTML. + +Чтобы вставить переменную в шаблон Django, нам нужно использовать двойные фигурные скобочки с именем переменной внутри: + +```html + {{ posts }} +``` + +Попробуй это в шаблоне `blog/templates/blog/post_list.html`. Замени всё, начиная со второго `
` и вплоть до третьего `
` кодом `{{ posts }}`. Сохрани файл и обнови страницу, чтобы увидеть результат: + +![Рисунок 13.1][1] + + [1]: images/step1.png + +Как ты можешь заметить, мы получили следующую строку: + +``` + [, ] +``` + +Это показывает, что Django понял переменную как список объектов. Помнишь из главы **Введение в Python** как мы можем аккуратно отобразить список? Правильно, циклом for! В шаблонах Django ты можешь использовать их таким образом: + +```html + {% for post in posts %} + {{ post }} + {% endfor %} +``` + +Попробуй вставить это в свой шаблон. + +![Рисунок 13.2][2] + + [2]: images/step2.png + +Сработало! Но мы хотим, чтобы они отображались как статические записи, которые мы создавали в главе **Введение в HTML**. Ты можешь смешивать HTML и теги шаблонов. Наш элемент `body` будет выглядеть следующим образом: + +```html + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +{% raw %}Всё что ты поместишь между `{% for %}` и `{% endfor %}` будет повторено для каждого объекта в списке. Обнови страницу:{% endraw %} + +![Рисунок 13.3][3] + + [3]: images/step3.png + +Ты заметила, что мы использовали немного другую запись в этот раз `{{ post.title }}` или `{{ post.text }}`? Мы обращаемся к различным полям нашей модели `Post`. Также `|linebreaksbr` прогоняет текст через фильтр, для преобразования переносов строк в параграфы. + +## Еще один момент + +Пришло время еще раз убедиться, что наш сайт будет работать в сети, согласна? Попробуем развернуть новую версию сайта на PythonAnywhere. Краткий обзор необходимых шагов... + +* Сначала загружаем код на Github + +``` + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push +``` + +* Затем заходим на [PythonAnywhere][4], открываем **Bash console** и набираем команду: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ git pull + [...] +``` + +* Наконец, переключаемся на вкладку [Web][5] и жмем кнопку **Reload**. Обновления запущены в жизнь! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Поздравляем! Теперь попробуй добавить новые записи через панель администратора Django (не забывай указывать published_date!) и перезагрузи страницу, чтобы проверить появились ли они. + +Работает как по волшебству? Есть чем гордиться! Отойди от компьютера на секунду - ты заслужила перерыв. :) + +![Рисунок 13.4][6] + + [6]: images/donut.png diff --git a/ru/django_templates/images/donut.png b/ru/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/ru/django_templates/images/donut.png differ diff --git a/ru/django_templates/images/images/donut.png b/ru/django_templates/images/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/ru/django_templates/images/images/donut.png differ diff --git a/ru/django_templates/images/images/step1.png b/ru/django_templates/images/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/ru/django_templates/images/images/step1.png differ diff --git a/ru/django_templates/images/images/step2.png b/ru/django_templates/images/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/ru/django_templates/images/images/step2.png differ diff --git a/ru/django_templates/images/images/step3.png b/ru/django_templates/images/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/ru/django_templates/images/images/step3.png differ diff --git a/ru/django_templates/images/step1.png b/ru/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/ru/django_templates/images/step1.png differ diff --git a/ru/django_templates/images/step2.png b/ru/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/ru/django_templates/images/step2.png differ diff --git a/ru/django_templates/images/step3.png b/ru/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/ru/django_templates/images/step3.png differ diff --git a/ru/django_urls/README.md b/ru/django_urls/README.md new file mode 100755 index 00000000000..3cb60caee70 --- /dev/null +++ b/ru/django_urls/README.md @@ -0,0 +1,130 @@ +# URL-адреса Django + +Мы собираемся сделать нашу первую веб-страничку — домашнюю страницу твоего блога! Но для начала, давай чуть ближе познакомимся с URL-адресами в Django. + +## Что такое URL-адрес? + +URL — это просто адрес в интернете. Ты можешь увидеть URL каждый раз, когда посещаешь веб-сайт — он отображается в адресной строке твоего браузера (да! `127.0.0.1:8000` это URL-адрес! И `https://djangogirls.org` — тоже URL): + +![URL-адрес][1] + + [1]: images/url.png + +Любая страница в Интернете нуждается в собственном URL-адресе. Таким образом ваше приложение точно знает, что показать пользователю, который открывает конкретный URL-адрес. В Django мы используем кое-что под названием `URLconf` (англ. URL configuration, конфигурация URL). URLconf — это набор шаблонов, которые Django попробует сравнить с полученным URL, чтобы выбрать правильный метод для отображения (view). + +## Как URL-адреса работают в Django? + +Давай откроем файл `mysite/urls.py` в нашем редакторе и посмотрим, как он выглядит: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` + + +Как можешь заметить, Django уже кое-что разместил здесь для нас. + +Строки, начинающиеся с символа `#` являются комментариями -- это означает, что они будут игнорироваться Python. Удобно, не правда ли? + +URL-адрес администрирования, который мы посещали в предыдущей главе, уже здесь присутствует: + +```python + url(r'^admin/', include(admin.site.urls)), +``` + + +Таким образом, любому URL-адресу, начинающемуся с `admin/`, Django будет находить соответствующее *view* (представление). В этом случае мы охватываем большое множество различных URL-адресов, которые явно не прописаны в этом маленьком файле -- так он становится более аккуратным и удобочитаемым. + +## Regex + +Спрашиваешь себя, как Django сопоставляет URL-адреса и представления? Ну, это не так просто. В Django используются так называемые регулярные выражения (англ. "regular expressions" — сокращённо `regex`). Регулярные выражения имеют множество (множество!) правил, которые формируют поисковый шаблон. Поскольку регулярные выражения являются довольно сложной темой, мы остановимся на них чуть подробнее. + +Если ты все еще хочешь разобраться в написании шаблонов - нам потребуется лишь ограниченное число правил для описания шаблона, например: + + ^ начало текста + $ конец текста + \d цифра + + предыдущий пункт должен быть повторен как минимум один раз + () часть шаблона + + +Все остальное в шаблоне url будет интерпретироваться буквально. + +Теперь представь, что у нас есть веб-сайт с адресом `http://www.mysite.com/post/12345/`, где `12345` номер записи в блоге. + +Писать представления для всех номеров будет весьма утомительно. С помощью регулярных же выражений мы можем создать шаблон, соответствующий url, который позволит извлекать из адреса номер: `^post/(\d+)/$`. Давай разобьём шаблон на части, чтобы понять его логику: + +* **^post/** говорит Django рассматривать url с `post/` в начале (сразу после `^`) +* **(\d+)** означает, что дальше должен присутствовать номер (одна или несколько цифр) и мы хотим извлечь его из url +* **/** говорит Django об очередном символе `/` после номера +* **$** означает конец url, т.е. шаблону соответствуют только адреса с `/` на конце + +## Твой первый URL-адрес в Django! + +Пришло время создать твой первый URL-адрес! Мы хотим, чтобы 'http://127.0.0.1:8000/' возвращал домашнюю страничку нашего блога со списком записей в нем. + +Мы также хотим сохранить файл `mysite/urls.py` в максимально аккуратном виде, так что мы импортируем URL-адреса для нашего приложения `blog` в `mysite/urls.py`. + +Удали комментарии (строки, начинающиеся с `#`) и добавь импорт `blog.urls` в главный URL (`''`). + +Файл `mysite/urls.py` должен выглядеть следующим образом: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + + +Django теперь будет перенаправлять все запросы 'http://127.0.0.1:8000/' к `blog.urls` и искать там дальнейшие инструкции. + +При написании регулярных выражений на Python, всегда указывай `r` в начале строки. Это полезный намек для Python, что строка может содержать специальные символы, предназначенные не для самого Python, а для регулярного выражения. + +## blog.urls + +Создай новый пустой файл `blog/urls.py`. Отлично! Добавь в него следующие две строки: + +```python +from django.conf.urls import url +from . import views +``` + + +Так мы импортировали все методы Django и все `views` (представления) из приложения `blog` (у нас их пока нет, но через минуту они появятся!) + +После этого мы можем добавить наш первый URL-шаблон: + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + + +Как ты можешь заметить, мы связали `view` под именем `post_list` с URL-адресом `^$`. Это регулярное выражение будет соответствовать `^` (началу) и следующему `$` (концу), т.е. пустой строке. Это правильно, потому что для обработчиков URL в Django 'http://127.0.0.1:8000/' не является частью URL. Этот шаблон скажет Django, что `views.post_list` — это правильное направление для запроса к твоему веб-сайту по адресу 'http://127.0.0.1:8000/'. + +Последняя часть `name='post_list'` — это имя URL, которое будет использовано чтобы идентифицировать его. Оно может быть таким же, как имя представления (англ. view), а может и чем-то совершенно другим. Мы будем использовать именованные URL позднее в проекте, поэтому важно указывать их имена уже сейчас. Мы также должны попытаться сохранить имена URL-адресов уникальными и легко запоминающимися. + +Все в порядке? Тогда открой http://127.0.0.1:8000/ в браузере, чтобы увидеть результат. + +![Ошибка][2] + + [2]: images/error1.png + +Теперь нет никакого "оно работает", верно? Не беспокойся, это всего лишь страница ошибки, здесь нечего пугаться! Она, на самом деле, довольно полезна: + +Ты можешь прочесть, что не существует атрибута с именем 'post_list' -- **no attribute 'post_list'**. Не напоминает ли *post_list* тебе что-нибудь? Так мы назвали свое представление! Это значит, что всё на месте, просто мы ещё не создали наше *представление*. Не беспокойся, мы этим займемся. + +> Если хочешь узнать больше о Django URLconfs, посмотри официальную документацию: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/ru/django_urls/images/error1.png b/ru/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/ru/django_urls/images/error1.png differ diff --git a/ru/django_urls/images/images/error1.png b/ru/django_urls/images/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/ru/django_urls/images/images/error1.png differ diff --git a/ru/django_urls/images/images/url.png b/ru/django_urls/images/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/ru/django_urls/images/images/url.png differ diff --git a/ru/django_urls/images/url.png b/ru/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/ru/django_urls/images/url.png differ diff --git a/ru/django_views/README.md b/ru/django_views/README.md new file mode 100755 index 00000000000..6363a32ac90 --- /dev/null +++ b/ru/django_views/README.md @@ -0,0 +1,40 @@ +# Представления в Django – время создавать! + +Пришло время избавиться от ошибки, на которую мы наткнулись в прошлой главе :) + +*view* это то место, где мы разместим "логику" работы нашего приложения. Оно запросит информацию из `модели`, которую мы создали ранее, и передаст её в `шаблон`. Шаблонами мы займёмся в следующей главе. Представления похожи на методы в Python и лишь немногим сложнее того, с чем мы уже сталкивались в главе **Введение в Python**. + +Представления размещаются в файле `views.py`. Мы добавим свои *представления* в файл `blog/views.py`. + +## blog/views.py + +Хорошо, давай откроем этот файл и посмотрим на его содержимое: + +```python +from django.shortcuts import render + +# Create your views here. +``` + + +Не слишком много кода. Простейшее *представление* может выглядеть следующим образом. + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + + +Как ты можешь заметить, мы создали метод (`def`) с именем `post_list`, который принимает в `request` в качестве аргумента и `return` (возвращает) результат работы метода `render`, который соберет наш шаблон страницы `blog/post_list.html`. + +Сохрани файл, перейди по адресу http://127.0.0.1:8000/ и посмотри что у нас получилось. + +Другая ошибка! Читаем, что произошло: + +![Ошибка][1] + + [1]: images/error.png + +Это просто: *TemplateDoesNotExist* -- такого шаблона не существует. Давай исправим ошибку и создадим шаблон в следующей главе! + +> Подробнее о представлениях в Django можно узнать из официальной документации: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/ru/django_views/images/error.png b/ru/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/ru/django_views/images/error.png differ diff --git a/ru/django_views/images/images/error.png b/ru/django_views/images/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/ru/django_views/images/images/error.png differ diff --git a/ru/domain/README.md b/ru/domain/README.md new file mode 100755 index 00000000000..2aca96d1f81 --- /dev/null +++ b/ru/domain/README.md @@ -0,0 +1,71 @@ +# Домен + +Heroku предоставил нам домен, но он довольно длинный, его сложно запомнить, да и выглядит он страшно. Было бы неплохо иметь короткий и легко запоминаемый домен, верно? + +В этой главе мы покажем как купить домен и привязать его к Heroku! + +## Где регистрировать домен? + +Типичный домен стоит около $15 в год. Существуют варианты и дешевле, и дороже, в зависимости от провайдера. Существует множество компаний, у которых ты можешь купить домен: простой [поиск в интернете][1] выдаст тысячи предложений. + + [1]: https://www.google.com/search?q=register%20domain + +Наш любимый выбор [I want my name][2]. Они рекламируют себя как "управление доменами без боли" и это действительно так. + + [2]: https://iwantmyname.com/ + +## Как зарегистрировать домен в IWantMyName? + +Перейди по ссылке [iwantmyname][3] и впиши желаемый домен в форму поиска. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +Ты должна увидеть список доступных доменов с выбранным именем. Как ты можешь заметить, смайлик указывает занят ли домен или доступен для покупки. + +![][5] + + [5]: images/2.png + +Мы решили купить `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Переходим к оформлению заказа. Ты должна авторизоваться на iwantmyname, если не сделала этого до сих пор. После этого укажи номер своей кредитки и соверши покупку! + +Теперь перейди в раздел `Domains` через меню и выбери свой новый домен. Затем найди ссылку `manage DNS records` и кликни по ней: + +![][7] + + [7]: images/4.png + +После этого найди следующую форму: + +![][8] + + [8]: images/5.png + +И заполни её следующей информацией: - Hostname: www - Type: CNAME - Value: your domain from Heroku (for example djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Нажми кнопку Add и Save changes в низу экрана. + +Может пройти несколько часов прежде чем твой домен начнет работать, будь терпеливой! + +## Настройка домена на Heroku + +Нам также нужно сообщить Heroku, что теперь ты будешь использовать свой домен. + +Перейди в [Панель управления Heroku][10], авторизируйся и выбери свое приложение. Затем зайди в настройки приложения и добавь свой домен в разделе `Domains`, после - сохрани изменения. + + [10]: https://dashboard.heroku.com/apps + +Вот и все! \ No newline at end of file diff --git a/ru/dynamic_data_in_templates/README.md b/ru/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..b167b696ae7 --- /dev/null +++ b/ru/dynamic_data_in_templates/README.md @@ -0,0 +1,79 @@ +# Динамически изменяющиеся данные в шаблонах + +Отдельные части уже размещены в нужных местах: модель `Post`, определена в файле `models.py`, `post_list` - в файле `views.py` и добавлен шаблон. Но как нам отобразить записи в шаблоне HTML-страницы? Ведь именно этого нам и нужно добиться: взять определенный контент (модели, сохраненные в базе данных) и аккуратно отобразить их в шаблоне, верно? + +Для этого и предназначены *представления*: соединять между собой модели и шаблоны. В `post_list` *представлениям* нужно будет взять модели, которые мы хотим отобразить и передать их шаблону. Таким образом, в *представлениях* мы определяем что (какая модель) будет отображена в шаблоне. + +Хорошо, так как мы этого добьемся? + +Нам нужно открыть файл `blog/views.py`. Таким образом *представление* `post_list` будет выглядеть следующим образом: + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + + +Помнишь мы говорили о включении кода из других файлов? Теперь нам нужно включить модель, которую мы определили в файле `models.py`. Мы добавим строку `from .models import Post` следующим образом: + +```python +from django.shortcuts import render +from .models import Post +``` + + +Точка перед `models` означает *текущую директорию* или *текущее приложение*. Поскольку `views.py` и `models.py` находятся в одной директории, мы можем использовать точку `.` и имя файла (без расширения `.py`). Затем мы импортируем модель (`Post`). + +Но что дальше? Чтобы получить реальную запись из модели `Post`, нам нужен `QuerySet`. + +## QuerySet + +Ты уже должна быть знакома с принципом работы QuerySets. Мы говорили о нем в главе [Django ORM (QuerySets)][1]. + + [1]: ../django_orm/README.md + +Сейчас нас интересует список записей блога, отсортированных по `published_date`, согласна? Мы уже делали это в главе о QuerySets! + +```python + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Теперь нам нужно включить эту строку кода в файл`blog/views.py`, добавив её в функцию `def post_list(request)`: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + + +Пожалуйста, обрати внимание, что мы создали *переменную* для QuerySet: `posts`. Можешь думать о ней как об имени для нашего QuerySet. Теперь мы можем обращаться к нему, используя имя. + +Кроме того, код использует функцию `timezone.now()`, так что нужно также импортировать `timezone`. + +Нам осталось передать QuerySet `posts` в шаблон (мы расскажем о том, как отобразить его на странице в следующей главе). + +В функции `render` мы уже имеем параметр `request` (т.е. все что мы получим от пользователя в качестве запроса через Интернет) и файл шаблона `'blog/post_list.html'`. Последний параметр, который выглядит как `{}`, это место, куда мы можем добавить что-нибудь для использования в шаблоне. Мы должны задавать имена, передаваемым шаблону вещам (мы будем придерживаться `'posts'` прямо сейчас :)). В итоге параметр будет выглядеть следующим образом: `{'posts': posts}`. Обрати внимание, что часть перед `:` является строкой; её нужно обернуть в кавычки `''`. + +В результате файл `blog/views.py` должен выглядеть следующим образом: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + + +Вот и все! Теперь пришло время перейти к шаблону и отобразить QuerySet на странице! + +Подробнее о QuerySets в Django можно узнать в официальной документации: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ diff --git a/ru/extend_your_application/README.md b/ru/extend_your_application/README.md new file mode 100755 index 00000000000..8b47ff6d4c4 --- /dev/null +++ b/ru/extend_your_application/README.md @@ -0,0 +1,197 @@ +# Расширяем свое приложение + +Мы уже выполнили часть необходимых шагов для создания веб-сайта: мы знаем как создать модель, URL, представление и шаблон. Мы также знаем как улучшить визуальный дизайн с помощью CSS. + +Время практики! + +Первое, что нам потребуется в блоге - страница для отображения конкретной записи, верно? + +У нас уже есть модель `Post`, так что нам не нужно добавлять дополнительный код в файл `models.py`. + +## Создадим в шаблоне ссылку на страницу поста + +Мы начнем с добавления ссылки внутри файла `blog/templates/blog/post_list.html`. Пока он выглядит следующим образом: + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + + +{% raw %}Нам хотелось бы иметь ссылку с заголовка поста в списке на страницу подробной информации о посте. Давай изменим `

{{ post.title }}

` чтобы получилась ссылка на пост:{% endraw %} + +```html +

{{ post.title }}

+``` + +{% raw %}Самое время разобраться с загадочным `{% url 'post_detail' pk=post.pk %}`. Как можешь предположить, синтаксис `{% %}` означает использование тегов шаблонов Django. На этот раз мы используем тот, что создаст для нас URL!{% endraw %} + +`blog.views.post_detail` это путь к *представлению* `post_detail`, которое нам нужно создать. Пожалуйста, обрати внимание: `blog` - это имя нашего приложения (директория `blog`), `views` - имя файла `views.py` без расширения и последнее - `post_detail` - имя *представления*. + +Теперь, когда мы перейдем по адресу http://127.0.0.1:8000/ мы получим ошибку (как и ожидается, поскольку у нас нет прописанного URL и *представления* для `post_detail`). Она будет выглядеть следующим образом: + +![Ошибка NoReverseMatch][1] + + [1]: images/no_reverse_match2.png + +## Создадим URL для страницы поста + +Давай создадим URL в `urls.py` для *представления* `post_detail`! + +Мы хотим, чтобы адрес страницы нашего первого поста был таким: **URL**: http://127.0.0.1:8000/post/1/ + +Давай создадим URL в файле `blog/urls.py` и укажем Django на *представление* под названием `post_detail`, которое будет отображать пост целиком. Добавь строчку `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` в файл `blog/urls.py`. Файл должен выглядеть примерно так: + +```python + from django.conf.urls import url + from . import views + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + ] +``` + +Фрагмент `^post/(?P[0-9]+)/$` выглядит страшновато, но не волнуйтесь — мы его сейчас объясним: - он начинается с `^`, что означает, как мы помним, "начало строки" - `post/` значит всего лишь, что после начала строки URL должен содержать слово **post** и косую черту **/**. Пока все в порядке. - `(?P[0-9]+)` - эта часть посложнее. Она означает, что Django возьмет все, что придется на эту часть строки и передаст представлению в качестве переменной `pk`. `[0-9]` означает, что допустимы только цифры (от 0 до 9), но не буквы. `+` означает, что цифр должно быть от одной и больше. Таким образом адрес `http://127.0.0.1:8000/post//` будет недействительным, а `http://127.0.0.1:8000/post/1234567890/` совершенно правильным! - `/` - затем нам нужен еще один символ **/** - `$` - "конец"! + +Если ты введешь адрес `http://127.0.0.1:8000/post/5/` в браузер, Django должен понять, что тебе требуется *представление* под именем `post_detail`, и передать информацию о переменной `pk` (равной `5`) этому *представлению*. + +`pk` сокращение от `primary key` (первичный ключ). Это имя часто используют в Django проектах. Но ты можешь назвать эту переменную как пожелаешь (помни: строчные буквы и `_` вместо пробелов!). Для примера, вместо `(?P[0-9]+)` мы могли бы иметь переменную `post_id`, таким образом эта часть кода выглядела бы как: `(?P[0-9]+)`. + +Славненько, мы добавили новый шаблон URL в файл `blog/urls.py`! Давай обновим страницу: http://127.0.0.1:8000/ Бууум! Ещё одна ошибка! Как и ожидалось! + +![AttributeError][2] + + [2]: images/attribute_error2.png + +Помнишь, каким должен быть следующий шаг? Конечно: добавить представление! + +## Добавим представление для страницы поста + +В этот раз *представление* получит дополнительный параметр `pk`. Но как дать нашему *представлению* знать о нем? Для этого мы определим функцию как `def post_detail(request, pk):`. Обрати внимание, что мы должны использовать тоже имя переменной, что мы выбрали для обработки URL (`pk`). Пропуск переменной будет неправилен и приведет к ошибке! + +Теперь мы хотим получить одну конкретную запись из блога. Для этого потребуется использовать QuerySet: + +```python + Post.objects.get(pk=pk) +``` + +Однако в этом коде есть проблема. Если не существует экземпляра объекта `Post` с заданным `primary key` (`pk`) мы получим страшную ошибку! + +![Ошибка DoesNotExist][3] + + [3]: images/does_not_exist2.png + +Мы этого не хотим! Однако, Django, конечно, имеет средство, которое позволит нам её обойти: `get_object_or_404`. В случае, если не существует экземпляра объекта `Post` с заданным `pk`, мы получим намного более приятную страницу (которая называется `Page Not Found 404`). + +![Страница не найдена][4] + + [4]: images/404_2.png + +Хорошая новость в том, что ты можешь сделать свою страницу `Page not found`. Но для нас сейчас это не самая важная задача и мы её пропустим. + +Хорошо, пришло время добавить *представление* в файл `views.py`! + +Нам нужно открыть файл `blog/views.py` и добавить в него следующий код: + +```python + from django.shortcuts import render, get_object_or_404 +``` + +Рядом с другими строками, начинающимися с `from`. В конец же файла мы добавим наше новое *представление*: + +```python + def post_detail(request, pk): +     post = get_object_or_404(Post, pk=pk) +     return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Именно. Теперь обнови страницу http://127.0.0.1:8000/ + +![Представление списка записей][5] + + [5]: images/post_list2.png + +Заработало! Только что произойдет, если ты попробуешь перейти по ссылке из заголовка записи? + +![Ошибка TemplateDoesNotExist][6] + + [6]: images/template_does_not_exist2.png + +Ой, нет! Другая ошибка! Но мы уже знаем как иметь с ней дело, верно? Нам нужно добавить шаблон! + +## Создадим шаблон для страницы поста + +Мы создадим файл `post_detail.html` в директории `blog/templates/blog`. + +Он должен содержать следующее: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + +И снова мы расширяем `base.html`. В блоке `content` мы отображаем дату публикации (published_date, если она существует), заголовок и текст. Нам также нужно обсудить пару важных вещей, хорошо? + +{% raw %}`{% if ... %} ... {% endif %}` это тег шаблона, который мы можем использовать, если нам нужно что-то проверить (помнишь конструкцию `if ... else ..` из главы **Введение в Python**?). В данном случае мы хотим проверить, не пуста ли дата публикации `published_date` поста.{% endraw %} + +Отлично, можешь перезагрузить страницу и проверить пропала ли ошибка `Page not found`. + +![Отдельная страницы записи][7] + + [7]: images/post_detail2.png + +Ура! Все работает! + +## Еще одна вещь: развертывание! + +Было бы неплохо проверить, что веб-сайт все еще будет работать на PythonAnywhere, верно? Давай еще раз проведем развертывание. + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push +``` + +* Затем набери в [Bash консоли PythonAnywhere][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + +* И нажми **Reload** на вкладке [Web tab][9]. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +Вот и все! Поздравляем :) diff --git a/ru/extend_your_application/images/404_2.png b/ru/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/ru/extend_your_application/images/404_2.png differ diff --git a/ru/extend_your_application/images/attribute_error2.png b/ru/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/ru/extend_your_application/images/attribute_error2.png differ diff --git a/ru/extend_your_application/images/does_not_exist2.png b/ru/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/ru/extend_your_application/images/does_not_exist2.png differ diff --git a/ru/extend_your_application/images/no_reverse_match2.png b/ru/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/ru/extend_your_application/images/no_reverse_match2.png differ diff --git a/ru/extend_your_application/images/post_detail2.png b/ru/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/ru/extend_your_application/images/post_detail2.png differ diff --git a/ru/extend_your_application/images/post_list2.png b/ru/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/ru/extend_your_application/images/post_list2.png differ diff --git a/ru/extend_your_application/images/template_does_not_exist2.png b/ru/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/ru/extend_your_application/images/template_does_not_exist2.png differ diff --git a/ru/how_the_internet_works/README.md b/ru/how_the_internet_works/README.md new file mode 100755 index 00000000000..f22cb9de4a2 --- /dev/null +++ b/ru/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# Как работает Интернет + +> Эта глава вдохновлена выступлением «Как работает Интернет» Джессики Маккеллар (http://web.mit.edu/jesstess/www/). + +Можем поспорить, что ты пользуешься Интернетом каждый день. Но знаешь ли ты на самом деле, что происходит после ввода адреса, такого как https://djangogirls.org, в браузер и нажатия `Enter`? + +Первое, что тебе нужно понять, это то, что веб-сайт представляет собой просто группу файлов, сохраненных на жестком диске. Так же, как твои фильмы, музыка или фотографии. Тем не менее, есть одна особенность, которая является уникальной для сайтов: они содержат компьютерный код, называемый HTML. + +Если ты не знакома с программированием, то сначала может быть трудно понять HTML, но твой веб-браузер (например, Chrome, Safari, Firefox, и т. д.) обожает его. Веб-браузеры созданы для того чтобы понимать этот код, следовать его указаниям и представлять файлы, из которых состоит твой веб-сайт, именно так, как ты этого хочешь. + +Как и с любым файлом, нам нужно хранить HTML файлы где-то на жестком диске. Для Интернета мы используем специальные, мощные компьютеры, называемые *серверами*. У них нет экрана, мыши или клавиатуры, потому что их основной целью является хранение и обслуживание данных. Вот почему они называются *серверами*--потому что они *обслуживают* (serve) твои данные. + +Хорошо, но ты хочешь знать, как выглядит Интернет, так? + +Мы нарисовали тебе картинку! Он выглядит вот так: + +![Рисунок 1.1][1] + + [1]: images/internet_1.png + +Довольно беспорядочно, правда? На самом деле, это сеть связанных машин (упомянутых выше *серверов*). Сотен тысяч машин! Километры и километры кабелей по всему миру! Ты можешь посетить веб-сайт с картой подводных кабелей (http://submarinecablemap.com/), чтобы увидеть, насколько сложной является сеть. Вот скриншот с сайта: + +![Рисунок 1.2][2] + + [2]: images/internet_3.png + +Поразительно, не так ли? Однако, очевидно, что невозможно соединить кабелем каждую машину, подключенную к Интернету. Таким образом, чтобы достичь нужной машины (например, хранящей https://djangogirls.org), мы должны передать запрос через множество других машин. + +Этот процесс выглядит следующим образом: + +![Рисунок 1.3][3] + + [3]: images/internet_2.png + +Представь себе, что когда ты вводишь адрес https://djangogirls.org, то отправляешь письмо, в котором говорится: «Дорогие Django Girls, я хочу увидеть сайт djangogirls.org. Отправьте мне его, пожалуйста!» + +Твое письмо отправляется в ближайшее почтовое отделение. Затем оно направляется в другое, которое немного ближе к адресату, а затем в следующее и так далее до его доставки в пункт назначения. Единственное отличие в том, что при отправке множества писем (*пакетов данных*) по одному адресу, каждое из них может пойти через совершенно разные почтовые отделения (*маршрутизаторы*). Это зависит от того, как они были распределены в каждом отделении. + +![Рисунок 1.4][4] + + [4]: images/internet_4.png + +Да, все так просто. Ты отправляешь сообщения и ждешь ответа. Конечно, вместо бумаги и ручки ты используешь байты данных, но идея та же! + +Вместо адресов с названием улицы, города, почтового индекса и названия страны мы используем IP-адреса. Твой компьютер сначала просит DNS (Domain Name System) перевести djangogirls.org в IP-адрес. Это работает примерно как в случае старых телефонных книг, где можно по имени человека, с которым ты хочешь связаться, найти его номер телефона и адрес. + +Когда ты отправляешь письмо, оно должно обладать определенными особенностями, чтобы его доставили правильно: адресом, маркой и т.д. Ты также используешь язык, который понимает получатель, верно? То же самое относится к *пакетам данных*, которые ты отправляешь, чтобы увидеть веб-сайт. Мы используем протокол под названием HTTP (англ. HyperText Transfer Protocol, протокол передачи гипертекста). + +Поэтому, в принципе, когда у тебя есть веб-сайт, то необходимо иметь и *сервер* (машину), где он находится. Когда *сервер* получает входящий *запрос* (в письме), он отправляет обратно твой веб-сайт (в другом письме). + +Поскольку это руководство по Django, разумно будет спросить -- что же он делает в этой системе. Когда ты отправляешь ответ, то ты не всегда хочешь отправлять одно и то же письмо всем получателям. Намного лучше, если твои письма являются персонифицированными, особенно для человека, который только что тебе написал сам, правильно? Django помогает тебе с созданием этих персонализированных, интересных писем :). + +Ну, хватит болтать, время заняться делом! \ No newline at end of file diff --git a/ru/how_the_internet_works/images/internet_1.png b/ru/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/ru/how_the_internet_works/images/internet_1.png differ diff --git a/ru/how_the_internet_works/images/internet_2.png b/ru/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/ru/how_the_internet_works/images/internet_2.png differ diff --git a/ru/how_the_internet_works/images/internet_3.png b/ru/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/ru/how_the_internet_works/images/internet_3.png differ diff --git a/ru/how_the_internet_works/images/internet_4.png b/ru/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/ru/how_the_internet_works/images/internet_4.png differ diff --git a/ru/html/README.md b/ru/html/README.md new file mode 100755 index 00000000000..447b7b6a1c5 --- /dev/null +++ b/ru/html/README.md @@ -0,0 +1,212 @@ +# Введение в HTML + +Так что же это за шаблон, ты можешь спросить. + +Шаблон -- это файл, который мы можешь использовать повторно для отображения различной информации в заданном формате, например, ты можешь использовать шаблон, чтобы упростить написание письма, поскольку письма хоть и различаются по содержанию и получателю, но сохраняют общую структуру. + +Шаблоны в Django написаны на языке, называемом HTML (это тот HTML, о котором было упоминание в первой главе **Как работает Интернет**). + +## Что такое HTML? + +HTML -- это простой код, который может быть интерпретирован твоим браузером -- таким как Chrome, Firefox или Safari -- чтобы отобразить веб-страницу пользователю. + +HTML (от англ. "HyperText Markup Language") - язык гипертекстовой разметки. **Гипертекст** - это тип текста, поддерживающий гиперссылки между страницами. Под **разметкой** понимается введение в текст документа кода, который будет говорить браузеру (в нашем случае) как интерпретировать веб-страницу. HTML код строится при помощи **тегов**, каждый из которых должен начинаться с `<` и заканчиваться `>`. Эти теги представляют **элементы** разметки. + +## Твой первый шаблон! + +Создание шаблона означает создание файла шаблона. Все есть файл, верно? Ты уже заметила это, наверно. + +Шаблоны сохраняются в директории `blog/templates/blog`. Для начала создай директорию `templates` внутри папки blog. Затем создай другую директорию `blog` внутри папки templates: + + blog + └───templates + └───blog + + +(Ты, вероятно, можешь задаться вопросом: зачем нам нужны две директории с одинаковым названием `blog` - как ты узнаешь позже, это просто удобное соглашение об именовании, которое делает жизнь проще, когда вещи серьезно усложняются.) + +Теперь создай файл `post_list.html` (для начала оставь его пустым) внутри директории `blog/templates/blog`. + +Посмотри как выглядит твой веб-сайт после этого: http://127.0.0.1:8000/ + +> Если тебя все еще встречает ошибка `TemplateDoesNotExists`, попробуй перезапустить сервер. Перейди в командную строку, останови веб-сервер нажатием Ctrl+C (Ctrl и С одновременно) и запусти его снова командой `python manage.py runserver`. + +![Рисунок 11.1][1] + + [1]: images/step1.png + +Ошибки больше нет! Поздравляем :) Однако, твой веб-сайт все равно ничего не отображает, кроме пустой страницы, поскольку твой шаблон пуст. Нам нужно это исправить. + +Добавь следующий код в файл шаблона: + +```html + +

Hi there!

+

It works!

+ +``` + + +Как теперь выглядит твой веб-сайт? Нажми сюда, чтобы узнать: http://127.0.0.1:8000/ + +![Рисунок 11.2][2] + + [2]: images/step3.png + +Заработало! Хорошая работа :) + +* Наиболее базовой тег, ``, всегда присутствует в начале веб-страницы и `` - в конце. Как ты можешь заметить, основной контент веб-сайта находится между тегами `` и `` +* `

` - это тег для параграфов; `

`, соответственно, закрывает каждый параграф + +## Head & body + +Каждая HTML-страница также делится на два элемента: **head** и **body**. + +* **head** -- это элемент, содержащий информацию о документе, которая не отображается на экране. + +* **body** -- это элемент, который содержит все, что будет отражено на веб-странице. + +Мы используем тег `` чтобы сообщить браузеру о настройках страницы и тег `` - о её содержимом. + +Например, ты можешь разместить элемент title между тегов ``: + +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` + + +Сохрани файл и обнови страницу. + +![Рисунок 11.3][3] + + [3]: images/step4.png + +Видишь, как браузер понял, что "Ola's blog" -- это заголовок страницы? Он понял `Ola's blog` и разместил текст в заголовке вкладки в твоем браузере (заголовок также будет использоваться при сохранении закладок и т.п.). + +Вероятно, ты уже заметила, что каждый открывающий тег имеет пару -- *закрывающий*, с символом `/`, элементы таким образом становятся *вложенными* (ты не можешь закрыть тег, пока остаются открытыми теги внутри него). + +Это как складывать вещи в коробки. У нас есть одна большая коробка, ``; внутри неё лежит коробка ``, которая содержит еще меньшие коробки: `

`. + +Ты должна следовать этим правилам *закрытия* тегов и *вложенности* элементов, если ты станешь их нарушать - браузер не сможет интерпретировать код и корректно отобразить страницу. + +## Настраиваем шаблон + +Ты можешь немного повеселиться сейчас и попробовать настроить шаблон по своему вкусу! Вот несколько полезных тегов: + +* `

Заголовок

` - главный заголовок страницы +* `

Подзаголовок

` для заголовков второго уровня +* `

Заголовок третьего уровня

` ... и так далее, вплоть до `
` +* `текст` подчеркивает твой текст +* `текст` - жирный шрифт +* `
` переход на следующую строку (внутрь br тега нельзя ничего поместить) +* `link` создает ссылку +* `
  • первый элемент
  • второй элемент
` создает список, такой же как этот! +* `
` определяет раздел страницы + +Вот пример готового шаблона: + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` + + +Мы создали три `div` элемента. + +* Первый элемент `div` содержит название блока, которое также является ссылкой +* Два других `div` элемента содержат текст записи и дату публикации, `h2` тег с заголовком записи, который также является ссылкой, и два `p` (параграфа) с текстом, один для даты и другой для самого текста записи. + +Это даст нам следующий эффект: + +![Рисунок 11.4][4] + + [4]: images/step6.png + +Ура! Однако, до сих пор наш шаблон отображал лишь **одну и ту же информацию** - тогда как раньше мы говорили, что шаблоны позволяют нам отображать **различную** информацию в **одном и том же формате**. + +Что мы действительно хотим - это отображать существующие записи, добавленные через панель администратора Django, этим и займемся в следующий раз. + +## Еще одно: развертывание! + +Хотелось бы увидеть все это в живую в интернете, согласна? Давай проведем еще одно развертывание веб-сайта на PythonAnywhere: + +### Commit и push кода в репозиторий Github + +Во-первых, давай посмотрим, какие файлы были изменены с момента последнего развертывания (выполни эти команды локально, не на PythonAnywhere): + + $ git status + + +Убедись, что находишься в директории `djangogirls` и сообщи `git` выбрать все изменения в пределах папки: + + $ git add --all . + + +> **Примечание**: `-A` (сокращение от "all" - "все") означает, что `git` также обратит внимание на удаленные файлы (по умолчанию, он отслеживает новые/измененные файлы). Также помни (из третьей главы), что `.` означает текущую директорию. + +Прежде чем мы загрузим файлы, давай проверим, что именно `git` будет загружать (все файлы, который `git` готов отправить на сервер отмечаются шрифтом зеленого цвета): + + $ git status + + +Мы почти у цели, пришло время сохранить изменения в истории. К сохраняемой версии мы приложим небольшое сообщение, в котором кратко опишем изменения. Можешь набрать в качестве сообщения все что захочешь, однако, полезно использовать информативную запись, так будет проще вспомнить внесенные изменения в будущем. + + $ git commit -m "Changed the HTML for the site." + + +> **Примечание**: Убедись, что используешь двойные кавычки вокруг комментария. + +После того, как мы сделали это, мы загрузим (заpush'им) изменения на Github: + + git push + + +### Загружаем новый код на PythonAnywhere и перезапускаем веб-приложение + +* Открой вкладку ["терминалы"][5] на PythonAnywhere и переключись на уже запущенную **консоль Bash** (или новую). Затем набери следующую команду: + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +Можешь обратить внимание как твой код будет загружаться на сервер. Если хочешь проверить успешность процедуры - открой вкладку **Файлы** и просмотри свой код на PythonAnywhere. + +* Наконец, переключись на вкладку [Web][6] и нажми кнопку **Reload**. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +Обновления должны отобразиться на веб-сайте! Переключись на него и обнови страницу. Ты должна сразу заметить улучшения :) diff --git a/ru/html/images/step1.png b/ru/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/ru/html/images/step1.png differ diff --git a/ru/html/images/step3.png b/ru/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/ru/html/images/step3.png differ diff --git a/ru/html/images/step4.png b/ru/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/ru/html/images/step4.png differ diff --git a/ru/html/images/step6.png b/ru/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/ru/html/images/step6.png differ diff --git a/ru/images/application.png b/ru/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/ru/images/application.png differ diff --git a/ru/installation/README.md b/ru/installation/README.md new file mode 100755 index 00000000000..dcc794f313e --- /dev/null +++ b/ru/installation/README.md @@ -0,0 +1,49 @@ +# Если ты занимаешься дома + +Если ты занимаешься по этому руководство дома, а не на одной из [встреч Django Girls](https://djangogirls.org/events/), то можешь пропустить этот раздел и приступить сразу же к главе [Как работает интернет?](../how_the_internet_works/README.md). + +Дело в том, что мы всё равно рассматриваем все эти вещи по ходу руководства, а в этом разделе мы просто собрали все инструкции по установке вместе. Встречи Django Grils включают в себя "вечер настроек", когда мы устанавливаем всё что нужно, чтобы не тратить на это время в течение основного семинара, это очень удобно для нас. + +Если ты также считаешь эту идею удачной, то можешь следовать содержанию главы. Чтобы сразу перейти к изучению нового материала, пропустив установку необходимых программ, просто пропусти эту главу - мы будем объяснять все необходимые вещи по мере продвижения по руководству. + +Удачи! + +# Установка + +В процессе мастер-класса мы будем создавать блог и у нас есть несколько подготовительных задач по установке, которые не помешало бы выполнить заранее, чтобы тебе не пришлось отвлекаться от программирования. + +# Установка Python + +{% include "/python_installation/instructions.md" %} + +# Настрока virtualenv и установка Django + +{% include "/django_installation/instructions.md" %} + +# Установка редактора кода + +{% include "/code_editor/instructions.md" %} + +# Установка Git + +{% include "/deploy/install_git.md" %} + +# Создание учётной записи на GitHub + +Перейди на [GitHub.com](https://www.github.com) и зарегистрируй новый бесплатный аккаунт. + +# Создание учётной записи на PythonAnywhere + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Начинай читать + +Поздравляем, всё готово к работе! Если у тебя ещё осталось немного свободного времени до семинара, было бы полезно начать читать одну из первых глав: + + * [Как работает Интернет](../how_the_internet_works/README.md) + + * [Введение в командную строку](../intro_to_command_line/README.md) + + * [Введение в Python](../python_introduction/README.md) + + * [Что же представляет из себя Django?](../django/README.md) diff --git a/ru/intro_to_command_line/README.md b/ru/intro_to_command_line/README.md new file mode 100755 index 00000000000..738d5c35480 --- /dev/null +++ b/ru/intro_to_command_line/README.md @@ -0,0 +1,279 @@ +# Знакомство с командной строкой + +Вот это интересно, да?! Ты напишешь свою первую строку кода всего через несколько минут :) + +**Позволь представить нашего первого нового друга: командную строку!** + +Следующие шаги покажут как использовать черное окно, которым пользуются все хакеры. В начале оно может показаться немного пугающим, но, на самом деле это просто окно, которое ждет от тебя команды. + +> **Примечание** Пожалуйста, обратите внимание, что в этой книге мы используем термины «каталог» и «папка» взаимозаменяемо, эти слова обозначают одно и то же. + +## Что такое командная строка? + +Окно, которое обычно называют **командной строкой** или **интерфейсом командной строки (англ. CLI, Command Line Interface)**, является текстовым приложением для просмотра, обработки и манипулирования файлами на вашем компьютере. Как Проводник Windows или Finder на Mac, но без графического интерфейса. Другими названиями для командной строки являются: *cmd*, *CLI*, *prompt*, *консоль* или *терминал*. + +## Открываем интерфейс командной строки + +Для того, чтобы начать экспериментировать, нам нужно сначала открыть интерфейс командной строки. + +### Windows + +Перейти в меню Пуск → Все программы → Стандартные → Командная строка. + +### Mac OS X + +Приложения → Утилиты → Терминал. + +### Linux + +Вероятно, командная строка скрывается по адресу: Приложения → Стандартные → Терминал, но это может зависеть от конкретной системы. Если не сможешь найти - Google поможет :) + +## Командная строка + +Теперь ты должна увидеть окно белого или черного цвета, которое ожидает команд. + +Если ты используешь Mac или Linux, то, вероятно, увидишь символ `$`: + + $ + + +В Windows ты увидишь знак `>`: + + > + + +Каждую команду будет предварять этот знак и один пробел, но тебе не придется их вводить. Компьютер сделает это за нас :) + +> Небольшое примечание: в твоем случае до знака командной строки может быть что-то вроде `C:\Users\ola >` или `Olas-MacBook-Air:~ ola$`, и это 100% правильно. В данном руководстве мы просто будем сокращать запись до разумного минимума. + +## Твоя первая команда (УРА!) + +Давай начнем с чего-то простого. Введи следующую команду: + + $ whoami + + +или + + > whoami + + +И затем нажми `enter`. Вот наш результат: + + $ whoami + olasitarska + + +Как видишь, компьютер только что напечатал твоё имя пользователя. Аккуратный, правда? :) + +> Попробуй набирать каждую команду самостоятельно, а не копировать и вставлять. Ты запомнишь больше таким образом! + +## Основы + +В каждой операционной системе набор команд для командной строки немного отличается, поэтому не забывай следовать инструкциям для своей операционной системы. Давай попробуем, готова? + +### Текущий каталог + +Было бы приятно знать, где мы находимся сейчас, верно? Давай посмотрим. Введи следующую команду и нажми `enter`: + + $ pwd + /Users/olasitarska + + +Если ты в Windows: + + > cd + C:\Users\olasitarska + + +Ты, вероятно, увидишь нечто похожее на своем компьютере. Когда ты открываешь командную строку, то обычно находишься в домашнем каталоге текущего пользователя. + +> Примечание: «pwd» означает «вернуть рабочий каталог» 'print working directory'. + +* * * + +### Список файлов и каталогов + +Так что же в нем? Было бы здорово узнать. Давайте посмотрим: + + $ ls + Applications + Desktop + Downloads + Music + ... + + +Windows: + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM
Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### Смена текущего каталога + +Теперь вернемся в наш каталог рабочего стола: + + $ cd Desktop + + +Windows: + + > cd Desktop + + +Проверь, что рабочий каталог действительно изменился: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Вот и он! + +> ПРО совет: Если ты введешь `cd D` и затем нажмешь `Tab` на клавиатуре, в командной строке будет автоматически набрана остальная часть имени, что позволит быстрее перемещаться по каталогам. Если существует более одной папки, название которой начинается с «D», нажми `Tab` дважды, чтобы получить список вариантов. + +* * * + +### Создание каталога + +Как насчет создания каталога practice на рабочем столе? Вы можете сделать это таким образом: + + $ mkdir practice + + +Windows: + + > mkdir practice + + +Эта маленькая команда создаст папку с именем `practice` на рабочем столе. Ты можешь проверить, появилась ли она, просто взглянув на рабочий стол или введя команду `ls` / `dir`! Попробуй :) + +> ПРО совет: Если ты не хочешь вводить одни и те же команды снова и снова, попробуйте нажать на `стрелку вверх` и `стрелку вниз` на клавиатуре, чтобы просмотреть недавно использованные команды. + +* * * + +### Тренеруемся! + +Небольшая задачка: в недавно созданной папке `practice` создай папку с названием `test`. Используй команды `cd` и `mkdir`. + +#### Решение: + + $ cd practice + $ mkdir test + $ ls + test + + +Windows: + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + +Поздравляем! :) + +* * * + +### Чистка + +Мы не хотим оставлять беспорядок, поэтому давай удалим все, что мы создали до этого момента. + +Во-первых, мы должны вернуться на рабочий стол: + + $ cd .. + + +Windows: + + > cd.. + + +Используя `..` с командой `cd` ты можешь сменить текущий каталог на родительский (то есть каталог, содержащий в себе текущий). + +Проверь, где ты находишься: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Пришло время удалить каталог `practice`: + +> **Внимание**: удаление файлов с помощью `del`, `rmdir` или `rm` безвозвратно, это означает, что *удаленные файлы будут потеряны навсегда*! Поэтому будь очень осторожна с этими командами. + + $ rm -r practice + + +Windows: + + > rmdir /S practice + practice, Are you sure ? Y + + +Готово! Давай проверим, что папка действительно удалена: + + $ ls + + +Windows: + + > dir + + +### Выход + +Вот и все на данный момент! Теперь можно безопасно закрыть командную строку. Давай сделаем это как хакеры, согласна? :) + + $ exit + + +Windows: + + > exit + + +Круто, да?:) + +## Краткий обзор + +Вот краткий обзор некоторых полезных команд: + +| Команда (Windows) | Команда (Mac OS / Linux) | Описание | Пример | +| ----------------- | ------------------------ | ----------------------- | ------------------------------------------------- | +| exit | exit | Закрыть окно | **exit** | +| cd | cd | изменить каталог | **cd test** | +| dir | ls | список каталогов/файлов | **dir** | +| copy | cp | копировать файл | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | переместить файл | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | создать новый каталог | **mkdir testdirectory** | +| del | rm | удалить файл/каталог | **del c:\test\test.txt** | + +Это лишь некоторые из команд, которые можно использовать в командной строке, но сегодня тебе больше и не пригодится. + +Если тебе интересно, [ss64.com][1] содержит полный справочник команд для всех операционных систем. + + [1]: http://ss64.com + +## Готова? + +Давай погрузимся в мир Python! diff --git a/ru/python_installation/README.md b/ru/python_installation/README.md new file mode 100755 index 00000000000..a50e21ae58e --- /dev/null +++ b/ru/python_installation/README.md @@ -0,0 +1,13 @@ +# Давай начнем работать с Python + +Мы, наконец-то, здесь! + +Для начала, позволь рассказать что такое Python. Python - это очень популярный язык программирования, который может использоваться для создания веб-сайтов, игр, научного программного обеспечения, графики и многого, многого другого. + +Python возник в конце 80-х годов, и его основной целью является быть удобным для чтения людьми (не только машинами!). Именно поэтому он выглядит намного проще, чем другие языки программирования. Это делает его простым для изучения, но не волнуйся, Python кроме этого еще и очень мощный язык! + +# Установка Python + +> **Примечание** Если ты уже прошла через шаги установки, не нужно делать это снова - можешь переходить прямо к следующей главе! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/ru/python_installation/images/add_python_to_windows_path.png b/ru/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/ru/python_installation/images/add_python_to_windows_path.png differ diff --git a/ru/python_installation/instructions.md b/ru/python_installation/instructions.md new file mode 100755 index 00000000000..7a385f25015 --- /dev/null +++ b/ru/python_installation/instructions.md @@ -0,0 +1,66 @@ +> Этот подраздел основан на руководстве Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django написан на Python. Нам нужен Python, чтобы сделать что-нибудь в Django. Давай начнем с его установки! Мы хотим, чтобы ты установила Python 3.4, поэтому, если у тебя уже есть более ранняя версия, то её придется обновить. + +### Windows + +Ты можешь загрузить Python для Windows с официального веб-сайта: https://www.python.org/downloads/release/python-343/. После загрузки ***.msi** файла, ты должна запустить его (двойной щелчок) и следовать инструкциям. Важно помнить путь (каталог), куда ты установила Python. Это понадобится позже! + +Обрати внимание на второй экран мастера установки, который называется "Customize" (Настройка): тебе нужно пролистать его вниз и выбрать опцию "Add python.exe to the Path" (Добавить python.exe к системной переменной Path), как на рисунке: + +![Не забудьте добавить Python в системную переменную Path](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Вполне вероятно, что у тебя уже установлен Python. Чтобы проверить это (а также версию языка), открой консоль и введи следующую команду: + + $ python3 --version + Python 3.4.3 + + +Если Python не установлен, или ты хочешь использовать другую версию языка, то можешь установить его следующим образом: + +#### Debian или Ubuntu + +Введи эту команду в консоль: + + $ sudo apt-get install python3.4 + + +#### Fedora (версии вплоть до 21) + +Используй следующую команду в консоли: + + $ sudo yum install python3.4 + + +#### Fedora (версии 22 и выше) + +Используй следующую команду в консоли: + + $ sudo dnf install python3.4 + + +#### openSUSE + +Используй следующую команду в консоли: + + $ sudo zypper install python3 + + +### OS X + +Тебе нужно перейти по ссылке https://www.python.org/downloads/release/python-343/ и скачать дистрибутив Python: + + * Скачай файл *Mac OS X 64-bit/32-bit installer*, + * Сделай двойной щелчок на *python-3.4.3-macosx10.6.pkg* для запуска установщика. + +Убедись, что установка прошла успешно, открыв приложение *Терминал* и запустив команду `python3`: + + $ python3 --version + Python 3.4.3 + + +* * * + +Если у тебя остались какие-либо сомнения, или что-то пошло не так и ты понятия не имеешь что делать дальше - спроси своего тренера! Иногда дела идут не совсем гладко, поэтому лучше попросить помощи у кого-то с большим опытом. diff --git a/ru/python_introduction/README.md b/ru/python_introduction/README.md new file mode 100755 index 00000000000..648cba43db4 --- /dev/null +++ b/ru/python_introduction/README.md @@ -0,0 +1,806 @@ +# Введение в Python + +> Часть этой главы основана на учебных пособиях Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +Давай напишем немного кода! + +## Консоль Python + +Чтобы начать играть с Python, нам нужно открыть *командную строку* на твоем компьютере. Ты уже должна знать, как это сделать -- мы изучали это в главе [Введение в интерфейс командой строки][1]. + + [1]: ../intro_to_command_line/README.md + +После того, как будешь готова, следуйте приведенным ниже инструкциям. + +Мы хотим открыть консоль Python, так что набери `python` если работаешь в Windows, или `python3` для Mac OS/Linux, и нажми `enter`. + + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## Твоя первая команда Python! + +После запуска Python, консоль изменилась на `>>>`. Для нас это означает, что сейчас мы можем использовать только команды на языке Python. Тебе не нужно вводить `>>>` - Python будет делать это за нас. + +Если ты хочешь выйти из консоли Python, в любой момент -- просто введи `exit()` или используй сочетание клавиш `Ctrl + Z` для Windows и `Ctrl + D` для Mac/Linux. Тогда ты больше не будешь видеть `>>>`. + +Пока что мы не хотим выходить из консоли Python. Мы хотим узнать больше о ней. Давай начнём с чего-нибудь совсем простого. Например, попробуй набрать простое математическое выражение, вроде `2 + 3` и нажми `enter`. + + >>> 2 + 3 + 5 + + +Прекрасно! Видишь, как выскочил ответ? Python знает математику! Ты можешь попробовать другие команды, такие как: - `4 * 5` - `5 - 1` - `40 / 2` + +Поиграй с этим немного и затем вернись сюда :). + +Как видишь, Python является прекрасным калькулятором. Если тебе интересно, что еще можно сделать... + +## Строки + +Как насчет твоего имени? Введи свое имя в кавычках, вот так: + + >>> "Ola" + 'Ola' + + +Сейчас ты создала свою первую строку! Это последовательность символов, которые могут быть обработаны компьютером. Строка должна всегда начинаться и заканчиваться одинаковым символом. Им может быть одинарная (`'`) или двойная (`"`) кавычка (разницы нет!) Кавычки говорят Python'у, что внутри них находится строка. + +Строки могут быть слиты воедино. Попробуй так: + + >>> "Hi there " + "Ola" + 'Hi there Ola' + + +Ты также можешь умножать строки на число: + + >>> "Ola" * 3 + 'OlaOlaOla' + + +Если тебе нужно поставить апостроф внутри строки, то есть два способа сделать это. + +Использование двойных кавычек: + + >>> "Runnin' down the hill" + "Runnin' down the hill" + + +или предварение апострофа обратной косой чертой (``): + + >>> 'Runnin\' down the hill' + "Runnin' down the hill" + + +Прикольно, да? Чтобы увидеть своё имя прописными буквами, просто набери: + + >>> "Ola".upper() + 'OLA' + + +Ты только что использовала **функцию** `upper` для своей строки! Функция (такая как `upper()`) представляет собой набор инструкций, который должен выполнить Python на заданном объекте (в нашем случае: `"Ola"`) при её вызове. + +Если ты хочешь узнать количество букв в своём имени, то и для этого тоже существует функция! + + >>> len("Ola") + 3 + + +Интересно, почему иногда мы вызываем функцию добавлением `.` к концу строки (как `"Ola".upper()`), а иногда сначала пишем имя функции и затем помещаем строку в скобки? Ну, в некоторых случаях функции принадлежат объектам, например функция `upper()`, которая может быть применена только к строкам. В этом случае мы называем функцию **методом**. В другом случае функции не относятся к чему-то конкретному и могут использоваться для различных типов объектов, например функция `len()`. Вот почему мы передаем `"Ola"` в качестве параметра функции `len`. + +### Краткий обзор + +OK, достаточно о строках. Пока ты узнала о: + +* **консоль** - ввод команд (кода) в интерактивную командную строку Python приводит к ответам на Python +* **числа и строки** - в Python числа используются для вычислений, а строки - для текстовых объектов +* **операторы** - такие как + и *, объединяют значения для получения нового +* **функции** - такие как upper() и len(), выполняют действия над объектами. + +Таковы основы каждого языка программирования, который ты можешь выучить. Готова к чему-то посложнее? Мы уверены, что готова! + +## Ошибки + +Давай попробуем кое-что новенькое. Можем ли мы получить длину числа так же, как длину твоего имени? Введи `len(304023)` и нажми `Enter`: + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +Мы получили нашу первую ошибку! Она говорит о том, что у объектов типа «int» (целые числа) нет длины. Так что же мы можем сейчас сделать? Может быть мы можем написать наше число в виде строки? У строк ведь есть длина, верно? + + >>> len(str(304023)) + 6 + + +Сработало! Мы использовали функцию `str` внутри функции `len`. `str()` преобразует все в строки. + +* Функция `str` преобразует объекты в **строки** +* Функция `int` преобразует объекты в **целые числа** + +> Важно: мы можем преобразовать число в текст, но не всегда удается преобразовать текст в числа - например, каков будет результат `int('hello')`? + +## Переменные + +Переменные -- важное понятие в программировании. Переменная -- это не более чем имя для чего-то, чтобы использовать его позднее. Программисты используют переменные для хранения данных, чтобы их код был более читабельным, и для того, чтобы им не пришлось запоминать что есть что. + +Допустим, мы хотим создать новую переменную с именем `name`: + + >>> name = "Ola" + + +Видишь? Это очень легко! Просто введи: name равно Ola. + +Как ты уже заметила, твоя программа не возвращает ничего, как было ранее. Так откуда мы знаем, что переменная действительно существует? Просто введи `name` и нажми `Enter`: + + >>> name + 'Ola' + + +Ура! Твоя первая переменная:)! Ты всегда можешь изменить то, к чему она относится: + + >>> name = "Sonja" + >>> name + + +Ты можешь использовать их также и в функциях: + + >>> len(name) + 5 + + +Круто, правда? Переменными, конечно, может быть что угодно, и цифры тоже! Попробуй следующее: + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +Но что делать, если мы использовали неправильное имя? Можешь догадаться, что произойдет? Давай попробуем! + + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + + +Ошибка! Как ты можешь видеть, в Python есть различные типы ошибок, эта называется **NameError**. Python выдаст эту ошибку при попытке использовать переменную, которая пока не определена. При возникновении этой ошибки проверь свой код, чтобы узнать, не написала ли ты неправильно имя переменной. + +Попрактикуйся в этом какое-то время и посмотри, что ты сможешь сделать! + +## Функция print + +Попробуй ввести: + + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + + +Если просто ввести `name`, интерпретатор Python вернет строковое *представление* переменной 'name', которым, в нашем случае, являются буквы M-a-r-i-a, окруженные одинарными кавычками, ''. Когда ты вводишь `print(name)`, Python "печатает" содержание переменной на экран, без кавычек, что удобнее. + +Как мы увидим позднее, `print()` пригодится когда нам будет нужно печатать что-то изнутри функций или когда мы захотим напечатать что-то на нескольких строчках. + +## Списки + +Помимо строк и целых чисел Python имеет богатую коллекцию других типов объектов. Сейчас мы собираемся представить тебе один из них - **list** (список). Списки - это именно то, о чем ты подумала: объекты, которые являются списками других объектов :) + +Давай начнем с создания списка: + + >>> [] + [] + + +Отлично, это пустой список. Не особенно полезен, да? Давай создадим список лотерейных номеров. Мы не хотим повторять их каждый раз, так что присвоим список переменной: + + >>> lottery = [3, 42, 12, 19, 30, 59] + + +Замечательно, у нас есть список! Что мы можем с ним сделать? Для начала посмотрим как много лотерейных номеров в нашем списке. Есть идеи какую функцию можно использовать для этого? Ты её уже знаешь! + + >>> len(lottery) + 6 + + +Точно! `len()` вернет тебе количество объектов в списке. Удобно, правда? Может быть мы теперь отсортируем его: + + >>> lottery.sort() + + +Эта команда не возвращает ничего, она просто меняет порядок номеров в списке. Давайте выведем его на экран и посмотрим что получилось: + + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + + +Как видишь, номера в списке теперь отсортированы от меньшего к большему. Поздравляем! + +Может быть нам нужно изменить порядок? Давай сделаем это! + + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + + +Просто, правда? Если хочешь добавить что-то к своему списку, то можешь воспользоваться этой командой: + + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + + +Если ты хочешь получить первый номер в списке, то можешь воспользоваться **индексами**. Индекс это номер позиции в списке, на котором находится нужное нам значение. Программисты предпочитают начать считать с 0, так что первому объекту в списке соответствует индекс 0, следующему —1, и так далее. Попробуй ввести: + + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + + +Как видишь, ты можешь обратиться к различным объектам в своем списке используя имя списка и индекс объекта в квадратных скобках. + +Чтобы удалить что-либо из списка, тебе понадобятся **индексы**, с которыми мы уже разобрались выше, и команда `pop()`. Давай попробуем закрепить пройденное примером; мы будем удалять первый элемент из нашего списка. + + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + + +Сработало как заклинание! + +В качестве дополнительной тренировки попробуй следующие индексы: 6, 7, 1000, -1, -6 и -1000. Сможешь предсказать результат? Видишь логику работы? + +Ты можешь найти перечень всех методов, относящихся к списку, в этой главе официальной документации Python: https://docs.python.org/3/tutorial/datastructures.html + +## Словари + +Словари схожи со списками, но ты обращаешься к значениям словаря по ключу, а не по индексу. Ключом может быть любая строка или число. Давай создадим пустой словарь: + + >>> {} + {} + + +Это показывает, что мы создали пустой словарь. Ура! + +Теперь попробуй следующую команду (можешь заменить значения на своё имя, страну и т.д.): + + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + + +Этой командой ты создала переменную `participant` с тремя парами ключ-значение: + +* Ключ `name`, указывающий на значение `'Ola'` (`строковый` объект), +* ключ `country`, указывающий на значение `'Poland'` (еще одна `строка`), +* и ключ `favorite_numbers`, указывающий на значение `[7, 42, 92]` (объект типа `список` с тремя числами внутри). + +Значение конкретного ключа можно узнать следующим образом: + + >>> print(participant['name']) + Ola + + +Видишь, синтаксис похож на работу со списком. Но вместо того чтобы запоминать индекс, тебе нужно помнить ключ. + +Что случится, если мы спросим у Python значение несуществующего в словаре ключа? Можешь предположить? Давай попробуем и узнаем наверняка! + + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + + +Смотри, другая ошибка! Эта называется **KeyError**. Python услужливо напоминает, что ключа `'age'` не существует в словаре. + +Когда стоит использовать словарь, а когда список? Это хороший вопрос для самостоятельного размышления. Сделай предположение перед тем, как читать дальше. + +* Тебе нужна упорядоченная последовательность элементов? Список - наш выбор. +* Тебе нужны сочетания ключ - значение, чтобы быстро искать значения (по ключу) в дальнейшем? Словарь отлично подойдет. + +Словари, как и списки, *изменяемы*, т. е. они могут быть изменены после того как были созданы. Ты можешь добавить новые пары ключ/значение в словарь следующим образом: + + >>> participant['favorite_language'] = 'Python' + + +Также как в примере со списками, использование функции `len()` вернет число пар ключ/значение в словаре. Попробуй сама: + + >>> len(participant) + 4 + + +Надеюсь все вышеизложенное понятно. :) Готова к новым приключениям со словарями? На следующей строке тебя ждут изумительные вещи. + +Ты можешь использовать команду `pop()` для удаления элементов из словаря. Скажем, ты хочешь удалить элемент с ключом `'favorite_numbers'`, просто набери следующую команду: + + >>> participant.pop('favorite_numbers') + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + + +Как видно, пара ключ-значение с ключом 'favorite_numbers' была удалена. + +Помимо этого, ты можешь заменить значение, ассоциированное с уже существующим ключом. Набери: + + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + + +Значение, на которое ссылается ключ `'country'` было изменено с `'Poland'` на `'Germany'`. :) Захватывает? Еще бы! Ты выучила еще одну потрясающую штуку. + +### Содержание + +Шикарно! Теперь ты знаешь немало о программировании. Мы познакомились с: + +* **ошибками** - теперь ты знаешь как читать и анализировать ошибки, которые возникают, если Python не понимает твоей команды +* **переменными** - именами для объектов, которые упрощают твой код и делают его более читабельным +* **списками** - последовательностями объектов в заданном порядке +* **словарями** - объектами, хранящими пары ключ-значение + +Готова к продолжению? :) + +## Сравниваем вещи + +Немалая часть программирования требует сравнения вещей. Что проще всего сравнить друг с другом? Числа, конечно. Давай посмотрим как это работает: + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + + +Мы передали Python несколько чисел для сравнения. Как ты можешь заметить, Python сравнивает не только числа, но и результаты методов (например, умножения). Неплохо, правда? + +Хочешь спросить почему мы написал двойной символ равенства `==`, чтобы проверить одинаковы ли числа? Потому что одинарные символ равенства `=` уже задействован под присваивание значения переменным. Ты всегда, **всегда** должна писать два символа равенства `==`, если хочешь проверить одинаковы ли объекты. Мы также можем проверить различаются ли объекты. Для этого, мы используем `!=`, как показано в примере выше. + +Дадим Python еще два задания: + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +С `>` и `<` все понятно, но что значат `>=` и `<=`? Читай их следующим образом: + +* x `>` y означает: x больше y +* x `<` y означает: x меньше y +* x `<=` y означает: x меньше или равен y +* x `>=` y означает: x больше или равен y + +Супер! Хочешь еще? Тогда попробуй вот это: + + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + + +Ты можешь передать Python так много чисел, как захочешь, и он будет возвращать ответ! Хитро, правда? + +* **and** - если ты используешь `and` оператор, оба сравнения по бокам от него должны быть True (верны), чтобы результат всей команды был равен True +* **or** - если ты используешь `or` оператор, достаточно одному из сравнений по бокам от него быть равным True, чтобы результат всей команды также равнялся True + +Ты когда-нибудь слышала выражение "сравнивать яблоки и апельсины"? Попробуем что-то подобное в Python: + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +Как мы видим, Python не знает как сравнить число (`int`) и строку (`str`) между собой. Поэтому он просто возвращает нам ошибку **TypeError** и предупреждает, что объекты заданных типов не могут быть сравнены. + +## Логические значения + +Между прочим, ты только что познакомилась с новым типом объектов в Python. Он называется **Boolean** (логический) -- и это наверно самый простой тип из всех. + +Существует только два логических объекта в Python: - True (Истина) - False (Ложь) + +Чтобы Python понимал тебя, ты всегда должна писать True с заглавной буквы (остальные прописные). **true, TRUE, tRUE не будет восприниматься -- только True.** (Та же логика применима к False, само собой.) + +Ты можешь присваивать переменным логические значения! Смотри сюда: + + >>> a = True + >>> a + True + + +Или так: + + >>> a = 2 > 5 + >>> a + False + + +Попрактикуйся с логическими значениями на примере этих выражений: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Поздравляем! Логические значения одна из самых классных фишек программирования и ты только что научилась ими пользоваться! + +# Сохраняй! + +До сих пор мы писали весь код в интерактивной консоли, где Python сразу анализировал, обрабатывал и выполнял наши команды. Мы были ограничены одной строкой. Обычно, программы сохраняются в файлах и выполняются **интерпретатором** или **компилятором** нашего языка программирования. Пока мы только просили **интерпретатор** Python выполнять наши однострочные команды из консоли. Однако, нам понадобиться больше места для следующих задач, поэтому задача минимум: + +* Закрыть интерактивную консоль Python +* Открыть наш текстовый редактор +* Сохранить код в новом файле +* Запустить его! + +Чтобы закрыть интерактивную консоль Python просто набери функцию `exit()` : + + >>> exit() + $ + + +Это вернет тебя в командную строку. + +В главе [Текстовый редактор][2] мы выбрали себе редактор. Нам нужно открыть его сейчас и записать следующий код в новый файл: + + [2]: ../code_editor/README.md + +```python +print('Hello, Django girls!') +``` + + +> **Примечание** Ты должна уже была заметить одну из крутейших вещей в редакторах кода: цвета! В интерактивной консоли Python весь текст был одного цвета, сейчас же функция `print` должна отличаться по цвету от текста, который передается в неё в качестве атрибута. Это называется «синтаксическая подсветка», и это действительно удобная штука для программирования. Цвет подсветки может подсказать тебе о незакрытой кавычке или опечатке в ключевом слове (таком как `def` в определении функции, с которым мы скоро познакомимся). Это одна из причин, по которой мы используем редакторы кода :) + +Очевидно, ты уже искушенный Python разработчик, так что не стесняйся добавить что-нибудь по своему вкусу из ранее изученного. + +Теперь нам нужно сохранить файл с кодом и дать ему подходящее имя. Давай назовем его **python_intro.py** и сохраним на рабочий стол. Мы можем назвать файл как хотим, но важно чтобы название заканчивалось на **.py**. Расширение **.py** говорит операционной системе, что это **исполняемый файл python**, и Python может его запустить. + +После сохранения файла пришло время запустить его! Используя навыки из раздела о командной строке, открой терминал и **поменяй текущую директорию** на рабочий стол. + +Для Mac команда будет выглядеть так: + + $ cd /Users//Desktop + + +Для Linux (слово "Desktop" может быть переведено на твой язык, например "Рабочий стол"): + + $ cd /home//Desktop + + +И для windows: + + > cd C:\Users\\Desktop + + +Если возникли проблемы - просто обратись за помощью. + +Теперь используй Python чтобы запустить код в файле: + + $ python3 python_intro.py + Hello, Django girls! + + +Отлично! Ты только что запустила свою первую программу, чей код был сохранен в файле. Чувствуешь воодушевление? + +Можно передвигаться дальше к такому незаменимому в программировании инструменту как: + +## If...elif...else + +Зачастую определенный код в программе должен выполняться только при соблюдении определенных условий. Поэтому в Python есть такая вещь как **условный оператор if**. + +Замени код в своем файле **python_intro.py** на: + +```python +if 3 > 2: +``` + + +Если мы сохраним его и запустим, то получим ошибку: + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python предполагает, что мы должны дать ему инструкции, которые будут им выполнены при соблюдении условия `3 > 2` (т. е. при равенстве условия логическому значению `True`). Давай попробуем заставить Python напечатать на экране “It works!”. Внеси следующие изменения в **python_intro.py**: + +```python +if 3 > 2: + print('It works!') +``` + + +Обратила внимание как мы сделали отступ во второй строке из 4 символов пробела? Мы поступаем так, чтобы Python понимал какой код после условного оператора if должен быть выполнен, если условие равно True. Можно ограничиться и одним пробелом, однако, практически все программисты Python используют 4, чтобы код выглядел аккуратно и читабельно. Каждая `табуляция` также считается за 4 пробела. + +Сохраняем и запускаем еще раз: + + $ python3 python_intro.py + It works! + + +### Что, если условие не True? + +В предыдущем примере код выполнялся только когда условие равнялось True. Однако, Python имеет операторы `elif` и `else`: + +```python +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') +``` + + +Если запустить этот код, он напечатает: + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +Если 2 больше 5, то будет выполнена следующая команда. Просто, правда? Давай посмотрим как работает оператор `elif`: + +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` + + +и запускаем: + + $ python3 python_intro.py + Hey Sonja! + + +Видишь, что произошло? `elif` позволяет добавить дополнительные условия, которые запускаются если предыдущие не срабатывают. + +Можно использовать сколько угодно `elif` после первого `if`. Например: + +```python +volume = 57 +if volume < 20: + print("It's kinda quiet.") +elif 20 <= volume < 40: + print("It's nice for background music") +elif 40 <= volume < 60: + print("Perfect, I can hear all the details") +elif 60 <= volume < 80: + print("Nice for parties") +elif 80 <= volume < 100: + print("A bit loud!") +else: + print("My ears are hurting! :(") +``` + + +Python проходит через каждую проверку условия и выводит: + + $ python3 python_intro.py + Perfect, I can hear all the details + + +### Содержание + +В последних трех упражнениях ты познакомилась с: + +* **сравнением вещей** - в Python ты можешь сравнивать вещи друг с другом при помощи `>`, `>=`, `==`, `<=`, `<` и `and`, `or` операторов +* **Boolean** - тип объекта, который может иметь только два значения: `True` или `False` +* **сохранением файлов** - хранение кода в файлах позволяет выполнять длинные программы. +* **if...elif...else** - условные операторы, которые позволяют выполнять код только при определенных условиях. + +Пришло время для последней части этой главы! + +## Твоя собственная функция! + +Помнишь функции, такие как `len()`, которые можно использовать в Python? Тогда у нас есть хорошие новости — сейчас ты научишься писать свои собственные функции! + +Функция - это последовательность инструкций, которые должен выполнить Python. Каждая функция в Python начинается с ключевого слова `def`, имеет свое имя и параметры. Давай начнем с простого примера. Замени код в **python_intro.py** на следующий: + +```python +def hi(): + print('Hi there!') + print('How are you?') + +hi() +``` + + +Отлично, наша первая функция готова! + +Ты можешь задаться вопросом, почему мы написали имя функции в конце файла. Причина в том, что Python читает и исполняет код из файла сверху вниз. Поэтому, для использования нашей функции мы должны вызвать её в конце файла. + +Давай запустим и посмотрим что произойдет: + + $ python3 python_intro.py + Hi there! + How are you? + + +Это было просто! Давай напишем нашу первую функцию с параметрами. Мы будем использовать предыдущий пример - функцию, которая пишут 'hi' и имя пользователя: + +```python +def hi(name): +``` + + +Как ты можешь заметить, мы передали нашей функции параметр `name`: + +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + +hi() +``` + + +Помни: функция `print` расположена внутри блока оператора `if` с отступом в четыре пробела. Это потому, что она запускается тогда, когда выполняется условие. Давай посмотрим, как это работает: + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' + + +Упс, ошибка. К счастью, Python выдает довольно подробное сообщение об ошибке. Оно говорит нам, что функция `hi()` (которую мы определили) имеет один обязательный аргумент (`name`) и мы забыли передать его при вызове функции. Давай исправим это в конце файла: + +```python +hi("Ola") +``` + + +И запустим еще раз: + + $ python3 python_intro.py + Hi Ola! + + +И если мы поменяем имя? + +```python +hi("Sonja") +``` + + +И повторим: + + $ python3 python_intro.py + Hi Sonja! + + +Теперь, как ты думаешь, что произойдет, если ты наберешь другое имя? (Не Ola или Sonja) Попробуй сама и проверь была ли ты права. Результат должен быть таким: + + Hi anonymous! + + +Шикарно, верно? Так тебе не придется повторяться каждый раз, когда ты захочешь изменить имя. И это именно та причина, для которой нам и нужны функции - ты никогда не захочешь повторять свой код! + +Давай попробуем что-то похитрее -- существует немало имен и писать условие для каждого будет тяжело, правда? + +```python +def hi(name): + print('Hi ' + name + '!') + +hi("Rachel") +``` + + +Давай выполним этот код: + + $ python3 python_intro.py + Hi Rachel! + + +Поздравляем! Ты только что научилась писать свои собственные функции :) + +## Циклы + +Ну вот и последняя часть. Быстро время пролетело, верно? :) + +Программисты не любят повторяться. Программирование — это автоматизация вещей, поэтому мы не хотим приветствовать каждого человека по имени вручную, верно? Здесь пригодятся циклы. + +Еще помнишь о списках? Давай создадим список девушек: + +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` + + +Мы хотим поздороваться с каждой по имени. У нас есть функция `hi`, которая этим и занимается, так что давай поместим её в цикл: + +```python +for name in girls: +``` + + +Оператор `for` работает по схожему принципу что и `if`; код после обоих операторов должен иметь отступ в четыре пробела. + +Ниже полный код, который должен быть у нас в файле: + +```python +def hi(name): + print('Hi ' + name + '!') + +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` + + +И после запуска: + + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl + + +Как ты можешь заметить, все команды внутри цикла `for` (с отступом от левого края) будут выполняться для каждого элемента списка `girls`. + +Ты также можешь использовать цикл `for` на числах, используя функцию `range`: + +```python +for i in range(1, 6): + print(i) +``` + + +Что выведет на экран: + +``` +1 +2 +3 +4 +5 +``` + + +Функция `range` создает список чисел, следующих от первого до второго с заданным шагом (начало, конец и шаг мы передаем функции как параметры, если шаг не указать, как в примере выше, он будет по умолчанию равен 1). + +Обрати внимание что второе число (конец списка) не включается в результат работы функции (`range(1, 6)` создает список от 1 до 5, не включающий 6). Это потому, что «range» — полуоткрытый диапазон, то есть включает в себя первое значение, но не включает последнего. + +## Содержание + +Вот и всё. **Ты чертовски крута!** Эта глава была непростой, так что ты можешь гордиться собой. Мы-то точно тобой гордимся — вон как далеко продвинулась уже! + +Тебе может потребоваться перерыв - прогуляйся и дай отдых глазам перед тем, как мы перейдем к следующей главе. :) + +![Пирожок][3] + + [3]: images/cupcake.png diff --git a/ru/python_introduction/images/cupcake.png b/ru/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/ru/python_introduction/images/cupcake.png differ diff --git a/ru/template_extending/README.md b/ru/template_extending/README.md new file mode 100755 index 00000000000..e44f1180444 --- /dev/null +++ b/ru/template_extending/README.md @@ -0,0 +1,124 @@ +# Расширение шаблона + +Еще одной удобной вещью в Django является **расширение шаблонов**. Что это значит? Ты можешь использовать различные блоки HTML-кода для разных частей своего веб-сайта. + +Так тебе не придется повторяться каждый раз, когда потребуется использовать туже информацию/структуру. И если появится необходимость что-то изменить - не придется вносить правки в каждую страницу - достаточно скорректировать шаблон! + +## Создаем базовый шаблон + +Базовый шаблон - это наиболее общая типовая форма страницы, которую ты расширяешь для отдельных случев. + +Давай создадим файл `base.html` в директории `blog/templates/blog/`: + +``` + blog + └───templates +     └───blog +             base.html +             post_list.html +``` + +Теперь открой его и скопируй все из `post_list.html` в `base.html`: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Затем в файле `base.html` замени все между тегами `` и `` следующим кодом: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +Мы просто заменили все между `{% for post in posts %}{% endfor %}` следующим: + +```html + {% block content %} + {% endblock %} +``` + +Что это означает? Ты только что создала `block` - тег шаблона, позволяющий вставлять HTML-код этого блока в другие шаблоны, расширяющие `base.html`. Мы покажем как это сделать через секунду. + +Теперь сохрани все и открой `blog/templates/blog/post_list.html` снова. Тебе нужно удалить весь код вне тегов body, а также ``, в итоге файл будет выглядеть следующим образом: + +```html + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + +А теперь добавь следующую строку в начало файла: + +``` + {% extends 'blog/base.html' %} +``` + +{% raw %}Таким образом мы расширили шаблон `base.html` шаблоном `post_list.html`. Осталось последнее: обернуть все (кроме добавленной выше первой строки) в `{% block content %}` и `{% endblock content %}`. Таким образом:{% endraw %} + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + +Готово! Проверь, что твой веб-сайт работает нормально :) + +> Если появилась ошибка `TemplateDoesNotExists`, которая говорит что не существует файла `blog/base.html`, после того как ты запустила веб-сервер через команду `runserver` в рабочей строке, попробуй остановить его (одновременно нажми Ctrl + C находясь в командной строке) и перезапусти веб-сервер командой `python manage.py runserver`. diff --git a/ru/whats_next/README.md b/ru/whats_next/README.md new file mode 100755 index 00000000000..d0c03193faa --- /dev/null +++ b/ru/whats_next/README.md @@ -0,0 +1,40 @@ +# Что дальше? + +Поздравь себя! **Ты нереально крута**. Мы очень гордимся! <3 + +### Что делать дальше? + +Сделай перерыв и расслабься. Ты только что закончила огромную работу. + +И не забудь подписаться на: + +* Страничку Django Girls в [Facebook][1] и [Twitter][2], чтобы оставаться в курсе новостей + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Можем ли мы посоветовать дополнительные ресурсы для обучения? + +Кончено! Прежде всего попробуй [Учебнике Django Girls: Дополнительные темы][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Позднее ты можешь попробовать ресурсы из списка ниже. Мы очень рекомендуем все из них! + +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/sk/GLOSSARY.md b/sk/GLOSSARY.md new file mode 100755 index 00000000000..38a876ffe64 --- /dev/null +++ b/sk/GLOSSARY.md @@ -0,0 +1,3 @@ +# editor kódu + +Editor kódu je aplikácia, pomocou ktorej môžeš svoj kód uložiť, takže sa k nemu môžeš neskôr vrátiť. Kde ho môžeš zohnať, zistíš v [kapitole o editore kódu](./code_editor/README.md) \ No newline at end of file diff --git a/sk/README.md b/sk/README.md new file mode 100755 index 00000000000..e2f0d550b3f --- /dev/null +++ b/sk/README.md @@ -0,0 +1,48 @@ +# Príručka k Django Girls + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Toto dielo je zverejnené pod medzinárodnou licenciou Creative Commons Attribution-ShareAlike ("uvedenie autora – rovnaké šírenie") 4.0. Ak chcete zobraziť kópiu tejto licencie, navštívte https://creativecommons.org/licenses/by-sa/4.0/ + +## Úvod + +Mala si niekedy pocit, že svet je stále viac a viac o technológiách a ty v nich zaostávaš? Uvažovala si niekedy, že by si si vytvorila webovú stránku, ale nikdy si nemala dosť motivácie začať? Zdalo sa ti niekedy, že svet softvéru je pre teba príliš komplikovaný a že sama nezvládneš nič vytvoriť? + +Máme pre teba dobrú správu! Programovanie nie je také zložité, ako sa zdá a chceme ti ukázať, aké môže byť zábavné. + +Tento návod z teba neurobí mávnutím čarovného prútika programátorku. Ak chceš byť dobrá, čakajú ťa mesiace či dokonca roky štúdia a praxe. Chceme ti ale ukázať, že vytvorenie webovej stránky nie je také ťažké, ako sa zdá. Pokúsime sa ti vysvetliť rôzne technológie tak, aby si sa ich nemusela báť. + +Dúfame, že sa ti tieto veci zapáčia tak veľmi ako nám! + +## Čo ťa tento návod naučí? + +Po skončení budeš mať funkčnú webovú aplikáciu: tvoj vlastný blog. Ukážeme ti, ako ho zverejniť na webe, kde ho môže každý navštíviť! + +Výsledok bude vyzerať asi takto: + +![Obrázok 0.1][2] + + [2]: images/application.png + +> Ak budeš na tomto projekte pracovať sama a nemáš mentora, ktorý ti pomáha, môžeš v prípade problémov navštíviť tento chat: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Požiadali sme našich mentorov, ale aj absolventky, aby sa na tomto chate občas ukázali a pomohli ostatným, ktorí môžu zápasiť s problémami! Neboj sa pripojiť a opýtať sa, na čo potrebuješ! + +OK, [začnime pekne po poriadku...][3] + + [3]: ./how_the_internet_works/README.md + +## Informácie a možnosti ako sa zapojiť + +Tento návod vytvorili a udržiavajú [DjangoGirls][4]. Ak nájdete chyby alebo by ste chceli aktualizovať tento návod, prosím [postupujte podľa pokynov][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Chceš pomôcť s prekladom do iných jayzkov? + +V súčasnosti koordinujeme preklady cez platformu crowdin.com: + +https://crowdin.com/project/django-girls-tutorial + +Ak tvoj jazyk nie je v zozname na crowdin.com, [daj nám prosím vedieť][6] a povedz, aký jazyk máme pridať. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/sk/SUMMARY.md b/sk/SUMMARY.md new file mode 100755 index 00000000000..4db235abfb7 --- /dev/null +++ b/sk/SUMMARY.md @@ -0,0 +1,26 @@ +# Zhrnutie + +* [Úvod](README.md) +* [Inštalácia](installation/README.md) +* [Ako funguje Internet](how_the_internet_works/README.md) +* [Úvod do príkazového riadku](intro_to_command_line/README.md) +* [Inštalácia Pythonu](python_installation/README.md) +* [Editor kódu](code_editor/README.md) +* [Úvod do jazyka Python](python_introduction/README.md) +* [Čo je Django?](django/README.md) +* [Inštalácia Django](django_installation/README.md) +* [Tvoj prvý Django projekt!](django_start_project/README.md) +* [Django modely](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Nasadenie!](deploy/README.md) +* [Django url](django_urls/README.md) +* [Django views - čas tvoriť!](django_views/README.md) +* [Úvod do HTML](html/README.md) +* [Django ORM (tvorba dotazov)](django_orm/README.md) +* [Dynamické dáta v šablónach](dynamic_data_in_templates/README.md) +* [Šablóny Django](django_templates/README.md) +* [CSS - aby to pekne vyzeralo](css/README.md) +* [Rozširovanie šablón](template_extending/README.md) +* [Ako rozšíriť aplikáciu](extend_your_application/README.md) +* [Formuláre Django](django_forms/README.md) +* [Čo ďalej?](whats_next/README.md) diff --git a/sk/code_editor/README.md b/sk/code_editor/README.md new file mode 100755 index 00000000000..97a5ffc6e23 --- /dev/null +++ b/sk/code_editor/README.md @@ -0,0 +1,7 @@ +# Editor kódu + +O chvíľu napíšeš svoj prvý riadok kódu, takže je načase si stiahnuť editor kódu! + +> **Poznámka** Toto si už možno spravila v kapitole Inštalácia - ak áno, môžeš pokračovať rovno na ďalšiu kapitolu! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/sk/code_editor/instructions.md b/sk/code_editor/instructions.md new file mode 100755 index 00000000000..b2d8c066e7f --- /dev/null +++ b/sk/code_editor/instructions.md @@ -0,0 +1,31 @@ +Existuje veľa rôznych editorov a zväčša sa vyberajú podľa osobných preferencií. Väčšina Python programátorov používa zložité, ale veľmi výkonné IDE (integrované vývojové prostredie), ako napríklad PyCharm. Pre začiatočníka je to pravdepodobne menej vhodné; naše odporúčania sú rovnako výkonné, ale oveľa jednoduchšie. + +Naše návrhy sú uvedené nižšie, ale neváhaj sa opýtať svojho trénera, aké sú jeho preferencie - potom bude jednoduchšie od neho získať pomoc. + +## Gedit + +Gedit je open-source, editor zdarma dostupný pre všetky operačné systémy. + +[Stiahni si tu](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text je veľmi populárny editor so skúšobnou verziou zdarma. Je jednoduchý na inštaláciu a používanie, je dostupný pre všetky operačné systémy. + +[Stiahni si tu](https://www.sublimetext.com/3) + +## Atom + +Atom je veľmi nový editor vytvorený [GitHubom](https://github.com/). Je zdarma, open-source, jednoduchý na inštaláciu a používanie. Je dostupný pre Windows, OS X a Linux. + +[Stiahni si tu](https://atom.io/) + +## Prečo inštalujeme editor? + +Môžete Vás zaujímať, prečo inštalujeme takýto špeciálny editor kódu, radšej než používať niečo ako Word alebo Notepad. + +Prvý dôvod je, že kód musí byť **čistý text** a problém s programami ako Word a Textedit je ten, že v skutočnosti nevytvárajú čistý text, produkujú obohatený text (s fontom a formátovaním), používajú vlastné formáty ako [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Druhý dôvod je, že editor kódu je špecializovaný na editáciu kódu, takže môže poskytovať pomocné funkcie ako zvýraznenie kódu farbou podľa jeho významu alebo automaticky za Vás uzatvárať úvodzovky. + +Všetko uvidíme neskôr. Čoskoro budeš premýšľať o svojom starom vernom editore ako o svojom obľúbenom nástroji :) \ No newline at end of file diff --git a/sk/css/README.md b/sk/css/README.md new file mode 100755 index 00000000000..5c6611baa15 --- /dev/null +++ b/sk/css/README.md @@ -0,0 +1,296 @@ +# CSS - skrášli to! + +Náš blog vyzerá zatiaľ dosť škaredo, však? Je čas to napraviť! Použijeme na to CSS. + +## Čo je CSS? + +Kaskádové štýly (CSS, angl. Cascading Style Sheets) je jazyk, ktorý sa používa na popis vzhľadu a formátovania webstránky napísanej v značkovacom jazyku (napríklad HTML). Predstav si to ako make-up pre našu webstránku :). + +Ale asi nechceme začať úplne od nuly, však? Znova použijeme niečo, čo už bolo vytvorené programátormi a sprístupnené na internete zadarmo. Veď vieš, znovuobjavovanie kolesa nie je žiadna zábava. + +## Používajme Bootstrap! + +Bootstrap je jedným z najpopulárnejších HTML a CSS frameworkov pre vývoj krásnych webových stránok: https://getbootstrap.com/ + +Bol napísaný programátormi, ktorí pracovali pre Twitter a ďalej ho vyvíjajú dobrovoľníci z celého sveta. + +## Inštalácia Bootstrapu + +Na inštaláciu Bootstrapu musíš pridať do hlavičky `` vo svojom `.html` súbore (`blog/templates/blog/post_list.html`) toto: + +```html + + +``` + +Nepridá to do tvojho projektu žiadne súbory. Iba to ukazuje na súbory, ktoré už existujú na internete. Skúsme to, otvor svoju webstránku a obnov stránku. Tu to máme! + +![Obrázok 14.1][1] + + [1]: images/bootstrap1.png + +Už teraz vyzerá lepšie! + +## Statické súbory v Djangu + +Konečne sa pozrieme zblízka na veci, ktoré nazývame **statické súbory**. Sú to všetky tvoje CSS a obrázky -- súbory, ktoré nie sú dynamické, takže ich obsah nezávisí od kontextu požiadavky a budú rovnaké pre všetkých užívateľov. + +### Kam umiestniť statické súbory pre Django + +Ako si už videla, keď sme spustili `collectstatic` na serveri, Django už vie, kde má nájsť statické súbory pre vstavané "adminské" aplikácie. Teraz už musíme len pridať nejaké statické súbory pre našu vlastnú aplikáciu, `blog`. + +To urobíme tak, že vo vnútri našej aplikácie blog vytvoríme adresár s názvom `static`: + +``` +djangogirls +├── blog +│ ├── migrations +│ └── static +└── mysite +``` + +Django automaticky nájde všetky priečinky s názvom "static" vo všetkých priečinkoch tvojich aplikácií a bude môcť používať ich obsah ako statické súbory. + +## Tvoj prvý CSS súbor! + +Vytvorme teraz CSS súbor, ktorý tvojej web stránke pridá vlastný štýl. Vytvor nový adresár s názvom `css` vnútri adresára `static`. Potom vytvor nový súbor s názvom `blog.css` vo vnútri tohto adresára `css`. Pripravená? + +``` +djangogirls +└─── blog + └─── static + └─── css + └─── blog.css +``` + +Je čas napísať nejaké CSS! Otvor v editore kódu súbor `blog/static/css/blog.css`. + +Nepôjdeme príliš do hĺbky ohľadne prispôsobovania web stránky a učenia sa CSS, pretože je to celkom jednoduché a môžeš sa to naučiť sama po tomto workshope. Odporúčame ti urobiť si [kurz Codeacademy HTML & CSS][2], tam sa dozvieš všetko, čo potrebuješ vedieť, aby bola tvoja webstránka vďaka CSS krajšia. + + [2]: https://www.codecademy.com/tracks/web + +Ale urobme aspoň niečo. Čo keby sme zmenili farbu hlavičky? Počítače používajú špeciálne kódy, aby rozumeli farbám. Začínajú `#`, potom nasleduje 6 písmen (A-F) a číslic (0-9). Kódy farieb nájdeš napríklad tu: http://www.colorpicker.com/. Môžeš tiež použiť [preddefinované farby][3] ako napríklad `red` (červená) alebo `green` (zelená). + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +V súbore `blog/static/css/blog.css` pridaj nasledujúci kód: + +```css +h1 a { + color: #FCA205; +} +``` + +`h1 a` je CSS Selector. To znamená, že náš štýl aplikujeme na akýkoľvek element `a` vo vnútri elementu `h1` (napríklad ak máme v kóde niečo takéto: `

link

`). V tomto prípade elementu hovoríme, aby zmenil svoju farbu na `#FCA205`, čo je oranžová. Samozrejme, sem môžeš zadať vlastnú farbu! + +V CSS súbore definujeme štýly pre elementy v HTML súbore. Elementy sa identifikujú podľa svojho názvu (t. j. `a` `h1`, `body`), atribútom `class` (trieda) alebo atribútom `id`. Triedy a id sú názvy, ktorými nazveš elementy. Triedy definujú skupiny elementov a idy poukazujú na konkrétne elementy. Napríklad, nasledujúci tag môže byť identifikovaný v CSS pomocou tagu `a`, triedy `external_link` a idu `link_to_wiki_page`: + +```html + +``` + +Prečítaj si o [CSS selektoroch na w3schools][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Potom musíme povedať našej HTML šablóne, že sme pridali nejaké CSS. Otvor súbor `blog/templates/blog/post_list.html` a pridaj tento riadok na úplný začiatok: + +```html +{% load staticfiles %} +``` + +Práve načítavame statické súbory :). Potom medzi `` a ``, po odkazoch na CSS súbory Bootstrapu pridaj nasledujúci riadok (prehliadač číta súbory v poradí, v akom sú zadané, takže kód v našom súbore môže prepísať už načítaný kód z Bootstrapu): + + html + + + +Práve sme našej šablóne povedali, kde sa nachádza náš CSS súbor. + +Súbor by mal teraz vyzerať asi takto: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + +OK, ulož súbor a obnov stránku! + +![Obrázok 14.2][5] + + [5]: images/color2.png + +Pekne! Možno by sme chceli dať našej webovej stránke trochu vzduchu. Zväčšíme okraj na ľavej strane? Skúsme si to! + +```css +body { + padding-left: 15px; +} +``` + +Pridaj to do svojho CSS, ulož súbor a pozri, ako to funguje! + +![Obrázok 14.3][6] + + [6]: images/margin2.png + +Mohli by sme trochu upraviť font v našej hlavičke, nie? Skopíruj toto do svojej hlavičky `` v súbore `blog/templates/blog/post_list.html`: + +```html + +``` + +Tento riadok naimportuje z Google fontov (https://www.google.com/fonts) font, ktorý sa volá *Lobster*. + +Teraz pridaj riadok `font-rodina: 'Lobster';` do CSS súboru `blog/static/css/blog.css` vnútri deklarácie `h1 a` (to je ten kód medzi zátvorkami `{` a `}`) a obnov stránku: + +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` + +![Obrázok 14.3][7] + + [7]: images/font.png + +Super! + +Ako sme už spomenuli vyššie, CSS má koncept tried, ktorými v podstate pomenuješ časť HTML kódu a aplikuješ štýly len na túto konkrétnu časť, bez vplyvu na ostatné časti. Je to super užitočné, ak máš dva div-y, z ktorých každý robí niečo úplne iné (napríklad hlavička a príspevok), takže nechceš, aby vyzerali rovnako. + +Skús pomenovať niektoré časti HTML kódu. Pridaj triedu s názvom `page-header` do `div`u, ktorý obsahuje hlavičku, takto nejako: + +```html + +``` + +A teraz pridaj triedu, `post` do `div`u, v ktorom je blog post. + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + +Teraz pridáme deklarácie rôznym selektorom. Selektory, ktoré začínajú `.` sa týkajú tried. Na webe je ohľadne CSS veľa skvelých tutorialov a vysvetlení, ktoré ti pomôžu pochopiť nasledujúci kód. Ale teraz len skopíruj a vlož nasledujúci kód do súboru `blog/static/css/blog.css`: + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +Teraz s deklaráciami tried obklop HTML kód, ktorý zobrazuje posty. Nahraď toto: + +```html +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +v súbore `blog/templates/blog/post_list.html` týmto: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Ulož tieto súbory a obnov svoju web stránku. + +![Obrázok 14.4][8] + + [8]: images/final.png + +No paráda! Vyzerá to super, nie? Kód, ktorý sme práve vložili, fakt nie je veľmi ťažké pochopiť a väčšinu asi pochopíš už len tým, že ho prečítaš. + +Neboj sa trochu pohrať s týmto CSS, skús niektoré veci zmeniť. Ak niečo pokazíš, nevadí, vždy sa môžeš vrátiť späť! + +Mimochodom, naozaj odporúčame tento bezplatný on-line [kurz HTML & CSS Codeacademy ][2] ako domácu úlohu po skončení tohto workshopu, kde sa naučíš všetko, čo potrebuješ vedieť, aby boli tvoje webové stránky s CSS krajšie. + +Pripravená na ďalšiu kapitolu?! :) diff --git a/sk/css/images/bootstrap1.png b/sk/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/sk/css/images/bootstrap1.png differ diff --git a/sk/css/images/color2.png b/sk/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/sk/css/images/color2.png differ diff --git a/sk/css/images/final.png b/sk/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/sk/css/images/final.png differ diff --git a/sk/css/images/font.png b/sk/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/sk/css/images/font.png differ diff --git a/sk/css/images/margin2.png b/sk/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/sk/css/images/margin2.png differ diff --git a/sk/deploy/README.md b/sk/deploy/README.md new file mode 100755 index 00000000000..b44fdb35981 --- /dev/null +++ b/sk/deploy/README.md @@ -0,0 +1,324 @@ +# Nasadenie! + +> **Poznámka** Občas bude možno trochu ťažké prehrýzť sa touto kapitolou. Vydrž a dokonči ju, nasadenie je dôležitou časťou vývoja webových stránok. Táto kapitola je umiestnená uprostred tutorialu, takže mentor ti môže pomôcť s trochu náročnejšími časťami procesu spúšťania tvojej web stránky online. To znamená, že môžeš dokončiť tutorial aj sama, ak ti nevyjde čas. + +Až doteraz bola tvoja web stránka dostupná len v tvojom počítači, teraz sa však naučíš, ako ju nasadiť! Nasadenie je proces publikovania aplikácie na internete, takže ju ľudia konečne môžu vidieť :). + +Ako už vieš, web stránka musí byť umiestnená na serveri. Na internete je množstvo poskytovateľov serverov. My použijeme jedného, ktorý má pomerne jednoduchý proces nasadenia: [PythonAnywhere][1]. PythonAnywhere je bezplatný pre malé aplikácie, ktoré nemajú príliš veľa návštevníkov, takže zatiaľ ti to určite bude stačiť. + + [1]: https://pythonanywhere.com/ + +Ďalšou externou službou, ktorú budeme využívať je [GitHub][2], kde sa uchovávajú zdrojové kódy. Existujú aj ďalšie takéto služby, no dnes už majú takmer všetci programátori na GitHube konto a teraz ho budeš mať už aj ty! + + [2]: https://www.github.com + +GitHub použijeme ako odrazový mostík na prenos nášho kódu z a do PythonAnywhere. + +# Git + +Git je "systém na správu verzií", ktorý využíva množstvo programátorov. Tento softvér sleduje v priebehu času zmeny v tvojich súboroch, takže sa kedykoľvek môžeš vrátiť ku konkrétnej verzii. Niečo ako funkcia "sledovať zmeny" vo Worde, ale oveľa výkonnejšie. + +## Inštalácia Gitu + +> **Poznámka** Ak si už kroky inštalácie robila, nemusíš to robiť znova a môžeš preskočiť na ďalšiu časť a začať vytvárať Git repozitár. + +{% include "/deploy/install_git.md" %} + +## Spustenie Git repozitára + +Git sleduje zmeny na konkrétnej množine súborov, v niečom, čo sa nazýva úložisko kódu alebo repozitár (skrátene "repo"). Založme si repo pre náš projekt. Otvor konzolu a spusti nasledujúce príkazy v adresári `djangogirls`: + +> **Poznámka** Skontroluj si aktuálny pracovný adresár s príkazom`pwd` v OSX/Linux alebo `cd` vo Windowse pred inicializáciou úložiska. Mala by si byť v priečinku `djangogirls`. + +``` + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com +``` + +Inicializácia git repozitára je niečo, čo musíme urobiť len raz za projekt (a už nikdy nebudeš musieť znovu zadať užívateľské meno a e-mail). + +Git bude sledovať zmeny všetkých súborov a priečinkov v tomto adresári, ale sú aj niektoré súbory, ktoré chceme ignorovať. To urobíme tak, že vytvoríme súbor s názvom `.gitignore` v základnom adresári. Otvor si editor a vytvor nový súbor s týmto obsahom: + +``` + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store +``` + +A ulož ho ako `.gitignore` do hlavného adresára "djangogirls". + +> **Poznámka** Bodka na začiatku názvu súboru je dôležitá! Ak máš problém vytvoriť takýto súbor (napríklad Macom sa nepáči, ak chceš cez Vyhľadávanie (Finder) vytvoriť súbory, ktoré sa začínajú bodkou), potom použi funkciu "Uložiť ako" vo svojom editore, to je nepriestrelné. + +Vždy je dobré použiť príkaz `git status` pred `git add` alebo kedykoľvek, keď si nebudeš istá, čo sa zmenilo. To ti pomôže vyhnúť sa prekvapeniam ako napríklad pridanie nesprávnych súborov. Príkaz `git status` dáva informácie o nesledovaných (untracked) či zmenených (modified) súboroch, alebo súboroch pripravených na zmenu (staged), o stave vetvy a veľa ďalšieho. Výstup by mal vyzerať takto nejako: + +``` + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) +``` + +A nakoniec uložíme naše zmeny. Teraz prejdi na konzolu a zadaj nasledujúce príkazy: + +``` + $ git add -A . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py +``` + +## Prenos nášho kódu na GitHub + +Choď na [GitHub.com][2] a zaregistruj sa na nové bezplatné konto. (Ak si to už urobila v prípravke na workshop, tak to je skvelé!) + +Potom vytvor nové úložisko a pomenuj ho "my-first-blog". Nechaj políčko "initialise with README" nezaškrtnuté, možnosť .gitignore nechaj prázdnu (to sme už urobili ručne) a nechaj licenciu nastavenú ako None. + +![][3] + + [3]: images/new_github_repo.png + +> **Poznámka** Názov `my-first-blog` je dôležitý -- mohla by si si vybrať aj niečo iné, ale bude sa to ďalej vyskytovať veľakrát a musela by si to zakaždým nahradiť. Asi bude ľahšie, ak ostaneš pri názve `my-first-blog`. + +Na ďalšej obrazovke sa zobrazí klon URL tvojho repozitára. Vyber si verziu "HTTPS", skopírujte ju, a o chvíľu ju použijeme v termináli: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Teraz musíme pripojiť Git repozitár v počítači k tomu na GitHube. + +Napíš do konzoly nasledujúci príkaz (nahraď `` svojím užívateľským menom na GitHube, ale bez lomených zátvoriek): + +``` +$ git remote add origin https://github.com//my-first-blog.git +$ git push -u origin master +``` + +Zadaj svoje užívateľské meno a heslo na GitHube a malo by sa ti zobraziť niečo takého: + +``` +Username for 'https://github.com': hjwp +Password for 'https://hjwp@github.com': +Counting objects: 6, done. +Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. +Total 3 (delta 0), reused 0 (delta 0) +To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master +Branch master set up to track remote branch master from origin. +``` + + + +Tvoj kód je na GitHube. Kľudne si to over! Zistíš, že sa nachádza vo vyberanej spoločnosti - [Django][5], [Django Girls Tutorial][6] a mnoho iných skvelých open sourcových softvérových projektov uchováva svoj kód na GitHube :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Vytvorenie nášho blogu na PythonAnywhere + +> **Poznámka** Možno si už účet na PythonAnywhere vytvorila počas inštalácie - ak áno, nemusíš to robiť znova. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Natiahnutie nášho kódu na PythonAnywhere + +Po registrácii na PythonAnywhere, budeš presmerovaná na svoju nástenku alebo stránku "Konzoly". Vyber si možnosť spustiť "Bash" konzolu - to je PythonAnywhere verzia konzoly, rovnaká ako na tvojom počítači. + +> **Poznámka** PythonAnywhere je založený na Linuxe, takže ak si vo Windowse, konzola bude vyzerať trochu inak ako v tvojom počítači. + +Poďme teraz natiahnuť náš kód z GitHubu na PythonAnywhere vytvorením "klonu" nášho repo. Zadaj nasledujúci príkaz do konzoly na PythonAnywhere (nezabudni použiť užívateľské meno z GitHubu namiesto ``): + +``` +$ git clone https://github.com//my-first-blog.git +``` + +Toto natiahne kópiu tvojho kódu na PythonAnywhere. Môžeš si to overiť zadaním `tree my-first-blog`: + +``` +$ tree my-first-blog +my-first-blog/ +├── blog +│ ├── __init__.py +│ ├── admin.py +│ ├── migrations +│ │ ├── 0001_initial.py +│ │ └── __init__.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── manage.py +└── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py +``` + +### Vytvorenie virtualenv na PythonAnywhere + +Tak ako si to urobila vo svojom počítači, virtualenv môžeš vytvoriť aj na PythonAnywhere. V Bash konzole zadaj: + +``` +$ cd my-first-blog + +$ virtualenv --python=python3.4 myvenv +Running virtualenv with interpreter /usr/bin/python3.4 +[...] +Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(mvenv) $ pip install django whitenoise +Collecting django +[...] +Successfully installed django-1.8.2 whitenoise-2.0 +``` + +> **Poznámka:** Krok `pip install` môže trvať aj niekoľko minút. Trpezlivosť, trpezlivosť! Ale ak to trvá dlhšie ako 5 minút, niečo nie je v poriadku. Spýtaj sa svojho tútora. + + + +### Zber statických súborov. + +Zaujímalo ťa, čo je to vlastne ten "whitenoise"? Je to nástroj na obsluhu takzvaných "statických súborov". Statické súbory su také súbory, ktoré sa pravidelne nemenia, ani nespúšťajú kód programu, ako napríklad HTML či CSS súbory. Na serveroch fungujú inak ako na tvojom počítači a na ich obsluhu potrebujeme nástroj ako je "whitenoise". + +O statických súboroch sa naučíme trochu viac neskôr, keď budeme upravovať CSS pre našu stránku. + +Teraz len musíme na serveri spustiť jeden príkaz navyše - `collectstatic`. Ten povie Djangu, aby na serveri zhromaždil všetky statické súbory, ktoré potrebuje. Práve teraz sú to väčšinou súbory, ktoré zabezpečujú, aby adminská stránka vyzerala dobre. + +``` +(mvenv) $ python manage.py collectstatic + +You have requested to collect static files at the destination +location as specified in your settings: + + /home/edith/my-first-blog/static + +This will overwrite existing files! +Are you sure you want to do this? + +Type 'yes' to continue, or 'no' to cancel: yes +``` + +Napíš "yes" a ono to zmizne! Aj ty zbožňuješ vyrábať stránky plné výstupov z počítačov alebo nepochopiteľného textu? Ja osobne si k tomu vymýšľam čudné zvuky. Brp, brp, brp... + +``` +Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' +Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' +[...] +Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' +Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' +62 static files copied to '/home/edith/my-first-blog/static'. +``` + +### Vytvorenie databázy na PythonAnywhere + +Ďalšia vec, v ktorej sa líši tvoj počítač od servera: používa inú databázu. Takže užívateľské kontá a posty sa môžu na serveri líšiť od tých v počítači. + +Môžeme inicializovať databázu na serveri, rovnako ako sme to urobili v tvojom počítači, pomocou `migrate` a `createsuperuser`: + +``` +(mvenv) $ python manage.py migrate +Operations to perform: +[...] + Applying sessions.0001_initial... OK + + +(mvenv) $ python manage.py createsuperuser +``` + +## Publikovanie nášho blogu ako webovú aplikáciu + +Teraz je náš kód na PythonAnywhere, náš virtualenv pripravený, statické súbory sú zhromaždené a databáza inicializovaná. Môžeme to teda zverejniť ako webovú aplikáciu! + +Kliknutím na logo PythonAnywhere sa vráť na nástenku a tam klikni na kartu **Web**. Nakoniec, stlač **Add a new web app** (Pridaj novú aplikáciu). + +Po potvrdení názvu tvojej domény, vyber v dialógu **manual configuration** (pozor, *nie* "Django" možnosť). Ďalej vyber **Python 3.4** a kliknutím na tlačidlo Ďalej dokonči sprievodcu. + +> **Poznámka** Uisti sa, že si si vybrala možnosť "Manual configuration" (Manuálne nastavenie), nie "Django". Sme príliš cool, aby sme používali predvolené nastavenia PythonAnywhere Django ;-) + +### Nastavenie virtualenv + +Budeš presmerovaná na PythonAnywhere konfiguračnú obrazovku pre tvoju aplikáciu. Sem budeš musieť chodiť vždy, keď budeš chcieť urobiť nejaké zmeny v tvojej aplikácii na serveri. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +V časti "Virtualenv" klikni na červený text "Enter the path to a virtualenv" a zadaj: `/home//my-first-blog/myvenv/`. Klikni na modré políčko s fajočkou a ulož tak cestu predtým, ako budeš pokračovať ďalej. + +> **Poznámka** Nahraď svoje užívateľské meno podľa potreby. Ak urobíš chybu, PythonAnywhere ti zobrazí malé upozornenie. + +### Konfigurácia súboru WSGI + +Django funguje pomocou "protokolu WSGI", ktorý je štandardom pre obsluhu webových stránok pomocou Pythonu, a ktorý PythonAnywhere podporuje. Aby PythonAnywhere rozpoznal náš Django blog, musíme upraviť WSGI konfiguračný súbor. + +Klikni na link "WSGI configuration file" (v časti "Code" v hornej časti stránky -- bude sa volať nejako takto `/var/www/_pythonanywhere_com_wsgi.py`) a dostaneš sa do editora. + +Vymaž celý obsah a nahraď ho niečím takýmto: + +```python +import os +import sys + +path = '/home//my-first-blog' # use your own username here +if path not in sys.path: + sys.path.append(path) + +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Poznámka** Nezabudni nahradiť svoje vlastné užívateľské meno namiesto `` + +Úlohou tohto súboru je povedať PythonAnywhere, kde nájde našu aplikáciu a ako sa volá súbor s nastaveniami Djanga. Taktiež nastavuje nástroj "whitenoise" pre statické súbory. + +Klikni na **Save** a vráť sa na kartu **Web**. + +Hotovo! Klikni na veľké zelené tlačidlo **Reload** a potom sa už môžeš pozrieť na svoju aplikáciu. Odkaz na ňu nájdeš navrchu stránky. + +## Tipy pre ladenie + +Ak pri pokuse navštíviť svoju stránku uvidíš chybu, prvým miestom, kde hľadať problém je **error log**. Odkaz naňho nájdeš na PythonAnywhere v [karte Web][8]. Pozri, či tam nie sú nejaké chybové hlášky - tie najnovšie sú naspodku. Najčastejšie problémy bývajú: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* Vynechaný krok, ktorý sme robili v konzole: vytvorenie virtualenv, jeho aktivácia, inštalácia Djanga do virtualenvu, spustenie collectstatic, presun databázy. + +* Chyba v ceste virtualenv v karte Web -- ak je nejaký problém, zvyčajne tam bude malá červená chybová hláška. + +* Chyba vo WSGI konfiguračnom súbore -- zadala si cestu do adresára my-first-blog správne? + +* Vybrala si si rovnakú verziu Pythonu pre virtualenv ako pre webovú aplikáciu? Obidve by mali byť 3.4. + +* Môžeš skúsiť aj [Všeobecné tipy na ladenie na PythonAnywhere wiki][9]. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +A nezabudni, tvoj tréner je tu na to, aby ti pomohol! + +# Si online! + +Hlavná stránka tvojej aplikácie by ťa mala vítať nápisom "Welcome to Django", tak ako na tvojom počítači. Skús pridať `/admin/` na koniec adresy URL, a budeš presmerovaná na stránky administrácie. Prihlás sa s užívateľským menom a heslom a uvidíš, že môžeš pridávať nové príspevky (posty) na server. + +*OHROMNE* sa potľapkaj po chrbte! Nasadenie serveru je jedna z najzradnejších častí vývoja web stránok a často zaberie ľuďom aj niekoľko dní, kým to spojazdnia. Ale ty už máš teraz svoju stránku online, na skutočnom internete! diff --git a/sk/deploy/images/github_get_repo_url_screenshot.png b/sk/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/sk/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/sk/deploy/images/new_github_repo.png b/sk/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/sk/deploy/images/new_github_repo.png differ diff --git a/sk/deploy/images/pythonanywhere_web_tab_virtualenv.png b/sk/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/sk/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/sk/deploy/install_git.md b/sk/deploy/install_git.md new file mode 100755 index 00000000000..584d4bcd159 --- /dev/null +++ b/sk/deploy/install_git.md @@ -0,0 +1,19 @@ +### Windows + +Git si môžeš stiahnuť z [git-scm.com](https://git-scm.com/). Môžeš bez obáv klikať na "ďalej ďalej ďalej" pri všetkých krokoch okrem jedného. V kroku 5, označenom ako "Nastavenie prostredia PATH", zvoľ "Spustiť Git a príslušné Unixové nástroje z príkazového riadku systému Windows" (spodná možnosť). V ostatných prípadoch sú predvolené nastavenia v poriadku. Možnosť "Checkout Windows-style, commit Unix-style line endings" je OK. + +### MacOS + +Stiahni si Git z [git-scm.com](https://git-scm.com/) a riaď sa inštrukciami. + +### Linux + +Ak ho ešte nemáš nainštalovaný, git by mal byť dostupný pomocou správcu balíčkov, takže vyskúšaj: + +``` +sudo apt-get install git +# or +sudo yum install git +# or +sudo zypper install git +``` diff --git a/sk/deploy/signup_pythonanywhere.md b/sk/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..d0bd7bbc141 --- /dev/null +++ b/sk/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Je čas prihlásiť sa zdarma k účtu "Beginner" na PythonAnywhere. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Poznámka** Pri výbere používateľského mena, mysli na to, že URL tvojho blogu bude v tvare `tvojeuzivatelskemeno.pythonanywhere.com`, takže si vyber prezývku alebo názov o čom tvoj blog je. \ No newline at end of file diff --git a/sk/django/README.md b/sk/django/README.md new file mode 100755 index 00000000000..b63ab11c197 --- /dev/null +++ b/sk/django/README.md @@ -0,0 +1,27 @@ +# Čo je Django? + +Django (*džängou*) je bezplatný a open source webový framework na vytváranie webových aplikácií, napísaný v Pythone. Webový framework je súbor komponentov, ktoré ti pomôžu vytvárať stránky rýchlejšie a ľahšie. + +Pri tvorení webových stránok, potrebuješ vždy sadu podobných komponentov: spôsob, ako riešiť autentifikáciu užívateľov (registráciu, prihlásenie, odhlásenie), kontrolný panel web stránky, formuláre, spôsob, ako nahrávať súbory, atď. + +Našťastie si iní ľudia už dávno všimli, že weboví vývojári čelia pri tvorbe nového webu podobným problémom, takže sa spojili a vytvorili frameworky (Django je jedným z nich) a tie ti poskytujú hotové komponenty, ktoré môžeš používať. + +Frameworky sú tu na to, aby si nemusela znovu vynájsť koleso. Pomôžu ti uľahčiť tvorbu nových web stránok. + +## Prečo potrebuješ framework? + +Aby sme pochopili, čo vlastne Django je, potrebujeme sa zblízka pozrieť na servery. Prvá vec, čo o nich musíš vedieť, je, že budú obsluhovať tvoju stránku. + +Predstav si poštovú schránku (port), na ktorej sa sledujú prichádzajúce listy (žiadosti). To vlastne robí web server. Web server prečíta list a pošle odpoveď v podobe web stránky. Ale ak chceš niečo poslať, potrebuješ mať nejaký obsah. A Django je to, čo ti obsah pomôže vytvoriť. + +## Čo sa stane, ak niekto požaduje z tvojho servera web stránku? + +Keď na webový server príde žiadosť, tá je preposlaná do Djanga, ktoré sa pokúsi zistiť, čoho sa vlastne žiadosť týka. Najprv si zoberie adresu webstránky a zisťuje, čo má urobiť. Túto časť vykonáva Django **urlresolver** (všimni si, že adresa webstránku sa nazýva - Uniform Resource Locator - URL, takže názov *urlresolver* dáva zmysel). Nie je to nič extra inteligentné - zoberie zoznam vzorov a porovnáva ich s URL. Django overuje vzory od vrchu po spodok a ak nájde zhodu, Django pošle žiadosť príslušnej funkcii (ktorá sa nazýva *view* - pohľad). + +Predstav si poštárku s listom. Kráča ulicou a porovnáva čísla domov s číslom na liste. Ak sa zhoduje, nechá tam list. Takto funguje urlresolver! + +Vo funkcii *view* sa dejú všetky zaujímavé veci: môžeme sa pozrieť do databázy a vyhľadať nejaké informácie. Čo ak užívateľ požiada o zmenu v údajoch? Napríklad listom, v ktorom je žiadosť "Prosím, zmeňte popis mojej práce." *view* overí, či máš oprávnenie na túto zmenu, potom aktualizuje popis tvojej práce a naspäť pošle správu: "Hotovo!". Potom *view* vygeneruje odpoveď a Django ju môže odoslat tvojmu webovému prehliadaču. + +Samozrejme, vyššie uvedený popis je trochu zjednodušený, ale zatiaľ ešte nepotrebuješ vedieť všetky technické detaily. Pre všeobecnú predstavu to však stačí. + +Takže namiesto zložitého študovania detailov, jednoducho začneme v Djangu niečo vytvárať a všetky dôležité veci sa naučíme popri tom! \ No newline at end of file diff --git a/sk/django_admin/README.md b/sk/django_admin/README.md new file mode 100755 index 00000000000..660bd303332 --- /dev/null +++ b/sk/django_admin/README.md @@ -0,0 +1,49 @@ +# Django admin + +Na pridávanie, editovanie a mazanie postov, ktoré sme práve namodelovali, budeme používať Django admina. + +Otvorme súbor `blog/admin.py` a nahraďme jeho obsah týmto: + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Ako vidíš, importujeme model Post definovaný v predchádzajúcej kapitole. Aby bol náš model viditeľný na adminskej stránke, musíme ho zaregistrovať pomocou `admin.site.register(Post)`. + +OK, je čas pozrieť sa na náš Post model. Nezabudni v konzole spustiť web server pomocou príkazu `python manage.py runserver`. Spusti prehliadač a zadaj adresu http://127.0.0.1:8000/admin/. Uvidíš takúto prihlasovaciu stránku: + +![Prihlasovacia stránka][1] + + [1]: images/login_page2.png + +Pre prihlásenie musíš vytvoriť *superusera* - užívateľa, ktorý má kontrolu nad všetkým na stránke. Vráť sa do príkazového riadku, napíš `python manage.py createsuperuser` a stlač enter. Po výzve zadaj svoje meno (malé písmená, bez medzier), emailovú adresu a heslo. Ak nevidíš heslo, ktoré zadávaš, tým sa netráp - tak to má byť. Len ho zadaj a pokračuj stlačením `enter`. Výstup by mal vyzerať asi takto (kde užívateľské meno a email by mali byť tvoje vlastné): + +``` +(myvenv) ~/djangogirls$ python manage.py createsuperuser +Username: admin +Email address: admin@admin.com +Password: +Password (again): +Superuser created successfully. +``` + +Vráť sa do prehliadača. Prihlás sa zvolenými údajmi ako superuser, mala by sa ti zobraziť nástenka (dashboard) Django admina. + +![Django admin][2] + + [2]: images/django_admin3.png + +Prejdi do Postov a trochu experimentuj. Pridaj päť či šesť blog postov. Netráp sa veľmi s obsahom - trebárs skopíruj a vlož text z tohto tutorialu, nech ušetríš čas :). + +Uisti sa, že aspoň dva alebo tri posty (ale nie všetky) majú nastavený dátum publikovania. Bude to neskôr užitočné. + +![Django admin][3] + + [3]: images/edit_post3.png + +Ak chceš vedieť viac o Django admine, pozri si dokumentáciu Djanga: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +Teraz je asi vhodný čas dať si kávu (alebo čaj), alebo niečo pod zub a nabrať trochu energie. Práve si vytvorila svoj prvý Django model - zaslúžiš si trochu oddychu! diff --git a/sk/django_admin/images/django_admin3.png b/sk/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..25bcc4edda8 Binary files /dev/null and b/sk/django_admin/images/django_admin3.png differ diff --git a/sk/django_admin/images/edit_post3.png b/sk/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..34f2a195ec5 Binary files /dev/null and b/sk/django_admin/images/edit_post3.png differ diff --git a/sk/django_admin/images/login_page2.png b/sk/django_admin/images/login_page2.png new file mode 100644 index 00000000000..85137f4d162 Binary files /dev/null and b/sk/django_admin/images/login_page2.png differ diff --git a/sk/django_forms/README.md b/sk/django_forms/README.md new file mode 100755 index 00000000000..38652b5eeeb --- /dev/null +++ b/sk/django_forms/README.md @@ -0,0 +1,400 @@ +# Formuláre Django + +Posledná vec, ktorú chceme urobiť na našej web stránke je vytvoriť príjemný spôsob pridávania a úpravy blog postov. Django `admin` je v pohode, ale ťažko sa prispôsobuje a upravuje do krajšej podoby. Pomocou `formulárov` budeme mať absolútnu moc nad naším rozhraním - môžeme urobiť takmer čokoľvek, čo si vieme predstaviť! + +Na Django formulároch je fajn, že ich môžeme vytvoriť úplne od nuly alebo vytvoriť `ModelForm`, ktorý uloží výsledok formulára do modelu. + +To je presne, čo chceme robiť: vytvoríme formulár pre náš `Post` model. + +Tak ako všetky ostatné dôležité časti Djanga, formuláre majú svoj vlastný súbor: `forms.py`. + +Musíme vytvoriť súbor s týmto názvom v adresári `blog`. + +``` +blog + └── forms.py +``` + +OK, otvorme to a napíšme tento kód: + +``` +python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + +Najskôr musíme importovať Django formuláre (`from django import forms`) a, samozrejme, náš `Post` model (`from .models import Post`). + +`PostForm`, ako asi správne predpokladáš, je meno nášho formulára. Musíme Djangu povedať, že tento formulár je `ModelForm` (aby Django pre nás mohlo trochu čarovať) - za to je zodpovedný `forms.ModelForm`. + +Ďalej máme `triedu Meta`, kde Djangu povieme, ktorý model by mal byť použitý na vytvorenie tohto formulára (`model = Post`). + +Nakoniec môžeme Djangu povedať, ktoré formuláre budú v našom formulári. Pri tomto scenári, chceme boli zobrazené iba `title` (nadpis) a `text` - `author` by mala byť aktuálne prihlásená osoba (teda ty!) a dátum vytvorenia `created_date` by mal automaticky nastavený pri vytvorení postu (t.j. v kóde). + +To je všetko! Jediné, čo treba teraz urobiť, je použiť formulár v *zobrazení* (angl. view) a zobraziť ho v šablóne. + +Takže ešte raz vytvoríme: link na stránku, URL, zobrazenie a šablónu. + +## Link na stránku s formulárom + +Je čas otvoriť `blog/templates/blog/base.html`. Pridáme link do `divu` s názvom `page-header`: + +```html + +``` + +Všimni si, že chceme zavolať náš nový view (zobrazenie) `post_new`. + +Po pridaní riadku by tvoj html súbor mal vyzerať asi takto: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Keď uložíš a obnovíš stránku http://127.0.0.1:8000 uvidíš samozrejme známu chybu `NoReverseMatch`, však? + +## URL + +Otvor `blog/urls.py` a pridaj riadok: + +```python +url(r'^post/new/$', views.post_new, name='post_new'), +``` + +A výsledný kód bude vyzerať takto: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +Po obnovení stránky uvidíme chybu `AttributeError`, pretože nemáme implementovaný view (zobrazenie) `post_new`. Pridajme ho teraz. + +## view (zobrazenie) post_new + +Teraz otvoríme súbor `blog/views.py` a pridáme tam nasledujúce riadky so zvyškom importovacích riadkov `from`: + +```python +from .forms import PostForm +``` + +a náš *view*: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Nový formulár `Post` vytvoríme tak, že sputíme `PostForm()` a prepošleme ho šablóne. K tomuto *view* sa ešte vrátime, ale teraz poďme rýchlo vytvoriť šablónu formulára. + +## Šablóna + +Musíme vytvoriť súbor `post_edit.html` v adresári `blog/ templates/blog`. Aby formulár fungoval, potrebujeme niekoľko vecí: + +* musíme zobraziť formulár. To môžeme urobiť jednoducho takto `{% raw %}{{ form.as_p }}{% endraw %}`. +* riadok vyššie musí byť obalený HTML tagom: `...` +* potrebujeme tlačidlo `Uložiť`. Vytvoríme ho ako HTML tlačidlo: `` +* a nakoniec, hneď za otváracím tagom `
` musíme pridať `{% raw %}{% csrf_token %}{% endraw %}`. Toto je veľmi dôležité, vďaka tomu je formulár bezpečný! Ak na túto časť zabudneš, Django sa bude pri ukladaní formuláru sťažovať: + +![CSFR Zakázaná stránka][1] + + [1]: images/csrf2.png + +OK, pozrime sa, ako by malo vyzerať HTML v `post_edit.html`: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Obnovíme stránku! Aha! Tvoj formulár je na svete! + +![Nový formulár][2] + + [2]: images/new_form2.png + +Ale počkaj chvíľku! Keď niečo zadáš niečo do polí `title` a `text` a skúsiš to uložiť - čo sa stane? + +Nič! Sme stále na rovnakej stránke a náš text je preč... a žiaden nový príspevok sa nepridal. Takže čo sa pokazilo? + +Odpoveď znie: nič. Akurát budeme mať ešte trochu práce v našom *view* (zobrazení). + +## Uloženie formuláru + +Znova otvor `blog/views.py`. Momentálne máme v `post_new` len toto: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Keď odošleme formulár, vrátime sa do rovnakého view, ale teraz už máme v `request` aj nejaké údaje, presnejšie v `request.POST` (názov nemá nič spoločné s "postom" na blogu, ide len o to, že posielame - "postujeme" údaje). Pamätáš si, že naša definícia formuláru `
` v HTML súbore mala premennú `method="POST"`? Všetky polia z formulára sú teraz v `request.POST`. `POST` by si nemala premenovať na nič iné (jediná ďalšia platná hodnota pre premennú `method` je `GET`, teraz ale nemáme čas vysvetliť si rozdiel). + +Takže v našom *view* máme vyriešiť dve samostatné situácie. Po prvé: keď prídeme na stránku po prvýkrát a chceme prázdny formulár. Po druhé: keď sa vrátime do *view* so všetkými vyplnenými údajmi formulára. Takže potrebujeme pridať podmienku (na to použijeme `if`). + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Je čas na vyplnenie bodky `[...]`. Ak `method` je `POST` potom chceme vytvoriť `PostForm` s údajmi z formulára, však? To urobíme takto: + +```python +form = PostForm(request.POST) +``` + +Ľahké! Ďalej skontrolujme či je formulár v poriadku (všetky povinné polia sú vyplnené a nie sú zadané žiadne nesprávne hodnoty). To urobíme pomocou `form.is_valid()`. + +Skonotrolujeme, či je formulár platný a ak áno, môžeme ho uložiť! + +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + +V podstate urobím dve veci: uložíme formulár pomocou `form.save` a pridáme autora (keďže pole `author` nebolo v `PostForm` nebolo, no toto pole je povinné!). `commit=False` znamená, že ešte nechce uložiť model `Post` - najskôr chceme pridať autora. Väčšinou budeš používať `form.save()` bez `commit=False`, no v tomto prípade, to takto musíme spraviť. `post.Save()` uchová zmeny (pridanie autora) a máme vytvorený nový blog post! + +A bolo by skvelé, keby sme sa potom ihneď dostali na stránku `post_detail` nášho novovytvoreného blog postu, nie? Na to ale budeme potrebovať ešte jeden import: + +```python +from django.shortcuts import redirect +``` + +Pridaj to úplne na začiatok súboru. A teraz môžeme povedať: prejdi na stránku `post_detail` novovytvoreného postu. + +```python + return redirect('blog.views.post_detail', pk=post.pk) +``` + +`blog.views.post_detail` je názov view - zobrazenia, kam chceme ísť. Spomínaš si, že tento *view* vyžaduje premennú `pk`? Aby sme ju odovzdali zobrazenia, použijeme `pk=post.pk`, kde `post` je novo vytvorený blog post! + +Ok, dosť sme hovorili, ale asi by bolo dobré pozrieť sa ako celý *view* vyzerá, však? + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Pozrime sa, či to funguje. Poď na stránku http://127.0.0.1:8000/post/new/, pridaj `title` a `text`, ulož to... and voilà! Nový blog post je pridaný my sme presmerovaní na stránku `post_detail`! + +Možno si si všimla, že pred uložením postu nastavujeme dátum publikovania. Neskôr v **Django Girls Tutorial: Rozšírenie** sa zoznámime s *tlačidlom Publikovať*. + +To je úžasné! + +## Validácia formuláru + +Teraz si ukážeme, aké sú Django formuláre super. Príspevok na blogu (post) musí mať polia `title` a `text`. V našom modeli `Post` sme nepovedali (na rozdiel od `published_date`), že tieto polia sú nepovinné, takže Django štandardne očakáva, že budú nastavené. + +Skús uložiť formulár bez `title` a `text`. Hádaj, čo sa stane! + +![Validácia formuláru][3] + + [3]: images/form_validation2.png + +Django overí, či sú všetky polia formulára správne. Nie je to skvelé? + +> Keďže sme nedávno použili administrátorské rozhranie Djanga, systém si myslí, že sme prihlásení. Existuje zopár situácií, ktoré by mohli spôsobiť odhlásenie (zatvorenie prehliadača, reštart databázy a podobne). Pokiaľ by sa ti zobrazovala chyba pri vytváraní postu upozorňujúca na neprihláseného užívateľa, choď na adminskú stránku http://127.0.0.1:8000/admin and prihlás sa znova. Toto dočasne vyrieši problém. Čaká však na teba aj permanentné riešenie v kapitole **Domáca úloha: zvýš svojej stránke bezpečnosť!** po skončení hlavného tutorialu. + +![Chyba prihlásenia][4] + + [4]: images/post_create_error.png + +## Úprava formuláru + +Teraz už vieme, ako sa pridáva nový formulár. Ale čo ak chceme upravovať existujúci? Veľmi podobne, ako to, čo sme práve spravili. Vytvorme rýchlo pár dôležitých vecí (ak niečomu nerozumieš, opýtaj sa svojho trénera alebo sa pozri na predchádzajúce kapitoly, pretože všetky tieto kroky sme si už prebrali). + +Otvor `blog/templates/blog/post_detail.html` a pridaj tento riadok: + +```html + +``` + +takže šablóna teraz bude vyzerať takto: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +V `blog/urls.py` pridáme tento riadok: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Znova použijeme šablónu `blog/templates/blog/post_edit.html`, takže posledná vec, čo nám chýba je *view*. + +Otvorme 0>blog/views.py a na úplný koniec súboru pridaj toto: + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +To vyzerá skoro tak isto ako náš view `post_new`, však? Ale nie úplne. Po prvé: odovzdávame navyše parameter `pk` z URL. A ďalej: pomocou `get_object_or_404(Post, pk=pk)` dostaneme model `Post`, ktorý chceme upravovať a potom pri vytváraní formuláru odovzdávame tento post ako parameter `instance`, keď budeme formulár ukladať: + +```python +form = PostForm(request.POST, instance=post) +``` + +a tiež keď sme formulár otvorili s týmto postom určeným na úpravu: + +```python +form = PostForm(instance=post) +``` + +OK, vyskúšajme, či to funguje! Poďme na stránku `post_detail`. V pravom hornom rohu by malo byť tlačidlo na úpravu: + +![Tlačidlo Upraviť][5] + + [5]: images/edit_button2.png + +Keď naňho klikneš, uvidíš formulár s našim blog postom: + +![Úprava formuláru][6] + + [6]: images/edit_form2.png + +Môžeš si vyskúšať zmeniť názov alebo text a uložiť zmeny! + +Gratulujeme! Tvoja aplikácia je čím ďalej dokonalejšia! + +Ak potrebuješ viac informácií o Django formulároch, prečítaj si dokumentáciu: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## Bezpečnosť + +Možnosť vytvárať nové posty len kliknutím na link je úžasná! Ale, v tejto chvíli, ktokoľvek, kto navštívi tvoju stránku, bude môcť pridať nový blog post a to asi nie je presne to, čo by si chcela. Urobme to tak, že sa tlačidlo zobrazí nikomu inému okrem teba. + +V `blog/templates/blog/base.html` nájdi náš `div` `page-header` a kotviaci tag, ktorý si tam umiestnila už predtým. Mal by vyzerať takto: + +```html + +``` + +Do neho pridáme ďalší tag `{% if %}`, vďaka ktorému sa link zobrazí len užívateľom, ktorí sú prihlásení ako admina. Momentálne si to len ty! Zmeň tag `< >`, aby vyzeral takto: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Tento `{% if %}` zabezpečí, aby bol link odoslaný do prehliadača, len ak je používateľ požadujúci stránku prihlásený. Nezabráni to vytváraniu nových postov úplne, ale je to dobrý prvý krok. Viac o bezpečnosti si povieme v rozširujúcich lekciách. + +Keďže si zrejme prihlásená, ak obnovíš stránku, neuvidíš žiadnu zmenu. Načítaj však stránku v inom prehliadači alebo v inkognito okne a uvidíš, že link sa nezobrazí! + +## Ešte jedna vec: čas nasadiť aplikáciu! + +Pozrime sa, či to všetko funguje na PythonAnywhere. Je čas na ďalšie nasadenie! + +* Najprv odovzdaj svoj nový kód a pošli ho na Github + +``` +$ git status +$ git add -A . +$ git status +$ git commit -m "Pridane views na vytvorenie/editovanie blog postu vo vnutri stranky." +$ git push +``` + +* Potom v [Bash konzole PythonAnywhere][7]: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* A nakoniec preskoč na [kartu Web][8] and klinki na **Reload**. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +A to by malo byť všetko! Gratulujeme :) diff --git a/sk/django_forms/images/csrf2.png b/sk/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/sk/django_forms/images/csrf2.png differ diff --git a/sk/django_forms/images/drafts.png b/sk/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/sk/django_forms/images/drafts.png differ diff --git a/sk/django_forms/images/edit_button2.png b/sk/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/sk/django_forms/images/edit_button2.png differ diff --git a/sk/django_forms/images/edit_form2.png b/sk/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/sk/django_forms/images/edit_form2.png differ diff --git a/sk/django_forms/images/form_validation2.png b/sk/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/sk/django_forms/images/form_validation2.png differ diff --git a/sk/django_forms/images/new_form2.png b/sk/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/sk/django_forms/images/new_form2.png differ diff --git a/sk/django_forms/images/post_create_error.png b/sk/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/sk/django_forms/images/post_create_error.png differ diff --git a/sk/django_installation/README.md b/sk/django_installation/README.md new file mode 100755 index 00000000000..77aace25152 --- /dev/null +++ b/sk/django_installation/README.md @@ -0,0 +1,5 @@ +# Inštalácia Django + +> **Poznámka** Ak si už prešla krokmi Inštalácie, tak toto už máš hotové a môžeš ísť rovno na ďalšiu kapitolu! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/sk/django_installation/instructions.md b/sk/django_installation/instructions.md new file mode 100755 index 00000000000..b35d55ab25f --- /dev/null +++ b/sk/django_installation/instructions.md @@ -0,0 +1,122 @@ +> Časť tejto kapitoly je založené na tutorialoch Geek Girls Carrots (http://django.carrots.pl/). +> +> Časť tejto kapitoly je založená na [django-marcador tutorial](http://django-marcador.keimlink.de/) licencovanej pod medzinárodnou licenciou Creative Commons Attribution-ShareAlike 4.0. Tutoriál django-marcador je autorsky chránený Markusom Zapke-Gründemannom et al. + +## Virtuálne prostredie + +Skôr ako nainštalujeme Django, nainštalujeme si extrémne užitočný nástroj, ktorý ti pomôže udržiavať poriadok pri kódovaní v tvojom počítači. Je možné tento krok preskočiť, no veľmi ho odporúčame. Začať s najlepším možným nastavením ti ušetrí kopec problémov v budúcnosti! + +Takže poďme vytvoriť **virtuálne prostredie** (alebo aj *virtualenv*). Virtualenv oddelí nastavenia Python/Django pre každý projekt zvlášť. To znamená, že zmeny, ktoré urobíš na jednej web stránke, neovplyvnia iné stránky, ktoré vyvíjaš. Šikovné, však? + +Jediné, čo musíš urobiť je nájsť adresár, v ktorom chceš `virtualenv` vytvoriť, napríklad tvoj domovský adresár. Vo Windowse by mohol vyzerať napríklad `C:\Users\Meno` (kde `Meno` predstavuje tvoj login). + +V tomto tutoriale budeme používať nový adresár `djangogirls` v tvojom domovskom adresári: + +``` +mkdir djangogirls +cd djangogirls +``` + +Vytvoríme virtualenv s názvom `myenv`. Všeobecný príkaz má takýto formát: + +``` +python3 -m venv myvenv +``` + +### Windows + +Ak chceš vytvoriť nový `virtualenv`, musíš otvoriť konzolu (hovorili sme o tom pár kapitol dozadu, pamätáš?) a spusti `C:\Python34\python -m venv myvenv`. Bude to vyzerať takto: + +``` +C:\Users\Meno\djangogirls> C:\Python34\python -m venv myvenv +``` + +kde `C:\Python34\python` je adresár, v ktorom máš nainštalovaný Python a `myvenv` je názov tvojho `virtualenv`-u. Môžeš použiť aj iný názov, ale používaj malé písmená a žiadne medzery, diakritiku alebo špeciálne znaky. Je tiež dobré použiť krátky názov - budeš naňho často odkazovať! + +### Linux a OS X + +Vytvoriť `virtualenv` na Linuxe a OS X vyžaduje iba jednoduché spustenie `python3 -m venv myvenv`. Bude to vyzerať takto: + +``` +~/djangogirls$ python3 -m venv myvenv +``` + +`myvenv` je názov tvojho `virtualenv`-u. Môžeš použiť aj iný názov, ale ostaň pri malých písmenách a nepoužívaj medzery. Je tiež dorbé použiť krátky názov, pretože naň budeš často odkazovať! + +> **POZNÁMKA:** Inicializácia virtuálneho prostredie na Ubuntu 14,04 týmto spôsobom v súčasnosti dáva takúto chybu: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Obídeme to týmto príkazom `virtualenv`-u. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Práca s virtualenv + +Vyššie uvedený príkaz vytvorí adresár s názvom `myvenv` (alebo akékoľvek meno si vybrala), ktorý obsahuje naše virtuálne prostredie (v podstate kopec adresárov a súborov). + +#### Windows + +Virtuálne prostredie spusti príkazom: + +``` +C:\Users\Meno\djangogirls> myvenv\Scripts\activate +``` + +#### Linux a OS X + +Virtuálne prostredie spusti príkazom: + +``` +~/djangogirls$ source myvenv/bin/activate +``` + +Nezabudni nahradiť `myvenv` názvom svojho `virtualenv`-u! + +> **POZNÁMKA:** niekedy `source` nemusí byť k dispozícii. V takom prípade vyskúšaj použiť: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +To, že je `virtualenv` spustený, zistíš, keď bude príkazový riadok v konzole vyzerať takto: + +``` +(myvenv) C:\Users\Name\djangogirls> +``` + +alebo: + +``` +(myvenv) ~/djangogirls$ +``` + +Všimni si, že sa tam objavila predpona `(myenv)`! + +Pri práci vo virtuálnom prostredí bude `python` automaticky odkazovať na správnu verziu, takže môžeš pokojne používať `python` namiesto `python3`. + +OK, všetko potrebné máme prichystané. Konečne môžeme nainštalovať Django! + +## Inštalácia Djanga + +Teraz, keď máš `virtualenv` spustený, môžeš nainštalovať Django pomocou príkazu `pip`. V konzole spusti `pip install django==1.8` (všimni si, že používame dvojité rovná sa: `==`). + +``` +(myvenv) ~$ pip install django==1.8 +Downloading/unpacking django==1.8 +Installing collected packages: django +Successfully installed django +Cleaning up... +``` + +vo Windowse + +> Ak sa objaví chyba pri spustení pip vo Windowse, skontroluj, či cesta/názov tvojho projektu neobsahuje medzery, diakritiku alebo špeciálne znaky (napr. `C:\Users\Tvoje Meno\djangogirls`). Ak obsahuje, mala by si zvážiť presun na iné miesto, bez medzier, diakritiky a špeciálnych znakov (napríklad: `C:\djangogirls`). Po presune prosím vyskúšaj vyššie uvedený príkaz znova. + +na Linuxe + +> Ak sa objaví chyba pri spustejní pip v Ubuntu 12.04 spusti `python -m pip install - U --force-reinstall pip`, čím sa opraví inštalácia pip vo virtualenv-e. + +To je všetko! Teraz si už (konečne) pripravená vytvoriť Django aplikáciu! diff --git a/sk/django_models/README.md b/sk/django_models/README.md new file mode 100755 index 00000000000..c8f52509254 --- /dev/null +++ b/sk/django_models/README.md @@ -0,0 +1,183 @@ +# Django modely + +Teraz pôjdeme vytvoriť niečo, čo bude uchovávať naše posty v blogu. Aby sme to vedeli spraviť, musíme si najskôr povedať niečo o `objektoch`. + +## Objekty + +V programovaní sa používa pojem `objektovo orientované programovanie`. Myšlienka spočíva v tom, že namiesto vypisovania nudných sekvencií programátorských príkazov môžeme veci modelovať a definovať ako majú navzájom komunikovať. + +Takže čo je to objekt? Je to zbierka vlastností a akcií. Znie to čudne, ale ukážeme si príklad. + +Ak chceme modelovať mačku, vytvoríme objekt `Macka`, ktorá má nejaké vlastnosti, napríklad: `farba`, `vek`, `nalada` (t. j. dobra, zla, ospala ;)), a `majitel` (ktorý je objektom `Osoba` alebo možno v prípade túlavej mačky bude táto vlastnosť prázdna). + +Ďalej má `Macka` niekoľko akcií: `priast`, `skrabat` alebo `krmit` (v ktorej dáme mačke nejaké `MacacieZradlo`, ktoré by mohlo byť samostatným objektom s vlastnosťami, t.j. `chut`). + +``` +Macka +-------- +farba +vek +nalada +majitel +priast() +skrabat() +krmit(mac_zradlo) + + +MacacieZradlo +-------- +chut +``` + +Takže v podstate myšlienka je popísať reálne veci kódom pomocou vlastností (ktorým hovoríme `vlastnosti objektu/object properties`) a akcií (tie nazývame `metódy`). + +Ako teda budeme modelovať blog post? Chceme vytvoriť blog, však? + +Musíme odpovedať na otázku: Čo je vlastne blog post? Aké vlastnosti by mal mať? + +No, náš blog post určite potrebuje nejaký text s obsahom a titulkom, nie? Bolo by tiež fajn vedieť, kto ho napísal - takže potrebujeme autora. A nakoniec, chceme vedieť, kedy bol post vytvorený a zverejnený. + +``` +Post +-------- +title +text +author +created_date +published_date +``` + +Čo všetko môžeme s blog postom robiť? Bolo by dobré mať nejakú `metódu`, ktorá post publikuje, však? + +Takže budeme potrebovať metódu `publish`. + +Keďže už vieme, čo chceme dosiahnuť, začnime tvoriť model v Djangu! + +## Django model + +Keďže už vieme, čo je objekt, môžeme vytvoriť Django model pre náš blog post. + +Model v Djangu je špeciálny typ objektu - je uložený v `databáze`. Databáza je súbor údajov. Je to miesto, kde budeš ukladať informácie o užívateľoch, príspevkoch na blogu, atď. Na ukladanie údajov budeme používať databázu SQLite. Je to štandardný východzí databázový adaptér v Djangu -- nateraz nám bude stačiť. + +Model v databáze si môžeš predstaviť ako tabuľku so stĺpcami (polia) a riadkami (dáta). + +### Vytvorenie aplikácie + +Aby sme mali všetko pekne upratané, vytvoríme vo vnútri nášho projektu samostatnú aplikáciu. Je dobré mať všetko zorganizované hneď od začiatku. Aby sme vytvorili aplikáciu, musíš v konzole spustiť nasledujúci príkaz (v adresári `djangogirls`, kde sa nachádza súbor `manage.py`): + +``` +~/djangogirls$ (myvenv) python manage.py startapp blog +``` + +Uvidíš, že bude vytvorený nový adresár `blog`, ktorý obsahuje množstvo súborov. Adresáre a súbory v našom projekte by mali vyzerať takto: + +``` +djangogirls +├── mysite +| __init__.py +| settings.py +| urls.py +| wsgi.py +├── manage.py +└── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py +``` + +Po vytvorení aplikácie tiež musíš Djangu povedať, že by ju mal použiť. To urobíme v súbore `mysite/settings.py`. Musíme nájsť `INSTALLED_APPS` a pridať riadok obsahujúci `'blog'` tesne pred uzatváraciu zátvorku`)`. Takže výsledok nášho snaženia bude vyzerať takto: + +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` + +### Vytvorenie modelu blog postu + +V súbore `blog/models.py` definujeme všetky objekty, ktoré sa nazývajú `modely` - na tomto mieste definujeme náš blog post. + +Otvor `blog/models.py`, všetko z neho odstráň a napíš tento kód: + +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Dvakrát skontroluj, či si použila 2 podčiarkovníky (`_`) na oboch stranách `str`. Táto konvencia sa v Pythone často používa a niekedy sa tomu hovorí "dunder" (skratka pre anglické Double-UNDERscore). + +Vyzerá to asi strašidelne. Ale neboj sa, vysvetlíme si, čo tieto riadky znamenajú! + +Všetky riadky začínajúce s `from` alebo `import` pridávajú časti z iných súborov. Takže namiesto kopírovania rovnakých vecí v každom súbore môžeme zahrnúť niektoré časti pomocou `from ... import ...`. + +`class Post(models.Model):` - tento riadok definuje náš model (je to `objekt`). + +* `class` je špeciálne kľúčové slovo, ktoré naznačuje, že definujeme objekt. +* `Post` je meno nášho modelu. Môžeme mu dať iný názov (ale musíme sa vyhnúť špeciálnym a prázdnym znakom). Názov triedy vždy začnite písmenami. +* `models.Model` znamená, že Post je Django Model, takže Django vie, že by mal byť uložený v databáze. + +Teraz zadefinujeme vlastnosti, o ktorých sme hovorili: `title` (titulka), `text`, `created_date` (dátum vytvorenia), `published_date` (dátum zverejnenia) a `author` (autor). Na to ale musíme zadefinovať typ každého poľa (Je to text? Číslo? Dátum? Vzťah k inému objektu, t.j. používateľovi?). + +* `modely. CharField` - takto môžeš definovať text s obmedzeným počtom znakov. +* `models.TextField` - toto je pre dlhé texty bez obmedzenia. To znie ideálne pre blogový príspevok, nie? +* `models.DateTimeField` - dátum a čas. +* `models.ForeignKey` - odkaz na iný model. + +Nebudeme si tu vysvetľovať každý kúsok kódu, pretože by to zabralo príliš veľa času. Ak chceš vedieť viac o poliach modelu a definovaní ďalších vecí okrem tých, čo sme popísali vyššie, skús sa pozrieť do dokumentácie Djanga (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +A čo `def publish(self):`? To je presne tá metóda `publish`, o ktorej sme hovorili predtým. `def` znamená, že ide o funkciu/metódu a `publish` je názov metódy. Názov metódy môžeš zmeniť, ak chceš. Pravidlo pre názvy je, že používame malé písmená a podčiarkovníky namiesto medzier. Napríklad metóda, ktorá vypočíta priemernú cenu by sa mohla nazývať `pocitaj_priemernu_cenu`. + +Metódy často niečo vracajú (angl. `return`). Príklad nájdeš napríklad v metóde `__str__`. V tomto prípade, keď zavoláme `__str__()`, dostaneme text (**string**) s názvom postu. + +Ak čokoľvek nie je jasné, neváhaj a spýtaj sa mentora! Je nám jasné, že je to komplikované, najmä ak sa učíš, čo sú objekty a funkcie súčasne. Ale dúfame, že teraz už to vyzerá trochu menej magicky! + +### Vytváranie tabuliek pre modely v databáze + +Posledným krokom je pridať náš nový model do databázy. Najprv musíme Djangu dať vedieť, že sme urobili nejaké zmeny v našom modeli (práve sme ho vytvorili!). Napíš `python manage.py makemigrations blog`. Bude to vyzerať takto: + +``` +(myvenv) ~/djangogirls$ python manage.py makemigrations blog +Migrations for 'blog': + 0001_initial.py: + - Create model Post +``` + +Django pre nás pripravil migračný súbor, ktorý musíme aplikovať na našu databázu. Napíš `python manage.py migrate blog` a výstup by mal byť: + +``` +(myvenv) ~/djangogirls$ python manage.py migrate blog +Operations to perform: + Apply all migrations: blog +Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK +``` + +Hurá! Náš Post model je už v databáze! Bolo by fajn ho vidieť, nie? Prejdi na nasledujúcu kapitolu a uvidíš ako vyzerá tvoj Post! diff --git a/sk/django_orm/README.md b/sk/django_orm/README.md new file mode 100755 index 00000000000..3a588d17b63 --- /dev/null +++ b/sk/django_orm/README.md @@ -0,0 +1,180 @@ +# Django ORM a QuerySety + +V tejto kapitole sa naučíš, ako sa Django pripája k databáze a ukladá do nej údaje. Poďme na to! + +## Čo je QuerySet? + +QuerySet je v podstate zoznam objektov daného modelu. QuerySet ti umožňuje čítať dáta z databázy, filtrovať ich a zoraďovať. + +Najjednoduchšie bude ukázať si to na príklade. Vyskúšajme si to. + +## Django shell (konzola) + +Otvor svoju lokálnu konzolu (nie na PythonAnywhere) a napíš tento príkaz: + +``` +(myvenv) ~/djangogirls$ python manage.py shell +``` + +Malo by to mať tento efekt: + +``` +(InteractiveConsole) +>>> +``` + +Teraz si v interaktívnej Django konzole. Je to ako konzola Pythonu, ale s trochou Django mágie :). Môžeš tu, samozrejme, použiť všetky príkazy Pythonu. + +### Všetky objekty + +Skúsme najskôr zobraziť všetky naše príspevky. To môžeš urobiť týmto príkazom: + +``` +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Ups! Objavila sa chybová hláška! Hovorí nám, že žiaden Post (príspevok) neexistuje. To je správne - zabudli sme ho totiž najskôr naimportovať! + +``` +>>> from blog.models import Post +``` + +Je to jednoduché: importujeme model `Post` z `blog.models`. Skúsme teda znova zobraziť všetky príspevky: + +``` +>>> Post.objects.all() +[, ] +``` + +Je to zoznam príspevkov, ktoré sme už predtým vytvorili! Vytvorili sme ich pomocou Django administrátorského rozhrania. No radi by sme vytvorili nové príspevky pomocou Pythonu, tak ako na to? + +### Vytvorenie objektu + +Takto vytvoríš nový Post objekt v databáze: + +``` +>>> Post.objects.create(author=me, title='Sample title', text='Test') +``` + +Chýba nám však jedna prísada: `me`. Ako autorku musíme vložiť inštanciu `User` modelu. Ako to urobiť? + +Najskôr naimportujme User model: + +``` +>>> from django.contrib.auth.models import User +``` + +Akých užívateľov máme v našej databáze? Skús toto: + +``` +>>> User.objects.all() +[] +``` + +To je superuser, ktorého sme už vytvorili predtým. Teraz získajme inštanciu tohto užívateľa: + +```python +ja = User.objects.get(username='ola') +``` + +Ako vidíš, teraz získame (angl. `get`) užívateľa (angl. `User`) s užívateľským meno (angl. `username`), ktoré sa rovná 'ola'. Aké elegantné! Samozrejme musíš si to upraviť na svoje meno. + +Teraz už konečne môžeme vytvoriť náš prvý príspevok: + +``` +>>> Post.objects.create(author=ja, title='titulka', text='Test') +``` + +Hurá! Chceš si overiť, či to fungovalo? + +``` +>>> Post.objects.all() +[, , ] +``` + +Je to tam, jeden príspevok v zozname pribudol! + +### Pridaj viac príspevkov + +Teraz sa môžeš trochu pobaviť a pridať pár ďalších postov, aby si videla, ako to funguje. Pridaj dva-tri ďalšie príspevky a potom poďme na ďalšiu časť. + +### Filtrovanie objektov + +Dôležitou vlastnosťou QuerySetov je možnosť ich filtrovať. Povedzme, že chceme nájsť všetky príspevky, ktorých autorom je užívateľ (User) ola. Použijeme `filter` namiesto `all` v príkaze `Post.objects.all()`. V zátvorkách definujeme jednu alebo viac podmienok, ktoré majú byť splnené príspevkom, aby skončil v tvojom querysete. V našom prípade je to `author`, ktorý sa rovná `ja`. V Djangu to napíšeš takto: `author=ja`. Náš kúsok kódu bude teraz vyzerať takto: + +``` +>>> Post.objects.filter(author=ja) +[, , , ] +``` + +Alebo neskúsime vyhľadať všetky príspevky, ktoré obsahujú slovo 'titulka' v políčku `title`? + +``` +>>> Post.objects.filter(title__contains='titulka') +[, ] +``` + +> **Poznámka** Medzi `title` a `contains` sú dva podčiarkovníky (`_`). Django ORM používa túto syntax, aby oddelil názvy polí ("title") a operácie či filtre ("contains"). Ak použiješ iba jeden podčiarkovník, dostaneš chybu "FieldError: Cannot resolve keyword title_contains". + +Môžeš tiež získať zoznam všetkých publikovaných postov. To urobíme vyfiltrovaním príspevkov, ktoré majú nastavený `published_date` v minulosti: + +``` +>>> from django.utils import timezone +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +Bohužiaľ, príspevok, ktorý sme pridali z konzoly Pythonu, ešte nie je publikovaný. To môžeme zmeniť! Najskôr získaj inštanciu postu, ktorý chceme publikovať: + +``` +>>> post = Post.objects.get(title="Sample title") +``` + +A potom ho publikuj pomocou našej metódy `publish`! + +``` +>>> post.publish() +``` + +Teraz skús získať zoznam publikovaných postov znova (stlač šípku hore trikrát a stlač `enter`): + +``` +>>> Post.objects.filter(published_date__lte=timezone.now()) +[] +``` + +### Radenie objektov + +QuerySety tiež umožňujú zoradiť zoznamy objektov. Skúsme ich zoradiť podľa dátumu vytvorenia (pole `created_date`): + +``` +>>> Post.objects.order_by('created_date') +[, , , ] +``` + +Môžeme ich tiež zoradiť naopak pridaním `-` na začiatok: + +``` +>>> Post.objects.order_by('-created_date') +[, , , ] +``` + +### Reťazenie QuerySetov + +QuerySety môžeš dokonca kombinovať pomocou **reťazenia**: + +``` +>>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +To je skutočne mocný nástroj, s ktorým môžeš písať dosť komplexné požiadavky (queries). + +Super! Teraz už si pripravená na ďalšiu časť! Shell zatvoríš príkazom: + +``` +>>> exit() +$ +``` diff --git a/sk/django_start_project/README.md b/sk/django_start_project/README.md new file mode 100755 index 00000000000..cedf1ce9682 --- /dev/null +++ b/sk/django_start_project/README.md @@ -0,0 +1,144 @@ +# Tvoj prvý Django projekt! + +> Časť tejto kapitoly je založená na tutoriáli Geek Girls Carrots (http://django.carrots.pl/). +> +> Časti tejto kapiolty sú založená na [django-marcador tutorial][1] pod licenciou Creative Commons Attribution-ShareAlike 4.0 International License. Tutoriál django-marcador je autorsky chránený Markusom Zapke-Gründemannom et al. + + [1]: http://django-marcador.keimlink.de/ + +Vytvoríme jednoduchý blog! + +Prvý krok je vytvoriť nový Django projekt. To v podstate znamená, že spustíme pár skriptov, poskytovaných Djangom, ktoré pre nás vytvoria kostru Django projektu. Je to len pár zložiek a súborov, ktoré použijeme neskôr. + +Mená niektorých súborov a zložiek sú pre Django veľmi dôležité. Súbory, ktoré teraz vytvoríme, by si nemala premenovať. Ich presúvanie na iné miesto taktiež nie je dobrý nápad. Django potrebuje udržovať určitú štruktúru, aby bol schopný nájsť dôležité veci. + +> Nezabudni všetko spúšťať vo virtualenv. Pokiaľ vo svojej konzole nevidíš prefix `(myvenv)` musíš aktivovať virtualenv. Ako na to bolo vysvetlené v kapitole **Inštalácia Django** v časti **Práca s virtualenv**. Pokiaľ napíšeš `myvenv\Scripts\activate` na Windowsoch, alebo `source myvenv/bin/activate` na Mac OS / Linux, malo by všetko fungovať. + +Vo svojej MacOS alebo Linux konzole spusti tento príkaz; **nezabudni pridať bodku `.` na konci**: + +``` +(myvenv) ~/djangogirls$ django-admin startproject mysite . +``` + +Na Windowsoch: **nezabudni pridať bodku `.` na konci**: + +``` +(myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . +``` + +> Bodka `.` je dôležitá, pretože hovorí skriptom, aby nainštalovali Django v tvojej aktuálnej zložke (pre ktorú je bodka `.` skratkou) +> +> **Poznámka** Pri písaní predchádzajúcich príkazov nezabudni, že píšeš len časti, ktoré začínajú `django-admin` alebo `django-admin.py`. `(myvenv) ~/djangogirls$` a `(myvenv) C:\Users\Name\djangogirls>` sú len príkladom cesty, kam budeš zadávať svoje príkazy. + +`django-admin.py` je skript, ktorý pre teba vytvorí zložky a súbory. Momentálne by si mala mať štruktúru adresárov, ktorá vyzerá takto: + +``` +djangogirls +├───manage.py +└───mysite + settings.py + urls.py + wsgi.py + __init__.py +``` + +`manage.py` je skript, ktorý pomáha so správou stránky. Okrem iného budeme vďaka nemu môcť spustiť na našom počítači webový server, bez toho, aby sme inštalovali čokoľvek iné. + +Súbor `settings.py` obsahuje konfiguráciu tvojej webovej stránky. + +Pamätáš, keď sme rozprávali o doručovateľovi listov, ktorý zisťuje kam doručiť list? `urls.py` obsahuje zoznam vzorov, ktoré používa `urlresolver`. + +Zatiaľ ignorujme ostatné súbory, keďže ich teraz aj tak nebudeme meniť. Jediná vec na ktorú netreba zabudnúť je, že ich nesmieš omylom zmazať! + +## Zmena nastavení + +Spravme pár zmien v `mysite/settings.py`. Otvor súbor v editore kódu, ktorý si si nainštalovala predtým. + +Bolo by dobré mať na našej stránke správny čas. Choď na [zoznam časových pásiem na wikipedii][2] a skopíruj svoje časové pásmo (TZ). (napr. `Europe/Bratislava`) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +V súbore settings.py, nájdi riadok, ktorý obsahuje `TIME_ZONE` a uprav ho tak, aby obsahoval tvoje časové pásmo: + +```python +TIME_ZONE = 'Europe/Bratislava' +``` + +Prípadne zvoľ iné pásmo ako "Europe/Bratislava", ak je to potrebné + +Tiež budeme musieť pridať cestu k statickým súborom (všetko o statických súboroch a CSS sa dozvieme neskôr v ďalších kapitolách tutorialu). Prejdi dole na *koniec* súboru a hneď pod záznam `STATIC_URL` pridaj nový s názvom `STATIC_ROOT`: + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## Nastavenie databázy + +Existuje veľa rôznych databázových softvérov, ktoré umožňujú ukladať údaje pre tvoje web stránky. My budeme používať predvolenú databázu - `sqlite3`. + +Tá je už nastavená v tejto časti súboru `mysite/settings.py`: + +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +``` + +Databázu pre náš blog vytvoríme spustením tohto príkazu v konzole: `python manage.py migrate` (musíme byť v adresári `djangogirls`, ktorý obsahuje súbor `manage.py`). Ak všetko prešlo dobre, mala by si vidieť niečo takéto: + +``` +(myvenv) ~/djangogirls$ python manage.py migrate +Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth +Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... +Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK +``` + +A je to! Teraz treba spustiť webový server a uvidíme či je naša web stránka funkčná! + +Musíš sa nachádzať v adresári, v ktorom sa nachádza súbor `manage.py` (adresár `djangogirls`). V konzole spustíme webový server zadaním `python manage.py runserver`: + +``` +(myvenv) ~/djangogirls$ python manage.py runserver +``` + +Ak si vo Windowse a padne ti to s chybovou hláškou `UnicodeDecodeError`, použi namiesto toho tento príkaz: + +``` +(myvenv) ~/djangogirls$ python manage.py runserver 0:8000 +``` + +Teraz už musíš len skontrolovať, či tvoja web stránka funguje. Otvor si prehliadač (Firefox, Chrome, Safari, Internet Explorer alebo čokoľvek používaš) a zadaj adresu: + +``` +http://127.0.0.1:8000/ +``` + +Príkazový riadok bude obsadený webovým serverom, až kým ho nezastavíš. Ak chceš zadať viac príkazov, kým je spustený, otvor nové okno terminálu a aktivuj svoj virtualenv. Ak chceš zastaviť webový server, prepni sa späť do okna, v ktorom beží a stlač Ctrl + C súčasne (na Windowse možno budeš musiť stlačiť Ctrl + Break). + +Blahoželáme! Práve si vytvorila svoju prvú web stránku, ktorá beží na tvojom webovom serveri. Nie je to úžasné? + +![Fungovalo to!][3] + + [3]: images/it_worked2.png + +Pripravená na ďalší krok? Je na čase vytvoriť nejaký obsah! diff --git a/sk/django_start_project/images/it_worked2.png b/sk/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/sk/django_start_project/images/it_worked2.png differ diff --git a/sk/django_templates/README.md b/sk/django_templates/README.md new file mode 100755 index 00000000000..8d1a4535bd2 --- /dev/null +++ b/sk/django_templates/README.md @@ -0,0 +1,108 @@ +# Šablóny Django + +Je na čase zobraziť nejaké údaje! Na to nám Django ponúka užitočné vstavané **šablónové tagy**. + +## Čo sú to šablónové tagy? + +V HTML vlastne nemôžeš písať pythonský kód, pretože prehliadače mu nerozumejú. Poznajú len HTML. Vieme, že HTML je skôr statické, kým Python je oveľa dynamickejší. + +**Django šablónové tagy** nám umožňujú previesť Pythonské veci do HTML, takže dynamické webové stránky môžeš vytvoriť rýchlejšie a jednoduchšie. Paráda! + +## Zobraz šablónu so zoznamom príspevkov + +V predchádzajúcej kapitole sme našej šablóne dali zoznam príspevkov v premennej `posts`. Teraz to zobrazíme v HTML. + +Na vypísanie premennej v Django šablónach použijeme dvojitú zloženú zátvorku s názvom premennej vo vnútri, asi takto: + +```html +{{ posts }} +``` + +Vyskúšaj to vo svojej šablóne `blog/templates/blog/post_list.html`. Nahraď všetko od druhého `
` po tretí `
` týmto kódom: `{{ posts }}`. Ulož súbor a obnov stránku, aby sme videli výsledky: + +![Obrázok 13.1][1] + + [1]: images/step1.png + +Ako vidíš, dostali sme len toto: + +``` +[, ] +``` + +To znamená, že to Django chápe ako zoznam objektov. Pamätáš si z kapitoly **Úvod do Pythonu** ako môžeme zobraziť zoznamy? Áno, cyklami! V Django šablóne ich urobíš takto: + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Vyskúšaj si to vo svojej šablóne. + +![Obrázok 13.2][2] + + [2]: images/step2.png + +Funguje to! Ale my chceme, aby sa zobrazili ako tie statické príspevky, ktoré sme vytvorili predtým v kapitole **Úvod do HTML**. Môžeš skombinovať HTML a šablónové tagy. Naše `body` bude vyzerať takto: + +```html + + +{% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}Všetko, čo dáš medzi `{% for %}` a `{% endfor %}` sa bude opakovať pre každý objekt v zozname. Obnov svoju stránku:{% endraw %} + +![Obrázok 13.3][3] + + [3]: images/step3.png + +Všimla si si, že sme tentokrát použili trochu odlišné zápisy `{{ post.title }}` alebo `{{ post.text }}`? Pristupujeme k údajom v každom z polí definovanom v našom `Post` modeli. Okrem toho `|linebreaksbr` preposiela texty príspevkov cez filter, ktorý konvertuje zalomenie riadkov na odstavce. + +## Ešte jedna vec + +Bolo by fajn vidieť či bude tvoja web stránka stále funkčná aj na Internete, však? Skúsme to znova nasadiť na PythonAnywhere. Tu je rekapitulácia postupu... + +* Najskôr pošli svoj kód na Github + +``` +$ git status +[...] +$ git add -A . +$ git status +[...] +$ git commit -m "Modified templates to display posts from database." +[...] +$ git push +``` + +* Potom sa prihlás do [PythonAnywhere][4] a choď do **Bash konzoly** (alebo spusti novú) a zadaj: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd my-first-blog +$ git pull +[...] +``` + +* A nakoniec prejdi na [záložku Web][5] a stlač **Reload** na svojej webovej aplikácii. Aktualizácia by mala byť online! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Gratulujeme! Teraz skús pridať nový príspevok v Django adminovi (nezabudni pridať published_date!), potom obnov stránku a pozri sa, či sa príspevok zobrazí. + +Funguje ako hodinky? Sme hrdí! Teraz si na chvíľku oddýchni od počítača, zaslúžiš si trochu voľna. :) + +![Obrázok 13.4][6] + + [6]: images/donut.png diff --git a/sk/django_templates/images/donut.png b/sk/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/sk/django_templates/images/donut.png differ diff --git a/sk/django_templates/images/step1.png b/sk/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/sk/django_templates/images/step1.png differ diff --git a/sk/django_templates/images/step2.png b/sk/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/sk/django_templates/images/step2.png differ diff --git a/sk/django_templates/images/step3.png b/sk/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/sk/django_templates/images/step3.png differ diff --git a/sk/django_urls/README.md b/sk/django_urls/README.md new file mode 100755 index 00000000000..358bab87c2e --- /dev/null +++ b/sk/django_urls/README.md @@ -0,0 +1,126 @@ +# Django url + +Chystáme sa vytvoriť našu prvú web stránku: domovská stránka tvojho blogu! Ale ešte predtým sa poďme naučiť niečo o Django url. + +## Čo je URL? + +URL je jednoducho webová adresa. URL si môžeš všimnúť zakaždým, keď navštíviš webovú stránku - vidno ju v prehliadači v adresnom riadku (áno! `127.0.0.1:8000` je URL! A `https://djangogirls.org` je tiež URL): + +![Url][1] + + [1]: images/url.png + +Každá stránka na internete potrebuje svoju vlastnú URL. Týmto spôsobom aplikácia vie, čo by mala ukázať užívateľovi, ktorý otvorí URL. V Djangu používame takzvaný `URLconf` (URL konfigurácia). URLconf je súbor vzorov, ktoré sa Django pokúsi priradiť podľa prijatej URL, aby tak našiel správne zobrazenie. + +## Ako fungujú URL v Djangu? + +Otvorme súbor `mysite/urls.py` v editore kódu a pozrime sa, ako vyzerá: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` + +Ako vidíš, Django sem už pre nás niečo umiestnil. + +Riadky, ktoré začínajú s `#` sú komentáre - to znamená, že tie riadky Python nespustí. Šikovné, nie? + +Adminská URL, ktorú si navštívila v predchádzajúcej kapitole je už tu: + +```python +url(r'^admin/', include(admin.site.urls)), +``` + +To znamená, že pre každú URL, ktorá začína na `admin` Django nájde zodpovedajúce *zobrazenie (view)*. V tomto prípade pridávame množstvo adminských URL, takže to nie je všetko natlačené v jednom malom súbore -- je to čitateľnejšie a čistejšie. + +## Regex + +Zaujíma ťa, ako Django porovnáva URL so zobrazeniami? No, to je trochu zložitejšie. Django používa `regex`, čo je skratka pre "regulárne výrazy". Regex má veľa (veľa!) pravidiel, ktoré tvoria vzor vyhľadávania. Keďže regexy sú pokročilá téma, nebudeme sa nimi veľmi detailne zaoberať. + +Ak chceš porozumieť tvorbe vzorov, tu je príklad procesu - budeme potrebovať iba obmedzenú množinu pravidiel, ktorými vyjadríme vzor, ktorý hľadáme, konkrétne: + +``` +^ pre začiatok textu +$ pre koniec textu +\d pre číslicu ++ indikuje, že predchádzajúca položka sa má zopakovať aspoň raz +() ohraničuje časť vzoru +``` + +Všetko ostatné v definícii url bude brané doslovne. + +Teraz si predstav, že máš webovú stránky s adresou napríklad `http://www.mysite.com/post/12345/`, kde `12345` je číslo tvojho postu. + +Písať samostatné views pre všetky čísla postov by bolo vážne otravné. S regulárnym výrazom však vieme vytvoriť vzor, ktorý bude zodpovedať url a vyextrahovať z nej číslo, ktoré potrebujeme: `^post/(\d+)/$`. Rozoberme si to na drobné, aby sme videli, čo sa tu vlastne deje: + +* **^post/** hovorí Djangu, aby zobral čokoľvek, čo má na začiatku url `post` (hneď po `^`) +* **(\d+)** znamená, že tam bude číslo (jedna alebo viac číslic) a že chceme číslo zachytiť a extrahovať +* **/** povie Djangu, že bude nasledovať ďalší znak `/` +* **$** potom označuje koniec adresy URL, čo znamená, že vzoru budú zodpovedať iba reťazce s `/` na konci + +## Tvoja prvá Django url! + +Je čas vytvoriť našu prvú URL! Chceme, aby 'http://127.0.0.1:8000/' bola domovská stránka nášho blogu a zobrazovala zoznam príspevkov. + +Tiež chceme udržiavať súbor `mysite/urls.py` čistý, takže naimportujeme url z našej aplikácie `blog` do hlavného súboru `mysite/urls.py`. + +Neboj sa, zmaž všetky zakomentované riadky (tie, čo začínajú `#`) a pridaj riadok, ktorý naimportuje `blog.urls` do hlavnej url (`''`). + +Súbor `mysite/urls.py` by mal teraz vyzerať takto: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + +Django teraz presmeruje všetko, čo prichádza na 'http://127.0.0.1:8000/' do `blog.urls` a tam bude hľadať ďalšie inštrukcie. + +Pri písaní regulárnych výrazov je vždy dobré pridať pred reťazec `r`. To je užitočný tip pre Python, že reťazec môže obsahovať špeciálne znaky, ktoré nie sú urečené pre Python samotný, ale pre regulárny výraz. + +## blog.urls + +Vytvor nový prázdny súbor `blog/urls.py`. Dobre! Pridaj tieto prvé dva riadky: + +```python +from django.conf.urls import url +from . import views +``` + +Tu iba importujeme Django metódy a všetky naše `views` z aplikácie `blog` (zatiaľ žiadne nemáme, ale k tomu sa o chvíľu dostaneme!) + +Potom môžeme pridať náš prvý URL vzor: + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +Ako vidíš, priradili sme `view` s názvom `post_list` tejto URL: `^$`. Tento regulárny výraz sa bude zhodovať iba ak po `^` (začiatku) bude nasledovať `$` (koniec) - takže zodpovedať bude iba prázdny reťazec. To je správne, pretože v Django URL prekladači 'http://127.0.0.1:8000/' nie je súčasťou URL. Tento vzor povie Djangu, že `views.post_list` je to správne miesto, kam treba ísť, ak niekto vstúpi na stránku cez adresu 'http://127.0.0.1:8000/'. + +Posledná časť `name='post_list'` je názov URL, ktorý sa použije na identifikáciu view. Názov URL môže byť rovnaký ako názov view, ale pokojne to môže byť aj niečo úplne iné. Neskôr budeme v projekte používať pomenované URL, takže je dôležité pomenovať všetky URL v aplikácii. Názvy by mali byť unikátne a ľahké na zapamätanie. + +Všetko v poriadku? Otvor http://127.0.0.1:8000/ vo svojom prehliadači a pozri sa na výsledok. + +![Chyba][2] + + [2]: images/error1.png + +"Funguje to!" zmizlo, čo? Neboj sa, je to len chybová stránka, nič, čoho by si sa mala báť! Vlastne bývajú celkom užitočné: + +Môžeš si prečítať, že neexistuje **žiadny atribút post_list**. Pripomína ti *post_list* niečo? Tak sme nazvali náš view! To znamená, že je všetko v poriadku, len sme ešte nevytvorili náš *view*. Žiadne obavy, aj k tomu sa dostaneme. + +> Ak chceš vedieť viac o Django URLconfs, pozri sa na oficiálnu dokumentáciu: https://docs.djangoproject.com/en/1.8/topics/http/urls/ diff --git a/sk/django_urls/images/error1.png b/sk/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/sk/django_urls/images/error1.png differ diff --git a/sk/django_urls/images/url.png b/sk/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/sk/django_urls/images/url.png differ diff --git a/sk/django_views/README.md b/sk/django_views/README.md new file mode 100755 index 00000000000..8512c29d0ee --- /dev/null +++ b/sk/django_views/README.md @@ -0,0 +1,38 @@ +# Django views - čas tvoriť! + +Je čas zbaviť sa toho bugu, čo sme vytvorili v poslednej kapitole :) + +*View* je miesto, kam dávame "logiku" našej aplikácie. Bude požadovať informáciu z `modelu`, ktorý si už vytvorila a pošle to do `šablóny`. Šablónu (template) budeme vytvárať v nasledujúcej kapitole. Views sú vlastne len metódy Pythonu, ktoré sú trochu zložitejšie, ako tie, ktoré sme písali v kapitole **Úvod do Pythonu**. + +Views sú umiestnené v súbore `views.py`. Naše *views* budeme pridávať do súboru `blog/views.py`. + +## blog/views.py + +OK, otvorme tento súbor a pozrime sa, čo je v ňom: + +```python +from django.shortcuts import render + +# Create your views here. +``` + +Veľa toho nie je. Najjednoduchší *view* môže vyzerať zhruba takto. + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Ako vidíš, vytvorili sme metódu (`def`) nazvanú `post_list`, ktorá použije `request` (žiadosť) a `return` (vráti) metódu `render`, ktorou vykreslí (spojí dokopy) našu šablónu `blog/post_list.html`. + +Ulož súbor, prejdi na http://127.0.0.1:8000 / a pozri sa, čo sa udeje. + +Ďalšia chyba! Prečítaj si, o čo ide tentokrát: + +![Chyba][1] + + [1]: images/error.png + +To je jednoduché: *TemplateDoesNotExist*. Opravme túto chybu a v nasledujúcej kapitole vytvorme šablónu! + +> Viac informácií o Django views získaš v oficiálnej dokumentácii: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/sk/django_views/images/error.png b/sk/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/sk/django_views/images/error.png differ diff --git a/sk/domain/README.md b/sk/domain/README.md new file mode 100755 index 00000000000..043aa7a4030 --- /dev/null +++ b/sk/domain/README.md @@ -0,0 +1,71 @@ +# Doména + +Heroku ti dala doménu, avšak je dlhá a ťažko si ju zapamätať. Bolo by skvelé mať meno domény, ktoré by bolo krátke a ľahko sa pamätalo, že? + +V tejto kapitole ťa naučíme, ako si zakúpiť domenú a nasmerovať ju na Heroku! + +## Kde si registrovať doménu? + +Typická doména stojí $15 na rok. Existujú lacnejšie aj drahšie možnosti, v závislosti od poskytovateľa. Existuje veľa spoločností, od ktorých si môžeš kúpiť doménu: jednoduché [google vyhľadávanie][1] ti dá stovky možností. + + [1]: https://www.google.com/search?q=register%20domain + +Naša obľúbená je [I want my name][2]. Propagujú "bezbolestný manažment domény" a je to naozaj bezbolestné. + + [2]: https://iwantmyname.com/ + +## Ako registrovať doménu na IWantMyName? + +Choď na [iwantmyname][3] a napíš typ domény akú chceš mať do poľa vyhľadávania. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +Teraz by si mala vidieť zoznam všetkých dostupných domén, s pojmom, ktorý si zadala. Ako vidíš, usmievavá tvár naznačuje, že táto doména je dostupná a môžeš si ju zakúpiť, kým smutná tvár znamená, že už ju niekto vlastní. + +![][5] + + [5]: images/2.png + +Rozhodli sme sa kúpiť `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Prejdi k pokladni. Teraz by si sa mala prihlásiť do iwantmyname, pokiaľ ešte nemáš vytvorený účet. Po tom poskytni informácie o svojej kreditnej karte a kúp si doménu! + +Po tom, klikni na `Domains` v menu a vyber si novo zakúpenú doménu. Následne nájdi a klikni na odkaz `manage DNS records`: + +![][7] + + [7]: images/4.png + +Teraz musíš nájsť tento formulár: + +![][8] + + [8]: images/5.png + +A vyplniť nasledujúce údaje: - Hostname: www - Type: CNAME - Value: tvoja doména z Heroku (napríklad djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Klikni na tlačidlo Add a Save v spodnej časti stránky. + +Môže trvať niekoľko hodím, kým začne doména pracovať, takže buď trpezlivá! + +## Konfiguruj doménu na Heroku + +Taktiež musíš povedať Heroku, že chceš použiť svoju vlastnú doménu. + +Choď do [Heroku Dashboard][10], prihlás sa na svoj Heroku účet a vyber si svoju aplikáciu. Potom choď do nastavení aplikácie a pridaj svoju doménu v sekcii `Domains` a ulož zmeny. + + [10]: https://dashboard.heroku.com/apps + +To je všetko! \ No newline at end of file diff --git a/sk/dynamic_data_in_templates/README.md b/sk/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..cb6675ff9ab --- /dev/null +++ b/sk/dynamic_data_in_templates/README.md @@ -0,0 +1,75 @@ +# Dynamické dáta v šablónach + +Máme rozdielne kúsky na svojom mieste: `Post` model je definovaný v `models.py`, máme `post_list` v `views.py` a pridanú šablónu. Ale ako prinútime HTML šablónu, aby zobrazovala náš príspevok? Pretože to je to, čo chceme: vziať nejaký obsah (modely uložené v databáze) a zobraziť ich pekne v našej šablóne, že? + +To je presne to, čo majú *views* robiť: spojiť modely a šablóny. V našom `post_list` *view* potrebujeme vziať modely ktoré chceme zobraziť a posunúť ich do šablóny. Takže sa v podstate rozhodneme vo *view* čo (model) bude zobrazené v šablóne. + +Dobre, takže ako to dosiahneme? + +Musíme otvoriť náš `blog/views.py`. Zatiaľ `post_list` *view* vyzerá takto: + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Pamätáš si, keď sme rozprávali o zahrnutí kódu napísanom v rozdielnych súboroch? Teraz nastal čas kedy musíme zahrnúť model, ktorý sme napísali v `models.py`. Pridáme tento riadok `from .models import Post` takto: + +```python +from django.shortcuts import render +from .models import Post +``` + +Bodka za `from` znamená *aktuálna zložka* alebo *aktuálna aplikácia*. Pretože `views.py` a `models.py` sú v rovnakej zložke, môžeme jednoducho použiť `.` a meno súboru (bez `.py`). Potom importujeme názov modelu (`Post`). + +Ale čo ďalej? Na to aby sme boli schopní vziať konkrétny príspevok blogu z `Post` modelu potrebujeme niečo, čo sa volá `QuerySet`. + +## QuerySet + +Už by si mala vedieť ako funguje QuerySets. Hovorili sme o tom v kapitole [Django ORM (QuerySets)][1]. + + [1]: ../django_orm/README.md + +Takže teraz máme záujem o zoznam príspevkov blogu, ktoré sú uverejnené a zoradené podľa `published_date`, však? To sme už spravili v kapitole QuerySets! + +```python +Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') +``` + +Teraz vložíme tento kus kódu do súboru `blog/views.py` pridaním do funkcie `def post_list(request)`: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` + +Vezmi prosím na vedomie, že vytvárame *premennú* pre náš QuerySet: `posts`. Považuj to za meno nášho QuerySetu. Odteraz ho môžeme referovať pod týmto menom. + +Taktiež, kód používa funkciu `timezone.now()`, takže musíme pridať import pre `timezone`. + +Posledná chýbajúca časť je predanie `posts` QuerySetu do šablóny (v nasledujúcej kapitole si ukážeme ako ju zobraziť). + +V `render` funkcii už máme parameter `request` (takže všetko čo príjmeme od užívateľa cez Internet) a súbor šablóny `'blog/post_list.html'`. Posledný parameter, ktorý vyzerá takto: `{}` je miesto na ktoré môžeme dať nejaké veci ktoré môže použiť šablóna. Potrebujeme im dať mená (zatiaľ sa budeme držať `'posts'` :)). Malo by to vyzerať takto: `{'posts': posts}`. Všimni si, že časť pred `:` je reťazec: potrebuješ ju obaliť do úvodzoviek `''`. + +Nakoniec by náš súbor `blog/views.py` mal vyzerať takto: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +To je všetko! Čas prejsť na našu šablónu a zobraziť tento QuerySet! + +Pokiaľ si chceš prečítať niečo viac o QuerySets v Djangu mala by si sa pozrieť sem: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ diff --git a/sk/extend_your_application/README.md b/sk/extend_your_application/README.md new file mode 100755 index 00000000000..f4f79454546 --- /dev/null +++ b/sk/extend_your_application/README.md @@ -0,0 +1,198 @@ +# Ako rozšíriť aplikáciu + +Už sme dokončili všetky kroky potrebné k tomu, aby sme vytvorili našu webovú stránku: vieme ako napísať model, url, view a šablónu. Taktiež vieme ako spraviť našu stránku peknú. + +Čas na precvičovanie! + +Prvá vec, ktorú potrebujeme na našom blogu je, zjavne, stránka, na ktorej zobrazíme jeden príspevok, že? + +Už máme `Post` model, takže nepotrebujeme do `models.py` pridávať nič iné. + +## Vytvorenie šablóny odkazu na post detail + +Začneme tak, že pridáme link do súboru `blog/templates/blog/post_list.html`. Zatiaľ by mal vyzerať nejako takto: + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +{% raw %}Chceme, aby link z titulku príspevku smeroval na stránku detailov príspevku. Zmeňme `

{{ post.title }}

` tak, aby odkazoval na stránku detailu príspevku:{% endraw %} + +```html +

{{ post.title }}

+``` + +{% raw %}Je na čase vysvetliť záhadné `{% url 'post_detail' pk=post.pk %}`. Ako možno tušíš, `{% %}` notácia znamená, že používame tagy Django šablóny. Tentoraz použijeme jeden, ktorý pre nás vytvorí URL!{% endraw %} + +`blog.views.post_detail` je cesta k `post_detail` *view* ktorý chceme vytvoriť. Poznámka: `blog` je názov aplikácie (zložky `blog`), `views` je meno súboru `views.py` a posledná časť - `post_detail` - je meno *view*. + +Teraz keď pôjdeme na: http://127.0.0.1:8000/ uvidíme chybu (ako sa dá očakávať, keďže nemáme URL alebo *view* pre `post_detail`). Bude to vyzerať takto: + +![NoReverseMatch error][1] + + [1]: images/no_reverse_match2.png + +## Vytvor URL na detail príspevku + +Vytvorme URL v `urls.py` pre náš `post_detail` *view*! + +Chceme aby sa detaily nášho prvého príspevku zobrazili na tejto **URL**: http://127.0.0.1:8000/post/1/ + +Vytvorme URL v súbore `blog/urls.py` tak, aby odkazoval Django na *view* nazvaný `post_detail`, ktorý zobrazí celý príspevok blogu. Pridaj riadok `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` do súboru `blog/urls.py`. Súbor by mal vyzerať takto: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + +Táto časť `^post/(?P[0-9]+)/$` vyzerá desivo, ale neboj sa - o chvíľu ti ju vysvetlíme: - znova začína s `^` -- začiatkom - `post/` znamená len, že po začiatku by URL mala obsahovať slová **post** a **/**. Zatiaľ je všetko v poriadku. - `(?P[0-9]+)` - táto časť je zložitejšia. Znamená to, že Django vezme všetko, čo tu vložíš a premiestni to do premennej s názvom `pk`. `[0-9]` nám tiež hovorí, že to môžu byť len čísla, nie písmená (takže všetko medzi 0 a 9). `+` znamená, že musíme mať aspoň jedno číslo. Takže niečo ako `http://127.0.0.1:8000/post//` nie je validné, ale `http://127.0.0.1:8000/post/1234567890/` je úplne v poriadku! - `/` - potom znova potrebujeme **/** - `$` - "koniec"! + +To znamená, že ak zadáš `http://127.0.0.1:8000/post/5/` do svojho prehliadača, Django pochopí, že hľadáš *view* s názvom `post_detail` a prenesie informácie z `pk` rovné `5` do toho *view*. + +`pk` je skratka pre `primárny kľúč (primary key)`. Tento názov je často používaný v Django projektoch. Ale môžeš si pomenovať svoje premenná ako chceš (pamätaj: malé písmená a `_` namiesto medzier!). Napríklad namiesto `(?P[0-9]+)` môžeme mať premennú `post_id`, takže táto časť by vyzerala: `(?P[0-9]+)`. + +Dobre, pridali sme nový vzor URL do `blog/urls.py`! Obnovme stránku: http://127.0.0.1:8000/ Boom! Ďalšia chyba! Ako sa dalo očakávať! + +![AttributeError][2] + + [2]: images/attribute_error2.png + +Pamätáš si, čo je ďalší krok? Samozrejme: pridávanie view! + +## Pridaj view do detailu príspevku + +Tentokrát má náš *view* extra parameter `pk`. Náš *view* ho potrebuje zachytiť, že? Takže definujeme našu funkciu ako `def post_detail(request, pk):`. Všimni si, že musíme použiť rovnaké meno, ako to, ktoré sme špecifikovali v Url (`pk`). Vynechanie tejto premmenej je nesprávne a bude mať za následok chybu! + +Teraz chceme aby sme dostali jeden a iba jeden príspevok blogu. Na to môžeme použiť querysets takto: + +```python +Post.objects.get(pk=pk) +``` + +Ale tento kód má problém. Pokiaľ tu nie je žiaden `Post` s daným `primárnym kľúčom`(`pk`) budeme mať super škaredú chybu! + +![DoesNotExist error][3] + + [3]: images/does_not_exist2.png + +To nechceme! Ale samozrejme Django prichádza s niečim, čo si s tým poradí: `get_object_or_404`. V príade, že neexistuje žiaden `Post` s daným `pk` zobrazí oveľa krajšiu stránku (nazývanú `Page Not Found 404`). + +![Page not found][4] + + [4]: images/404_2.png + +Dobrá správa je, že si môžeš vytvoriť svoju vlastnú `Page not found` stránku a spraviť ju tak peknú ako len chceš. Ale to nie je momentálne príliš dôležité, takže to preskočíme. + +Dobre, čas pridať *view* do nášho `views.py` súboru! + +Mali by sme otvoriť `blog/views.py` a pridať nasledujúci kód: + +```python +from django.shortcuts import render, get_object_or_404 +``` + + +Blízko riadkov `from`. A na konci súboru pridáme náš *view*: + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + + +Áno. Nastal čas obnoviť stránku: http://127.0.0.1:8000/ + +![Post list view][5] + + [5]: images/post_list2.png + +Funguje to! Ale čo sa stane, keď klikneš na odkaz v názve príspevku blogu? + +![TemplateDoesNotExist error][6] + + [6]: images/template_does_not_exist2.png + +Ale nie! Ďalšia chyba! Ale už vieme, s čim mám dočinenia, že? Potrebujeme pridať šablónu! + +## Vytvor šablónu pre detail príspevku + +Vytvoríme súbor v `blog/templates/blog` s názvom `post_detail.html`. + +Bude to vyzerať takto: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endblock %} +``` + +Znova raz rozširujeme `base.html`. V bloku `content` chceme zobraziť published_date príspevku (pokiaľ existuje), titulok a text. Ale mali by sme prebrať pár dôležitých vecí, však? + +{% raw %}`{% if ... %} ... {% endif %}` je tag šablóny, ktorý môžeme použiť ak chceme niečo skontrolovať (pamätáš na `if ... else ..` z kapitoly **Úvod do Pythonu**?). V tomto prípade chceme skontrolovať, či `published_date` príspevku nie je prázdny.{% endraw %} + +Dobre, môžeme obnoviť našu stránku a pozrieť sa, či `Page not found` zmizlo. + +![Post detail page][7] + + [7]: images/post_detail2.png + +Jupí! Funguje to! + +## Ešte jedna vec: čas nasadiť aplikáciu! + +Bolo by dobré vedieť, či tvoja stránka stále funguje na PythonAnywhere, že? Pokúsme sa ju znova nasadiť. + +``` +$ git status +$ git add -A . +$ git status +$ git commit -m "Pridaný view a šablóna pre detail príspevku blogu a taktiež CSS pre stránku." +$ git push +``` + +* Potom v [Bash konzole PythonAnywhere][8]: + + [8]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* A nakoniec preskoč na [kartu Web][9] and klinki na **Reload**. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +A to by malo byť všetko! Gratulujeme :) diff --git a/sk/extend_your_application/images/404_2.png b/sk/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/sk/extend_your_application/images/404_2.png differ diff --git a/sk/extend_your_application/images/attribute_error2.png b/sk/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/sk/extend_your_application/images/attribute_error2.png differ diff --git a/sk/extend_your_application/images/does_not_exist2.png b/sk/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/sk/extend_your_application/images/does_not_exist2.png differ diff --git a/sk/extend_your_application/images/no_reverse_match2.png b/sk/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/sk/extend_your_application/images/no_reverse_match2.png differ diff --git a/sk/extend_your_application/images/post_detail2.png b/sk/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/sk/extend_your_application/images/post_detail2.png differ diff --git a/sk/extend_your_application/images/post_list2.png b/sk/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/sk/extend_your_application/images/post_list2.png differ diff --git a/sk/extend_your_application/images/template_does_not_exist2.png b/sk/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/sk/extend_your_application/images/template_does_not_exist2.png differ diff --git a/sk/how_the_internet_works/README.md b/sk/how_the_internet_works/README.md new file mode 100755 index 00000000000..0991dbd9c0d --- /dev/null +++ b/sk/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# Ako funguje Internet + +> Táto kapitola je inšpirovaná prednáškou "Ako funguje Internet" od Jessicy McKellar (http://web.mit.edu/jesstess/www/). + +Stavíme sa, že Internet používaš každý deň. Ale vieš, čo sa deje, keď napíšeš adresu, ako https://djangogirls.org do prehliadača a stlačíš `enter`? + +Prvá vec, ktorú potrebuješ vedieť je, že webové stránky sú len kopa súborov uložených na pevnom disku. Podobne ako tvoje filmy, hudba a obrázky. Ale je tu jedna časť, ktorá je špecifická pre webové stránky: obsahujú počítačový kód nazývaný HTML. + +Pokiaľ nemáš skúsenosti s programovaní, môže byť pochopenie HTML zo začiatku zložité, ale tvoj webový prehliadač (ako Chrome, Safari, Firefox atď.) ho milujú. Webové prehliadače sú navrhnuté na to, aby rozumeli kódu, nasledovali jeho inštrukcie a prezentovali súbory, ktoré tvoria tvoju webovú stránku presne tak, ako to chceš. + +Ako s každým súborom, potrebujeme uložiť HTML súbor niekde na pevnom disku. V prípade Interntu používame špeciálne, výkonné počítače nazývane *servery*. Nemajú obrazovku, myš alebo klávesnicu, pretože ich hlavnou úlohou je ukladať dáta a poskytovať ich. Preto ich voláme *servery* -- pretože *poskytujú* (anglicky serve) tvoje dáta. + +OK, avšak chceš vedieť, ako vyzerá Internet, že? + +Nakreslili sme ti obrázok! Vyzerá takto: + +![Obrázok 1.1][1] + + [1]: images/internet_1.png + +Vyzerá to ako neporiadok, že? V skutočnosti je to sieť prepojených strojov (nedávno spomenutých *serverov*). Stoviek a tisícok strojov! Mnoho, mnoho kilometrov káblov po celom svete! Môžeš navštíviť stránku Submarine Cable Map (http://submarinecablemap.com) aby si videla nakoľko komplikovaná sieť to je. Tu je obrázok zo stránky: + +![Obrázok 1.2][2] + + [2]: images/internet_3.png + +Nie je to fascinujúce? Ale zjavne nie je možné mať kábel medzi každým strojom pripojeným k Internetu. Takže na to, aby sme boli schopní kontaktovať stroj (napríklad ten na ktorom je uložená stránka https://djangogirls.org) musíme poslať žiadosť cez mnoho, mnoho rozdielnych strojov. + +Vyzerá to takto: + +![Obrázok 1.3][3] + + [3]: images/internet_2.png + +Predstav si, že keď napíšeš https://djangogirls.org, pošleš list, v ktorom stojí: "Drahé Django Girls, chcem vidieť stránku djangogirls.org. Prosím pošli mi ju!" + +Tvoj list ide na najbližšiu poštu. Potom ide na ďalšiu, ktorá je o čosi bližšie adresátovi, potom na ďalšiu a ďalšiu až kým nedorazí do svojej destinácie. Jediná unikátna vec je, že ako pošleš mnoho listov (*data paketov*) na rovnaké miesto, môžu ísť cez úplne odlišné pošty (*routy*). Záleží to na tom, ako sú distribuované na každej pošte. + +![Obrázok 1.4][4] + + [4]: images/internet_4.png + +Áno, je to tak jednoduché. Pošleš správu a očakávaš nejakú odpoveď. Samozrejme, namiesto papiera a pera použijes byty dát, ale myšlienka je rovnaká! + +Namiesto adries s menom ulice, mesta, PSČ a krajinou používame IP adresy. Tvoj počítač sa najprv opýta DNS (Domain Name System) aby preložil djangogirls.org na IP adresu. Funguje to trocha ako staré dobré telefónne zoznamy, kde si môžeš vyhľadať meno osoby ktorú chceš kontaktovať a nájsť jej telefón a adresu. + +Keď pošleš list, musí mať určité náležitosti, aby ho bolo možné správne doručiť: adresu, známku atď. Taktiež používaš jazyk, ktorému adresát rozumie, že? Rovnako to funguje aj s *data paketmi* ktoré pošleš aby sa ti zobrazila stránka. Používame protokol s názvom HTTP (Hypertext Transfer Protocol). + +Takže, v podstate, keď máš webovú stránku, musíš mať *server* (stroj) na ktorom bude žiť. Keď *server* obdrží prichádzajúcu *požiadavku* (v liste), pošle naspäť tvoju webovú stránku (v ďalšom liste). + +Keďže toto je Django tutoriál, spýtaš sa, čo robí Django. Keď pošleš odpoveď, nechceš vždy poslať rovnaké veci každému. Je oveľa lepšie ak sú tvoje listy osobné, hlavne pre osobu, ktorá ti práve teraz napísala, že? Django ti pomáha vytvoriť tieto osobné, zaujímavé listy :). + +Dosť bolo rečí, je čas tvoriť! \ No newline at end of file diff --git a/sk/how_the_internet_works/images/internet_1.png b/sk/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/sk/how_the_internet_works/images/internet_1.png differ diff --git a/sk/how_the_internet_works/images/internet_2.png b/sk/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/sk/how_the_internet_works/images/internet_2.png differ diff --git a/sk/how_the_internet_works/images/internet_3.png b/sk/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/sk/how_the_internet_works/images/internet_3.png differ diff --git a/sk/how_the_internet_works/images/internet_4.png b/sk/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/sk/how_the_internet_works/images/internet_4.png differ diff --git a/sk/html/README.md b/sk/html/README.md new file mode 100755 index 00000000000..280869a6940 --- /dev/null +++ b/sk/html/README.md @@ -0,0 +1,216 @@ +# Úvod do HTML + +Môžno sa pýtaš, čo jej šablóna? + +Šablóna je súbor, ktorý môžeme znova opakovane použiť, aby sme prezentovali nové informácie v konzistentnom formáte - šablónu môžeš použiť napríklad ako pomôcku pri písaní listu, pretože aj napriek tomu, že každý list môže obsahovať rozdielnu správu a byť adresovaný inej osobe, budú mať rovnaký formát. + +Formát Django šablóny je popísaný v jazyk nazývanom HTML (to je to HTML, ktoré sme spomenuli v prvej kapitole **Ako funguje Internet**). + +## Čo je HTML? + +HTML je jednoduchý kód, ktorý je interpretovaný tvojím webovým prehliadačom - ako napríklad Chrome, Firefox alebo Safari - aby tak zobrazil užívateľom webové stránky. + +HTML znamená "HyperText Markup Language". **HyperText** znamená, že sa jedná o typ textu, ktorý podporuje hypertextové odkazy medzi stránkami. **Markup** znamená, že sme vzali dokument a označili ho kódom aby sme niečomu povedali (v tomto prípade prehliadaču) ako interpretovať stránku. HTML kód je budovaný za pomoci **tagov**, každý začínajúci znakom `<` a končiaci znakom `>`. Tieto tagy reprezentujú značkovacie (Markup) **elementy**. + +## Tvoja prvá šablóna! + +Vytvorenie šablóny znamená vytvorenie súboru šablóny. + +Šablóny sú uložené v zložke `blog/templates/blog`. Takže najprv vytvor v zložke blogu zložku s názvom `templates`. Potom vytvor ďalšiu zložku s názvom `blog` v zložke templates: + +``` +blog +└───templates + └───blog +``` + +(Možno sa pýtaš prečo potrebujeme dve zložky s menom `blog` - ako neskôr zistíš, je to len užitočna konvencia, ktorá ti uľahčí život keď veci začnú byť komplikovanejšie.) + +A teraz vytvor súbor `post_list.html` (zatiaľ ho ponechaj prázdny) v zložke `blog/templates/blog`. + +Pozri sa, ako momentálne vyzerá tvoja stránka: http://127.0.0.1:8000/ + +> Pokiaľ stále vidíš chybu `TemplateDoesNotExists`, skús reštartovať tvoj server. Použi príkazový riadok, zastav server stlačením Ctrl+C (stlač naraz tlačidlá Control a C) a spusti ho znova pomocou príkazu `python manage.py runserver`. + +![Obrázok 11.1][1] + + [1]: images/step1.png + +Žiadne ďalšie chyby! Gratulujeme :) Avšak tvoja stránka zatiaľ neukazuje nič, okrem prázdnej stránky, pretože tvoja šablóna je taktiež prázdna. To musíme opraviť. + +Pridaj nasledujúci kód do tvojho súboru šablóny: + +```html + +

Ahoj!

+

Funguje to!

+ +``` + +Takže ako momentálne vyzerá tvoja stránka? To môžeš zistiť kliknutím na: http://127.0.0.1:8000/ + +![Obrázok 11.2][2] + + [2]: images/step3.png + +Funguje to! Dobrá práca :) + +* Najzákladnejší tag, ``, je vždy na začiatku každej webovej stránky a `` je vždy na jej konci. Ako môžeš vidieť, celý obsah stránky sa nachádza medzi začínajúcim tagom `` a uzatvárajúcim tagom `` +* `

` je tag pre element odstavca; `

` uzatvára každý odstavec + +## Head & body + +Každá HTML stránka je taktiež rozdelená do dvoch elementov: **head** a **body**. + +* **head** je element, ktorý obsahuje informácie o dokumente, ktoré nie sú zobrazené na obrazovke. + +* **body** je element, ktorý obsahuje všetko ostatné zobrazené ako časť webovej stránky. + +`` používame, aby sme povedali prehliadaču o konfigurácii stránky a `` aby sme mu povedali, čo na stránke je. + +Napríklad môžeš dať stránke titulok za použitia title elementu vo vnútri `` takto: + +```html + + + Ola's blog + + +

Ahoj!

+

Funguje to!

+ + +``` + +Ulož súbor a znova načítaj svoju stránku. + +![Obrázok 11.3][3] + + [3]: images/step4.png + +Všimni si ako prehliadač rozumie, že "Ola's blog" je titulok tvojej stránky? Interpretuje `Ola's blog` a vkladá text ako názov záložky (tento názov bude použitý aj keď si stránku uložíte a tak ďalej). + +Pravdepodobne si taktiež všimneš, že každý začínajúci tag má svoj *uzatvárajúci tag* obsahujúci `/`, a že elementy sú *vnorené* (tj. nemôžeš daný tag zatvoriť, kým nie sú taktiež zatvorené všetky tagy, ktoré sú v jeho vnútri). + +Je to ako vkladať veci do krabice. Máš jednú veľkú krabicu, ``; vo vnútri je ``, a tá obsahuje menšie krabice: `

`. + +Musíš nasledovať tieto pravidlá *uzatvárania* tagov a *vnorenia* elementov - pokiaľ ich nebudeš dodržovať, prehliadač nemusí byť schopný správne interpretovať tagy a tvoja stránka bude zobrazená nesprávne. + +## Uprav svoju šablónu + +Môžeš sa trocha pohrať s tým, že budeš upravovať svoju šablónu! Tu je pár užitočných tagov: + +* `

Hlavný nádpis

` - pre tvoj najdôležitejší nádpis +* `

Podnádpis

` pre nádpis na nižšej úrovni +* `

Pod-podnádpis

`.. a tak ďalej až do `
` +* `text` zdôrazňuje tvoj text +* `text` zvýrazňuje tvoj text o čosi viac +* `
` vkladá nový riadok (do br nemôžeš nič vložiť) +* `link` vytvára odkaz +* `
  • prvá položka
  • druhá položka
` vytvára zoznam ako tento! +* `
` definuje sekciu stránky + +Tu je príklad celej šablóny: + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

Môj prvý príspevok

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

Môj druhý príspevok

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` + +Vytvorili sme tri `div` sekcie. + +* Prvá `div` sekcia obsahuje titulok nášho blogu - je to nádpis a odkaz +* Ďalšie dva `div` elementy obsahujú príspevky blogu s časom publikovania, `h2` s nádpisom príspevku, na ktorý sa dá kliknúť a dva `p` (odstavce) textu, jeden pre dátum a druhý pre náš príspevok. + +Dá nám to tento efekt: + +![Obrázok 11.4][4] + + [4]: images/step6.png + +Jupí! Ale zatiaľ naša šablóna zobrazila len presne **rovnaké informácie** - kým pred chvíľou sme hovorili, že nám šablóny dovoľujú zobrazovať **rozdielne** informácie v **rovnakom formáte**. + +To čo v skutočnosti chceme spraviť je zobraziť reálne príspevky v našom Django admin rozhraní - a to je to, čo teraz spravíme. + +## Ešte jedna vec: nasaďte to! + +Bolo by skvelé, ak by sme všetky tieto veci mohli vidieť naživo na Internete, že? Spravme ďalšie PythonAnywhere nasadenie: + +### Commitni a pošli svoj kód na Github + +Najprv sa pozrime, ktoré súbory sa zmenili od posledného nasadenia (tieto príkazy spusti lokálne, nie na PythonAnywhere): + +``` +$ git status +``` + +Uisti sa, že si v zložke `djangogirls` a následne povedzme `gitu` nech zahrnie všetky zmeny v zložke: + +``` +$ git add -A . +``` + +> **Poznámka** - `-A` (skratka pre "all" (všetko)) znamená, že `git` rozozná, ak si vymazala súbory (štandardne rozoznáva len nové/modifikované súbory). Pamätaj si tiež (bolo to v kapitole 3), že `.` znamená aktuálny adresár. + +Predtým, ako nahrajeme všetky súbory, skontrolujme čo bude `git` nahrávať (všetky súbory, ktoré `git` nahraje by teraz mali byť zelené): + +``` +$ git status +``` + +Už sme skoro tam, teraz nastal čas mu povedať, aby uložil tieto zmeny v jeho histórii. Dáme mu "commit správu", kde popíšeme, čo sme zmenili. V tomto štádiu môžeš napísať čokoľvek, čo chceš, ale je nápomocné napísať čosi, čo je popisné natoľko, že si budeš v budúcnosti pamätať, čo si spravila. + +``` +$ git commit -m "Zmeny v HTML pre stránku." +``` + +> **Poznámka** - Uisti sa, že si použila dvojité úvodzovky okolo commit správy. + +Po tom, čo sme to dokončili, nahrajeme (push) naše zmeny na Github: + +``` +git push +``` + +### Stiahni svoj kód na PythonAnywhere a obnov svoju webovú aplikáciu + +* Otvor [konzolovú stránku PythonAnywhere][5] a prejdi do svojej **Bash konzole** (alebo naštartuj novú). Potom zadaj: + + [5]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd ~/my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +A sleduj ako sa tvoj kód sťahuje. Pokiaľ chceš skontrolovať, že dorazil, môžeš skočiť do **záložky Files** a pozrieť sa na svoj kód na PythonAnywhere. + +* Nakoniec skoč do [záložky Web][6] a stlač **Reload** na tvojej webovej aplikácii. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +Tvoj update by mal byť dokončený a funkčný! Obnov svoju stránku v prehliadači. Zmeny by mali byť viditeľné :) diff --git a/sk/html/images/step1.png b/sk/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/sk/html/images/step1.png differ diff --git a/sk/html/images/step3.png b/sk/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/sk/html/images/step3.png differ diff --git a/sk/html/images/step4.png b/sk/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/sk/html/images/step4.png differ diff --git a/sk/html/images/step6.png b/sk/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/sk/html/images/step6.png differ diff --git a/sk/images/application.png b/sk/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/sk/images/application.png differ diff --git a/sk/installation/README.md b/sk/installation/README.md new file mode 100755 index 00000000000..9a12e24590c --- /dev/null +++ b/sk/installation/README.md @@ -0,0 +1,49 @@ +# Pokiaľ robíš tutoriál doma + +Pokiaľ robíš tento tutoriál doma, nie na jednej z [Django Girls akcií](https://djangogirls.org/events/), môžeš úplne preskočiť túto kapitolu a pokračovať rovno s kapitolou [Ako funguje Internet](../how_the_internet_works/README.md). + +Je to preto, že tieto veci pokryjeme v celom tutoriále a toto je len dodatočná stránka, ktorá zjednocuje všetky inštalačné inštrukcie na jednom mieste. Django Girls akcie obsahujú "Inštalačné večery", kde nainštalujeme všetko, aby sme sa s tým nemuseli trápiť počas workshopu, takže táto stránka je pre nás užitočná. + +Pokiaľ ti táto kapitola príde užitočná, môžeš si ju celú prejsť. Ale pokiaľ sa chceš začať učiť veci predtým, ako si nainštalujete množstvo vecí na svoj počítač, preskoč túto kapitolu a my ti vysvetlíme inštalačnú časť neskôr. + +Veľa šťastia! + +# Inštalácia + +Počas workshopu budeš vytvárať blog a v tutoriále je pár nastavení, ktoré by bolo dobré prejsť predtým, aby si bola pripravení začať programovať. + +# Inštalácia Pythonu + +{% include "/python_installation/instructions.md" %} + +# Nastavenie virtualenv a inštalácia Django + +{% include "/django_installation/instructions.md" %} + +# Inštalácia editoru kódu + +{% include "/code_editor/instructions.md" %} + +# Inštalácia Gitu + +{% include "/deploy/install_git.md" %} + +# Vytvorenie GitHub účtu + +Choď na [GitHub.com](https://www.github.com) a založ (Sign Up) si nový účet zdarma. + +# Vytvor si PythonAnywhere účet + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Začni čítať + +Gratulujeme, si pripravená začať! Pokiaľ máš stále zvyšný čas pred začiatkom workshopu, bolo by užitočné, ak by si si prečítala pár začiatočníckych kapitol: + + * [Ako funguje Internet](../how_the_internet_works/README.md) + + * [Úvod do príkazového riadku](../intro_to_command_line/README.md) + + * [Úvod do jazyka Python](../intro_to_command_line/README.md) + + * [Čo je Django?](../django/README.md) \ No newline at end of file diff --git a/sk/intro_to_command_line/README.md b/sk/intro_to_command_line/README.md new file mode 100755 index 00000000000..704842c5210 --- /dev/null +++ b/sk/intro_to_command_line/README.md @@ -0,0 +1,306 @@ +# Úvod do rozhrania príkazového riadku + +Hm, je to vzrušujúce, však? Už o pár minút napíšeš svoj prvý riadok kódu :) + +**Dovoľ nám predstaviť ti tvojho nového priateľa: príkazový riadok!** + +Nasledujúce kroky ti ukážu ako používať tú čiernu obrzovku, čo používajú všetci hackeri. Zo začiatku môže vyzerať trochu desivo, ale je to naozaj len riadok, čo čaká na tvoje príkazy. + +> **Poznámka** Prosím všimni si, že v knižke používame výrazy 'adresár' aj 'zložka' zameniteľne, no ich význam je rovnaký. + +## Čo je to príkazový riadok? + +Okno, ktoré sa zvyčajne nazýva **príkazový riadok** alebo **rozhranie príkazového riadku** je textová aplikácia na prehliadanie, spracovanie a manipuláciu so súbormi v tvojom počítači. V podstate ako Prieskumník vo Windowse alebo Finder na Macu, akurát bez grafického rozhrania. Ďalšie názvy pre príkazový riadok môžu byť: *cmd*, *CLI*, *prompt*, *konzola* alebo *terminál*. + +## Otvor rozhranie príkazového riadku + +Aby sme mohli trochu experimentovať, musíme najskôr rozhranie príkazového riadku otvoriť. + +### Windows + +Choď na menu Štart → Všetky programy → Príslušenstvo → Príkazový riadok. + +### Mac OS X + +Aplikácie → Nástroje → Terminál. + +### Linux + +Pravdepodobne to nájdeš pod Aplikácie → Príslušenstvo → Terminál, ale to závisí na tvojom systéme. Ak to tam nie je, tak si to jednoducho vygoogli :) + +## Príkazový riadok + +Teraz by si už mala vidieť biele alebo čierne okno, ktoré čaká na tvoje príkazy. + +Ak si na Macu alebo Linuxe, zrejme uvidíš `$`, presne takto: + +``` +$ +``` + +Na Windowse to je znak `>`, takýto: + +``` +> +``` + +Každý príkaz budeš zadávať za tento znak a jednu medzeru. Ty to ale písať nemusíš, urobí to za teba tvoj počítač :) + +> Len malá poznámka: v tvojom prípade môže byť pred znakom $ niečo ako `C:\Users\ola>` alebo `Olas-MacBook-Air:~ ola$` a to je úplne v poriadku. V tomto tutoriale to ale zjednodušíme na úplné minimum. + +## Tvoj prvý príkaz (Hurá!) + +Začnime s niečím jednoduchým. Napíš tento príkaz: + +``` +$ whoami +``` + +alebo + +``` +> whoami +``` + +A stlač `enter`. Toto je výsledok: + +``` +$ whoami +olasitarska +``` + +Ako vidíš, počítač práve vypísal tvoje užívateľské meno. Milé, nie?:) + +> Skús každý príkaz napísať, nielen kopírovať. Viac si tak zapamätáš! + +## Základy + +Každý operačný systém má trochu iné príkazy pre príkazový riadok, takže postupuj podľa inštrukcií pre tvoj operačný systém. Tak čo, vyskúšame to? + +### Aktuálny adresár + +Bolo by fajn vedieť, kde sa nachádzame, však? Zistime to. Napíš tento príkaz a stlač `enter`: + +``` +$ pwd +/Users/olasitarska +``` + +Ak si vo Windowse: + +``` +> cd +C:\Users\olasitarska +``` + +Na svojom stroji pravdepodobne uvidíš niečo takéto. Keď otvoríš príkazový riadok, zvyčajne začneš vo svojom domovskom adresári. + +> Poznámka: 'pwd' je skratka pre 'print working directory'. + +* * * + +### Zoznam súborov a adresárov + +Tak čo je v ňom? Bolo by super zistiť to. Pozrime sa na to: + +``` +$ ls +Applications +Desktop +Downloads +Music +... +``` + +Windows: + +``` +> dir + Directory of C:\Users\olasitarska +05/08/2014 07:28 PM Applications +05/08/2014 07:28 PM Desktop +05/08/2014 07:28 PM Downloads +05/08/2014 07:28 PM Music +... +``` + +* * * + +### Zmena aktuálneho adresára + +Teraz prejdime do adresára Plochy: + +``` +$ cd Desktop +``` + +Windows: + +``` +> cd Desktop +``` + +Skontroluj, či sa adresár skutočne zmenil: + +``` +$ pwd +/Users/olasitarska/Desktop +``` + +Windows: + +``` +> cd +C:\Users\olasitarska\Desktop +``` + +A je to! + +> Profi tip: ak napíšeš `cd D` a potom stlačíš `tab`, príkazový riadok automaticky doplní zvyšok názvu, takže sa môžeš adresáre prechádzať rýchlejšie. Ak na "D" začína viac ako jeden adresár, stlač `tab` dvakrát a dostaneš zoznam možností. + +* * * + +### Vytvoriť adresár + +Čo takto vytvoriť pokusný adresár na ploche? Urobíš to takto: + +``` +$ mkdir pokus +``` + +Windows: + +``` +> mkdir practice +``` + +Tento príkazík vytvorí adresár s názvom `pokus` na tvojej ploche. Či je adresár naozaj tam môžeš zistiť jednoducho pohľadom na Plochu alebo spustením príkazu `ls` alebo `dir`! Vyskúšaj to :) + +> Profi tip: ak sa ti nechce vypisovať stále dookola tie isté príkazy, skús sa stlačením `šípky hore` a `šípky dole` vrátiť k nedávno použitým príkazom. + +* * * + +### Cvičenie! + +Malá výzva pre teba: v tvojom čerstvo vytvorenom adresári `pokus` vytvor adresár s názvom `test`. Použi príkazy `cd` a `mkdir`. + +#### Riešenie: + +``` +$ cd pokus +$ mkdir test +$ ls +test +``` + +Windows: + +``` +> cd pokus +> mkdir test +> dir +03/20/2016 11:05 AM test +``` + +Gratulujeme! :) + +* * * + +### Upratovanie + +Nechceme po sebe nechať neporiadok, takže odstránime všetko, čo sme doteraz vytvorili. + +Najkôr sa musíme vrátiť späť na Plochu: + +``` +$ cd .. +``` + +Windows: + +``` +> cd .. +``` + +Pomocou `..` s príkazom `cd` zmeníš svoj aktuálny adresár na rodičovský adresár (to je ten adresár, v ktorom sa nachádza tvoj aktuálny adresár). + +Skontroluj, kde sa nachádzaš: + +``` +$ pwd +/Users/olasitarska/Desktop +``` + +Windows: + +``` +> cd +C:\Users\olasitarska\Desktop +``` + +Je na čase zmazať adresár `pokus`: + +> **Pozor**: mazanie súborov pomocou `del` `rmdir` alebo `rm` je neodvolateľné, teda *odstránené súbory budú navždy preč*! Takže s týmito príkazmi buď opatrná. + +``` +$ rm -r pokus +``` + +Windows: + +``` +> rmdir /S pous +pokus, Are you sure ? Y +``` + +Hotovo! Uistime sa, či je to naozaj vymazané: + +``` +$ ls +``` + +Windows: + +``` +> dir +``` + +### Ukončenie + +Nateraz je to všetko! Môžeš pokojne zatvoriť príkazový riadok. Urobme to hackersky, dobre?:) + +``` +$ exit +``` + +Windows: + +``` +> exit +``` + +Super, čo?:) + +## Zhrnutie + +Tu je prehľad niektorých užitočných príkazov: + +| Príkaz (Windows) | Príkaz (Mac OS / Linux) | Popis | Príklad | +| ---------------- | ----------------------- | ------------------------------- | ------------------------------------------------- | +| exit | exit | zatvorí okno | **exit** | +| cd | cd | zmení adresár | **cd test** | +| dir | ls | vypíše zoznam adresárov/súborov | **dir** | +| copy | cp | kopíruje súbor | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | presunie súbor | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | vytvorí nový adresár | **mkdir testdirectory** | +| del | rm | odstráni adresár/súbor | **del c:\test\test.txt** | + +Toto je len veľmi malá časť príkazov, ktoré môžeš spustiť vo svojom príkazovom riadku, ale dnes budeš potrebovať len tieto. + +Ak ťa to zaujalo, na [ss64.com][1] nájdeš kompletný prehľad príkazov pre všetky operačné systémy. + + [1]: http://ss64.com + +## Pripravená? + +Vrhnime sa na Python! diff --git a/sk/python_installation/README.md b/sk/python_installation/README.md new file mode 100755 index 00000000000..ad2ee900d15 --- /dev/null +++ b/sk/python_installation/README.md @@ -0,0 +1,13 @@ +# Začnime s Pythonom + +Konečne sme tu! + +Na začiatok si povedzme, čo je Python. Python je veľmi obľúbený programovací jazyk, ktorý možno využiť na vytváranie webstránok, hier, vedeckých programov, grafiky a veľa, veľa ďalšieho. + +Python vznikol koncom 80-tych rokov minulého storočia a jeho hlavným cieľom bola čitateľnosť pre ľudí (nie len pre stroje!). To je dôvod, prečo vyzerá oveľa jednoduchšie ako iné programovacie jazyky. Vďaka tomu je ľahké sa ho naučiť, ale nebojte sa, Python je tiež naozaj výkonný! + +# Inštalácia Pythonu + +> **Poznámka** Ak si sa už cez kroky inštalácie prepracovala, nemusíš to robiť znova - môžeš preskočiť rovno na nasledujúcu kapitolu! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/sk/python_installation/images/add_python_to_windows_path.png b/sk/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/sk/python_installation/images/add_python_to_windows_path.png differ diff --git a/sk/python_installation/instructions.md b/sk/python_installation/instructions.md new file mode 100755 index 00000000000..a1565b278a6 --- /dev/null +++ b/sk/python_installation/instructions.md @@ -0,0 +1,72 @@ +> Táto časť je založená na príručke Geek Girls Carrots (http://django.carrots.pl/) + +Django je napísané v Pythone. Python potrebujeme na všetko, čo chceme robiť v Djangu. Začnime teda s inštaláciou! Chceme, aby si si nainštalovala Python 3.4, takže ak máš staršiu verziu, budeš ju musieť upgradovať. + +### Windows + +Python pre Windows si môžeš stiahnuť z webstránky https://www.python.org/downloads/release/python-343/. Po stiahnutí súboru ***.msi***, ho spusti (dvojklikom) a postupuj podľa inštrukcií. Je dôležité zapamätať si cestu (adresár), kde je nainštalovaný Python. Ešte to budeme potrebovať! + +Jedna vec, na ktorú si treba dať pozor: na druhej obrazovke sprievodcu inštaláciou, označenej ako "Prispôsobiť" (Customize), nezabudni prejsť dole a vybrať možnosť "Pridať python.exe do Cesty", takto: + +![Nezabudni pridať Python do Cesty](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Je veľmi pravdepodobné, že Python už máš predinštalovaný. Pre kontrolu, či je naozaj nainštalovaný (a ktorá verzia), spusti konzolu a napíš tento príkaz: + +``` +$ python3 -- version +Python 3.4.3 +``` + +Ak nemáš Python nainštalovaný, alebo ak chceš inú verziu, môžeš ho nainštalovať takto: + +#### Debian alebo Ubuntu + +Zadaj do konzoly tento príkaz: + +``` +$ sudo apt-get install python3.4 +``` + +#### Fedora (do verzie 21) + +Použi v konzole tento príkaz: + +``` +$ sudo yum install python3.4 +``` + +#### Fedora (od verzie 22) + +Použi v konzole tento príkaz: + +``` +$ sudo dnf instal python3.4 +``` + +#### openSUSE + +Použi v konzole tento príkaz: + +``` +$ sudo zypper install python3 +``` + +### OS X + +Inštalačný program Pythonu si môžeš stiahnuť zo stránky https://www.python.org/downloads/release/python-343/: + + * Stiahni si súbor s *Mac OS X 64/32-bitovým inštalátorom*, + * Dvojklikom na *python-3.4.3-macosx10.6.pkg* spusti inštalačný program. + +Ak si chceš overiť, že inštalácia bola úspešná, otvor aplikáciu *Terminal* a spusti príkaz `python3`: + +``` +$ python3 -- version +Python 3.4.3 +``` + +* * * + +V prípade nejakých pochybností, alebo ak sa niečo pokazilo a nemáš tušenie, čo robiť ďalej - opýtaj sa svojho trénera! Niekedy veci nejdú úplne hladko a je lepšie požiadať o pomoc niekoho, kto má viac skúseností. diff --git a/sk/python_introduction/README.md b/sk/python_introduction/README.md new file mode 100755 index 00000000000..08c93597f4b --- /dev/null +++ b/sk/python_introduction/README.md @@ -0,0 +1,846 @@ +# Úvod do jazyka Python + +> Časť tejto kapitoly je založená na tutoriáli Geek Girls Carrots (http://django.carrots.pl/). + +Poďme napísať nejaký kód! + +## Python prompt + +Aby sme mohli začať s Pythonom, musíte otvoriť *príkazový riadok* (angl. command line) na svojom počítači. Už by ste mali vedieť ako sa to robí -- naučili ste sa to v jednom z predchádzajúcich kapitol. + +Ak ste hotoví, pokračujte s inštrukciami nižšie. + +Chceme otvoriť Python konzolu, takže napíšte `python` na Windowse alebo `python3` na Mac alebo OS/Linux a stlačte `enter`. + +``` +$ python3 +Python 3.4.3 (...) +Type "help", "copyright", "credits" or "license" for more information. +>>> +``` + +## Váš prvý príkaz v Pythone! + +Po spustení príkazu Python sa prompt zmenil na `>>>`. Pre nás to znamená že odteraz by sme mali písať príkazy iba v jazyku Python. Nemusíte písať `>>>` - Python to urobí pre Vás. + +Ak by ste chceli kedykoľvek ukončiť konzolu Pythonu, len napíšte `exit()` alebo môžete použiť aj skratku `Ctrl + Z` vo Windowse alebo `Ctrl + D` pre Mac/Linux. Potom už nebudete vidieť toto: `>>>`. + +Ale teraz ešte vôbec nechceme ukončiť konzolu Python. Chceme sa o ňom naučiť viac. Začínajme s niečím jednoduchým. Napríklad skúste napísať nejaký matematický výraz, ako `2 + 3` a stlačte `enter`. + +``` +>>> 2 + 3 +5 +``` + +Super! Vidíte ako vyskočilo riešenie? Python vie počítať! Môžete skúsiť aj ďalšie príkazy, ako: - `4 * 5` - `5 - 1` - `40 / 2` + +Bavte sa s tým trošku, potom sa vráťte späť k nám :). + +Ako vidíte, Python je dobrá kalkulačka. A ak ste zvedaví, čo všetko vie ešte... + +## Reťazce + +Čo tak vaše meno? Napíšte svoje meno v úvodzovkách: + +``` +>>> "Ola" +"Ola" +``` + +Práve ste vytvorili svoj prvý reťazec! Je postupnosť znakov, ktoré môžu byť spracované počítačom. Reťazec musí vždy začínať a končíť s rovnakým znakom. Sú to jednoduché (`'`) alebo dvojité (`"`) úvodzovky (nie je medzi nimi žiadny rozdiel!). Úvodzovky naznačujú, že to čo je medzi nimi je reťazec (string). + +Reťazce možno spájať dohromady. Skús toto: + +``` +>>> "Ahoj" + "Ola" +'Ahoj Ola' +``` + +Reťazce môžete násobiť aj s číslom: + +``` +>>> "Ola" * 3 +'OlaOlaOla' +``` + +Ak potrebujete dať apostrof do vnútra reťazca, máte dva spôsoby, ako to urobiť. + +Použitím dvojitých úvodzoviek: + +``` +>>> "Runnin' down the hill" +"Runnin' down the hill" +``` + +alebo pomocou spätného lomítka - tento znak (ak je napísaný pred úvodzovkou) povie, že ona je súčasťou reťazca a nie koniec / začiatok reťazca (``): + +``` +>>> 'Runnin\' down the hill' +"Runnin' down the hill" +``` + +Pekné, hm? Ak chcete vidieť svoje meno veľkými písmenami, jednoducho zadajte: + +``` +>>> "Ola".upper() +'OLA' +``` + +Práve ste použili `upper` **funkciu** na svoj reťazec! Funkcia (ako `upper()`) je postupnosť inštrukcií, ktoré Python vykonáva na danom objekte (`"Ola"`), potom, čo ju zavoláte. + +Ak chcete poznať počet písmen, ktoré sú obsiahnuté vo vašom mene, tak na to má Python funkciu tiež! + +``` +>>> len("Ola") +3 +``` + +Ste zvedaví, prečo voláme niekedy funkciu s bodkou (`.`) na konci reťazca (ako `"Ola".upper()`) a niekedy najprv voláme funkciu a reťazec vložíme do zátvoriek? V niektorých prípadoch funkcie patria k objektom, ako napr. `upper()`, čo môže byt vykonaná len na reťazcoch. V takomto prípade sa tieto funkcie volajú **metódy**. Inokedy funkcie nepatria k žiadnemu konkrétnemu objektu a môžu byť použité na rôzne typy objektov, rovnako ako `len()`. Preto zadáme `"Ola"` ako parameter pre funkciu `len`. + +### Zhrnutie + +OK, dosť už reťazcoch. Zatiaľ ste sa naučili o: + +* **prompt** - píšeme príkazy (kód) do Python promptu, z čoho dostaneme výsledky zase v jazyku Python +* **čísla a reťazce** - v Pythone sú čísla použité pre počítanie a reťazce pre textové objekty +* **operátory** - ako + alebo *, z daných hodnôt vyrobia novú hodnotu (číslo či reťazec...) +* **funkcie** - napr. upper() alebo len(), vykonávajú činnosti na objektoch. + +Toto sú základy každého programovacieho jazyka. Ste pripravení na niečo ťažšie? Stavíme sa, že áno! + +## Chyby + +Teraz skúsme niečo nové. Je možné zistiť dĺžku nejakého čísla rovnako ako sme to robili s našim menom? Napíšte `len(304023)` a stlačte `enter`: + +``` +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +Dostali sme našu prvú chybovú hlášku! Hovorí nám, že objekty typu "int" (celé čísla, angl. integers) nemajú dĺžku. Tak čo môžeme teraz robiť? Možno by sme mohli napísať naše číslo ako reťazec? Reťazce majú dĺžku, pravda? + +``` +>>> len(str(304023)) +6 +``` + +Funguje to! Použili sme funkciu `str` vo vnútri funkcie `len`. Funkcia `str()` prevedie všetko na reťazce. + +* Funkcia `str` prevedie (konvertuje) všetko na **reťazce** (angl. string) +* Funkcia `int` prevedie všetko na **int** (celé čísla) + +> Dôležité: je možné konvertovať čísla na reťazce, ale opačne sa to nedá vždy - inak čo by bolo napr. `int('hello')`? + +## Premenné + +Veľmi dôležitý pojem v programovaní je pojem premennej. Premenná je nič iné ako názov niečoho, čo môžeme použiť aj neskoršie v programe. Programátori používajú premenné aby v nich ukladali dáta, aby ich zdrojový kód bol prehľadnejší a aby nemuseli všetko držať v hlave. + +Povedzme, že chceme vytvoriť novú premennú s názvom `meno`: + +``` +>>> name = "Ola" +``` + +Vidíte? Je to jednoduché: meno rovná sa Ola. + +Ako ste si to zbadali už, váš program nič nevrátil späť ako to robil v predchádzajúcich príkladoch. Tak ako vieme, či tá premenná existuje? Jednoducho napíšte `meno` a stlačte `enter`: + +``` +>>> name +'Ola' +``` + +Hurá! Vaša prvá premenná :)! Vždy je možné zmeniť jej obsah: + +``` +>>> name = "Sonja" +>>> name +'Sonja' +``` + +Môžete ju použiť aj vo funkciách: + +``` +>>> len(name) +5 +``` + +Úžasné, že? Samozrejme premenné môžu byť hocičo, takže aj čísla! Skúste toto: + +``` +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Ale čo by sa stalo, keby sme použili zlý názov? Uhádnete, čo sa stane? Skúsme! + +``` +>>> mesto = "Tokyo" +>>> mseto +Traceback (most recent call last): + File "", line 1, in +NameError: name 'mseto' is not defined +``` + +Chyba! Ako vidíte, Python má viacero chýb a táto jedna sa volá **NameError**. Python vám hodí túto chybu ak sa pokúsite použiť premennú ktorá ešte nebola definovaná. Ak sa stretnete s touto chybou v budúcnosti, vždy skontrolujte svoj kód, či nemáte preklep v niektorom názve. + +Bavte sa s tým trošku, a potom uvidíme čo môžeme ešte urobiť! + +## Funkcia print + +Vyskúšajte toto: + +``` +>>> meno = 'Maria' +>>> meno +'Maria' +>>> print(meno) +Maria +``` + +Ak zadáte len `meno`, Python interpreter odpovie reťazcovou *reprezentáciou* premennej 'meno', teda písmenami M-a-r-i-a medzi jednoduchými úvodzovkami, ''. Keď napíšete `print(meno)`, Python vypíše obsah premennej na obrazovku, bez úvodzoviek, čo vyzerá krajšie. + +Ako uvidíme neskôr, funkcia `print()` je tiež užitočná, keď chceme tlačiť veci z funkcií, alebo ak chceme tlačiť veci na viacerých riadkoch. + +## Zoznamy + +Okrem reťazcov a celých čísel, má Python všetky možné typy objektov. Teraz sa zoznámime s typom, ktorý sa volá **zoznam** (list). Zoznamy sú presne to, čo si myslíte, že sú: objekty, ktoré sú zoznamami iných objektov :) + +Poďme na to, vytvorte zoznam: + +``` +>>> [] +[] +``` + +Áno, tento zoznam je prázdny. Nie veľmi užitočné, však? Vytvorme zoznam s číslami lotérie. Nechceme sa dokola opakovať, takže ho hneď aj priradíme do premennej: + +``` +>>> loteria = [3, 42, 12, 19, 30, 59] +``` + +OK, máme zoznam! Čo s ním môžeme urobiť? Pozrime sa, koľko čísel lotérie máme v zozname. Máte predstavu, ktorú funkciu by sme mohli použiť? Toto už predsa viete! + +``` +>>> len(loteria) +6 +``` + +Áno! `len()` vám vráti počet objektov v zozname. Šikovné, nie? Možno by sme to teraz mohli usporiadať: + +``` +>>> loteria.sort() +``` + +Nič nám to nevrátilo, iba sa zmenilo poradie poradie, v ktorom sa čísla zobrazia v zozname. Vytlačme to znova a pozrime sa, čo sa stalo: + +``` +>>> print(loteria) +[3, 12, 19, 30, 42, 59] +``` + +Ako vidíte, čísla vo vašom zozname sú teraz zoradené od najnižšej po najvyššiu hodnotu. Gratulujeme! + +Chceli by sme otočiť poradie? Urobme to! + +``` +>>> loteria.reverse() +>>> print(loteria) +[59, 42, 30, 19, 12, 3] +``` + +Jednoduché, však? Ak chcete pridať niečo do svojho zoznamu, môžete tak urobiť zadaním tohto príkazu: + +``` +>>> loteria.append(199) +>>> print(loteria) +[59, 42, 30, 19, 12, 3, 199] +``` + +Ak chcete zobraziť iba prvé číslo, môžete to urobiť pomocou **indexov**. Index je číslo, ktoré hovorí, kde v zozname sa položka nachádza. Programátori radi počítajú od nuly, takž eprvý objekt vo vašom zozname je na indexe 0, ďalší je na 1 a tak ďalej. Vyskúšajte toto: + +``` +>>> print(loteria[0]) +59 +>>> print(loteria[1]) +42 +``` + +Ako vidíte, k rôznym objektom vo vašom zozname môžete pristupovať použitím názvu zoznamu a indexom objektu v hranatých zátvorkách. + +Aby ste odstránili niečo zo svojho zoznamu, budete potrebovať **indexy**, ako sme sa dozvedeli vyššie a príkaz **del** (del je skratka pre odstránenie, angl. delete). Vyskúšajme to na príklade a zopakujme si, čo sme sa už naučili; zmažeme prvé číslo v našom zozname. + +``` +>>> print(loteria) +[59, 42, 30, 19, 12, 3, 199] +>>> print(loteria[0]) +59 +>>> del loteria[0] +>>> print(loteria) +[42, 30, 19, 12, 3, 199] +``` + +Funguje to ako hodinky! + +Pre zábavu vyskúšajte aj nejaké iné indexy: 6, 7, 1000, -1, -6 alebo -1000. Skúste predpovedať výsledok predtým ako príkaz použijete. Dávajú výsledky zmysel? + +Zoznam všetkých dostupných metód pre zoznamy v tejto kapitole dokumentácie Pythonu: https://docs.python.org/3/tutorial/datastructures.html + +## Slovníky + +Slovník je podobný ako zoznam, ale k jeho hodnotám pristupujete vyhľadaním kľúča namiesto indexu. Kľúč môže byť akýkoľvek reťazec alebo číslo. Syntax na definovanie prázdneho slovníka je: + +``` +>>> {} +{} +``` + +To znamená, že ste práve vytvorili prázdny slovník. Hurá! + +Teraz skúste napísať nasledujúci príkaz (skúste ale nahradiť hodnoty vlastnými údajmi): + +``` +>>> ucastnicka = {'meno': 'Ola', 'krajina': 'Slovensko', 'oblubene_cisla': [7, 42, 92]} +``` + +Týmto príkazom ste práve vytvorili premennú s názvom `ucastnicka` s tromi pármi kľúč-hodnota: + +* Kľúč `meno` odkazuje na hodnotu `"Ola"` (objekt typu `reťazec/string`), +* `krajina` odkazuje na `"Slovensko"` (ďalší `reťazec`), +* a `oblubene_cisla` smeruje na `[7, 42, 92]` (`zoznam` s tromi číslami). + +Obsah jednotlivých kľúčov môžete skontrolovať touto syntaxou: + +``` +>>> print(ucastnicka['meno']) +Ola +``` + +Ako vidíte, podobá sa to na zoznam. Ale nemusíte si pamätať index - stačí meno. + +Čo sa stane ak si od Pythonu vypýtame hodnotu kľúča, ktorý neexistuje? Uhádnete? Vyskúšajme to a uvidíme! + +``` +>>> ucastnicka['vek'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'vek' +``` + +Aha, ďalšia chyba! Táto sa volá **KeyError** (chyba kľúča). Python je nápomocný a povie vám, že kľúč `'vek'` v tomto slovníku neexistuje. + +Kedy by používať slovník alebo zoznam? No, to je dobrá otázka. Porozmýšľaj predtým, ako si pozrieš odpoveď v nasledujúcom riadku. + +* Potrebuješ zoradenú postupnosť položiek? Vyber si zoznam (list). +* Potrebuješ priraďovať hodnoty kľúčovým slovám, aby si si ich mohla efektívne (podľa kľúča) neskôr vyhľadať? Použi slovník (dictionary). + +Slovníky, rovnako ako zoznamy sú *premenlivé*, čo znamená, že ich môžeme zmeniť po ich vytvorení. Po vytvorení môžeš do slovníka pridať nové dvojice kľúč/hodnota takto: + +``` +>>> ucastnicka['oblubeny_jazyk'] = 'Python' +``` + +Tak ako pri zoznamoch, použitím metódy `len()` na slovníkoch dostaneš počet párov kľúč-hodnota v slovníku. Poďme na to, zadaj tento príkaz: + +``` +>>> len(ucastnicka) +4 +``` + +Dúfam, že to dáva zmysel. :) Pripravená na trochu zábavy so slovníkmi? Tak šup na ďalší riadok za úžasnými vecami. + +Na odstránenie položky zo slovníka môžeš použiť príkaz `del`. Napríklad ak chceš odstrániť položku zodpovedajúcu kľúču `'oblubene_cisla'`, zadaj nasledujúci príkaz: + +``` +>>> del ucastnicka['oblubene_cisla'] +>>> ucastnicka +{'krajina': 'Slovensko', 'oblubeny_jazyk': 'Python', 'meno': 'Ola'} +``` + +Ako vidíš z výstupu, pár kľúč-hodnota zodpovedajúci kľúču 'oblubene_cisla' bol vymazaný. + +Taktiež môžeš zmeniť hodnotu priradenú k už vytvorenému kľúču v slovníku. Napíš: + +``` +>>> ucastnicka['krajina'] = 'Nemecko' +>>> ucastnicka +{'krajina': 'Nemecko', 'oblubeny_jazyk': 'Python', 'meno': 'Ola'} +``` + +Ako vidíš, hodnota kľúča `"krajina"` sa zmenila z `"Poľsko"` na `"Nemecko"`. :) Vzrušujúce? Hurá! Práve si sa naučila ďalšiu úžasnú vec. + +### Zhrnutie + +Skvelé! Teraz už vieš o programovaní dosť veľa. Pozrime sa, čo sme si vysvetlili v poslednej časti: + +* **chyby** (angl. error) - teraz už vieš ako čítať a rozumieť chybám, ktoré sa zobrazia, ak Python nerozumie príkazu, ktorý mu zadáš +* **premenné** - názvy objektov, ktoré ti uľahčujú písanie kódu a robia tiež kód zrozumiteľnejším +* **zoznamy** (angl. list) - zoznam objektov uložených v určitom poradí +* **slovníky** (angl. dictionary) - objekty uložené v pároch kľúč-hodnota + +Tešíš sa na ďalšiu časť? :) + +## Porovnávanie vecí + +Veľkú časť programovania predstavuje porovnávanie veci. Čo je najjednoduchšia vec na porovnanie? Čísla, samozrejme. Pozrime sa, ako to funguje: + +``` +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` + +Dali sme Pythonu pár čísiel na porovnanie. Ako vidíš, Python vie porovnávať nielen čísla, ale vie porovnávať aj výsledky metód. Pekné, nie? + +Zaujíma ťa, prečo sme použili dve "rovná sa" `==` vedľa seba, aby sme porovnali, či sú čísla rovnaké? Jeden znak `=` používame na priraďovanie hodnôt premenným. Takže, ak chceš skontrolovať, či sú veci rovnaké, musíš vždy, úplne **vždy** použiť dve `==`. Taktiež môžeme zisťovať, či sa veci navzájom líšia. Na to použijeme symbol `!=`, ako bolo uvedené v príklade vyššie. + +Zadaj Pythonu ešte dve úlohy: + +``` +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +`>` a `<` sú jasné, ale čo znamenajú `>=` a `<=`? Prečítať ich môžeš takto: + +* x `>` y znamená: x je väčšie ako y +* x `<` y znamená: x je menšie ako y +* x `<=` y znamená: x je menšie alebo sa rovná y +* x `> =` y znamená: x je väčšie alebo sa rovná y + +Skvelé! Chceš vyskúšať ešte jeden? Skús toto: + +``` +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` + +Môžeš dať Pythonu toľko čísel, koľko chceš a on ti dá vždy odpoveď! Vcelku šikovné, nie? + +* **and** - ak použiješ operátor `and`, obidve porovnávané veci musia byť pravdivé (True), aby príkaz bol pravda (True) +* **or** - ak použiješ operátor `or`, stačí aby jedna z porovnávaných vecí bola pravdivá, aby bol celý príkaz pravda (True) + +Už ste počula výraz "porovnávať hrušky s jablkami"? Skúsme pythonský ekvivalent: + +``` +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: unorderable types: int() > str() +``` + +Tu vidíš, že tak ako nevieme porovnávať hrušky s jablkami, ani Python neviem porovnať číslo (`int`) s reťazcom (`str`). Namiesto toho vypíše chybu **TypeError** a povie nám, ktoré dva typy sa nedajú porovnať. + +## Logické hodnoty (Boolean) + +Práve si spoznala nový typ objektov v Pythone. Volá sa **logická hodnota** (po anglicky im hovoríme Boolean), pravdepodobne najjednoduchší typ, ktorý existuje. + +Existujú iba dva typy Booleovských objektov: - True (Pravda) - False (Nepravda) + +Aby ich Python spoznal, musíš vždy napísať 'True' (s veľkým písmenom na začiatku a zvyšok malým písmom). **true, TRUE, tRUE nebudú fungovať -- iba True je správne.** (Samozrejme, to isté platí aj pre 'False'.) + +Logické hodnoty môžu byť aj premenné. Aha: + +``` +>>> a = True +>>> a +True +``` + +Môžeš to urobiť aj takto: + +``` +>>> a = 2 > 5 +>>> a +False +``` + +Precvič si to a zabav sa s logickými premennými - skús spustiť tieto príkazy: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Gratulujeme! Logické hodnoty patria k tomu najužitočnejšiemu z programovania a ty si sa práve naučila, ako sa používajú! + +# Ulož to! + +Zatiaľ sme písali všetok pythonský kód do konzoly interpretera, čiže môžeme na jedenkrát zadať iba jeden riadok kódu. Normálne programy sú uložené v súboroch, ktoré spúšťa buď **interpreter** alebo **kompilátor**. Doteraz sme spúšťali naše programy riadok po riadku v **interpreteri** Pythonu. Na ďalšie úlohy budeme potrebovať viac ako jeden riadok kódu, takže teraz rýchlo musíme: + +* Ukončiť interpreter Pythonu +* Otvoriť si zvolený editor kódu +* Uložiť v ňom nejaký kód do nového pythonského súboru +* Spustiť ho! + +Pre opustenie interpretera Pythonu, ktorý sme doteraz používali, zadaj jednoducho funkciu ~~~ exit()~~~: + +``` +>>> exit() +$ +``` + +Tak sa dostaneš späť na príkazový riadok. + +Už skôr si si vybrala editor kódu v kapitole [editor kódu][1]. Teraz ho potrebujeme otvoriť a napísať v ňom do nového súboru nejaký kód: + + [1]: ../code_editor/README.md + +```python +print('Hello, Django girls!') +``` + +> **Poznámka** Všimni si jednu z najúžasnejších vecí editorov kódu: farby! V pythonskej konzole bolo všetko napísané jednou farbou, teraz však vidíš, že funkcia `print` je napísaná inou farbou ako reťazec. Toto sa nazýva "zvýraznenie syntaxe" a pri programovaní je to fakt užitočná vec. Farba výrazov ti môže pomôcť, ak máš neuzavretý reťazec či preklep v názve špeciálnych slov (ako napríklad `def` vo funkcii, ktorú uvidíme neskôr). Toto je jedným z dôvodov, prečo používame editor kódu :) + +Samozrejme, teraz si už vcelku skúsená Python developerka, takže kľudne napíš nejaký kód, ktorý si sa dnes naučila. + +Teraz uložíme súbor a dáme mu nejaký zrozumiteľný názov. Nazvime ho **python_intro.py** a ulož ho plochu. Tento súbor môžeš nazvať akokoľvek chceš, ale dôležité je, aby jeho názov končil **.py**. Prípona **.py** nášmu operačnému systému hovorí, že je to **súbor spustiteľný Pythonom** a môže ho spustiť Pythonom. + +Súbor máme uložený, je čas ho spustiť! Pomocou poznatkov z kapitoly o príkazovom riadku, pomocou Terminálu **zmeň adresár** na plochu. + +Na Macu bude príkaz vyzerať takto: + +``` +$ cd /Users//Desktop +``` + +Na Linuxe to bude takto (slovo "Desktop" bude možno preložené): + +``` +$ cd /home//Desktop +``` + +A vo Windowse bude príkaz vyzerať takto: + +``` +> cd C:\Users\\Desktop +``` + +Ak máš akékoľvek ťažkosti, stačí požiadať o pomoc. + +Teraz použi Python na spustenie kódu v súbore: + +``` +$ python3 python_intro.py +Hello, Django girls! +``` + +Výborne! Práve si spustila svoj prvý pythonský program uložený v súbore. Skvelý pocit, však? + +Teraz sa môžeš posunúť na ďalší základný nástroj v programovaní: + +## If...elif...else + +Kopec vecí v kóde sa má spúšťať len ak sú splnené nejaké podmienky. Práve na to používa Python príkaz **if**. + +Nahraď kód v súbore **python_intro.py** týmto: + +```python +if 3 > 2: +``` + +Ak to uložíš a spustíš, dostaneš túto chybu: + +``` +$ python3 python_intro.py +File "python_intro.py", line 2 + ^ +SyntaxError: unexpected EOF while parsing +``` + +Python očakáva, že od nás dostane ďalšie inštrukcie, ktoré majú byť vykonané ak je podmienka `3 > 2` pravdivá (teda ak bude mať hodnotu `True`). Skúsme zariadiť, aby Python napísal "Funguje to!". Zmeň svoj kód v súbore **python_intro.py** takto: + +```python +if 3 > 2: + print('Funguje to!') +``` + +Všimla si si, ako sme odsadili druhý riadok o 4 medzery? To musíme urobiť preto, aby Python vedel, ktorú časť kódu má spustiť ak je výsledok pravdivý. Môžeš použiť len jednu medzeru, ale takmer všetci programátori v Pythone používajú 4 medzery, aby bol kód dobre čitateľný. Jeden `tab` sa tiež počíta ako 4 medzery. + +Ulož to a spusti to znova: + +``` +$ python3 python_intro.py +Funguje to! +``` + +### Čo ak podmienka nie je pravdivá? + +V predchádzajúcich príkladoch, bol kód vykonaný len vtedy, keď podmienky boli pravdivé. Ale Python má tiež príkazy `elif` a `else`: + +```python +if 5 > 2: + print('5 je naozaj viac ako 2') +else: + print('5 nie je viac ako 2') +``` + +Keď to spustíš, vypíše to: + +``` +$ python3 python_intro.py +5 je naozaj viac ako 2 +``` + +Ak by 2 bolo väčšie ako 5, spustil by sa druhý príkaz. Jednoduché, nie? Pozrime sa, ako funguje `elif`: + +```python +name = 'Sonja' +if name == 'Ola': + print('Ahoj Ola!') +elif name == 'Sonja': + print('Ahoj Sonja!') +else: + print('Ahoj neznama!') +``` + +a po spustení: + +``` +$ python3 python_intro.py +Ahoj Sonja! +``` + +Všimla si si, čo sa stalo? `elif` ti dovolí pridať dodatočné podmienky, ktoré sa spustia, ak sú predchádzajúce nesplnené. + +Za prvý `if` môžeš dať `elif` toľkokrát, koľko len chceš. Napríklad: + +```python +hlasitost = 57 +if hlasitost < 20: + print("Vcelku ticho.") +elif 20 <= hlasitost < 40: + print("Fajn na hudbu v pozadi") +elif 40 <= hlasitost < 60: + print("Super, pocujem vsetky detaily") +elif 60 <= hlasitost < 80: + print("Vyborne na party") +elif 80 <= hlasitost < 100: + print("Trochu hlucne!") +else: + print("Bolia ma usi! :(") +``` + +Python prejde všetkými podmienkami v poradí a vypíše: + +``` +$ python3 python_intro.py +Super, pocujem vsetky detaily +``` + +### Zhrnutie + +V posledných troch cvičeniach si sa naučila: + +* **porovnávať veci** - v Pythone môžeš porovnávať veci pomocou znamienok `>`, `>=`, `==`, `<=`, `<` a operátorov `and`, `or` +* **Booleovské/logické premenné** - typ objektu, ktorý môže mať len jednu z dvoch hodnôt: `True` (pravda) alebo `False` (nepravda) +* **Ukladať súbory** - ukladanie kódu v súboroch, takže môžete spúšťať väčšie programy. +* **Ak... elif... inde** - príkazy, ktoré ti umožňujú spustiť kód, iba ak sú splnené určité podmienky. + +Teraz je čas na poslednú časť tejto kapitoly! + +## Tvoje vlastné funkcie! + +Pamätáš si funkcie ako napríklad `len()`, ktoré môžeš v Pythone spúšťať? Máme pre teba dobrú správu - teraz sa naučíš ako napísať vlastnú funkciu! + +Funkcia je postupnosť inštrukcií, ktoré by mal Python spustiť. Každá funkcia v Pythone začína kľúčovým slovom `def`, má svoje meno a môže mať nejaké parametre. Začnime s niečím ľahkým. Nahraď kód v **python_intro.py** týmto: + +```python +def hi(): + print('Ahoj!') + print('Ako sa mas?') + +hi() +``` + +OK, naša prvá funkcia je pripravená! + +Možno sa čuduješ prečo sme na koniec súboru napísali názov funkcie. To preto, lebo Python číta súbor a vykonáva kód od vrchu po spodok. Takže aby sme mohli našu funkciu použiť, musíme jej názov napísať opäť. + +Spusťme to a pozrime sa, čo sa stane: + +``` +$ python3 python_intro.py +Ahoj! +Ako sa mas? +``` + +To bolo ľahké! Poďme vytvoriť našu prvú funkciu s parametrami. Použijeme predchádzajúci príklad - funkcia, ktorá hovorí "ahoj" osobe, ktorá ju spustí - s menom: + +```python +def hi(meno): +``` + +Ako vidíš, dali sme našej funkcii parameter, ktorý sme nazvali `meno`: + +```python +def hi(meno): + if meno == 'Ola': + print('Ahoj Ola!') + elif meno == 'Sonja': + print('Ahoj Sonja!') + else: + print('Ahoj neznama!') + +hi() +``` + +Zapamätaj si: Funkcia `print` je odsadená o 4 medzery vo vnútri príkazu `if`. Je to preto, lebo funkcia sa spustí, len ak je splnená podmienka. Pozrime sa ako to funguje: + +``` +$ python3 python_intro.py +Traceback (most recent call last): +File "python_intro.py", line 10, in + hi() +TypeError: hi() missing 1 required positional argument: 'meno' +``` + +Ups, chyba. Našťastie Python nám dáva vcelku užitočnú chybovú hlášku. Hovorí nám, že funkcia `hi()` (tá, čo sme definovali) má jeden povinný argument (s názvom `meno`) a že sme mu ju zabudli zadať pri volaní funkcie. Opravme to na konci súboru: + +```python +hi("Ola") +``` + +A znova ho spusti: + +``` +$ python3 python_intro.py +Ahoj Ola! +``` + +A čo ak zmeníme meno? + +```python +hi("Sonja") +``` + +A spustíme to: + +``` +$ python3 python_intro.py +Ahoj Sonja! +``` + +No a čo si myslíš, čo sa stane, ak tam napíšeš iné meno? (Nie Ola ani Sonja.) Vyskúšaj to a uvidíš, či bol tvoj predpoklad správny. Malo by ti vypísať toto: + +``` +Ahoj neznáma! +``` + +Úžasné, nie? Vďaka tomu nemusíš prepisovať dokola to isté zakaždým, keď chceš zmeniť meno osoby, ktorú má funkcia pozdraviť. A to je presne dôvod, prečo potrebujeme funkcie - aby sme nemuseli opakovať svoj kód! + +Urobme to teda trochu rozumnejšie - existujú viac ako dve mená a písať podmienku pre každé by bolo trochu náročné, však? + +```python +def hi(meno): + print('Ahoj ' + meno + '!') + +hi("Katka") +``` + +Teraz spusťme kód: + +``` +$ python3 python_intro.py +Ahoj Katka! +``` + +Gratulujeme! Práve si sa naučila ako sa píšu funkcie! :) + +## Cykly + +Toto je už posledná časť. Išlo to rýchlo, však? :) + +Programátori sa neradi opakujú. Programovanie je o automatizácii vecí, takže nechceme zdraviť každú osobu manuálne, nie? A vtedy nám prídu vhod cykly. + +Ešte si spomínaš na zoznamy? Pripravme zoznam dievčat: + +```python +dievcata = ['Katka', 'Monika', 'Zuzka', 'Ola', 'Ty'] +``` + +Chceme ich pozdraviť všetky menom. Na to máme funkciu `hi`, tak ju použime v cykle: + +```python +for meno in dievcata: +``` + +Príkaz ~~~ for ~~~ sa správa podobne ako príkaz ~~~ if ~~~ ; kód pod oboma z nich musí byť odsadený o štyri medzery. + +Tu je plný kód, ktorý napíšeme do súboru: + +```python +def hi(meno): + print('Ahoj ' + meno + '!') + +dievcata = ['Katka', 'Monika', 'Zuzka', 'Ola', 'Ty'] +for meno in dievcata: + hi(meno) + print('Dalsie dievca') +``` + +A keď to spustíme: + +``` +$ python3 python_intro.py +Ahoj Katka! +Dalsie dievca +Ahoj Monika! +Dalsie dievca +Ahoj Zuzka! +Dalsie dievca +Ahoj Ola! +Dalsie dievca +Ahoj Ty! +Dalsie dievca +``` + +Ako vidíš, všetko, čo dáš do príkazu `for` s oddsadením sa bude opakovať pre každý prvok zoznamu `dievcata`. + +`for` môžeš pomocou funkcie `range` použiť aj na čísla: + +```python +for i in range(1, 6): + print(i) +``` + +Čo vypíše: + +``` +1 +2 +3 +4 +5 +``` + +`range` je funkcia, ktorá vytvára zoznam čísel s postupnosťou čísel (krajné čísla funkcii poskytneš ako parametre). + +Všimni si, že druhé číslo sa nenachádza vo výstupnom zozname (teda `range(1, 6)` počíta od 1 po 5, ale neobsahuje číslo 6). To je preto, lebo "range" je jednostranne otvorený, čo znamená, že obsahuje prvú hodnotu, ale nie poslednú. + +## Zhrnutie + +To je všetko. **Si úplne geniálna!** Toto bola náročná kapitola, takže by si mala byť na seba pyšná. My sme rozhodne hrdí na teba, že si to zvládla až potiaľto! + +Teraz možno krátko rob niečo iné - natiahni sa trochu, poprechádzaj sa, nechaj svoje oči oddýchnuť si - a potom prejdeme na ďalšiu kapitolu. :) + +![Koláčik][2] + + [2]: images/cupcake.png diff --git a/sk/python_introduction/images/cupcake.png b/sk/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/sk/python_introduction/images/cupcake.png differ diff --git a/sk/template_extending/README.md b/sk/template_extending/README.md new file mode 100755 index 00000000000..192d0c710d6 --- /dev/null +++ b/sk/template_extending/README.md @@ -0,0 +1,124 @@ +# Rozširovanie šablón + +Ďalšou milou vecou, ktorú ti Django ponúka je **rozširovanie šablón**. Znamená to, že môžeš použiť rovnaké časti HTML kódu na rôznych stránkach svojho webu. + +Vďaka tomu nemusíš všetko opakovať v každom súbore, ak chceš použiť rovnakú informáciu alebo layout. A ak chceš niečo zmeniť, nemusíš to robiť v každej šablóne zvlášť, ale iba raz! + +## Vytvorenie základnej šablóny + +Základná šablóna je jednoducho šablóna, ktorú rozširuješ na každej stránke svojej web stránky. + +Vytvorme súbor `base.html` v `blog/templates/blog/`: + +``` +blog +└───templates + └───blog + base.html + post_list.html +``` + +Otvor ho a skopíruj doň všetko z `post_list.html` do súboru `base.html`: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Potom v `base.html` nahraď celé `` (všetko medzi `` a ``) týmto: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +V podstate sme nahradili všetko medzi `{% for post in posts %}{% endfor %}` týmto: + +```html +{% block content %} +{% endblock %} +``` + +Čo to znamená? Práve si vytvorila `block` (blok), čo je vlastne šablóna tagov, ktorá ti umožní vkladať HTML v tomto bloku do ďalších šablón, ktoré rozširujú `base.html`. Hneď ti ukážeme, ako sa to robí. + +Teraz to ulož a znova otvor `blog/templates/blog/post_list.html`. Zmaž všetko, okrem toho, čo je vnútri body a tiež zmaž ``, takže súbor bude vyzerať takto: + +```html +{% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+{% endfor %} +``` + +A teraz pridaj tento riadok na začiatok súboru: + +```html +{% extends 'blog/base.html' %} +``` + +{% raw %}To znamená, že rozširujeme šablónu `base.html` v `post_list.html`. Už ostáva len jedna vec: daj všetko (teda okrem riadku, ktorý sme práve pridali) medzi `{% block content %}` a `{% endblock content %}`. Takto:{% endraw %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +A je to! Skontroluj či tvoja web stránka funguje tak, ako má :) + +> Ak sa ti zobrazí chyba `TemplateDoesNotExists`, ktorá hovorí, že súbor `blog/base.html` neexistuje a v konzole ti beží `runserver`, skús ho zastaviť (stlačením Ctrl + C) a reštartuj ho spustením príkazu `python manage.py runserver`. diff --git a/sk/whats_next/README.md b/sk/whats_next/README.md new file mode 100755 index 00000000000..d6bd138cb37 --- /dev/null +++ b/sk/whats_next/README.md @@ -0,0 +1,40 @@ +# Čo ďalej? + +Môžeš si zablahoželať! **Si úplne úžasná**. Sme hrdí! <3 + +### Čo robiť teraz? + +Daj si pauzu a oddýchni si. Práve si urobila niečo ohromné. + +Potom nezabudni: + +* Sledovať Django Girls na [Facebooku][1] alebo [Twitteri][2] a zostať informovaná + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Viete odporučiť ďalšie zdroje? + +Áno! Ako prvé, neváhaj a vyskúšaj našu ďalšiu knihu [Django Girls Tutorial: Rozšírenie][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Neskôr môžeš skúsiť zdroje uvedené nižšie. Všetky veľmi odporúčame! + +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: http://django.carrots.pl/en/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 diff --git a/styles/website.css b/styles/website.css new file mode 100644 index 00000000000..e53ebbd161b --- /dev/null +++ b/styles/website.css @@ -0,0 +1,14 @@ +.book-langs-index .inner { + max-width: 800px; +} + +.book-langs-index .inner h3 { + text-align: center; + font-size: 30px; + font-family: "Trebuchet MS", Helvetica, sans-serif; +} +.book-langs-index .inner .languages li { + font-size: 24px; + font-family: "Trebuchet MS", Helvetica, sans-serif; + letter-spacing: 0; /* Fix for emoji flags */ +} diff --git a/tr/GLOSSARY.md b/tr/GLOSSARY.md new file mode 100755 index 00000000000..1e503fa6881 --- /dev/null +++ b/tr/GLOSSARY.md @@ -0,0 +1,3 @@ +# kod editörü + +Kod editörü, kodunuza sonradan geri dönebilmeniz için kodu kaydeden bir uygulamadır. Nereden edinebileceğinizi [Kod editörü bölümü](./code_editor/README.md)nde bulabilirsiniz \ No newline at end of file diff --git a/tr/README.md b/tr/README.md new file mode 100755 index 00000000000..442cec63ceb --- /dev/null +++ b/tr/README.md @@ -0,0 +1,53 @@ +# Django Girls Eğitimi + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Bu çalışma Creative Commons Attribution-ShareAlike 4.0 International License altında lisanslanmıştır. Lisansın bir kopyasını görmek için https://creativecommons.org/licenses/by-sa/4.0/ adresini ziyaret edin. + +## Çeviri + +Bu döküman İngilizce'den Türkçe'ye 28 kişiden oluşan tamamen gönüllü bir ekip tarafından çevrildi: Elif Kuş, Şirin Saygılı, Suzan Üsküdarlı, Oğuzcan Küçükbayrak, Mehmet Ragıp Altuncu, Şahin B., Kıvanç Yazan, Adil Öztaşer, olasitarska, Oğuz Erdoğmuş, ophelia, Tuğçe Şirin, Fazilet Çilli, Özge Barbaros, Evin Pınar Örnek, Yiğit Bekir Baya, Berna Erden, Akın Toksan, Çağıl, Berat Doğan, Taha Yusuf, Helin Ece Akgül, Müge Kurtipek, Nezihe Pehlivan, Can Güler, Wert Yuio, Barış Arda Yılmaz ve Aybüke Özdemir! Emeği geçen herkese sonsuz teşekkürler! Ellerinize sağlık! + +## Giriş + +Hiç dünyanın her geçen gün daha teknolojik olduğunu ve bir şekilde geride kaldığınızı hissettiniz mi? Hiç web sayfalarının nasıl yapıldığını merak edip başlamak için gereken motivasyona sahip olmadığınız oldu mu? Yazılım dünyasının sizin için, kendi başınıza bir şeyler yapmayı denemek için bile, çok karmaşık olduğunu düşündünüz mü? + +Öyleyse, sizin için iyi haberlerimiz var! Programlama göründüğü kadar zor değil ve size ne kadar keyifli olabileceğini göstermek istiyoruz. + +Bu eğitim sihirli bir şekilde sizi bir programcıya dönüştürmeyecek. Eğer bu konuda iyi olmak istiyorsanız, aylara ve hatta yıllara dayanan bir öğrenme ve pratiğe ihtiyacınız var. Fakat biz size programlamanın ya da websayfası oluşturmanın göründüğü kadar da karmaşık olmadığını göstermek istiyoruz. Farklı parçaları, değişik kısımları anlatabildiğimiz kadar iyi anlatmaya gayret edeceğiz ki artık teknoloji gözünüzü korkutmasın. + +Ümit ederiz ki sizin de teknolojiyi bizim kadar sevmenizi sağlayabiliriz! + +## Bu eğitim ile ne öğreneceksiniz? + +Eğitimi bitirdiğinizde, basit fakat çalışan bir web uygulamasına sahip olacaksınız: kendi blog uygulamanız. Size blogunuzu nasıl online hale getireceğinizi de göstereceğiz ki başkaları da çalışmanızı görebilsin! + +Aşağı yukarı şu şekilde gözükecek: + +![Şekil 0.1][2] + + [2]: images/application.png + +> Eğer eğitimi kendi başınıza takip ediyorsanız ve bir problem yaşadığınızda yardım edebilecek bir eğitmeniniz yoksa, sizin için bir chat odamız var:[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +Daha önce katılmış olan kişilerden ve eğitmenlerimizden zaman zaman chat odasında bulunmalarını ve eğitimi takip eden kişilere yardımcı olmalarını istedik! Chat odasında sorularınızı sormaktan çekinmeyin! + +Tamam, [hadi en baştan başlayalım...][3] + + [3]: ./how_the_internet_works/README.md + +## Hakkında ve katkıda bulunma + +Bu eğitim [DjangoGirls][4] tarafından sürdürülmektedir. Eğer hatalar bulursanız ve eğitimi güncellemek isterseniz lütfen [katkıda bulunma kılavuzunu takip edin][5]. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md + +## Bu eğitimi başka dillere çevirmemize yardımcı olmak ister misiniz? + +Hali hazırda, çeviriler crowdin.com platformunda tutuluyor: + +https://crowdin.com/project/django-girls-tutorial + +Eğer diliniz crowdin'de listelenmemiş ise, lütfen GitHub'da dilinizle alakalı bilgi veren bir [konu açın][6] böylece dilinizi ekleyebilelim. + + [6]: https://github.com/DjangoGirls/tutorial/issues/new \ No newline at end of file diff --git a/tr/SUMMARY.md b/tr/SUMMARY.md new file mode 100755 index 00000000000..612133adbb6 --- /dev/null +++ b/tr/SUMMARY.md @@ -0,0 +1,26 @@ +# Özet + +* [Giriş](README.md) +* [Kurulum](installation/README.md) +* [İnternet nasıl çalışır](how_the_internet_works/README.md) +* [Komut satırına giriş](intro_to_command_line/README.md) +* [Python kurulumu](python_installation/README.md) +* [Kod editörü](code_editor/README.md) +* [Python'a giriş](python_introduction/README.md) +* [Django nedir?](django/README.md) +* [Django kurulumu](django_installation/README.md) +* [İlk Django projen!](django_start_project/README.md) +* [Django modelleri](django_models/README.md) +* [Django admin](django_admin/README.md) +* [Yayına alın!](deploy/README.md) +* [Django url'leri](django_urls/README.md) +* [Django views - yaratma zamanı geldi!](django_views/README.md) +* [HTML'ye giriş](html/README.md) +* [Django ORM ve QuerySets (Sorgu Setleri)](django_orm/README.md) +* [Template içerisinde dinamik veri](dynamic_data_in_templates/README.md) +* [Django template](django_templates/README.md) +* [CSS - sayfanı güzelleştir](css/README.md) +* [Template genişletmek](template_extending/README.md) +* [Uygulamanı genişlet](extend_your_application/README.md) +* [Django formları](django_forms/README.md) +* [Sırada ne var?](whats_next/README.md) diff --git a/tr/code_editor/README.md b/tr/code_editor/README.md new file mode 100755 index 00000000000..da33bb10459 --- /dev/null +++ b/tr/code_editor/README.md @@ -0,0 +1,7 @@ +# Kod editörü + +İlk kod satırınızı yazmak üzeresiniz, bu yüzden önce bir kod editörü edinme zamanı! + +> **Not** Bunu daha önceki Kurulum bölümünde yapmış olabilirsiniz. Öyleyse, doğrudan bir sonraki bölüme geçebilirsiniz! + +{% include "/code_editor/instructions.md" %} \ No newline at end of file diff --git a/tr/code_editor/instructions.md b/tr/code_editor/instructions.md new file mode 100755 index 00000000000..7faec4864c6 --- /dev/null +++ b/tr/code_editor/instructions.md @@ -0,0 +1,31 @@ +Birçok farklı kod editörü var, hangi editörü kullanacağınız kişisel tercihinize bağlı. Çoğu Python programcısı PyCharm gibi karmaşık fakat son derece güçlü IDE'leri (Integrated Development Environments-Entegre Geliştirme Ortamları) kullanır. Başlangıç seviyesi için bunlar muhtemelen pek uygun olmayacaktır. Bizim önerdiklerimiz aynı derecede güçlü fakat çok daha basit editörler olacak. + +Bizim önerilerimizi aşağıda bulabilirsiniz, fakat eğitmenlerinize onların tercihlerini sormaktan çekinmeyin - onlardan yardım almak daha kolay olacaktır. + +## Gedit + +Gedit açık kaynaklı, ücretsiz bir editördür. Tüm işletim sistemlerinde kullanılabilir. + +[Buradan indirin](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text ücretsiz deneme sürümüne sahip oldukça popüler bir editördür. Kurulumu ve kullanımı basittir, tüm işletim sistemlerinde kullanılabilir. + +[Buradan indirin](https://www.sublimetext.com/3) + +## Atom + +Atom [GitHub](https://github.com/) tarafından geliştirilen oldukça yeni bir editör. Atom ücretsiz, açık kaynak kodlu, kurulumu ve kullanımı basit bir editördür. Windows, OSX ve Linux işletim sistemlerinde kullanılabilir. + +[Buradan indirin](https://atom.io/) + +## Neden bir kod editörü kuruyoruz? + +Neden Word ya da Notepad kullanmak yerine, özel bir kod editörü yazılımı kurduğumuzu merak ediyor olabilirsiniz. + +Birinci nedeni, kodun **düz metin** olması gerekliliği. Word ve TextEdit gibi programlar [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format) gibi özel formatları kullanarak düz metin yerine zengin metin (fontlu ve formatlı metin) üretiyorlar. + +İkinci neden, kod editörleri kod düzenlemek için özelleşmişlerdir, dolayısıyla kodu anlamına göre renklerle öne çıkarma (highlighting) veya tırnakları otomatik kapama gibi yararlı özellikler sağlar. + +Bütün bunları ileride uygulama içerisinde göreceğiz. Yakında güvenilir ihtiyar kod editörünü favori araçlarınız arasında görmeye başlayacaksınız :) \ No newline at end of file diff --git a/tr/css/README.md b/tr/css/README.md new file mode 100755 index 00000000000..ca8cfbf781c --- /dev/null +++ b/tr/css/README.md @@ -0,0 +1,296 @@ +# CSS - güzelleştir! + +Blogumuz hala epey çirkin gözüküyor, değil mi? Güzelleştirme zamanı! Bunun için CSS kullanacağız. + +## CSS Nedir? + +Basamaklı Stil Sayfaları (Cascading Style Sheets - CSS) bir websayfasının görünüm ve biçimlendirmelerini tanımlamak için kullanılan bir işaretleme (markup) dilidir (HTML gibi). CSS'i websayfanızın makyajı olarak görebilirsiniz ;). + +Fakat tekrar en baştan başlamak istemiyoruz, değil mi? Bir kez daha, programcılar tarafından önceden hazırlanmış ve internette ücretsiz olarak yayınlanmış bir şeyi kullanacağız. Bilirsiniz tekerleği yeniden icat etmek eğlenceli değildir. + +## Hadi Bootstrap kullanalım! + +Bootstrap güzel websayfaları geliştirmek için kullanılan en popüler HTML ve CSS çerçevesidir (framework): https://getbootstrap.com/ + +Twitter yazılımcıları tarafından geliştirilmeye başlanmış ve şu anda dünyanın her yerinden gönüllüler tarafından geliştirilmektedir. + +## Bootstrap kurulumu + +Bootstrap kurmak için `.html` dosyanızda `` kısmına şunları eklemeniz gerekli (`blog/templates/blog/post_list.html`): + +```html + + +``` + +Bu, projemize hiçbir yeni dosya eklemez. Yalnızca internet üzerinde var olan dosyalara işaret eder. Şimdi websitenizi açın ve sayfayı yenileyin. İşte oldu! + +![Şekil 14.1][1] + + [1]: images/bootstrap1.png + +Şimdiden daha güzel gözüküyor! + +## Django'da statik dosyalar + +Son olarak **statik dosyalar** diye bahsettiğimiz şeylere daha yakından bakalım. Statik dosyalar, CSS ve resimlerindir -- dinamik olmayan, bu nedenle içerikleri istek bağlamından bağımsız ve her kullanıcı için aynı dosyalar. + +### Django'da statik dosyaları nereye koymalı + +Sunucuda `collectstatic` komutunu çalıştırdığımız zaman gördüğün gibi, Django dahili "admin" uygulaması için statik dosyaların nerede olduğunu biliyor. Şimdi de bizim kendi `blog` uygulamamız için bazı statik dosyalar eklememiz gerekiyor. + +Bunu blog uygulamamızın içerisinde `static` isimli bir klasör oluşturarak yapacağız: + +``` +djangogirls +├── blog +│ ├── migrations +│ └── static +└── mysite +``` + +Django uygulama klasörlerinizin altındaki "static" isimli tüm klasörleri otomatik olarak bulacak ve içindekileri statik dosya olarak kullanabilecektir. + +## İlk CSS dosyanız! + +Şimdi web sayfamıza kendi stilimizi eklemek için bir CSS dosyası oluşturalım. `static` klasörü içinde `css` adlı yeni bir klasör oluşturalım. Şimdi de `css` klasörü içinde `blog.css` adlı yeni bir dosya oluşturalım. Hazır mısınız? + +``` +djangogirls +└─── blog + └─── static + └─── css + └─── blog.css +``` + +Şimdi CSS yazma zamanı! `blog/static/css/blog.css` dosyasını kod editöründe açın. + +Biz burada özelleştirme ve CSS'in detaylarına çok fazla girmeyeceğiz, çünkü gerçekten kolay ve workshop'tan sonra kendinizi bu konuda geliştirebilirsiniz. Web sitelerini CSS'le güzelleştirmek hakkında bilmen gerekenleri öğrenmek için, [Codeacademy HTML & CSS kursu][2]nu özellikle öneriyoruz. + + [2]: https://www.codecademy.com/tracks/web + +Ancak az da olsa yapalım. Acaba başlığımızın rengini mi değiştirsek? Bilgisayarlar renkleri anlamak için özel kodlar kullanır. Bu kodlar `#` ile başlar ve arkasından 6 harf (A-F) ve numaralarda (0-9) gelir. Renk kodlarını örneğin burada bulabilirsin: http://www.colorpicker.com/. Ayrıca [önceden tanımlanmış renkler][3]i de kullanabilirsin, `red` (kırmızı) ve `green` (yeşil) gibi. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +`blog/static/css/blog.css` dosyanıza şu kodu eklemelisiniz: + +```css +h1 a { + color: #FCA205; +} +``` + +`h1 a` bir CSS Seçicisidir (Selector). Bu demek oluyor ki biz stilimizi, bir `h1` öğesi içerisinde olan tüm `a` öğelerine (örneğin kodumuzun içerisinde `

link

` gibi bir şey olduğunda) uyguluyoruz. Bu durumda, rengi `#FCA205` yani turuncu yapmasını söylüyoruz. Elbette, buraya kendi arzu ettiğin rengi koyabilirsin! + +Bir CSS dosyasında, HTML dosyasındaki öğeler için stil belirleriz. Öğeler, öğenin ismi (örn. `a`, `h1`, `body`), `sınıf` özniteliği (attribute) ya da `id` özniteliği ile tanımlanırlar. Sınıf ve id (kimlik), bir elemente senin tarafından verilen isimlerdir. Sınıflar bir öğe grubunu tanımlar, id'ler ise belirli bir öğeye işaret ederler. Örneğin şu aşağıdaki etiket CSS tarafından, `a` etiket adı, `external_link` sınıfı ya da `link_to_wiki_page` id'si kullanılarak tanımlanabilir: + +```html + +``` + +Daha fazla bilgi için [w3schools'da CSS seçicileri][4]ni okuyabilirsin. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Sonrasında, ayrıca HTML şablonumuza (template) bir takım CSS eklemeleri yaptığımızı bildirmemiz gerekiyor. `blog/templates/blog/post_list.html` dosyasını açın ve en başına şu satırı ekleyin: + +```html +{% load staticfiles %} +``` + +Burada yaptığımız yalnızca statik dosyaları yüklemek. :) Sonrasında, `` ve ``, tagları arasına, Bootstrap CSS dosyalarına yönelik bağlantılardan sonra (web tarayıcımız dosyaları yazıldıkları sırasıyla okuduğundan, bizim dosyamızdaki kodlar Bootstrap dosyasının içerisindekileri geçersiz kılabilir), şu satırı ekleyin: + +```html + +``` + +Az evvel şablonumuza (template) CSS dosyamızın nerede olduğunu söylemiş olduk. + +Dosyanız şu şekilde gözüküyor olmalı: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

yayınlanma tarihi: {{ post.yayinlama_tarihi }}

+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+ {% endfor %} + + +``` + +Tamamdır, dosyayı kaydedip sayfayı yenileyebilirsiniz. + +![Şekil 14.2][5] + + [5]: images/color2.png + +Güzel! Şimdi de sitemizi biraz rahatlatıp sol kenar boşluğunu (margin'i) arttırsak mı? Hadi deneyelim! + +```css +body { + padding-left: 15px; +} +``` + +Bunu CSS dosyanıza ekleyin, dosyayı kaydedin ve nasıl çalıştığını görelim! + +![Şekil 14.3][6] + + [6]: images/margin2.png + +Belki de başlığımızın yazı tipini özelleştirebiliriz? Aşağıdaki satırı `blog/templates/blog/post_list.html` dosyasının içinde `` bölümüne yapıştırın: + +```html + +``` + +Bu satır *Lobster* adlı bir fontu Google Fonts (https://www.google.com/fonts) sitesinden sayfamıza aktarır. + +Şimdi `blog/static/css/blog.css` dosyamızdaki `h1 a` deklarasyon bloğunun içine (`{` ve `}` kodları arasına) `font-family: 'Lobster';` satırını ekleyip sayfayı yenileyin: + +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` + +![Şekil 14.3][7] + + [7]: images/font.png + +Harika! + +Yukarıda bahsettiğimiz üzere, CSS'te class (sınıf) diye bir kavram var. Class'lar, temel olarak HTML kodunuzun bir parçasına isim vermenize yarar ve yalnızca o parçanın stilini değiştirirken diğer parçaların etkilenmemesini sağlar. İki div'iniz var diyelim; fakat çok farklı şeyler yapıyorlarsa (örneğin biri başlık diğeri gönderinin metni) ve bu nedenle de aynı şekilde gözükmelerini istemiyorsanız, sınıflar müthiş yararlıdır. + +Devam edelim ve HTML kodumuzun bir kısmına isim verelim. Başlığı içeren `div`'e `page-header` isimli bir class ekleyelim: + +```html + +``` + +Şimdi de gönderi metnini içeren `div`'e `post` isimli bir sınıf ekleyelim. + +```html +
+

yayınlanma tarihi: {{ post.yayinlama_tarihi }}

+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+``` + +Şimdi farklı seçicilere (selectors) bildirim (deklarasyon) blokları ekleyeceğiz. `.` ile başlayan seçiciler sınıflara işaret eder. Web'de, aşağıdaki kodu anlamanıza yardımcı olacak pek çok güzel CSS öğreticisi ve açıklama mevcut. Şimdilik sadece bu kodu kopyalayıp `blog/static/css/blog.css` dosyamıza yapıştıralım: + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +Sonra da blog gönderilerimizi gösteren HTML kodunu sınıf bildirimleriyle saralım. <0>blog/templates/blog/post_list. html dosyasındaki şu kodu atıp: + +```html +{% for post in posts %} +
+

yayınlanma tarihi: {{ post.yayinlama_tarihi }}

+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+{% endfor %} +``` + +bununla değiştirelim: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.yayinlama_tarihi }} +
+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + +Bu dosyaları kaydedin ve web sayfanızı yenileyin. + +![Şekil 14.4][8] + + [8]: images/final.png + +Heyo! Harika görünüyor, değil mi? Yapıştırdığımız bu kodları anlamak pek de zor değil. Büyük bir kısmını sırf okuyarak anlayabilirsiniz. + +CSS ile biraz oynamaktan korkmayın ve bazı şeyleri değiştirmeyi deneyin. Bir şeyi bozarsanız tasalanmayın, yaptığınızı her zaman geri alabilirsiniz! + +Her durumda atölye sonrası ödevi olarak ücretsiz [Codeacademy HTML & CSS Kursu][2]'nu, websayfanızı CSS ile güzelleştirmeyi öğrenmek için almanızı tavsiye ediyoruz. + +Sonraki bölüm için hazır mısınız? :) \ No newline at end of file diff --git a/tr/css/images/bootstrap1.png b/tr/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/tr/css/images/bootstrap1.png differ diff --git a/tr/css/images/color2.png b/tr/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/tr/css/images/color2.png differ diff --git a/tr/css/images/final.png b/tr/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/tr/css/images/final.png differ diff --git a/tr/css/images/font.png b/tr/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/tr/css/images/font.png differ diff --git a/tr/css/images/margin2.png b/tr/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/tr/css/images/margin2.png differ diff --git a/tr/deploy/README.md b/tr/deploy/README.md new file mode 100755 index 00000000000..2ee7aecf409 --- /dev/null +++ b/tr/deploy/README.md @@ -0,0 +1,325 @@ +# Yayına alın! + +> **Not** Bir sonraki bölüm ara ara zor gelebilir. Dayanın ve bölümü bitirin; yayına alma, website geliştirme sürecinin önemli bir parçasıdır. Biraz daha uğraşmalı olan websitesini canlıya alma işine eğitmeninizin yardım edebilmesi için bu bölümü tutorial'ın ortasına yerleştirdik. Böylece eğer zaman yetmezse tutorial'ı kendi başınıza bitirebilirsiniz. + +Şimdiye kadar websiteniz sadece kendi makinanızda idi, şimdi yayına nasıl alacağınızı öğreneceksiniz! Yayına alma uygulamanızı internette yayınlama sürecidir, böylelikle insanlar sonunda gidip uygulamanızı görebilirler :). + +Öğrendiğimiz üzere, bir websitesi bir sunucunun üstünde olmalıdır. Internette birçok sunucu sağlayıcı bulunuyor. Görece kolay bir yayına alma süreci olanlardan birini kullanacağız: [PythonAnywhere][1]. PythonAnymwhere çok fazla ziyaretçisi olmayan ufak uygulamalar için ücretsiz yani sizin için kesinlikle yeterli olacaktır. + + [1]: https://pythonanywhere.com/ + +Dışarıdan kullanacağımız diğer servis bir kod barındırma hizmeti olan [Github][2]. Başkaları da var, ama nerdeyse her programcının bir Github hesabı var, sizin de olacak! + + [2]: https://www.github.com + +Github'ı kodumuzu PythonAnywhere'e taşımak için bir atlama tahtası olarak kullanacağız. + +# Git + +Git, birçok programcı tarafından kullanılan bir "sürüm kontrol sistemi"dir. Bu yazılım dosyaların zaman içindeki değişimlerini izler, böylelikle sonradan eski sürümlere ulaşabilirsiniz. Biraz Microsoft Word'deki "değişiklikleri izle" özelliği gibi, ama çok daha güçlü. + +## Git'i kurmak + +> **Not** Kurulum adımlarını halihazırda yaptıysanız, bunu tekrar yapmanıza gerek yok - bir sonraki alt bölüme geçip Git reponuzu oluşturabilirsiniz. + +{% include "/deploy/install_git.md" %} + +## Git repomuzu oluşturmak + +Git, kod reposu (veya "repository") denen belli dosyaların değişikliklerini izler. Projemiz için bir tane oluşturalım. Konsolunuzu açın ve `djangogirls` klasöründe aşağıdaki komutları çalıştırın: + +> **Not** Reponuzu başlatmadan önce, `pwd` (OS/Linux) veya `cd` (Windows) komutu ile bulunduğunuz dizini kontrol edin. `djangogirls` dizininde olmanız gerekiyor. + +``` +Hatırlatma: Kullanıcı adı seçerken özel Türkçe karakter kullanmayın. +$ git init +Initialized empty Git repository in ~/djangogirls/.git/ +$ git config --global user.name "Adınız" +$ git config --global user.email you@example.com +``` + +Git reposunu başlatma işi, proje başına bir kere yapmamız gereken birşey (ayrıca kullanıcı adı ve eposta adresini tekrar girmenize gerek olmayacak). + +Git bu dizindeki tüm dizin ve dosyalardaki değişiklikleri kaydedecek, ama takip etmemesini istediğimiz bazı dosyalar var. Bunu dizinin dibinde `.gitignore` adında bir dosya oluşturarak yapıyoruz. Editörünüzü açın ve aşağıdaki içeriklerle yeni bir dosya yaratın: + +``` +*.pyc +__pycache__ +myvenv +db.sqlite3 +.DS_Store +``` + +Ve "djangogirls" dizinin en üst seviyesine `.gitignore` olarak kaydedin. + +> **Not** Dosya adının başındaki nokta önemli! Eğer dosyayı oluştururken zorlanırsanız (örneğin Mac'ler Finder ile nokta ile başlayan dosya yaratmanızdan hoşlanmıyor), editörünüzdeki "Farklı Kaydet" özelliğini kullanın, kesin çalışır. + +`git add` kullanmadan önce veya nelerin değiştiğinden emin değilseniz, `git status` komutunu kullanmakta yarar var. Bu, yanlış dosyaların eklenmesi ve gönderilmesi gibi istenmeyen sürprizlerin engelenmesine yardımcı olacak. `git status` komutu, takip edilmeyen/değişen/gönderilecek dosyalar (staged), dal durumu (branch status) gibi bilgiler verir. Çıktının aşağıdaki gibi olması gerekiyor: + +``` +$ git status +On branch master + +Initial commit + +Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + +nothing added to commit but untracked files present (use "git add" to track) +``` + +Ve son olarak değişikliklerimizi kaydediyoruz. Komut satırına gidin ve aşağıdaki komutları çalıştırın: + +``` +$ git add --all +$ git commit -m "Django Girls uygulamam, ilk commit" + [...] + 13 files changed, 200 insertions (+) + create mode 100644 .gitignore + [...] +create mode 100644 mysite/wsgi.py +``` + +## Kodunuzu Github'a gönderme + +[GitHub.com>][2] adresine gidin ve kendinize yeni bedava bir kullanıcı hesabı açın. (Bunu atölye hazırlıklarında zaten yaptıysanız, harika!) + +Arkasından "ilk-blogum" (veya "my-first-blog") isminde yeni bir repo oluşturun. "Initialize with a README" kutucuğunu işaretlemeden bırakın, .gitignore opsiyonunu boş bırakın (onu elle yaptık) ve 'License'ı 'None' olarak bırakın. + +![][3] + + [3]: images/new_github_repo.png + +> **Not** `ilk-blogum` ismi önemli -- başka birşey de seçebilirsiniz, ama aşağıdaki yönergelerde çok geçiyor, her seferinde değiştirmeniz gerekir. En kolayı `ilk-blogum` ismi ile devam etmek. + +Bir sonraki ekranda, repo'yu klonlamak için gereken URL'yi göreceksiniz. "HTTPS"li versiyonunu seçin, kopyalayın. Birazdan onu komut penceresine yapıştıracağız: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +Şimdi bilgisayarınızdaki Git reposunu Github'daki repo ile ilişkilendirmemiz gerekiyor. + +Aşağıdakini komut satırına yazın (`` kısmını Github hesabını yarattığınız sırada kullandığınız kullanıcı adı ile değiştirin, büyüktür küçüktür işaretlini eklemeyin): + +``` +$ git remote add origin https://github.com//ilk-blogum.git +$ git push -u origin master +``` + +Github kullanıcı adı ve şifrenizi girin, arkasından aşağıdakine benzer bir şey görmeniz gerekiyor: + +``` +Username for 'https://github.com': zeynep +Password for 'https://zeynep@github.com': +Counting objects: 6, done. +Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. +Total 3 (delta 0), reused 0 (delta 0) +To https://github.com/zeynep/my-first-blog.git + * [new branch] master -> master +Branch master set up to track remote branch master from origin. +``` + + + +Kodunuz artık Github'da. Siteye girin ve kontrol edin! İyi bir çevrede olduğunu göreceksiniz - [Django][5], the [Django Girls Tutorial][6], ve daha birçok harika açık kaynak yazılım projesi de kodlarını Github'da tutuyor :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# Blogumuzun PythonAnywhere üzerinde kurulumu + +> **Not** En baştaki kurulum adımlarında PythonAnywhere hesabını açmış olabilirsiniz - öyleyse bu kısmı tekrar yapmanıza gerek yok. + +{% include "/deploy/signup_pythonanywhere.md" %} + +## Kodunuzu PythonAnywhere üzerine çekmek + +PythonAnywhere'de hesap açtığınızda, 'dashboard' (gösterge paneli) sayfanıza veya "Consoles" sayfasına yönlendirileceksiniz. "Bash" konsolu başlatma seçeneğini seçin -- bu bilgisayarınızdaki konsolun PythonAnywhere versiyonu. + +> **Not** PythonAnywhere Linux tabanlı, o yüzden kendi makinanız Windows ise konsol biraz farklı gözükecektir. + +Reponuzun bir klonunu yaratarak kodumuzu Github'dan PythonAnywhere üzerine çekelim. Aşağıdakileri PythonAnywhere konsoluna yazın (`` yerine kendi Github kullanıcı adınızı yazmayı unutmayın): + +``` +$ git clone https://github.com//ilk-blogum.git +``` + +Bu kodunuzun bir kopyasını PythonAnywhere üzerine indirecektir. `tree ilk-blogum` yazarak kontrol edin: + +``` +$ tree ilk-blogum +ilk-blogum/ +├── blog +│ ├── __init__.py +│ ├── admin.py +│ ├── migrations +│ │ ├── 0001_initial.py +│ │ └── __init__.py +│ ├── models.py +│ ├── tests.py +│ └── views.py +├── manage.py +└── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py +``` + +### PythonAnywhere üzerine bir virtualenv (sanal ortam) oluşturmak + +Bilgisayarınızda nasıl bir virtualenv (sanal ortam) oluşturduysanız, aynı şekilde PythonAnywhere üzerinde de oluşturabilirsiniz. Bash konsoluna, aşağıdakileri yazın: + +``` +$ cd ilk-blogum + +$ virtualenv --python=python3.4 myvenv +Running virtualenv with interpreter /usr/bin/python3.4 +[...] +Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(mvenv) $ pip install django whitenoise +Collecting django +[...] +Successfully installed django-1.8.2 whitenoise-2.0 +``` + +> **Not** `pip install` birkaç dakika sürebilir. Sabır, sabır! Ama 5 dakikadan uzun sürüyorsa, birşeyler yanlış olmuştur. Eğitmeninize sorun. + + + +### Statik dosyaların toplanması. + +"whitenoise"un ne olduğunu merak ettiniz mi? "Statik dosyalar" için kullanılan bir araç. Statik dosyalar, HTML veya CSS dosyaları gibi düzenli olarak değişmeyen veya kod çalıştırmayan dosyalardır. Bu dosyalar sunucularda bilgisayarımızdakinden farklı çalışırlar. Bu yüzden onları sunucudan yayınlamak için "whitenoise" gibi bir araca ihtiyacımız var. + +Tutorial'ın ilerleyen kısımlarında sitemizin CSS'ini düzenlerken statik dosyalar konusuna biraz daha fazla gireceğiz. + +Şimdilik sadece sunucuda `collectstatic` diye ek bir komut çalıştıracağız. Bu komut, Django'ya sunucdaki bütün statik dosyaları toparlamasını söyler. An itibariyle bunlar çoğunlukla admin sitesini güzelleştiren dosyalar. + +``` +(mvenv) $ python manage.py collectstatic + +You have requested to collect static files at the destination +location as specified in your settings: + + /home/zeynep/ilk-blogum/static + +This will overwrite existing files! (Bu işlem halihazırdaki dosyalarınız üzerinde değişiklik yapar!) +Are you sure you want to do this? (Bu işlemi yapmak istediğinizden emin misiniz?) + +Type 'yes' to continue, or 'no' to cancel: yes (Onaylıyorsanız 'yes', vazgeçtiyseniz 'no' yazın) +``` + +"yes" yazın ve işte başladı! Bilgisayarlara sayfa sayfa yazı yazdırmayı sevmiyor musunuz? Ben hep beraberinde küçük küçük sesler çıkarırım. Trr, trr, trr... + +``` +Copying '/home/zeynep/ilk-blogum/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' +Copying '/home/zeynep/ilk-blogum/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' +[...] +Copying '/home/zeynep/ilk-blogum/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' +Copying '/home/zeynep/ilk-blogum/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' +62 static files copied to '/home/zeynep/ilk-blogum/static'. +``` + +### PythonAnywhere üzerinde veritabanının oluşturulması + +Bilgisayarınız ve sunucu arasında farklı olan bir başka şey daha: farklı bir veritabanı kullanıyor. Dolayısıyla bilgisayarınızdaki ve sunucudaki kullanıcı hesapları ve blog yazıları farklı olabilir. + +Sunucudaki veritabanına aynen bilgisayardaki gibi `migrate` (taşımak) ve `createsuperuser` (yetkili bir kullanıcı oluşturmak) komutlarıyla oluşturup ilk örnek verilerle ile doldurabiliriz: + +``` +(mvenv) $ python manage.py migrate +Operations to perform: +[...] + Applying sessions.0001_initial... OK + + +(mvenv) $ python manage.py createsuperuser +``` + +## Blog'umuzu web uygulaması olarak yayınlama + +Artık kodumuz PythonAnywhere üzerinde, virtualenv'imiz hazır, statik dosyalar toplandı, ve veritabanı hazırlandı. Blogumuzu bir web uygulaması olarak yayınlamaya hazırız! + +PythonAnywhere logosuna tıklayarak 'dashboard'a geri gidin, burda **Web** sekmesine tıklayın. En son **Add a new web app** (yeni bir web uygulaması yaratın) linkine tıklayın. + +Açılan pencerede alan adınızı kontrol edin, **manual configuration** (elle konfigürasyon)'ı seçin ("Django" opsiyonunu *değil*). Arkasından **Python 3.4**'ü seçin ve işlemi bitirmek için 'Next'e basın. + +> **Not** "Manual configuration" seçeneğini seçtiğinizden emin olun, "Django" seçeneğini değil. Hazır PythonAnywhere Django kurulumunu seçmek için fazla havalıyız ;-) + +### virtualenv'in (sanal ortamın) ayarlanması + +Son bahsettiğimiz adım sizi web uygulamanızın PythonAnywhere ayar ekranına getirecek. Sunucudaki uygulamanızda değişiklik yapmak istediğinizde bu ekranı kullanmanız gerekiyor. + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +"Virtualenv" bölümünde "Enter the path to a virtualenv" (virtualenv için dizin yolu girin) linkini tıklayın ve şunu yazın: `/home//ilk-blogum/myenv`. Devam etmeden önce, dizin yolunu kaydetmek için tik işareti olan mavi kutuyu tıklayın. + +> **Not** İlgili yeri kendi kullanıcı adınızı yazın. Eğer hata yaparsanız, PythonAnywhere size bir uyarı gösterecektir. + +### WSGI dosyasının ayarlanması + +Django, "WSGI protokolü"nü kullanarak çalışır. WSGI, PythonAnywhere'in de desteklediği Python kullanan websitelerinin servis edilmesi için kullanılan bir standart. PythonAnywhere'in Django blogumuzu anlaması için WSGI ayar dosyasını düzenleyiyoruz. + +"WSGI Configuration file" (WSGI ayar dosyası) linkine tıklayın ("Code" denen kısımda, sayfanın üst tarafında -- adı `/var/www/_pythonanywhere_com_wsgi.py`'a benzer birşey olacak). Burdan bir edöitöre yönlendirileceksiniz. + +Tüm içeriği silin ve onların yerine aşağıdakileri yazın: + +```python +import os +import sys + +path = '/home//ilk-blogum' # burada kendi kullanıcı adınızı yazın +if path not in sys.path: + sys.path.append(path) + +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` + +> **Not** `` diye geçen kısıma kendi kullanıcı adınızı yazmayı unutmayın + +Bu dosyanın işi, PythonAnywhere'e web uygulamamızın nerde yaşadığını ve Django ayar dosyasının adının ne olduğunu söylemek. Aynı zamanda "whitenoise" statik dosya aracını ayarlıyor. + +**Save** (kaydet)'e basın. Arkasından **Web** sekmesine geri gidin. + +Hazırız! Yeşil ve büyük **Reload** (Yeniden yükle) butonuna tıklayın. Uygulamanıza girip görebileceksiniz. Sayfanın tepesinde uygulamaya giden linki bulabilirsiniz. + +## Hata ayıklama önerileri + +Eğer sitenize girdiğinizde bir hata görürseniz, hata ayıklama bilgileri için ilk bakacağınız yer, **error log**'unuz (hata kayıtlarınız). Buraya olan linki PythonAnywhere'deki [Web sekme][8]sinde bulabilirsiniz. Burda hata mesajları olup olmadığına bakın; en yeni mesajlar en altta. Sık karşılaşılan problemler şunlar: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* Konsolda yaptığımız adımlardan birinin unutulması: virtualenv'in oluşturulması, çalışır hale getirilmesi, içine Django'nun kurulumu, collectstatic'in çalıştırılması, veritabanının taşınması (migrate ettirilmesi). + +* Web sekmesinde virtualenv dizin yolunda bir hata yapılması -- eğer problem varsa, ilgili yerde küçük kırmızı bir hata mesajı olur. + +* WSGI ayar dosyasına bir hata yapmak -- ilk-blogum dizinine olan yolu doğru yazdığınızdan emin misiniz? + +* Virtualenv'ınız için seçtiğiniz Python versiyonu web uygulamanız için seçtiğiniz Python versiyonu ile aynı mı? İkisinin de 3.4 olması gerekiyor. + +* [Python Anywhere vikisinde (bilgi sayfalarında) genel hata ayıklama önerileri][9] bulunuyor. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +Ve eğitmeniniz size yardıma hazır, unutmayın! + +# Siteniz canlıda! + +Sitenizin varsayılan sayfası "Welcome to Django" diyor olmalı, aynen bilgisayarınızda olduğu gibi. URL'nin sonuna `/admin/` yazın, 'giriş' tuşuna bastığınızda admin sitesi açılacak. Kullanıcı adı ve şifrenizle giriş yapın, sunucuda yeni blog yazıları girebildiğinizi göreceksiniz. + +Kendinize *KOCAMAN* bir aferin diyin! Yayına alma web geliştirme işinin en uğraştırmalı kısımlarından biridir ve genelde çalışana kadar insanların birkaç gününü alır. Ama işte siteniz canlıda, gerçek internette! \ No newline at end of file diff --git a/tr/deploy/images/github_get_repo_url_screenshot.png b/tr/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/tr/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/tr/deploy/images/new_github_repo.png b/tr/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/tr/deploy/images/new_github_repo.png differ diff --git a/tr/deploy/images/pythonanywhere_web_tab_virtualenv.png b/tr/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/tr/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/tr/deploy/install_git.md b/tr/deploy/install_git.md new file mode 100755 index 00000000000..d889bf59a6e --- /dev/null +++ b/tr/deploy/install_git.md @@ -0,0 +1,19 @@ +### Windows + +Git'i [git-scm.com](https://git-scm.com/) adresinden indirebilirsiniz. 5. adıma kadar "next"e basarak geçebilirsiniz. 5. adımda "Adjusting your PATH environment" dediği yerde, "Run Git and associated Unix tools from the Windows command-line" (en alttaki opsiyonu) seçin. Onun dışında, varsayılanlar iyi. Kodu çekerken Windows-stili, kodu gönderirken Unix-stili satır sonları iyidir. + +### MacOS + +Git'i [git-scm.com](https://git-scm.com/)'den indirin ve yönergeleri izleyin. + +### GNU/Linux + +Halihazırda yüklü değilse, git'i paket yöneticinizle indirebilirsiniz. Şunlardan birini deneyin: + +``` +sudo apt-get install git +# veya +sudo yum install git +# veya +sudo zypper install git +``` \ No newline at end of file diff --git a/tr/deploy/signup_pythonanywhere.md b/tr/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..2c74b993403 --- /dev/null +++ b/tr/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +Sırada PythonAnywhere sitesinde bedava bir "Beginner" ( yeni başlayan) hesabı açma işi var. + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **Not** Burada kullanıcı isminizi seçerken bilin ki blogunuzun URL'si `kullanıcıadınız.pythonanywhere.com` şeklinde olacak. O yüzden ya kendi rumuzunuzu(nickname) seçin ya da blogunuzun konusu ile ilgili bir isim seçin. \ No newline at end of file diff --git a/tr/django/README.md b/tr/django/README.md new file mode 100755 index 00000000000..eec2f580ad2 --- /dev/null +++ b/tr/django/README.md @@ -0,0 +1,27 @@ +# Django nedir? + +Django (*/ˈdʒæŋɡoʊ/ jang-goh*) Python ile yazılmış ücretsiz ve açık kaynak bir web uygulama iskeletidir (framework). Bir web iskeleti, websitesi geliştirmeyi hızlandıran ve kolaylaştıran bir grup bileşendir. + +Bir websitesi geliştirdiğinizde benzer türde bileşenlere her zaman ihtiyacınız olur: kullanıcılar için kimlik denetimi (üye olma, üye girişi, üye çıkışı), websiteniz için bir yönetim paneli, formlar, dosyaları yüklemek için bir yol, vs. + +Şansınıza çok önceden başka insanlar yeni bir site oluştururken web geliştiricilerinin benzer problemlerle karşı karşıya kaldığını fark etti ve bir araya gelip iskeletler (Django bunlardan biri) oluşturdular. Bu iskeletler size kullanabileceğiniz hazır bileşenler verir. + +İskeletler sizi tekerleği yeniden icat etmekten kurtarır ve websitesi geliştirirken yükünüzün bir kısmını hafifletmekte yardımcı olur. + +## Neden bir iskelete ihtiyacınız var? + +Django'nun tam olarak ne işe yaradığını anlamak için sunucular konusuna daha çok girmemiz gerekiyor. İlk bilmeniz gereken şey, sunucunuzun ondan bir web sayfası sunmasını istediğinizi bilmesi gerektiği. + +Bir posta kutusunun (port) gelen mektuplar (requests) için izlendiğini düşünün. Bu bir web sunucusu tarafından yapılıyor. Sunucu mektubu okuyor ve bir web sayfası göndererek cevap veriyor. Ama bir şey gönderecekseniz, içeriğe ihtiyacınız var. Django içeriği oluşturmanıza yardımcı olan bir şeydir. + +## Birisi sunucunuzdan bir web sitesi istediğinde ne olur? + +Web sunucusuna bir istek geldiğinde tam olarak ne istendiğini çıkarmak için Django'ya geçirilir. O da önce web sayfasının adresini alır ve ne yapması gerektiğini çıkarmaya çalışır. Bu kısım Django'nun **url çözücüsü** (urlresolver) tarafından yapılıyor (websitesi adresine URL - Uniform Resource Locator - deniyor, dolayısıyla *url çözücü* ismi mantıklı oluyor). Çok akıllı değil - bir kalıp listesi alıyor ve URL'yi bunlarla eşleştirmeye çalışıyor. Django kalıpları yukarıdan aşağı kontrol ediyor ve eşleşen bir şey varsa isteği (request'i) ilişkilendirilmiş işleve (fonksiyona) geçiriyor. Bu işlev bir *view*'a karşılık geliyor. View kelimesi Türkçe'de görünüm anlamına gelir. Django'da özel bir terim olduğu için, biz sadece <1>view kelimesini kullanacağız.). + +Mektup dağıtan bir postacı düşünün. Sokak boyunca yürüyor ve her evin numarasını mektubun üstündeki numara ile karşılaştırıyor. Eğer eşleşirse, mektubu oraya koyuyor. Url çözücü işte böyle çalışır! + +*view* işlevinde her türlü ilginç şey yapılıyor: Bir bilgi için veritabanına bakabiliriz. Belki de kullanıcı veride bir şeyin değişmesini istemiştir? "Lütfen iş tanımımı değiştirin" diyen bir mektup gibi. *view* buna yapmaya izniniz olup olmadığını kontrol edebilir, sonra da sizin için iş tanımınızı güncelleyip geriye "Yapıldı!" diye bir ileti gönderir. Arkasından *view* bir cevap üretir ve Django bunu kullanıcının web tarayıcısına gönderebilir. + +Tabi ki yukardaki biraz basitleştirilmiş bir açıklama, ama şimdilik bütün teknik ayrıntıyı bilmene gerek yok. Genel bir fikrin olması yeterli. + +Doğrudan çok fazla detaya girmek yerine, Django ile birşeyler oluşturacağız ve önemli kısımları yolda öğreneceğiz! \ No newline at end of file diff --git a/tr/django_admin/README.md b/tr/django_admin/README.md new file mode 100755 index 00000000000..8e18bf79029 --- /dev/null +++ b/tr/django_admin/README.md @@ -0,0 +1,44 @@ +# Django admin + +Modelini hazırladığımız yazıları eklemek, düzenlemek ve silmek için Django admin'i kullanacağız. + +Hadi `blog/admin.py` dosyasını açalım ve içeriğini şununla değiştirelim: + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +Gördüğünüz gibi, bir önceki bölümde tanımladığımız Post modelini admin.py dosyamıza dahil (import) ettik. Modelimizi admin sayfasında görünür yapmak için modeli `admin.site.register(Post)` ile belirtmemiz gerekir.. + +Tamam, artık admin sayfasında Post modelimize göz atabiliriz. Web sunucusunu çalıştırmak için komut satırında `python manage.py runserver` komutunu çalıştırmayı unutmayın. Tarayıcınızda http://127.0.0.1:8000/admin/ adresini adres çubuğuna yazın. Aşağıdaki gibi bir giriş sayfası göreceksiniz: + +![Giriş sayfası][1] + + [1]: images/login_page2.png + +Giriş yapmak için, sitede her şeyin üzerinde kontrolü olan bir kullanıcı, yani bir *superuser* oluşturmanız gerekiyor. Komut satırında `python manage.py createsuperuser` yazın ve enter tuşuna basın. Giriş satırı geldiğinde, kullanıcı adınızı (küçük harfler ile ve boşluksuz), email adresinizi ve parolanızı girin. Parolayı yazarken ekranda bir şey çıkmayacaktır. Sadece yazın ve `enter` tuşuna basıp devam edin. Çıktısı aşağıdaki formatta olacaktır (kullanıcı adı ve email sizinki olacak): + +``` +(myvenv) ~/djangogirls$ python manage.py createsuperuser Username: admin Email address: admin@admin.com Password: Password (again): Superuser created successfully. +``` + +Tarayıcınıza dönün. Oluşturduğunuz superuser'ın bilgileri ile giriş yaptığınızda Django'nun admin panelini göreceksiniz. + +![Django admin][2] + + [2]: images/django_admin3.png + +Posts'a tıklayın ve biraz kurcalayın. Mesela üç beş tane blog yazısı ekleyin ve ne yazacağım diye düşünmeyin - zaman kazanmak için bu tutorial'dan kopyalayıp yapıştırabilirsiniz. :) + +En azından iki ya da üç yazıya (ama hepsinin değil) yayınlama tarihi girdiğinizden emin olun. Bunu ileriki adımlarda kullanacağız. + +![Django admin][3] + + [3]: images/edit_post3.png + +Eğer Django admin ile ilgili daha fazla şey öğrenmek istiyorsanız Django'nun belgelerine göz atabilirsiniz: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +Şimdi enerjinizi toplamak için kendinize bir çay veya kahve alabilirsiniz. Ne de olsa ilk Django modelinizi oluşturdunuz - biraz molayı hak ediyorsunuz. :) \ No newline at end of file diff --git a/tr/django_admin/images/django_admin3.png b/tr/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..25bcc4edda8 Binary files /dev/null and b/tr/django_admin/images/django_admin3.png differ diff --git a/tr/django_admin/images/edit_post3.png b/tr/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..34f2a195ec5 Binary files /dev/null and b/tr/django_admin/images/edit_post3.png differ diff --git a/tr/django_admin/images/login_page2.png b/tr/django_admin/images/login_page2.png new file mode 100644 index 00000000000..85137f4d162 Binary files /dev/null and b/tr/django_admin/images/login_page2.png differ diff --git a/tr/django_forms/README.md b/tr/django_forms/README.md new file mode 100755 index 00000000000..9a98665c387 --- /dev/null +++ b/tr/django_forms/README.md @@ -0,0 +1,398 @@ +# Django Forms + +Günlüğümüzde son olarak yapmak istediğimiz şey, günlük yazılarını eklemek ve düzenlemek için güzel bir yapı oluşturmak. Django'nun `admin` arayüzü çok havalı, ama özelleştirilmesi ve güzelleştirilmesi oldukça zor. Bunu `forms` (formlar) kullanarak kendi arayüzümüz üstünde mutlak bir güce sahip olacağız - neredeyse hayal ettiğimiz her şeyi yapabiliriz! + +Django formlarının güzel yanı, hem sıfırdan bir form tanımlayabilmemiz hem de sonuçları modele kaydedecek bir `ModelForm` oluşturabilmemizdir. + +Tam olarak yapmak istediğimiz şey: `Post` modelimiz için bir form oluşturmak. + +Django'nun diğer önemli parçaları gibi, formların da kendi dosyası var: `forms.py`. + +`blog` dizinimizde bu isimde bir dosya oluşturmalıyız. + +``` +blog + └── forms.py +``` + +Tamam, hadi dosyayı açalım ve aşağıdaki kodu yazalım: + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('baslik', 'yazi',) +``` + +Önce Django formları (`from django import forms`) ve tabii ki `Post` modelimizi içe aktarmalıyız (`from .models import Post`). + +`PostForm`, tahmin etmiş olabileceğiniz gibi, formumuzun ismi. Django'ya bu formun bir `ModelForm` olduğunu belirtmeliyiz. Bunu `forms.ModelForm` sayesinde Django bizim için yapacaktır. + +Sırada Django'ya bu formu (`model = Post`) oluşturmak için hangi modelin kullanılması gerektiğini anlattığımız `class Meta` var). + +Son olarak, formumuzda hangi alan(lar)ın bulunması gerektiğini söyleyebiliriz. Bu senaryoda sadece `baslik` ve `yazi` alanlarının gösterilmesini istiyoruz - `yazar` şu anda giriş yapmış olması gereken kişidir (yani siz!) ve biz ne zaman yeni bir yazı oluşturursak `yaratilis_tarihi` otomatik olarak (örn. kod içinde) ayarlanmalıdır, değil mi? + +Ve hepsi bu kadar! Şimdi tek yapmamız gereken formu bir *view* içinde kullanıp, template (şablon) içinde göstermek. + +Bir kez daha: sayfaya bir bağlantı, bir URL, bir view ve bir template üreteceğiz. + +## Formun bulunduğu sayfaya bağlantı oluşturma + +Şimdi `blog/templates/blog/base.html` şablonunu açma zamanı. Öncelikle `page-header` adlı `div` öğesinin içine bir bağlantı ekleyeceğiz: + +```html + +``` + +Yeni view'i `post_new` olarak isimlendirdik. + +Yukarıdaki satırı ekledikten sonra html dosyanız böyle görünmeli: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + +Dokümanı kaydedip http://127.0.0.1:8000 sayfasını yeniledikten sonra, siz de tanıdık `NoReverseMatch` hatasını görüyor olmalısınız, değil mi? + +## URL + +`blog/urls.py` dosyasını açalım ve yeni bir satır ekleyelim: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + +Ve kodun son hali şu şekilde görünecektir: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + +Sayfayı yeniledikten sonra, `AttributeError` şeklinde bir hata görürüz, bunun sebebi de henüz `post_new` view'ını (görünümünü) kodlamamış olmamız. Şimdi bu dosyayı da ekleyelim. + +## post_new view + +Şimdi `blog/views.py` dosyasını açıp aşağıdaki satırları diğer `from` satırlarının olduğu yere ekleyelim: + +```python +from .forms import PostForm +``` + +ve bizim *view*'ımız: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Yeni bir `Post` formu oluşturmak için `PostForm()` fonksiyonunu çağırmak ve template'e iletmek gerekir. Bu *view*'a geri döneceğiz, fakat öncesinde form için hızlıca bir şablon oluşturalım. + +## Template + +Öncelikle `blog/templates/blog` dizininde `post_edit.html` isimli bir dosya oluşturmalıyız. Bir formu çalışır hale getirmek için birkaç şeye ihtiyacımız var: + +* form'u görüntülemeliyiz. Bunu basitçe bu şekilde yapabiliriz: `{% raw %}{{ form.as_p }}{% endraw %}`. +* yukarıdaki örnek satır HTML form etiketi içine alınmalı: `...` +* bir `Kaydet` butonuna ihtiyacımız var. Bunu bir HTML butonu ile yapıyoruz: `` +* son olarak, hemen `
` etiketinden sonra `{% raw %}{% csrf_token %}{% endraw %}` satırını eklememiz lazım. Formlarımızın güvenliğini sağladığı için bu çok önemlidir! Bunu koymayı unutup formu kaydedersek Django hata verecektir: + +![CSFR Korumalı sayfa][1] + + [1]: images/csrf2.png + +Peki, şimdi de `post_edit.html` in içindeki HTML kodunun nasıl görünmesi gerektiğine bakalım: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +

Yeni gönderi

+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} +``` + +Yenileme zamanı! Hey! Formun görüntülendi! + +![Yeni form][2] + + [2]: images/new_form2.png + +Ama, bir dakika! `baslik` ve `yazi` alanlarına bir şey yazıp kaydettiğimizde ne olacak? + +Hiçbir şey! Yine aynı sayfaya döndük ve bütün yazdıklarımız kayboldu... ve yeni bir gönderi de eklenmemiş. Yanlış giden ne? + +Yanıt: hiçbir şey. Sadece *view*'ımızda biraz daha iş yapmamız gerekiyor. + +## Formu kaydetme + +Tekrar `blog/views.py` dosyasını açalım. Şuan `post_new` view'ı içinde sadece bunlar var: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Formu kaydettiğimizde tekrar aynı view'a yönlendirileceğiz, ama bu sefer `request` nesnesinde, daha doğrusu `request.POST` (isimlendirmesinin, bizim blog uygulamasının "post" modeli ile alakası yok, gerçekte veri gönderdiğimiz (İngilizcede "post" işlemi) için isimlendirme bu şekilde) içerisinde, daha fazla verimiz olacak. HTML dosyasında `
` tanımımızdaki `method="POST"` değişkenini hatırlıyor musun? Formdan gelen tüm alanlar şimdi `request.POST`'un içerisinde. `POST`'un ismini değiştirmememiz lazım (`method` için geçerli diğer değer sadece `GET`'dir, ama şimdi ikisi arasındaki farkın ne olduğunu anlatacak kadar vaktimiz yok). + +Oluşturduğumuz *view*'da iki ayrı durumu halletmemiz gerek. Birincisi: sayfaya ilk eriştiğimiz ve boş bir form istediğimiz zaman. İkincisi: henüz yazdığımız tüm form verileriyle *view*'a geri döndüğümüz zaman. Yani bir koşul eklememiz gerekiyor (bunun için `if` kullanacağız). + +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` + +Şimdi boşluğu `[...]` doldurma zamanı geldi. `method`, `POST` ise o zaman `PostForm`u verilerle oluşturmamız lazım, değil mi? Bunu yapmak için: + +```python +form = PostForm(request.POST) +``` + +Çok kolay! Şimdi de formu (yani tüm gerekli alanların doldurulduğu ve hatalı değerlerin kaydedilmeyeceğini) kontrol etmemiz lazım. Bunu da `form.is_valid()` ile yapıyoruz. + +Formun doğruluğunu kontrol ediyoruz ve doğru ise kaydedebiliriz! + +```python +if form.is_valid(): + post = form.save(commit=False) + post.yazar = request.user + post.yayinlama_tarihi = timezone.now() + post.save() +``` + +Temel olarak, burada iki şey yaptık: formu `form.save` ile kaydettik ve bir yazar ekledik (`PostForm`'da bir `yazar` tanımlı olmadığı ve bu zorunlu bir alan olduğu için!). `commit=False`, `Post` modelini henüz kaydetmek istemediğimizi belirtir - ilk önce yazarı eklemek istiyoruz. Genellikle `form.save()`, `commit=False` olmadan kullanacaksınız, ama bu durumda, bunu kullanmamız gerekiyor. `post.save()` değişiklikleri (yazarı ekleme) koruyacaktır ve yeni bir blog gönderisi oluşturulur! + +Hemen `post_detail` sayfasına gidip yeni yaratmış olduğumuz blog postunu görsek harika olur, degil mi? Bunu yapabilmek için önemli bir şey daha lazım: + +```python +from django.shortcuts import redirect +``` + +Bunu dosyanın en başına ekleyelim. Şimdi yeni yarattığımız blog postu için `post_detail` sayfasına gidebiliriz. + +```python +return redirect('blog.views.post_detail', pk=post.pk) +``` + +`blog.views.post_detail` gitmek istediğimiz görünümün ismidir. Unutmayalım ki bu *view* için bir `pk` değişkeni lazım. Bu değeri görünümlere aktarmak için `pk=post.pk` yazarız. Burada `post` yeni yarattığımız blog postudur! + +Çok şey söyledik ama herhalde *view* u tümüyle bir görmek isteriz artık, değil mi? + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.yazar = request.user + post.yayinlama_tarihi = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Bakalım çalışacak mı? http://127.0.0.1:8000/post/new/ sayfasına gidip bir `baslik` ve `yazi` ekleyelim, sonra da kaydedelim... ve işte! Yeni blog postu eklenmiş ve `post_detail` sayfasına yönlendirildik! + +Postu kaydetmeden önce yayin tarihine değer atandığını fark etmiş olabilrsin. Daha sonra *yayınla butonu* nu **Django Girls Tutorial: Ek konular** da anlatacağız. + +Süper! + +## Form doğrulama + +Şimdi de Django formlarının ne kadar havalı olduğunu görelim. Bir blog postunun `baslik` ve `yazi` alanları olmalı. `Post` modelimizde bu alanlar mecburi değil demedik ( `yayinlama_tarihi` demiş olduğumuz gibi), dolayısı ile Django bu alanlara değer atanması gerektiğini varsayar. + +`baslik` veya `yazi` olmadan formu kaydetmeye çalışın. Ne olacak, tahmin et! + +![Form doğrulama][3] + + [3]: images/form_validation2.png + +Django tüm alanlara doğru tür değerlerin atandığını bizim için kontrol ediyor. Ne güzel, değil mi? + +> Yakın zamanda Django'nun admin arayüzünü kullandığımız için, sistem bizi hala oturumda varsayıyor. Bazı durumlar bizim oturumdan çıkmamıza neden olabilir (web tarayıcısını kapatmak, veritabanını tekrar başlatmak, vb). Eğer oturumda olan kullanıcı olmadığı için post yaratmada hata alırsak admin sayfası olan http://127.0.0.1:8000/admin gidip tekrar bir oturum açmalıyız. Bu durumu geçici de olsa da halleder. Kalıcı çözüm, ana tutorialdan sonra **Ödev: Web sitene güvenlik ekleme!** bölümünde anlatılacak. + +![Oturum hatası][4] + + [4]: images/post_create_error.png + +## Form düzenleme + +Artık yeni bir form oluşturmayı biliyoruz. Peki, mevcut bir formu güncellemek için ne yapmalı? Demin yaptığımıza çok benziyor. Şimdi, hızlıca bir kaç şey yaratalım (anlamadığın bir şey olduğu zaman, mentöre veya önceki bölümlere danışabilirsin, çünkü bu adımları daha önce yaptık). + +`blog/templates/blog/post_detail.html` dosyasını açıp şu satırı ekleyelim: + +```python + +``` + +ki template buna benzesin: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.yayinlama_tarihi %} +
+ {{ post.yayinlama_tarihi }} +
+ {% endif %} + +

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+{% endblock %} +``` + +`blog/urls.py` dosyasına şu satırı ekleyelim: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + +Daha önce kullandığımız `blog/templates/blog/post_edit.html` template'i tekrar kullanacağız, tek eksik bir *view*. + +Şimdi `blog/views.py` dosyasını açıp en sonuna şu satırı ekleyelim: + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.yazar = request.user + post.yayinlama_tarihi = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Bu nerdeyse bizim `post_new` view'e benziyor, değil mi? Ama, tam da değil. İlk önce: Url'den ekstra bir `pk` parameteresi yolladık. Sonra: güncellemek istediğimiz `Post` modelini `get_object_or_404(Post, pk=pk)` ile alıp, bir form yarattığımızda bu postu bir `örnek kopya` (instance) olarak hem formu kaydettiğmizde yolluyoruz: + +```python +form = PostForm(request.POST, instance=post) +``` + +hem de güncellemek istediğimiz postu görmek için form açtığımız zaman yolluyoruz: + +```python +form = PostForm(instance=post) +``` + +Haydi, deneyelim. Bakalım çalışacak mı? `post_detail` sayfasına gidelim. Sağ üst köşede bir edit (güncelleme) butonu olmalı: + +![Düzenle butonu][5] + + [5]: images/edit_button2.png + +Butona tıklarsak blog postunu görmemiz lazım: + +![Formu düzenle][6] + + [6]: images/edit_form2.png + +İstediğimiz gibi başlık ve yazıyı değiştirebilir ve sonra da kaydedebilriz! + +Tebrikler! Uygulaman gittikçe tamamlanıyor! + +Django formları hakkında daha fazla bilgi bulmak için https://docs.djangoproject.com/en/1.8/topics/forms/ adresindeki dokümanlara bakabilirsin + +## Güvenlik + +Bir bağlantıya (link) tıklayarak yeni bir blog oluşturabilmek harika! Ancak, şu haliyle siteye gelen herkes bir blog yaratıp kaydedebilir. Bu da istenen bir durum değil. Butonun sadece sana görünmesini sağlayalım. + +`blog/templates/blog/base.html` dosyasında yarattığımız `page-header` `div` ve anchor etiketlerini (tags) bulalım. Şuna benziyor olmalı: + +```html + +``` + +Şimdi bir `{% if %}` etiketi daha ekleyeceğiz ki link sadece admin olarak oturum açmış kişilere görünsün. Şimdilik, bu kişi sadece sensin! `` etiketini şöyle değiştirelim: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Bu `{% if %}` linkin tarayıcıya ancak kullanıcı oturum açmış ise gönderilmesini sağlar. Bu yeni post yaratılmasını kesin olarak engellemese de iyi bir başlangıç. Güvenlik konusu ek derslerde daha çok ele alınacak. + +Oturum içi olduğumuz için, şimdi sayfayı yenilersek, farklı bir şey görmeyeceğiz. Sayfayı farklı bir tarayıcıda veya incognito bir pencerede yükleyelim. O zaman bu link görünmeyecek! + +## Bir şey daha: deployment (yayına alma) zamanı! + +Bakalım PythonAnywhere'de calışacak mı? Tekrar yayına alalım! + +* İlk önce kodumuzu commit edelim, sonra Github'a push edelim + +```$ git status +$ git add --all . +$ git status +$ git commit -m "Web sitesine güncelleme ve yaratma için view eklendi." +$ git push +``` + +* Sonra bir [PythonAnywhere Bash konsol][7] una gidip: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd ilk-blogum +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* Nihayet, [Web tab][8] ına gidip **Reload** edelim. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +O kadar! Tebrikler :) diff --git a/tr/django_forms/images/csrf2.png b/tr/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/tr/django_forms/images/csrf2.png differ diff --git a/tr/django_forms/images/drafts.png b/tr/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/tr/django_forms/images/drafts.png differ diff --git a/tr/django_forms/images/edit_button2.png b/tr/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/tr/django_forms/images/edit_button2.png differ diff --git a/tr/django_forms/images/edit_form2.png b/tr/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/tr/django_forms/images/edit_form2.png differ diff --git a/tr/django_forms/images/form_validation2.png b/tr/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/tr/django_forms/images/form_validation2.png differ diff --git a/tr/django_forms/images/new_form2.png b/tr/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/tr/django_forms/images/new_form2.png differ diff --git a/tr/django_forms/images/post_create_error.png b/tr/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/tr/django_forms/images/post_create_error.png differ diff --git a/tr/django_installation/README.md b/tr/django_installation/README.md new file mode 100755 index 00000000000..f164d84c1ba --- /dev/null +++ b/tr/django_installation/README.md @@ -0,0 +1,5 @@ +# Django kurulumu + +> **Not** Eğer kurulum adımlarını zaten yaptıysanız sonraki bölüme geçebilirsiniz! + +{% include "/django_installation/instructions.md" %} \ No newline at end of file diff --git a/tr/django_installation/instructions.md b/tr/django_installation/instructions.md new file mode 100755 index 00000000000..af93ae18de3 --- /dev/null +++ b/tr/django_installation/instructions.md @@ -0,0 +1,122 @@ +> Bu bölümün bir kısmı Geek Girls Carrots tarafından hazırlanmış eğitimlere dayanılarak hazırlanmıştır (http://django.carrots.pl/). +> +> Bu bölümün bir parçası Creative Commons Attribution-ShareAlike 4.0 International License ile lisanslı [django-marcador tutorial](http://django-marcador.keimlink.de/)'a dayanılarak hazırlanmıştır. Django-marcador tutorial'ının hakları Markus Zapke-Gründemann'e aittir. + +## Virtual environment (Sanal ortam) + +Django'yu yüklemeden önce kod ortamınızı düzenli tutmak için son derece yararlı bir araç yükleyeceğiz. Bu adımı atlayabilirsiniz, fakat atlamamanızı tavsiye ederiz. En iyi olası kurulum ile başlamanız sizi gelecekteki bir sürü sorundan koruyacaktır! + +Öyleyse bir **virtual environment**(diğer adıyla *virtualenv*) kuralım. Virtualenv Python/Django kurulumunuzu her proje için ayrı tutup izole eder. Bu, bir websitesine yapacağınız değişikliklerin diğer geliştirdiklerinize yansımayacağı anlamına gelir. Muazzam, değil mi? + +Yapmanız gereken tek şey `virtualenv` oluşturmak için bir dizin bulmak; örneğin giriş dizininiz. Windows'da bu `C:\Users\isim` olabilir (`isim` kısmı kullanıcı adınız olacak şekilde). + +Bu eğitim için giriş dizininizde yeni açtığımız `djangogirls` adlı bir klasör kullanacağız: + +``` +mkdir djangogirls +cd djangogirls +``` + +`myvenv` adında bir virtualenv oluşturacağız. Genel komut aşağıdaki şekilde olacak: + +``` +python3 -m venv myvenv +``` + +### Windows + +Yeni bir `virtualenv` oluşturmak için konsolu açıp (nasıl yapıldığını birkaç adım önce anlatmıştık - hatırlıyorsunuz değil mi?) `C:\Python34\python -m venv myvenv` komutunu çalıştırın. Şöyle görünmeli: + +``` +C:\Users\İsim\djangogirls> C:\Python34\python -m venv myvenv +``` + +`C:\Python34\python` dizini önceden Python'u kurduğunuz dizin ve `myenv` ise `virtualenv`'inizin ismi olacaktır. İstediğiniz herhangi bir ismi kullanabilirsiniz, ama küçük harfle yazılmasına ve boşluk, aksan karakterleri (örn: å) ve özel karakterleri kullanmamaya dikkat edin. Ayrıca ismi kısa tutmak iyi bir fikir olabilir, zira bu ismi çok kullanıyor olacaksınız! + +### GNU/Linux ve OS X + +Linux ve OS X işletim sistemlerinde `virtualenv` oluşturmak için `python3 -m venv myvenv` komutunu çalıştırmak yeter. Komut şu şekilde görünecektir: + +``` +~/djangogirls$ python3 -m venv myvenv +``` + +Burada `myvenv` sizin `virtualenv`'inizin ismi. Dilerseniz istediğiniz herhangi bir isim kullanabilirsiniz, ama büyük harf ve boşluk kullanmamaya dikkat edin. İsmi çok fazla kullanacağınız için kısa tutmak da işinize yarayacaktır. + +> **NOT:** Ubuntu 14.04 işletim sisteminde sanal ortam yaratmaya çalışırken şu hatayla karşılaşabilirsiniz: +> +> Error: Command '['/home/zeynep/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Bu sorunu çözmek için `virtualenv` komutunu kullanabilirsiniz. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Virtualenv ile çalışmak + +Yukarıdaki komutlar `myvenv` (veya seçtiğiniz isimde) bir klasör oluşturacaktır. Bu klasörde birçok dosya ve klasör bulunur. + +#### Windows + +Şu komutu çalıştırarak virtualenv'i başlatın: + +``` +C:\Users\Name\djangogirls> myvenv\Scripts\activate +``` + +#### GNU/Linux ve OS X + +Şu komutu çalıştırarak virtualenv'i başlatın: + +``` +~/djangogirls$ source myvenv/bin/activate +``` + +`myvenv` yerine kendi seçtiğiniz `virtualenv` ismini koymayı unutmayın! + +> **NOT:** bazen `source` komutu kullanılamıyor durumda olabilir. Böyle durumlarda onun yerine aşağıdaki komutu da kullanabilirsiniz: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Konsolunuzda şuna benzer bir şey gördüğünüzde `virtualenv`'in başladığını anlayabilirsiniz: + +``` +(myvenv) C:\Users\Name\djangogirls> +``` + +ya da: + +``` +(myvenv) ~/djangogirls$ +``` + +En başta beliren `(myvenv)`'e dikkat edin! + +Virtualenv ile çalışırken `python` otomatik olarak doğru sürümü çalıştıracaktır. Yani `python3` yerine `python` yazabilirsiniz. + +Artık bütün gerekli uygulamaları bir araya getirdiğimize göre sonunda Django'yu yükleyebiliriz! + +## Django'yu yüklemek + +`virtualenv`'i başlattığınız için artık Django'yu `pip` kullanarak yükleyebiliriz. Konsola `pip install django==1.8` komutunu yazın. (İki tane eşittir işareti kullandık: `==`). + +``` +(myvenv) ~$ pip install django==1.8 +Downloading/unpacking django==1.8 +Installing collected packages: django +Successfully installed django +Cleaning up... +``` + +Windows'ta + +> Eğer Windows işletim sisteminde pip komutunu kullanırken bir hatayla karşılaştıysanız proje adresinizin boşluk, aksan veya özel karakter içerip içermediğini (`C:\Users\User Name\djangogirls` gibi) kontrol edin. Eğer durum buysa projenizi boşluk veya özel karakter içermeyen bir adrese taşıyın; önerimiz `C:\djangogirls` olacaktır. Taşıma işleminden sonra yukarıdaki komutu tekrar deneyin. + +Linux'ta + +> Eğer Ubuntu 12.04 işletim sisteminde pip komutunu çağırırken bir hata iletisiyle karşılaştıysanız `python -m pip install -U --force-reinstall pip` komutunu çalıştırarak pip kurulumunu onarmayı deneyin. + +İşte bu kadar! Sonunda Django uygulamanızı oluşturmaya hazırsınız! diff --git a/tr/django_models/README.md b/tr/django_models/README.md new file mode 100755 index 00000000000..5c20b45d3bd --- /dev/null +++ b/tr/django_models/README.md @@ -0,0 +1,184 @@ +# Django modelleri + +Şimdi blogumuzdaki bütün yazıları kaydedebileceğimiz bir şey oluşturmak istiyoruz. Ama bunu yapabilmek için önce `nesneler` denen şeylerden bahsetmemiz gerekiyor. + +## Nesneler + +Programlamada `Nesneye yönelik programlama` denen bir kavram bulunuyor. Buradaki ana fikir her şeyi sıkıcı bir düzende programlama komutları ile yazmak yerine şeyleri modelleyip birbirleri ile nasıl etkileşime geçeceklerini tanımlayabileceğimiz. + +Peki bir nesne nedir? Özelliklerin ve hareketlerin bir bütünüdür. Kulağa garip geliyor olabilir ama bir örnekle açıklayacağız. + +Eğer bir kediyi modellemek istiyorsak `Kedi` nesnesini oluştururuz ve bu nesne şöyle özelliklere sahip olur:`renk`, `yas`, `ruh_hali` (örneğin; iyi, kötü, uykulu ;)) ve `sahibi` (ki bu da bir `İnsan` nesnesi olur ya da eğer sokak kedisi ise bu özellik boş olabilir). + +`Kedi` bazı hareketlere sahiptir: `miyavla`, `tirmala` ya da `beslen` (bu durumda kediye biraz `KediMamasi` vermemiz gerekir ki o da kendine ait özellikleri olan başka bir nesne olur. Özelliklere örnek olarak `tat` verilebilir). + +``` +Kedi +-------- +renk +yas +ruh_hali +sahibi +miyavla() +tirmala() +beslen(kedi_mamasi) + +KediMamasi +-------- +tat +``` + +Yani aslında ana fikir, gerçek nesneleri kod içinde özellikleriyle (`nesne özellikleri`) ve hareketleriyle (`metodlar`) tanımlamak. + +Öyleyse blog gönderilerini nasıl modelleyeceğiz? Bir blog tasarlamak istiyoruz degil mi? + +Cevaplamamız gereken soru: Blog gönderisi nedir? Özellikleri ne olmalıdır? + +Tabii ki blog gönderimizin içeriği için yazı ve bir de başlık lazım, değil mi? Kimin yazdığını da bilsek iyi olur - dolayısı ile bir yazara da ihtiyacımız var. Son olarak, gönderinin ne zaman yaratıldığını ve yayınlandığını bilmek isteriz. + +``` +Post +------ +baslik +yazi +yazar +yaratilis_tarihi +yayinlama_tarihi +``` + +Bir blog gönderisi ile ne tür şeyler yapılabilir? Gönderiyi yayınlayan bir `method` olması güzel olurdu, değil mi? + +Bu yüzden `yayinla` metoduna ihtiyacımız olacak. + +Ne elde etmek istediğimizi bildiğimize göre, haydi bunu Django'da modellemeye başlayalım! + +## Django modeli + +Nesnenin ne olduğunu bildiğimize göre, blog gönderimiz için bir Django modeli oluşturabiliriz. + +Django'da bir model özel bir çeşit nesnedir - `veritabanı`'na kaydedilir. Veritabanı veri topluluğuna verilen isimdir. Burası, kullanıcıları, blog gönderileri gibi bilgileri saklayacağımız yerdir. Verilerimizi depolamak için SQLite veritabanını kullanacağız. Bu varsayılan Django veritabanı adaptörüdür - şimdilik bizim için yeterli olacaktır. + +Veritabanındaki bir modeli sütunları (alan adı) ve satırları (veri) olan bir hesap çizelgesi olarak düşünebiliriz. + +### Uygulama oluşturma + +Her şeyi derli toplu tutmak için, projemizin içinde ayrı bir uygulama oluşturacağız. Her şeyin en başından düzenli olması çok iyidir. Bir uygulama oluşturmak için aşağıdaki komutu konsolda çalıştırmamız gerekiyor ( `djangogirls` dizininden `manage.py` dosyasının bulunduğu yer): + +``` +(myvenv) ~/djangogirls$ python manage.py startapp blog +``` + +İçinde birkaç dosya olan yeni bir `blog` klasörü fark edeceksiniz. Projemizdeki klasörler ve dosyalar şöyle olmalı: + +``` +djangogirls +├── mysite +| __init__.py +| settings.py +| urls.py +| wsgi.py +├── manage.py +└── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py +``` + +Uygulamamızı oluşturduktan sonra, Django'ya bunu kullanmasını da söylememiz lazım. Bunu `mysite/settings.py` dosyası ile yapıyoruz. `INSTALLED_APPS` dosyasını bulup `'blog'` u tam `)` karakterinin üzerine yazmamız lazım. Sonunda dosya şuna benzemelidir: + +``` +python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` + +### Post (Blog gönderisi) modeli oluşturma + +`blog/models.py` dosyasında `Models` deki tüm nesneler tanımlanır - burası bizim blog postunu tanımlayacağımız yerdir. + +Şimdi `blog/models.py` dosyasını açalım ve içindeki her şeyi silip şu kodu yazalım: + +``` +python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + yazar = models.ForeignKey('auth.User') + baslik = models.CharField(max_length=200) + yazi = models.TextField() + yaratilis_tarihi = models.DateTimeField( + default=timezone.now) + yayinlama_tarihi = models.DateTimeField( + blank=True, null=True) + + def yayinla(self): + self. yayinlama_tarihi = timezone.now() + self.save() + + def __str__(self): + return self.baslik +``` + +> `str` nin her iki tarafında 2 tane alt çizgi (`_`) kullandığınızı kontrol edin. İki alt çizgi Python dilinde sık kullanılır. + +Biraz korkunç görünüyor, değil mi? Ama merak etmeyin, her şeyin ne demek olduğunu anlatacağız! + +`from` veya `import` ile başlayan tüm satırlar başka yerlerden bir şeyleri projemize dahil eder. Yani, başka yerlerde tanımlanmış kodları dosyalarımıza kopyalamak yerine, bu kodların bir kısmını `from ... import ...` ile projemize dahil edebiliriz. + +`class Post(models.Model):` - bu satır modelimizi tanımlar (bir `nesne` dir). + +* `class` bir nesne tanımladığımızı belirten bir anahtar kelimedir. +* `Post` modelimizin ismidir. Başka bir isim de verebilirdik (yeter ki özel karakterler ve boşluk kullanmayalım). Class isimleri her zaman büyük harf ile başlamalıdır. +* `models.Model` Post'un bir Django Modeli olduğunu belirtir, bu şekilde Django onu veritabanında tutması gerektiğini bilir. + +Şimdi daha önce bahsettiğimiz özellikleri tanımlayabiliriz: `baslik`, `yazi`, `yaratilis_tarihi`, `yayinlama_tarihi` ve `yazar` (Türkçe karakterleri kullanamadığımızı unutmayalım). Bunun için her alanın tipini belirtmemiz lazım (metin mi? Sayı mı? Tarih mi? Başka bir nesneye referans mı, ör. Kullanıcı?). + +* `models.CharField` - kısıtlı uzunlukta metin tanımlamak için kullanılır. +* `models.TextField` - bu da uzun metinleri tanımlar. Blog gönderileri için biçilmiş kaftan, değil mi? +* `models.DateTimeField` -bu da gün ve saati tanımlamada kullanılır. +* `models.ForeignKey` - başka bir model ile bağlantı içerir. + +Burada her detayı anlatmıyoruz, çünkü çok fazla vakit alır. Eğer detayları merak ederseniz veya farklı tür alanlar tanımlamak isterseniz Django'nun dokümantasyonlarına bakabilirsiniz (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). + +Peki `def yayinla(self):` nedir? Daha önce bahsettiğimiz `yayinla` methodudur. `def` bir fonksiyon/method olduğunu belirtir, `yayinla` ise bu methodun adıdır. İstersen methodun ismini değiştirebilirsin. Methodlara isim verirken küçük harf kullanmaya ve boşluk yerine alt çizgi kullanmaya dikkat etmemiz gerekiyor. Örneğin ortalama fiyatı hesaplayan bir methoda `ortalama_fiyati_hesapla` ismi verilebilir. + +Genellikle methodlar bir şey geri döndürür (`return` anahtar kelimesi döndür anlamına gelir). `__str__` methodunda bunun örneğini görebiliriz. Bu durumda `__str__()` methodunu çağırdığımızda Post başlığının yazısını (**string**) elde ederiz. + +Buraya kadar model hakkında anlamadığın bir şeyler varsa mentörüne sormaktan çekinme! Bu konuların biraz karmaşık olduğunun farkındayız. Özellikle hem nesneleri hem de fonksiyonları aynı anda öğrenmek kolay değil. Umarız gizemi biraz azalmaya başlamıştır! + +### Modeller için veritabanında tablo oluşturma + +Son adımımız yeni modelimizin veritabanına eklenmesini sağlamak. İlk önce Django'ya modelde bir takım değişiklikler yaptığımızı haber vermemiz gerekiyor (modeli yeni oluşturduk!). `python manage.py makemigrations blog` yazın. Şöyle görünmeli: + +``` +(myvenv) ~/djangogirls$ python manage.py makemigrations blog +Migrations for 'blog': + 0001_initial.py: + - Create model Post +``` + +Django bize veritabanımıza uygulayabileceğimiz bir taşıma (migrasyon) dosyası oluşturdu. `python manage.py migrate blog` yazdığın zaman şunu görmelisin: + +``` +(myvenv) ~/djangogirls$ python manage.py migrate blog +Operations to perform: + Apply all migrations: blog +Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK +``` + +Yaşasın! Post modelimiz artık veritabanımızda! Görsek ne güzel olur, değil mi? Gelecek bölümde Post'un nasıl göründügünü göreceğiz! diff --git a/tr/django_orm/README.md b/tr/django_orm/README.md new file mode 100755 index 00000000000..f8d1e284b29 --- /dev/null +++ b/tr/django_orm/README.md @@ -0,0 +1,176 @@ +# Django ORM ve QuerySets (Sorgu Setleri) + +Bu bölümde Django'nun veritabanına nasıl bağlandığını ve veriyi nasıl sakladığını öğreneceğiz. Hadi başlayalım! + +## QuerySet (SorguSeti) Nedir? + +QuerySet (SorguSeti), esas olarak, verilen bir modelin nesnelerinin listesidir. QuerySet veritabanından veri okumamıza, veriyi filtrelememize ve sıralamamıza imkan sağlar. + +En kolayı örnekle öğrenmektir. Hadi deneyelim, olur mu? + +## Django shell (kabuk) + +Yerel konsolumuzu açalım (PythonAnywhere'dekini değil) ve şu komutu yazalım: + +``` +(myvenv) ~/djangogirls$ python manage.py shell +``` + +Etkisi aşağıdaki gibi olmalı: + +``` +(InteractiveConsole) +>>> +``` + +Şu an Django'nun etkileşimli konsolundayız. Python istemine benziyor, ama biraz Django büyüsü eklenmiş :) Kuşkusuz burada da Python komutlarının tümünü kullanabiliriz. + +### Tüm nesneler + +Önce tüm gönderilerimizi görüntülemeyi deneyelim. Bunu aşağıdaki komut ile yapabiliriz: + +``` +>>> Post.objects.all() +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Post' is not defined +``` + +Aman! Bir hata meydana geldi. Bize bir gönderi olmadığını söylüyor. Doğru - önce gönderiyi almayı unuttuk! + +``` +>>> from blog.models import Post +``` + +`Post` modelini `blog.models` model havuzundan kolayca kodumuza dahil ettik. Şimdi bütün gönderileri tekrar göstermeyi deneyelim: + +``` +>>> Post.objects.all() +[, ] +``` + +Daha önce yarattığımız gönderilerin listesi! Bu gönderileri Django yönetici arayüzü kullanarak yaratmıştık. Şimdi ise Python kullanarak yeni gönderiler yaratmak istiyoruz, bunu nasıl yapabiliriz? + +### Nesne oluşturma + +Veritabanına yeni bir gönderi eklemek için: + +``` +>>> Post.objects.create(yazar=ben, baslik='Harika bir gönderi', yazi='Ne desem bilemedim') +``` + +Ancak bir eksiğimiz var: `ben`. Gönderinin yazar özelliğine `User` modelinden türetilen bir nesneyi parametre olarak vermemiz gerekiyor. Nasıl verebiliriz? + +Öncelikle kullanıcı modelini dahil edelim: + +``` +>>> from django.contrib.auth.models import User +``` + +Veritabanımızda hangi kullanıcılar var? Şu şekilde görebiliriz: + +``` +>>> User.objects.all() +[] +``` + +Daha önce yarattığımız ayrıcalıklı kullanıcı! Şimdi veritabanından kullanıcı nesnesi alalım: + +``` +ben = User.objects.get(username='zeynep') +``` + +Gördüğünüz gibi, `username` özelliği 'zeynep' olan `User` nesnesini `get` ile aldık. Müthiş! Tabiki, kullanıcı adını kendi kullanıcı adınıza göre ayarlamalısınız. + +Gönderimizi artık kaydedebiliriz: + +``` +>>> Post.objects.create(yazar=ben, baslik='Harika bir gönderi', yazi='Ne desem bilemedim') +``` + +Yaşasın! Çalışıp çalışmadığını kontrol etmek ister misin? + +``` +>>> Post.objects.all() +[, , ] +``` + +İşte bu kadar, listede bir gönderi daha! + +### Daha fazla gönderi ekle + +Şimdi biraz eğlenenebiliriz ve nasıl çalıştığını görmek için daha fazla gönderi ekleyebiliriz. 2-3 tane daha ekleyin ve bir sonraki kısma devam edin. + +### Nesneleri filtrelemek + +QuerySets in büyük bir parçası nesneleri filtreleyebilme kabiliyetidir. Diyelim ki, Zeynep tarafından yazılmış tüm gönderileri bulmak istiyoruz. `Post.objects.all()` içindeki `all` yerine `filter` kullanacağız. Parantez içine istediğimiz blog gönderilerinin sağlaması gereken şartları belirteceğiz. Örneğimizde, `yazar` `ben`'e eşitti. Django'da bu filtre şöyle yazılır: `yazar=ben`. Şu an kod parçacığımız şöyle görünüyor: + +``` +>>> Post.objects.filter(yazar=ben) +[, , , ] +``` + +Ya da belki `baslik` alanında içinde 'Nefis' kelimesini içeren tüm gönderileri görmek istiyoruz? + +``` +>>> Post.objects.filter(baslik__contains='Nefis') +[] +``` + +> **Not** `baslik` ve `contains` arasında iki tane alt çizgi (`_`) var. Django'nun ORM'i bu söz dizimini, özelliği ("baslik") ve operasyon veya filtreyi ("contains") ayırmak için kullanır. Sadece tek alt çizgi kullanırsanız, "FieldError: Cannot resolve keyword baslik_contains" hatası alırsınız. + +Ayrıca yayınlanmış tüm gönderilerin bir listesini alabiliriz. Bunu geçmişte `yayinlama_tarihi` alanı belirtilmiş tüm gönderileri filtreleyerek yapıyoruz: + +> > > from django.utils import timezone Post.objects.filter(yayinlama_tarihi__lte=timezone.now()) [] + +Maalesef, Python konsolundan eklediğimiz gönderi henüz yayınlanmadı. Bunu değiştirebiliriz! İlk olarak yayınlamak istediğimiz gönderinin bir örneğini alalım: + +``` +>>> post = Post.objects.get(baslik="Harika bir gönderi") +``` + +Ardından `yayinla` methodu ile gönderiyi yayınlayalım! + +``` +>>> post.yayinla() +``` + +Şimdi yayınlanmış gönderileri tekrar almaya çalışalım (3 kez yukarı yön ve ardından `enter` tuşuna basın): + +``` +>>> Post.objects.filter(yayinlama_tarihi__lte=timezone.now()) +[] +``` + +### Nesneleri Sıralama + +QuerySets ayrıca nesne listesini sıralamanızı da sağlar. Nesneleri `yaratilis_tarihi` özelliğine göre sıralamayı deneyelim: + +``` +>>> Post.objects.order_by('yaratilis_tarihi') +[, , , ] +``` + +Başına `-` ekleyerek sıralamayı tersine de çevirebiliriz: + +``` +>>> Post.objects.order_by('-yaratilis_tarihi'') +[, , , ] +``` + +### Sorgu Setlerini Zincirlemek + +Sorgu setlerini **zincirleyerek** beraber kullanabilirsiniz: + +``` +>>> Post.objects.filter(yayinlama_tarihi__lte=timezone.now()).order_by('yayinlama_tarihi') +``` + +Zincirleme gerçekten çok güçlüdür ve oldukça karmaşık sorgular yazmanıza imkan sağlar. + +Güzel! Şimdi bir sonraki bölüm için hazırız. Kabuğu kapatmak için, şunu yazalım: + +``` +>>> exit() +$ +``` \ No newline at end of file diff --git a/tr/django_start_project/README.md b/tr/django_start_project/README.md new file mode 100755 index 00000000000..4bd061ea868 --- /dev/null +++ b/tr/django_start_project/README.md @@ -0,0 +1,144 @@ +# İlk Django projen! + +> Bu bölümün kaynağı Geek Girls Carrots (http://django.carrots.pl/) eğitim materyalidir. +> +> Bölümün parçaları Creative Commons Attribution-ShareAlike 4.0 International License ile lisanslı [django-marcador tutorial][1]'a dayanılarak hazırlanmıştır. Django-marcador tutorial'ının hakları Markus Zapke-Gründemann'e aittir. + + [1]: http://django-marcador.keimlink.de/ + +Basit bir blog oluşturacağız! + +İlk adım yeni bir Django projesi başlatmaktır. Aslında, bizim için bir Django projesinin iskeletini yaratacak Django tarafından sağlanan bazı komut dosyaları çalıştıracağız. Bu sadece daha sonra kullanacağımız dosyalar ve dizinler grubudur. + +Bazı dosya ve dizinlerin isimleri Django için çok önemlidir. Oluşturmak üzere olduğumuz dosyaları yeniden adlandırmamalısınız. Onları başka bir yere taşımak da iyi bir fikir değil. Django'nun önemli şeyleri bulabilmesi için belirli yapısını koruması gerekir. + +> virtualenv içindeki her şeyi çalıştırmayı unutmayın. Eğer konsolunuzda bir önek `(myvenv)` görmüyorsanız virtualenv'nizi çalışır hale getirmelisiniz. **Django yükleme** bölümünün **virtualenv ile Çalışma** kısmında nasıl yapılacağını açıkladık. Windows'da ` myvenv\Scripts\activate` ya da Mac OS / Linux'ta `source myvenv/bin/activate` yazmak sizin için bunu yapacaktır. + +MacOS veya Linux konsolunuzda aşağıdaki komutu çalıştırmalısınız; **sonuna nokta `.` koymayı unutmayın**: + +``` +(myvenv) ~/djangogirls$ django-admin startproject mysite . +``` + +Windows'ta; ** sonunda nokta `.` koymayı unutmayın**: + +``` +(myvenv) C:\Users\Name\djangogirls> django-admin.py startproject mysite . +``` + +> Nokta `.` bu durumda çok önemlidir çünkü; koda, Django'yu şu an bulunduğunuz dizine yüklemesini söyler. ( nokta `. ` kısayol referansıdır) +> +> **Not** Yukarıdaki komutları yazarken sadece `django-admin` veya `django-admin.py` ile başlayan bölümü yazmayı unutmayın. Burada gösterilen `(myvenv) ~/djangogirls$` ve `(myvenv) C:\Users\Name\djangogirls>` kısımları, sadece, komut satırınızdaki girdilerinizi çağıracak olan komut isteği örnekleridir. + +`django-admin.py` sizin için dosya ve dizinler oluşturacak bir komut dosyasıdır. Şimdi aşağıdaki gibi görünen bir dizin yapınız olmalı: + +``` +djangogirls +├───manage.py +└───mysite + settings.py + urls.py + wsgi.py + __init__.py +``` + +`manage.py` site yönetimine yardımcı olan bir komut dosyasıdır. Bu dosya sayesinde, başka herhangi bir şey kurmadan bilgisayarımızda bir web sunucusunu başlatabileceğiz. + +`Settings.py` dosyası, web sitesinizin yapılandırmasını içerir. + +Bir mektubu nereye götüreceğini kontrol eden postacının hakkında konuştuğumuzu hatırlıyor musun? `urls.py` dosyası `urlresolver`(urlçözümleyici) tarafından kullanılan desenler listesi içerir. + +Şu an için değişiklik yapmayacağımız diğer dosyaları yoksayalım. Unutmamanız gereken tek şey kazayla onları silmeyin! + +## Ayarları değiştirme + +Hadi `mysite/settings.py` dosyasında bazı değişiklikler yapalım. Daha önceden kurduğunuz kod düzenleyicinizi kullanarak dosyayı açın. + +Web sitemizin doğru bir saate sahip olması güzel olurdu. [wikipedia timezones list][2] 'e gidin ve ilgili saat diliminizi (TZ -time zone-) kopyalayın. (örn. `Europe/Istanbul` ) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +`settings.py` dosyasında <0>TIME_ZONE ifadesini içeren satırı bulun ve kendi seçtiğiniz zaman dilimine göre uyarlayın: + +```python + TIME_ZONE = 'Europe/Istanbul' +``` + +"Europe/Istanbul" uygun şekilde değiştirildi + +Sabit dosyalar için de bir tane yol eklememiz gerekecek (Daha sonra eğitimde sabit dosyalar ve CSS hakkındaki her şeyi öğreneceğiz). Dosyanın *sonuna* en aşağı `STATIC_URL` girdisinin altına gidin ve `STATIC_ROOT` adında bir şey ekleyin: + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + +## Veritabanı Kurulumu + +Web uygulamalarınız için farklı birçok veritabanı yazılımı vardır. Biz varsayılanı kullanacağız, `sqlite3`. + +Sqlite varsayılan olduğu için zaten `mysite/settings.py` dosyamızda kurulu: + +```python + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } +``` + +Blogumuzun veritabanını oluşturmak için konsolda şu komutu çalıştırın:`python manage.py migrate` (`manage.py` dosyasını içeren `djangogirls` klasöründe olmalıyız). İşler iyi giderse şöyle bir şey görmelisiniz: + +``` +(myvenv) ~/djangogirls$ python manage.py migrate +Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth +Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... +Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK +``` + +Hepsi bu kadar! Web server'ı çalıştırma ve websitemizin çalıştığını görme zamanı! + +`manage.py` dosyasının bulunduğu dizinde olmalıyız (`djangogirls` klasörü). Konsol üzerinden `python manage.py runserver` komutunu çalıştırarak web servere başlatabilirsiniz: + +``` +(myvenv) ~/djangogirls$ python manage.py runserver +``` + +Eğer Windows'taysanız ve `UnicodeDecodeError` hatası varsa, bu komutu kullanın: + +``` +(myvenv) ~/djangogirls$ python manage.py runserver 0:8000 +``` + +Şimdi tek yapmanız gereken, sitenizin çalışıp çalışmadığını kontrol etmek. Tarayıcınızı (Firefox, Chrome, Safari, Internet Explorer ya da ne kullanıyorsanız) açın ve şu adresi girin: + +``` +http://127.0.0.1:8000/ +``` + +Web sunucusu, siz durdurana kadar komut istemi almaya devam edecektir. Server çalışıyorken daha fazla komut girebilmek için yeni bir terminal penceresi açın ve virtualenv'inizi aktive edin. Web server'ı durdurmak için çalıştığı pencereye tekrar gelin ve CTRL+C ye -Control ve C butonlarına birlikte - basın (Windows için Ctrl+Break'e basmanız gerekiyor olabilir). + +Tebrikler! ilk web siteni oluşturdun ve web server kullanarak çalıştırdın! Harika, değil mi? + +![İşte çalışıyor!][3] + + [3]: images/it_worked2.png + +Sonraki adım için hazır mısın? İçerikleri oluşturma zamanı! diff --git a/tr/django_start_project/images/it_worked2.png b/tr/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/tr/django_start_project/images/it_worked2.png differ diff --git a/tr/django_templates/README.md b/tr/django_templates/README.md new file mode 100755 index 00000000000..19d9dd70a29 --- /dev/null +++ b/tr/django_templates/README.md @@ -0,0 +1,108 @@ +# Django template + +Bazı verileri gösterme zamanı! Django bunun için bize faydalı bazı yerleşik **template etiketleri** sunuyor. + +## Template etiketleri nedir? + +Görüyoruz ki aslında, HTML'de Python kodu yazamayız, çünkü tarayıcılar bunu anlamaz. Tarayıcılar yalnızca HTML'den anlar. Biliyoruz ki Python daha dinamik bir dil iken, HTML oldukça statiktir. + +**Django template etiketleri** Python benzeri yapıların HTML'ye aktarılmasını sağlar, böylece dinamik web sitelerini daha kolay ve hızlı oluşturabiliriz! + +## Gönderi listesi template'ini göster + +Bir önceki bölümde, template'e `posts` değişkeni içinde gönderiler listesi verdik. Şimdi, bunu HTML'de göstereceğiz. + +Django şablonunda bir değişken yazdırmak için, değişken adını çift kıvrımlı parantez içinde şu şekilde kullanırız: + +```html +{{ posts }} +``` + +Bunu `blog/templates/blog/post_list.html` şablonunda deneyelim. İkinci `
`'den üçüncü `
`'e kadar olan her şeyi `{{ posts }}` ile değiştirelim. Ne olduğunu görmek için dosyayı kaydedip sayfayı yenileyelim: + +![Şekil 13.1][1] + + [1]: images/step1.png + +Gördüğümüz sadece bu: + +``` +[, ] +``` + +Yani Django bunu bir nesneler listesi olarak algılıyor. **Python'a giriş**'ten listelerin nasıl gösterildiğini hatırlıyor musun? Evet, döngülerle! Bir Django template ile bunu şöyle yaparsın: + +```html +{% for post in posts %} + {{ post }} +{% endfor %} +``` + +Bunu kendi template'imizle deneyelim. + +![Şekil 13.2][2] + + [2]: images/step2.png + +İşe yarıyor! Fakat bunların daha önce **HTML'ye giriş** bölümünde oluşturduğumuz statik gönderiler gibi görünmesini istiyoruz. HTML ve template etiketlerini karıştırabiliriz. `body` şöyle görünecektir: + +```html + + +{% for post in posts %} +
+

published: {{ post.yayinlama_tarihi }}

+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+{% endfor %} +``` + +{% raw %}`{% for %}` ve `{% endfor %}` arasına koyduğunuz her şey listedeki her nesne için tekrarlanır. Sayfanı yenile:{% endraw %} + +![Şekil 13.3][3] + + [3]: images/step3.png + +`{{ post.baslik }}` ya da `{{ post.yazi }}` için biraz farklı bir yazım kullandığımızı farkettin mi? Böylece `Post` modelinde tanımlanan alanlardaki verilere ulaşıyoruz. Ayrıca `|linebreaksbr` (satırsonu), gönderilerin metnini, satır sonlarını paragraflara çeviren bir filtreden geçiriyor. + +## Bir şey daha + +Web sitemizin İnternet'te hâlâ çalıştığını görmek iyi olacak, değil mi? PythonAnywhere yükleyelim yine. Adımları hatırlayalım... + +* İlk önce kodumuzu Github'a push komutu ile yükleyelim + +``` +$ git status +[...] +$ git add --all . +$ git status +[...] +$ git commit -m "Veritabanındaki postları görebilmek için template'i değiştirdim." +[...] +$ git push +``` + +* [PythonAnywhere][4]'e bağlanalım ve **Bash konsolu**'na gidelim (veya yeni bir konsol açalım) ve şunu çalıştıralım: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd ilk-blogum +$ git pull +[...] +``` + +* Ve son olarak da [Web tab][5] sekmesine gidip web uygulamamızdaki **Reload**'a basalım. Şimdi güncellememiz yayında olmalı! + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +Tebrikler! Şimdi devam edelim ve Django admininde yeni bir gönderi eklemeyi deneyelim (yayinlama_tarihi eklemeyi unutmayalım!), sonrasında gönderinin görünüp görünmediğini görmek için sayfayı yenileyelim. + +Şiir gibi çalışıyor, değil mi? Gurur duyabiliriz! Şimdi bilgisayar başından bir süre kalkalım, çünkü bir molayı hak ettik. :) + +![Şekil 13.4][6] + + [6]: images/donut.png \ No newline at end of file diff --git a/tr/django_templates/images/donut.png b/tr/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/tr/django_templates/images/donut.png differ diff --git a/tr/django_templates/images/step1.png b/tr/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/tr/django_templates/images/step1.png differ diff --git a/tr/django_templates/images/step2.png b/tr/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/tr/django_templates/images/step2.png differ diff --git a/tr/django_templates/images/step3.png b/tr/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/tr/django_templates/images/step3.png differ diff --git a/tr/django_urls/README.md b/tr/django_urls/README.md new file mode 100755 index 00000000000..a3a05b0f9c0 --- /dev/null +++ b/tr/django_urls/README.md @@ -0,0 +1,126 @@ +# Django url'leri + +İlk web sayfamızı yapmak üzereyiz: blogunuzun anasayfası! Ama önce, biraz Django url'lerini öğrenmeye başlayalım. + +## URL nedir? + +URL basitçe bir web adresidir. Bir web sayfasını her ziyaret ettiğinizde tarayıcınızın adres barında bir URL görürsünüz (evet! `127.0.0.1:8000` bir URL'dir! Ve `https://djangogirls.org` da bir URL'dir): + +![Url][1] + + [1]: images/url.png + +Internetteki her sayfanın kendi URL'inin olması gerekir. Böylelikle bir URL açıldığında uygulama ne göstermesi gerektiğini bilir. Django'da `URLconf` (URL konfigürasyonu) denilen bir şey kullanıyoruz. URLconf, Django'ya gelen URL için doğru view'un bulunmasını sağlar. + +## URL'ler Django'da nasıl çalışır? + +Kod editörümüzde `mysite/urls.py` dosyasını açalım ve neye benzediğine bakalım: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` + +Gördüğünüz gibi Django bizim için bir şeyler koymuş bile. + +`#` ile başlayan satırlar yorum satırlarıdır - bu satırlar Python tarafından çalıştırılmayacak manasına gelir. Çok pratik, değil mi? + +Geçen bölümde gittiğimiz admin URL şimdiden burda: + +```python + url(r'^admin/', include(admin.site.urls)), +``` + +`admin` ile başlayan her URL için Django ona denk gelen bir *view* bulur manasına gelir. Bu şekilde bir sürü admin URLlerini ekliyoruz böylece hepsi bu küçük dosyanın içinde sıkıştırılmış bir şekilde durmuyor -- bu hali daha okunabilir ve düzenli. + +## Regex (Kurallı İfade) + +Django'nun URL'leri view'larla nasıl eşleştirdiğini merak ediyor musunuz? Bu kısım biraz karışık. Django bunun için `regex` kullanıyor. Regex, "regular expressions"ın kısaltılmış hali ve düzenli ifadeler anlamına geliyor. Regex'in bir arama kalıbı oluşturmak için birçok (birçok!) kuralı var. Regexler ileri bir konu olduğu için nasıl çalıştığının detayına girmeyeceğiz. + +Gene de kalıpları nasıl oluşturduğumuzu anlamak isterseniz, aşağıdaki bir örnek var - aradığımız kalıbı oluşturmak için kuralların sadece bir kısmına ihtiyacımız olacak, şöyle: + +``` +^ metnin başlangıcı için +$ metnin sonu için +\d rakamlar için ++ bir önceki karakterin en az bir kere bulunması gerektiğini belirtmek için +() kalıbın belli bir kısmını yakalamak için +``` + +Url tanımındaki diğer herşey birebir eşlenecek. + +Şimdi `http://www.mysite.com/post/12345/` adresinde bir websitemiz olduğunu düşünelim. `12345` da gönderimizin numarası. + +Her gönderi için ayrı bir view yazmak gerçekten can sıkıcı olurdu. Düzenli ifadelerle (regexlerle) url ile eşlecek bir kalıp oluşturup gönderi numarasını çıkartabiliriz: `^post/(\d+)/$`. Parçalara bölüp ne yaptığımıza bakalım: + +* **^post/** Django'ya `post/` ile başlayan her şeyi almasını söylüyor ( `^`) +* **(\d+)** ise bir sayı (birden fazla rakam) olduğunu ve bu sayıyı yakalamak ve çıkarmak istediğimizi belirtiyor +* **/** ise Django'ya arkasından bir `/` karakteri gelmesi gerektiğini söylüyor +* **$** ise URL'nin sonuna işaret ediyor, yani sadece sonu `/` ile biten string'ler bu kalıpla eşleşecek + +## İlk Django url'niz! + +İlk URL'imizi oluşturma zamanı! 'http://127.0.0.1:8000/'ın blogumuzun ana sayfası olmasını istiyoruz ve bize bir gönderi listesi göstermesini istiyoruz. + +Aynı zamanda `mysite/urls.py` dosyasını basit tutmak istiyoruz, bunun için ana `mysite/urls.py` dosyasına `blog` uygulamamızdan url'leri import edeceğiz (içeri alacağız). + +Yorum satırlarını silin (`#` ile başlayan satırları) ve ana url'ye `blog.urls` satırlarını import edecek (içeri alacak) bir satır ekleyin (`''`). + +`mysite/urls.py` dosyanız şöyle olmalıdır: + +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + +Django artık 'http://127.0.0.1:8000/'ye gelen her şeyi `blog.urls`'ya yönlendirecek ve ordaki yönergelere bakacak. + +Python'da düzenli ifadeler her zaman string'in başına `r` ekleyerek yapılır. Bu Python için string'in özel karakterler içerdiğini, doğrudan Python için değil düzenli ifadeler için bir string olduğu konusunda ipucu verir. + +## blog.urls + +`blog/urls.py` adında yeni boş bir dosya oluşturun. Harika! Şu iki satırı ekleyin: + +```python +from django.conf.urls import url +from . import views +``` + +Burada sadece Django'nun methodlarını ve `blog` uygulamasındaki tüm `view`leri içeri aktarıyoruz (uygulamamız henüz yok, ama birazdan o kısma da geçeceğiz!) + +Bundan sonra ilk URL kalıbımızı ekleyebiliriz: + +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` + +Gördüğünüz üzere, `^$` URL'sine `post_list` adında bir `view` atıyoruz. Bu düzenli ifade `^` (başlangıç) ve `$` (bitiş)'e uyan stringlerle eşleşir - yani sadece boş string'lerle eşleşir. Bu doğru çünkü Django URL çözücülerinde 'http://127.0.0.1:8000/' URL'nin parçası değildir. Bu kalıp, Django'ya eğer siteye biri 'http://127.0.0.1:8000/' adresinden gelirse gitmesi gereken yerin `views.post_list` olduğunu söylüyor. + +Son kısım olan `name='post_list'` view'u tanımlamak için kullanılan URL'nin adı. Bu view'un adı ile aynı olabilir ama tamamen farklı bir şey de olabilir. Named URL'leri (isimlendirilmiş URL'leri) projenin ilerleyen kısımlarında kullanacağız, o yüzden uygulamadaki her URL'yi isimlendirmemiz önemli. Aynı zamanda URL isimlerini tekil ve kolay hatırlanabilir yapmamız gerekir. + +Her şey tamam mı? Tarayıcınızda http://127.0.0.1:8000/'ye gidin ve sonuçları görün. + +![Hata][2] + + [2]: images/error1.png + +Artık "It works" demiyor, di mi? Meraklanmayın, sadece bir hata sayfası, korkacak birşey yok! Aslında çok kullanışlılar: + +Sayfada gördüğünüz şey: **no attribute 'post_list'**. *post_list* size bir şey hatırlatıyor mu? Bu view'un ismi! Bu her şey yerli yerinde sadece henüz *view* yok manasına geliyor. Hiç merak etmeyin, oraya geleceğiz. + +> Django URLconfs ile ilgili daha fazla bilgi edinmek istiyorsanız resmi dokümantasyona bakabilirsiniz: https://docs.djangoproject.com/en/1.8/topics/http/urls/ \ No newline at end of file diff --git a/tr/django_urls/images/error1.png b/tr/django_urls/images/error1.png new file mode 100644 index 00000000000..8bf6b9829a1 Binary files /dev/null and b/tr/django_urls/images/error1.png differ diff --git a/tr/django_urls/images/url.png b/tr/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/tr/django_urls/images/url.png differ diff --git a/tr/django_views/README.md b/tr/django_views/README.md new file mode 100755 index 00000000000..c28c8f0705e --- /dev/null +++ b/tr/django_views/README.md @@ -0,0 +1,38 @@ +# Django views - yaratma zamanı geldi! + +Evvelki bölümde yaptığımız hatayı yok edelim :) + +*view*, "uygulama mantığının" ifade edildiği yerdir. Daha önce oluşturulan `model` den bilgi alıp `template`'e iletir. Gelecek bölümde bir template oluşturacağız. View'ler bildiğiniz Python methodlarıdır. Ancak, **Python'a Giriş** bölümünde yazdığımız methodlardan biraz daha karmaşıktır. + +View'ler `views.py` doyasına yazılır. Şimdi, `blog/views.py` dosyasına *view* ekleyelim. + +## blog/views.py + +Dosyayı açıp inceleyelim: + +```python +from django.shortcuts import render + +# View'lar buraya yazılacak. +``` + +Henüz fazla bir şey görünmüyor. En basitinden *view* şöyle olabilir. + +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Burada, `request (istek)` i alıp template `blog/post_list.html` ile görüntüleyen `render` methodunu `döndüren` `post_list` isimli bir method yarattık. + +Dosyamızı kaydedelim ve http://127.0.0.1:8000/ e gidip bakalım. + +Yine hata! Okuyup anlamaya çalışalım: + +![Hata][1] + + [1]: images/error.png + +Bu hatayı düzeltmek kolay: *TemplateDoesNotExist* (Template bulunamadı). Bu hatayı template oluşturarak gelecek bölümde düzeltelim! + +> Django view hakkında daha fazla bilgi edinmek için dokümantasyonları okuyun: https://docs.djangoproject.com/en/1.8/topics/http/views/ \ No newline at end of file diff --git a/tr/django_views/images/error.png b/tr/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/tr/django_views/images/error.png differ diff --git a/tr/domain/README.md b/tr/domain/README.md new file mode 100755 index 00000000000..2623864b4bb --- /dev/null +++ b/tr/domain/README.md @@ -0,0 +1,71 @@ +# Domain (Alan Adı) + +Heroku size bir alan adı verdi, ama uzun, hatırlaması zor ve çirkin. Kısa ve kolay hatırlanabilir bir alan adı olsaydı harika olurdu, değil mi? + +Bu bölümde size yeni bir alan adı satın alıp Heroku'ya yönlendirmeyi öğreteceğiz! + +## Alan adını nerden alabiliriz? + +Bir alan adı ortalamada senelik $15 civarında oluyor. Alan adı sağlayıcısına göre daha ucuzları ve daha pahalıları var. Alan adı satın alabileceğiniz bir sürü şirket var: basit bir [google araması][1] size yüzlerce seçenek getirir. + + [1]: https://www.google.com/search?q=register%20domain + +Bizim favorimiz [I want my name][2]. Kendilerini "acısız alan adı yönetimi" diye nitelendiriyorlar ve gerçekten acısız. + + [2]: https://iwantmyname.com/ + +## IWantMyName ile alan adı nasıl satın alınır? + +[iwantmyname][3]'e gidin ve arama kutusuna istediğiniz alan adını girin. + + [3]: https://iwantmyname.com + +![][4] + + [4]: images/1.png + +Aradığınız ada sahip alan adlarının bir listesini görüyor olmanız lazım. Gülen surat, alan adını alabileceğinizi; üzülen surat ise alan adının halihazırda başkasında olduğunu gösteriyor. + +![][5] + + [5]: images/2.png + +`djangogirls.in` alan adını almaya karar verdik: + +![][6] + + [6]: images/3.png + +'Checkout'a gidin. Eğer hesabınız yoksa, kaydolmanız gerekir. Arkasından kredi kartı bilgilerinizi girin ve alan adını satın alın! + +Menüde '`Domains`'e (alan adları) tıklayın ve yeni satın alınmış alan adınızı seçin. Arkasından `managen DNS records` (DNS kayıtlarınızı yönetin) linkine tıklayın: + +![][7] + + [7]: images/4.png + +Arkasından bu formu bulmanız gerekiyor: + +![][8] + + [8]: images/5.png + +Ve aşağıdaki detayları girin: - Hostname: www - Type: CNAME - Value: Heroku'daki alan adınız (örneğin djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +Önce 'Add' (ekle) butonuna tıklayın. Sonra da alttaki 'Save Changes'e (değişiklikleri kaydet) tıklayın. + +Alan adınızın çalışır hale gelmesi birkaç saati sürebilir, sabırlı olun! + +## Alan adını Heroku'da Ayarlayın + +Heroku'ya da kendi özel alan adınızı kullanmak istediğinizi belirtmeniz gerekiyor. + +[Heroku Dashboard][10]'una gidin, Heroku hesabınıza girin ve uygulamanızı seçin. 'Settings'e (ayarlar) girin ve `Domains` (alan adı) kısmına alan adınızı girin. Değişiklikleri kaydedin. + + [10]: https://dashboard.heroku.com/apps + +İşte bu kadar! \ No newline at end of file diff --git a/tr/dynamic_data_in_templates/README.md b/tr/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..536a99c3bea --- /dev/null +++ b/tr/dynamic_data_in_templates/README.md @@ -0,0 +1,75 @@ +# Template içerisinde dinamik veri + +Birkaç parçayı yerine oturttuk: `Post` (gönderi) modelini `models.py`'de tanımladık, `views.py`'de `post_list` (gönderi listesi) var ve template ekledik. Ama gönderilerimizi HTML'de görünür kıldık mı? Çünkü bu yapmak istediğimiz şey: içeriği (veritabanında kayıtlı modellerimiz) al ve güzelcene template içerisinde göster, değil mi? + +Bu tam olarak *view*'lerin yapmasını beklediğimiz şey: modelleri ve template'leri bağlamak. `post_list` *view*'de göstermek istediğimiz modelleri alıp template'e iletmemiz gerekecek. Yani temelde bir *view*de template içinde neyin (hangi modelin) gösterileceğine karar veriyoruz. + +Peki, bunu nasıl yapacağız? + +`blog/views.py`'ı açacağız. Şu anda `post_list` *view*ü şöyle: + +```python +from django.shortcuts import render + +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + +Kodları farklı dosyalara eklemekten bahsettiğimizi hatırlıyor musunuz? Şimdi `models.py`'de yazdığımız modeli ekleme zamanı. `from .models import Post` satırını şu şekilde ekleyeceğiz: + +```python +from django.shortcuts import render +from .models import Post +``` + +`from`'dan sonraki nokta, *mevcut dizin* veya *mevcut uygulama* anlamına geliyor. `views.py` ve `models.py` aynı dizinde oldukları için sadece `.` ve dosyanın adı (`.py` olmadan) kullanabiliyoruz. Arkasından modelin adını (`Post`)'u dahil ediyoruz). + +Sırada ne var? `Post` modelinden gönderileri almamız için `QuerySet` dediğimiz bir şeye ihtiyacımız var. + +## QuerySet (Sorgu Seti) + +QuerySet'in nasıl çalıştığı konusunda bir fikriniz oluşmuştur. [Django ORM (QuerySets) bölümü][1]nde konuşmuştuk. + + [1]: ../django_orm/README.md + +Şimdi yayınlanmış ve `yayinlama_tarihi`'ne göre sıralanmış bir gönderi listesi istiyoruz, değil mi? Bunu QuerySets bölümünde yapmıştık zaten! + +``` +Post.objects.filter(yayinlama_tarihi__lte=timezone.now()).order_by('yayinlama_tarihi') +``` + +Şimdi bu kodu `blog/views.py` dosyasında `def post_list(request)` fonksiyonuna ekleyelim: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(yayinlama_tarihi__lte=timezone.now()).order_by('yayinlama_tarihi') + return render(request, 'blog/post_list.html', {}) +``` + +QuerySet'imiz için bir *değişken* yarattığımıza dikkat edin: `posts`. Bu QuerySet'in ismi. Bundan sonra ondan ismi ile bahsedebiliriz. + +Bu kod `timezone.now()` fonksiyonunu kullanıyor, dolayısıyla `timezone` için bir 'import' eklememiz gerekiyor. + +Son eksik kalan kısım `posts` QuerySet'ini template'e iletmek (nasıl göstereceğimizi bir sonraki bölümde işleyeceğiz). + +`render` fonksiyonunda halihazırda `request` diye bir parametremiz var (dolayısıyla Internet üzerinden kullanıcı ile ilgili aldığımız her şey) ve bir de template dosyamız `'blog/post_list.html'` var. `{}` şeklindeki son parametremiz, template içinde kullanılmak üzere bir şeyler ekleyebileceğimiz bir değişken. Bunlara isimler vermemiz gerekiyor (`'posts'` ismini kullanmaya devam edeceğiz şimdilik :)). Şöyle olması lazım: `{'posts': posts}`. `:`'dan önceki kısmın bir string olduğuna dikkat edin; etrafına tek tırnak koymanız gerekiyor `''`. + +Nihayetinde `blog/views.py` şu şekle gelmiş olmalı: + +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(yayinlama_tarihi__lte=timezone.now()).order_by('yayinlama_tarihi') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` + +İşte bu kadar! Template'e geri gidip QuerySet'leri görünür hale getirme zamanı! + +Django'da QuerySet'lerle ilgili daha fazla bilgi istiyorsanız şuraya bakabilirsiniz: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ \ No newline at end of file diff --git a/tr/extend_your_application/README.md b/tr/extend_your_application/README.md new file mode 100755 index 00000000000..322759c5365 --- /dev/null +++ b/tr/extend_your_application/README.md @@ -0,0 +1,190 @@ +# Uygulamanı genişlet + +Websitemizi oluşturmak için gerekli adımların hepsini tamamladık: bir modelin, url'nin, view'ün ve template'in nasıl yazılacağını biliyoruz. Websitemizi nasıl güzelleştirebiliriz onu da biliyoruz. + +Pratik zamanı! + +Blog'umuzda lazım olan ilk şey bir gönderiyi göstermek için bir sayfa, değil mi? + +Halihazırda bir `Post` modelimiz var, dolayısıyla `models.py` dosyasına bir şey eklememize gerek yok. + +## Bir gönderinin detayı için bir şablon linki oluşturun + +`blog/templates/blog/post_list.html` dosyasına bir link (bağlantı) ekleyerek başlayacağız. Şu ana kadar yaptıklarımızın şöyle gözüküyor olması lazım: + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.yayinlama_tarihi }} +
+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + + +{% raw %}Gönderi listesindeki bir gönderinin başlığından bir gönderinin detay sayfasına bir link (bağlantı) olsun istiyoruz. `

{{ post.baslik }}

`'i gönderinin detay sayfasına link verecek şekilde değiştirelim:{% endraw %} + +```html +

{{ post.baslik }}

+``` + +{% raw %}Gizemli `{% url 'post_detail' pk=post.pk %}` satırını anlatma zamanı. Şüphelendiğiniz üzere, `{% %}` notasyonu, Django template tags (şablon etiketleri) kullandığımız manasına geliyor. Bu sefer bizim için URL oluşturacak bir template etiketi kullanacağız!{% endraw %} + +`blog.views.post_detail`, oluşturmak istediğimiz `post_detail` *view*'una bir yol. Lütfen dikkat: `blog` uygulamamızın adı (`blog` dizini); `views`, `views.py` dosyasının adından geliyor ve son kısım - `post_detail` - *view*'ün adından geliyor. + +Şimdi http://127.0.0.1:8000/'ye gittiğimizde bir hata alacağız (beklediğimiz bir şey, çünkü URL'miz veya `post_detail` için bir *view*'ümüz yok). Şöyle görünecektir: + +![NoReverseMatch error (Tersi yok hatası)][1] + + [1]: images/no_reverse_match2.png + +## Bir gönderinin detayı için URL oluşturun + +`post_detail` *view*'ümüz için `urls.py`'un içinde bir URL oluşturalım! + +İlk gönderimizin detayının şu **URL**'de gösterilmesini istiyoruz: http://127.0.0.1:8000/post/1/ + +`blog/urls.py` dosyasında `post_detail` adında bir Django *view*'una işaret eden bir URL yapalım. Bu <1>view bir gönderinin tümünü gösterecek. `blog/urls.py` dosyasına `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` satırını ekleyin. Dosyanın şu hale gelmiş olması gerekiyor: + + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + +Şu kısım `^post/(?P[0-9]+)/$` korkutucu gözüküyor, ama endişelenmeyin, açıklayacağız: - Gene `^` ile başlıyor. - "başlangıç' - `post/` sadece URL'nin başlangıçtan sonra **post** ve **/<1> ifadelerinin geçmesi gerektiği anlamına geliyor. Şimdilik iyi gidiyor. - `(?P[0-9]+)` - bu kısım biraz daha karışık. Buranın anlamı şu: Django bu alana yerleştirdiğimiz her şeyi alacak ve onu `pk` adında bir değişken olarak view'e aktaracak. `[0-9]` bize eşleşenlerin sadece rakam (yani harf olamaz) olabileceğini söylüyor (0 ile 9 arasındaki her şey). `+` en az bir veya daha fazla rakam olması gerektiğini ifade ediyor. Yani `http://127.0.0.1:8000/post//` eşleşmez ama `http://127.0.0.1:8000/post/1234567890/` eşleşir! - `/` - gene **/** - `$` - "son"!

+Bu şu demek, eğer tarayıcınıza `http://127.0.0.1:8000/post/5/` yazarsanız, Django `post_detail` adında bir *view* aradığınızı anlar ve `pk` eşittir `5` bilgisini *view*'e aktarır. + +`pk`, `primary key`'in (tekil anahtarın) kısaltılmış hali. Bu isim sıklıkla Django projelerinde kullanılır. Değişkeninize istediğiniz ismi verebilirsiniz (hatırlayın: küçük harfler ve boşluk yerine `_`!). Örneğin `(?P[0-9]+)` yerine `post_id` değişkenini kullanabilirdik. O zaman şöyle olurdu: `(?P[0-9]+)`. + +Tamam, `blog/urls.py` dosyasına yeni bir URL kalıbı ekledik! Sayfayı tazeleyelim: http://127.0.0.1:8000/ Bam! Yeni bir hata daha! Beklenildiği üzere! + +![AttributeError (Özellik hatası)][2] + +Bir sonraki adımın ne olduğunu hatırlıyor musunuz? Tabi ki: view'ü eklemek! + +## Gönderi detayı için bir view ekleyin + +Bu sefer *view*'ümüze `pk` adında bir parametre ekleyeceğiz. *view*'ümüzün onu yakalaması gerekiyor, değil mi? Fonksiyonumuzu `def post_detail(request, pk):` olarak tanımlayacağız. Dikkat edin, url'lerde kullandığımız ismin birebir aynısını kullanmamız gerekiyor (`pk`). Bu değişkeni kullanmamak yanlıştır ve hataya sebep olacaktır! + +Şimdi sadece ve sadece bir blog gönderisini almak istiyoruz. Bunu yapmak için querysets'i şu şekilde kullanabiliriz: + +``` +Post.objects.get(pk=pk) +``` + +Ama bu kodun bir problemi var. Eğer gelen `primary key` (`pk` - tekil anahtar) ile bir `Post` (gönderi) yoksa, çok çirkin bir hatamız olacak! + +![DoesNotExist error (Yok hatası)][3] + +Bunu istemiyoruz! Ama tabi Django'da bunu ele alan bir şey var: `get_object_or404`. Eğer verilen `pk` ile bir `Post` bulunamazsa, çok daha güzel bir sayfa gösterilecek (`Sayfa bulunamadı 404` sayfası). + +![Page not found (Sayfa bulunamadı)][4] + +İyi haber şu, kendi `Sayfa bulunamadı` sayfasını yapabilir ve istediğiniz kadar güzelleştirebilirsiniz. Ama şu anda çok önemli değil, o yüzden bu kısmı atlayacağız. + +Evet, `views.py` dosyamıza bir *view* ekleme zamanı! + +`blog/views.py` dosyasını açıp aşağıdaki kodu ekleyelim: + +``` +from django.shortcuts import render, get_object_or_404 +``` + +Bunu diğer `from` satırlarının yakınına eklememiz gerekiyor. Dosyanın sonuna *view*'ümüzü ekleyeceğiz: + +``` +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + +Evet. http://127.0.0.1:8000/ sayfasını tazeleme zamanı + +![Post list view (Gönderi listesi görünümü)][5] + +Çalıştı! Fakat blog gönderisi başlığındaki bir bağlantıya tıkladığınızda ne oluyor? + +![TemplateDoesNotExist error (Template yok hatası)][6] + +Of hayır! Başka bir hata! Ama onu nasıl halledeceğimizi biliyoruz, di mi? Bir template eklememiz gerekiyor! + +## Gönderi detayı için bir template oluşturun + +`blog/templates/blog` dizininde `post_detail.html` adında bir dosya oluşturacağız. + +Şöyle görünmeli: + +```html +{% extends 'blog/base.html' %} + +{% block content %} +
+ {% if post.yayinlama_tarihi %} +
+ {{ post.yayinlama_tarihi }} +
+ {% endif %} +

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+{% endblock %} +``` + +Bir kere daha `base.html` dosyasını genişleteceğiz. `content` bloğunda bir gönderinin varsa yayınlama tarihini , başlığını ve metnini göstermek istiyoruz. Ama daha önemli şeyleri konuşmalıyız, değil mi? + +{% raw %}`{% if ... %} ... {% endif %}` bir şeyi kontrol etmek istediğimizde kullanabileceğimiz bir template etiketidir ( **Python'a giriş** bölümünden <1>if ... else .. 'i hatırladınız mı?). Bu senaryoda gönderinin `yayinlama_tarihi`'nin boş olup olmadığına bakmak istiyoruz.{% endraw %} + +Tamam, sayfamızı tazeleyip `Sayfa bulunamadı` hatasının gidip gitmediğine bakabiliriz. + +![Post detail page (Gönderi detay sayfası)][7] + +Heyo! Çalışıyor! + +## Bir şey daha: deployment (yayına alma) zamanı! + +Sitenizin hala PythonAnywhere'de çalışıp çalışmadığına bakmakta fayda var, değil mi? Yeniden taşımayı deneyelim. + +``` +$ git status +$ git add --all . +$ git status +$ git commit -m "Detaylı blog gönderileri için CSS'e ilaveten view ve template eklendi." +$ git push +``` + +* Sonra bir [PythonAnywhere Bash konsol][8] una gidip: + +``` +$ cd ilk-blogum +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* Nihayet, [Web tab][9] ına gidip **Reload** edelim. + +O kadar! Tebrikler :) + + [2]: images/attribute_error2.png + [3]: images/does_not_exist2.png + [4]: images/404_2.png + [5]: images/post_list2.png + [6]: images/template_does_not_exist2.png + [7]: images/post_detail2.png + [8]: https://www.pythonanywhere.com/consoles/ + [9]: https://www.pythonanywhere.com/web_app_setup/ diff --git a/tr/extend_your_application/images/404_2.png b/tr/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/tr/extend_your_application/images/404_2.png differ diff --git a/tr/extend_your_application/images/attribute_error2.png b/tr/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/tr/extend_your_application/images/attribute_error2.png differ diff --git a/tr/extend_your_application/images/does_not_exist2.png b/tr/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/tr/extend_your_application/images/does_not_exist2.png differ diff --git a/tr/extend_your_application/images/no_reverse_match2.png b/tr/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/tr/extend_your_application/images/no_reverse_match2.png differ diff --git a/tr/extend_your_application/images/post_detail2.png b/tr/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/tr/extend_your_application/images/post_detail2.png differ diff --git a/tr/extend_your_application/images/post_list2.png b/tr/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/tr/extend_your_application/images/post_list2.png differ diff --git a/tr/extend_your_application/images/template_does_not_exist2.png b/tr/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/tr/extend_your_application/images/template_does_not_exist2.png differ diff --git a/tr/how_the_internet_works/README.md b/tr/how_the_internet_works/README.md new file mode 100755 index 00000000000..4da59c92276 --- /dev/null +++ b/tr/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# İnternet nasıl çalışır + +> Bu bölüm Jessica McKellar'ın "How the Internet works" yani "İnternet nasıl çalışır" adlı bir konuşmasından esinlenerek oluşturuldu. (http://web.mit.edu/jesstess/www/). + +Bahse varız ki İnternet'i her gün kullanıyorsunuz. Fakat tarayıcınıza https://djangogirls.org gibi bir adres girip `enter` tuşuna bastığınızda neler olduğunu biliyor musunuz? + +Öncelikle bir web sitesinin bir sabit diske kaydedilmiş bir grup dosya olduğunu anlamanız gerekir. Tıpkı filmleriniz, müzikleriniz ya da resimleriniz gibi. Ancak, web sitelerine özel şöyle bir durum var: HTML adı verilen bir bilgisayar kodu içerirler. + +Eğer programlamaya aşina değilseniz HTML'yi kavramak başlangıçta zor olabilir, ama web tarayıcılarınız (Chrome, Safari, Firefox, vs.) ona bayılıyor. Web tarayıcılarınız bu kodu anlamak, komutlarını yerine getirmek ve size bu websitesini oluşturan dosyaları sunmak için tasarlanmıştır, tam da olmasını istediğiniz gibi. + +Her dosya gibi, bu HTML dosyalarını da sabit diskte bir yerde saklamamız gerekir. Internet için, *sunucu* denilen özel ve güçlü bilgisayarlar kullanıyoruz. Bir ekranları, fareleri ya da klavyeleri yok çünkü esas amaçları veriyi saklamak ve sunmak. Bu yüzden onlara *sunucu* diyoruz -- çünkü size veri *sunuyorlar*. + +Peki, fakat İnternet'in nasıl göründüğünü bilmek istiyorsunuz. Değil mi? + +Size bir resmini çizdik, İnternet işte buna benzer: + +![Şekil 1.1][1] + + [1]: images/internet_1.png + +Çok karışık, değil mi? Aslında bu birbirine bağlı makinelerin(yukarıda bahsi geçen *sunucu*lar) birbirine bağlandığı bir ağ. Yüz binlerce makine! Dünyanın dört bir yanını saran yüz binlerce kilometrelik kablolar! İnternet'in ne kadar karışık olduğunu görmek için denizaltı kablo haritası web sitesine(http://submarinecablemap.com) göz atabilirsiniz. İşte web sitesinden bir ekran görüntüsü: + +![Şekil 1.2][2] + + [2]: images/internet_3.png + +Büyüleyici, değil mi? Ama açıkça belli ki, İnternet'e bağlanan tüm makineler arasında kablolar olması mümkün değil. Yani, bir makineye ulaşmak için( örneğin https://djangogirls.org web sitesinin kayıtlı olduğu) bir çok farklı makineden istek geçmesi gerekli. + +Şöyle gözükmekte: + +![Şekil 1.3][3] + + [3]: images/internet_2.png + +Tarayıcınıza https://djangogirls.org yazdığınızda, "Sevgili Django Girls, ben djangogirls.org web sitesini görmek istiyorum. Lütfen bana gönderin!" diyen bir mektup gönderdiğinizi düşünün. + +Mektubunuz size en yakın postaneye gider. Daha sonra sizden biraz daha uzak bir postaneye gider, daha sonra biraz daha uzaktakine, daha uzağa ve en son gitmesi gereken yere. Tek farklı olan, aynı yere bir çok mektup(*veri paketi*) gönderirseniz, tamamen farklı postanelerden(*yönlendirici*) geçebilir. Bu, her bir postanede nasıl dağıtım yapıldığına bağlıdır. + +![Şekil 1.4][4] + + [4]: images/internet_4.png + +Evet, bu kadar basit. Bir mektup yollarsınız ve cevap beklersin. Tabii ki, kağıt kalem yerine bayt biriminde veri kullanırsınız, fakat fikir aynı! + +Sokak adı, şehir, alan kodu ve ülke adı yerine, biz IP adreslerini kullanırız. Bilgisayarınız ilk olarak DNS'den (Domain Name System - Alan Adı Sistemi) djangogirls.org adresini bir IP adresine çevirmesini ister. Bu biraz ulaşmak istediğiniz kişinin adına bakarak telefon numarası ve adresini bulabildiğiniz eski telefon rehberleri gibi çalışır. + +Bir mektup gönderdiğinizde, bazı özelliklerin doğru teslim edilmesi gerekecektir: bir adres, pul vs. Ayrıca alıcının anlayacağı bir dil kullanıyorsunuz, değil mi? Aynısı bir web sitesini görmek için gönderdiğiniz *veri paketleri* için de geçerli. HTTP(Hypertext Transfer Protocol - HiperMetin transfer protokolü) adı verilen bir protokol kullanırız. + +Basit olarak, bir web siteniz olduğunuzda, içinde yaşayacağı bir *sunucu* makineniz olması gerekli. *Sunucu* (bir mektupla gelen) bir *istek* aldığında, (başka bir mektupla) size web sitenizi gönderir. + +Bu bir Django eğitimi olduğu için, Django'nun ne yaptığını soracaksınız. Bir yanıt gönderirken, herkese her zaman aynı şeyi göndermek istemezsiniz. Mektupları özellikle size yazan kişi için kişiselleştirmek çok daha iyi, değil mi? Django bu kişiselleştirilmiş, ilginç mektupları yazmanıza yardımcı olur :). + +Bu kadar konuşma yeter, bir şeyler yaratma vakti! \ No newline at end of file diff --git a/tr/how_the_internet_works/images/internet_1.png b/tr/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/tr/how_the_internet_works/images/internet_1.png differ diff --git a/tr/how_the_internet_works/images/internet_2.png b/tr/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/tr/how_the_internet_works/images/internet_2.png differ diff --git a/tr/how_the_internet_works/images/internet_3.png b/tr/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/tr/how_the_internet_works/images/internet_3.png differ diff --git a/tr/how_the_internet_works/images/internet_4.png b/tr/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/tr/how_the_internet_works/images/internet_4.png differ diff --git a/tr/html/README.md b/tr/html/README.md new file mode 100755 index 00000000000..f941d5fd368 --- /dev/null +++ b/tr/html/README.md @@ -0,0 +1,217 @@ +# HTML'ye giriş + +Template nedir diye sorabilirsiniz. + +Template, farklı bilgileri hep aynı biçimde sunmak için tekrar tekrar kullanabileceğimiz bir dosyadır - örneğin, mektup yazmanıza yardımcı olan bir template kullanabilirsiniz çünkü yazacağınız tüm mektuplar farklı mesajlar içerse ve farklı kişilere gönderilse de aynı sayfa düzenine sahip olacaktır. + +Bir Django template düzeni HTML adını verdiğimiz bir dilde tanımlanır (**İnternet nasıl çalışır** adlı ilk bölümde bahsettiğimiz HTML). + +## HTML nedir? + +HTML Chrome, Firefox veya Safari gibi web tarayıcılar tarafından bir web sayfasını kullanıcıya görüntülemek için yorumlanan basit bir koddur. + +HTML "HyperText Markup Language" (HiperMetin İşaretleme Dili) anlamına gelir. **HyperText (HiperMetin)** sayfalar arası bağlantıları destekleyen türden bir metin demektir. **Markup (İşaretleme)**, bir belgeyi alıp onu kodlarla işaretleyerek, nasıl yorumlanacağını (tarayıcıya) söyledik demektir. HTML kodu **etiketler** ile oluşturulur, etiketlerin her biri `<` ile başlar ve `>` ile biter. Bu etiketler biçimlendirme **öğelerini** temsil eder. + +## İlk template'iniz! + +Bir template oluşturmak bir template dosyası oluşturmak demektir. Her şey bir dosyadır, değil mi? Bunu muhtemelen zaten fark etmişsinizdir. + +Template'lar `blog/templates/blog` dizininde saklanır. Öyleyse blog klasörü altında `templates` adlı bir klasör oluşturalım. Sonra da templates klasörü altında yine `blog` adlı bir klasör oluşturalım: + +``` +blog +└───templates + └───blog +``` + +(Neden iki tane `blog` adlı klasöre gerek olduğunu merak etmiş olabilirsin. Daha sonra da anlaşılacağı gibi, sitemiz karmaşıklaştıkça bu şekilde isimlendirme tarzı işimizi oldukça kolaylaştırır.) + +Şimdi de `blog/templates/blog` dizini içine `post_list.html` adlı bir dosya oluşturalım (şimdilik içini boş bırakalım). + +Web sitemizin nasıl göründüğüne bir bakalım: http://127.0.0.1:8000/ + +> Eğer `TemplateDoesNotExists` hatası alırsanız sunucuyu yeniden başlatmayı deneyin. Komut satırına gidip, Ctrl+C (Control ve C tuşlarına eş zamanlı basarak) yaptıktan sonra sunucuyu tekrar başlatmak için `python manage.py runserver` komutunu çalıştırın. + +![Şekil 11.1][1] + + [1]: images/step1.png + +Artık hata kalmadı! Tebrikler :) Ama, web sitemiz aslında boş bir sayfadan başka bir şey yayınlamıyor, çünkü template boş. Bunu düzeltelim. + +Template dosyamıza şunları ekleyelim: + +```html + +

Merhaba!

+

Çalışıyor!

+ +``` + +Web siteniz şimdi nasıl görünüyor? Öğrenmek için tıklayın: http://127.0.0.1:8000 / + +![Şekil 11.2][2] + + [2]: images/step3.png + +Çalıştı! Tebrikler :) + +* Tüm web sayfaları en temel etiket olan`` etiketi ile başlar ve her zaman `` ile biter. Gördüğünüz gibi, web sitesinin tüm içeriği `` başlangıç etiketi ve `` bitiş etiketinin arasında yer alır +* `

` paragraf öğelerini belirten etikettir; her paragrafın bitişinde de `

` olacaktır + +## Head ve body (Başlık ve gövde) + +Aynı zamanda tüm HTML sayfaları **head** ve **body** olmak üzere iki öğeye ayrılır. + +* **head** belge hakkında ekranda görüntülenmeyen bilgiler içeren öğedir. + +* **body** ise ekranda gösterilen tüm öğeleri içeren öğedir. + +`` öğesini tarayıcıya sayfanın yapılandırmasını anlatmak için, `` öğesini ise sayfada aslında ne olduğunu anlatmak için kullanırız. + +Örneğin, web sayfasının (title) başlık elemanını `` 'in içine böyle koyabilirsiniz: + +```html + + + Zeynep'in blogu + + +

Merhaba!

+

Çalışıyor!

+ + +``` + +Dosyayı kaydedin ve sayfanızı yenileyin. + +![Şekil 11.3][3] + + [3]: images/step4.png + +Tarayıcınızın "Zeynep'in blogu" başlığını nasıl anladığını fark ettiniz mi? `Zeynep'in blogu` kısmını başlık olarak yorumlayarak yazıyı tarayıcının başlık kısmına yerleştirdi. (Bu yazı yer işaretleri gibi yerlerde de kullanılır). + +Her açılan etiketin benzer bir *kapatan etiket*, `/` ile başlayan, ile kapatılmalıdır. Ayrıca bu etiketler *iç içe* yerleştirilebilir (bu da bir etiketi kapatabilmek için, içindeki tüm etiketlerin kapanmış olmasını gerektirir). + +Bir şeyleri kutulara yerleştirmek gibi. Büyük bir kutuda `` olsun; onun içinde `` kutusu olsun, onun da içinde daha küçük kutular olsun: `

`. + +Etiketleri düzgün *kapatma* ve *iç içe * yerleştirme kurallarına uymak çok önemli. Aksi takdirde tarayıcı belgenizi doğru yorumlayamaz ve gösteremez. + +## Template özelleştirme + +Şimdi artık biraz eğlenip template'inizi özelleştirmeyi deneyebilirsiniz! İşte bunun için faydalı birkaç etiket: + +* `

Bir başlık

` - ana başlığınız için +* `

Bir alt başlık

` - bir sonraki seviyedeki bir başlık için +* `

Bir alt alt başlık

` ... ve böyle `
` ya kadar iner +* `metin` metni vurgular +* `metin` metni iyice vurgular +* `
` - alt satıra gider (br etiketi içine bir şey konulmaz) +* `bağlantı` bir bağlantı oluşturur +* `
  • ilk madde
  • ikinci madde
` - tıpkı bunun gibi bir liste yapar! +* `
` - sayfanın bir bölümünü tanımlar + +Şimdi de tam bir template örneği: + + +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

İlk Blogum

+

Çok heyecanlıyım! Bu benim ilk blogum. Ne kadar zevkli bir işmiş bilgisayarlarla uğraşmak. Artık bilgisayar başından kalkmam.

+
+ +
+

published: 14.06.2014, 12:14

+

İkinci gönderim

+

Bir varmış bir yokmuş, evvel zaman içinde, Ne kadar zevkli bir işmiş bilgisayarlarla uğraşmak. Artık bilgisayar başından kalkmam. kalbur saman içinde, develer tellal iken, pireler berber iken; ben annemin beşiğini tıngır mıngır sallar iken.

+
+ + +``` + +Burada üç tane `div` bölümü oluşturduk. + +* İlk `div` öğesi blogumuzun başlığını içeriyor - bir başlık ve bir bağlantıdan oluşuyor +* Sonraki iki `div` öğesi blog gönderilerimizi içeriyor; bunlarda bir yayın tarihi, tıklanabilir bir `h2` başlığı ve biri tarih diğeri gönderi metnimiz için olmak üzere, iki tane `p` (paragraf) var. + +Bize yaşattığı duygu: + +![Şekil 11.4][4] + + [4]: images/step6.png + +Yaşasın! Şimdiye dek, template tam olarak sadece **aynı bilgiyi ** görüntüledi - öncesinde ise template'in **farklı** bilgileri **aynı formatta** görüntülememize izin verdiğinden bahsetmiştik. + +Gerçekten yapmak istediğimiz ise Django adminde ekli gerçek gönderileri göstermek - ve bir sonraki adımımız da bu. + +## Birşey daha: dağıtım! + +Bunları İnternet'te canlı olarak görmek çok güzel olur, değil mi: + +### Kodumuzu commit ve push komutları ile Github'a yükleyelim + +İlk önce son deployment dan sonra hangi dosyaların değiştiğine bakalım. Bu komutları lokal bilgisayarımızda çalıştıralım, PythonAnywhere'de değil: + +``` +$ git status +``` + +`djangogirls` dizininde olduğumuzdan emin olalım ve `git` 'e bu dizinde yapılan tüm değişiklikleri dahil etmesini söyleyelim: + +``` +$ git add --all . +``` + +> **Not:** `-A` (hepsi için bir kısaltma - İngilizce'de "all" hepsi demek) `git`'in silinmiş dosyaları tanır (normalde sadece yeni/güncellenmiş dosyaları tanır). Hatırlatma: `.` içinde olduğumuz klasör anlamına gelir (3. Bölüm). + +Dosyalarımızı yüklemeden önce `git`'in hangilerini yükleyeceğine (`git`'in yükleyeceği dosyalar yeşil gösterilir) bakalım: + +``` +$ git status +``` + +Neredeyse bitirdik, şimdi bu değişikliği tarihçesine kaydetmesini söyleyelim. Commit için değişiklikleri açıklayan bir mesaj yazalım. Bu aşamada istediğimizi yazabiliriz, fakat tanımlayıcı yazılar gelecekte neler yapmış olduğumuzu hatırlatması açısından faydalı olacaktır. + +``` +$ git commit -m "Site için HTML dosyasını değiştirdim." +``` + +> **Not** Tamamlama mesajını çift tırnak içerisinde kullandığımızdan emin olalım. + +Bunu tamamladıktan sonra, değişiklikleri Github'a push komutunu kullanarak yükleyelim: + +``` +git push +``` + +### Pull ile yeni kodu PythonAnywhere e alıp web uygulamasını tekrar yükleyelim + +* [PythonAnywhere consoles page][5]sayfasını ve **Bash console** u açalım (ya da yeni bir tane açalım). Sonra da çalıştıralım: + + [5]: https://www.pythonanywhere.com/consoles/ + +``` +$ cd ~/ilk-blogum +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +Kodumuzun indirilmesini izleyelim. Kodun geldiğini kontrol etmek istersek **Files (dosyalar) sekme**sini açıp PythonAnywhere'de kodumuzu görebiliriz. + +* Son olarak, [Web sekmesi][6]ne gidip uygulamanızın **Yenile** butonuna basın. + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +Güncelleme hazır olmalı! Devam edelim ve tarayıcıda web sitesini yenileyelim. Değişiklikler görünüyor olmalı :) \ No newline at end of file diff --git a/tr/html/images/step1.png b/tr/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/tr/html/images/step1.png differ diff --git a/tr/html/images/step3.png b/tr/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/tr/html/images/step3.png differ diff --git a/tr/html/images/step4.png b/tr/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/tr/html/images/step4.png differ diff --git a/tr/html/images/step6.png b/tr/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/tr/html/images/step6.png differ diff --git a/tr/images/application.png b/tr/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/tr/images/application.png differ diff --git a/tr/installation/README.md b/tr/installation/README.md new file mode 100755 index 00000000000..22f4ae2fa24 --- /dev/null +++ b/tr/installation/README.md @@ -0,0 +1,49 @@ +# Eğer tutorial'ı evde yapıyorsanız + +Eğer tutorial'ı [Django Girls etkinlikleri](https://djangogirls.org/events/)nin birinde değil de evde yapıyorsanız, bu bölümü atlayabilirsiniz ve doğrudan [İnternet nasıl çalışır?](../how_the_internet_works/README.md) bölümüne gidebilirsiniz. + +Çünkü burada anlatılanları tutorial boyunca zaten işliyoruz, bu kısım kurulum talimatlarının tek yerde toparlandığı ek bir sayfa sadece. Django Girls etkinlikleri, tutorial sırasında uğraşmamak için herşeyi kurduğumuz bir "kurulum akşamı"nı içeriyor. Bu sayfayı onun için kullanıyoruz. + +Eğer yararlı olduğunu düşünüyorsanız, bu bölümü okuyabilirsiniz. Ama bilgisayarınıza bir şeyler kurmadan önce bir kaç şey öğrenmeye başlamak istiyorsanız, bu bölümü atlayın. Size kurulum işlerini sonra anlatacağız. + +İyi şanslar! + +# Kurulum + +Atölyede bir blog yapıyor olacaksınız, eğitim günü kodlamaya hazır olmanız için önceden ayarlamakta fayda olan birkaç kurulum var. + +# Python Yükleyin + +{% include "/python_installation/instructions.md" %} + +# Bir "virtualenv" kurun ve Django'yu yükleyin + +{% include "/django_installation/instructions.md" %} + +# Bir kod düzenleyicisi yükleyin + +{% include "/code_editor/instructions.md" %} + +# Git yükleyin + +{% include "/deploy/install_git.md" %} + +# GitHub hesabı oluşturun + +[GitHub.com](https://www.github.com)'a gidin ve ücretsiz yeni bir kullanıcı hesabı oluşturun. + +# PythonAnywhere hesabı oluşturun + +{% include "/deploy/signup_pythonanywhere.md" %} + +# Okumaya başlayın + +Tebrikler, ayarlarınız tamam ve hazırsınız! Eğer atölyeden önce hala vaktiniz var ise, başlangıç bölümlerinden bazılarını okumanız yararlı olacaktır: + + * [İnternet nasıl çalışır](../how_the_internet_works/README.md) + + * [Komut satırına giriş](../intro_to_command_line/README.md) + + * [Python'a giriş](../intro_to_command_line/README.md) + + * [Django nedir?](../django/README.md) \ No newline at end of file diff --git a/tr/intro_to_command_line/README.md b/tr/intro_to_command_line/README.md new file mode 100755 index 00000000000..6e4d8448ca5 --- /dev/null +++ b/tr/intro_to_command_line/README.md @@ -0,0 +1,304 @@ +# Komut satırı arayüzüne giriş + +Ha, heyecan verici, değil mi?! İlk kodunuzu birkaç dakika içinde yazacaksınız :) + +**Sizi yeni arkadaşınızla tanıştıralım: komut satırı!** + +Gelecek aşamalar size tüm "hacker"ların kullandığı siyah pencerenin nasıl kullanıldığını gösterecek. Başta biraz korkutucu görünebilir fakat bu sadece sizden komut bekleyen bir pencere. + +> **Not**Lütfen bu kitap boyunca 'dizin' veya 'klasör' terimlerini birbirinin yerine kullandığımızı ve aynı anlama geldiklerini unutmayınız. + +## Komut satırı nedir? + +Genellikle **komut satırı** veya **komut satırı arabirimi** adı verilen pencere, bilgisayarınızdaki dosyaları görmek, düzenlemek ve yönetmek için kullanılan metin tabanlı bir uygulamadır. Tıpkı Windows Gezgini veya Mac'deki Finder gibi, fakat grafik arayüzü olmadan. Komut satırının diğer adları: *cmd*, *CLI*, *komut istemcisi*, *konsol* veya *terminal (uçbirim)*dir. + +## Komut satırı arabirimini açın + +Birkaç deneme yapmak için önce komut satırı arabirimini açmamız gerekir. + +### Windows + +Başlat menüsü → Tüm Programlar → Donatılar → Komut Satırı. + +### Mac OS X + +Uygulamalar → Araçlar → Terminal. + +### GNU/Linux + +Muhtemelen Uygulamalar → Donatılar → Terminal altında olmalı, fakat sistemler arası farklılık gösterebilir. Eğer orada değilse İnternet'te arayın :) + +## İstemci + +Şu anda yüksek ihtimalle sizden komut bekleyen siyah ya da beyaz bir ekran görüyor olmalısınız. + +Eğer Mac veya GNU/Linux kullanıyorsanız, yüksek ihtimalle `$` işareti göreceksiniz, tıpkı bunun gibi: + +``` +$ +``` + +Windows'da ise `>` işareti göreceksiniz, bunun gibi: + +``` +> +``` + +Tüm komutlar bu işaret ve bir boşluktan sonra gelir fakat bunu yazmak zorunda değilsiniz. Bilgisayarınız bunu sizin için yapacaktır :) + +> Ufak bir not: sizin durumunuzda bu `C:\Users\ola>` veya `Olas-MacBook-Air:~ ola$` ve benzeri bir şekilde olabilir ve bu kesinlikle doğru. Bu eğitimde bunu sade ve basit bir şekilde anlatacağız. + +## İlk komutunuz(Yaşasın!) + +Basit bir şeyle başlayalım. Aşağıdaki komutu yazın: + +``` +$ whoami +``` + +ya da + +``` +> whoami +``` + +Ve ardından `enter` tuşuna basın. Sonucumuz bu: + +``` +$ whoami zeynep +``` + +Gördüğünüz gibi, bilgisayar az önce kullanıcı adınızı yazdı. Muntazam, değil mi?:) + +> Her komutu yazmaya çalışın, kopyala-yapıştır yapmayın. Bu şekilde daha akılda kalıcı olur! + +## Temeller + +Tüm işletim sistemleri komut satırı için birbirinden biraz farklı komutlar kullanır, bu nedenle işletim sisteminize uygun yönergeleri izlediğinizden emin olun. Deneyelim mi? + +### Geçerli Dizin + +Nerede olduğumuzu bilmek güzel olurdu, değil mi? Bakalım. Bu komutu yazın ve `enter` tuşuna basın: + +``` +$ pwd +/Users/zeynep +``` + +Windows'ta iseniz: + +``` +> cd +C:\Users\zeynep +``` + +Muhtemelen makinenizde benzeri bir yazı göreceksiniz. Komut satırını açtığınızda genellikle kullanıcınızın ev dizininde başlarsınız. + +> Not: 'pwd'nin anlamı "print working directory" yani "çalışma dizinini yazdır"dır. + +* * * + +### Dosya ve dizinleri listele + +Yani içeride ne var? Bilmek harika olurdu. Haydi bakalım: + +``` +$ ls +Uygulamalar +Masaüstü +İndirilenler +Müzik +... +``` + +Windows: + +``` +> dir Directory of C:\Users\zeynep +05/08/2014 07:28 PM Uygulamalar +05/08/2014 07:28 PM Masaüstü +05/08/2014 07:28 PM İndirilenler +05/08/2014 07:28 PM Müzik +... +``` + +* * * + +### Geçerli dizini değiştir + +Şimdi, haydi Masaüstü dizinimize gidelim: + +``` +$ cd Masaüstü +``` + +Windows: + +``` +> cd Masaüstü +``` + +Gerçekten değişmiş mi bir bakalım: + +``` +$ pwd +C:\Users\zeynep\Masaüstü +``` + +Windows: + +``` +> cd +C:\Users\zeynep\Masaüstü +``` + +İşte oldu! + +> Profesyonel ipucu: eğer `cd D` yazarsanız ve `tab` tuşuna basarsanız, komut satırı ismin kalanını otomatik tamamlar ve gitmek istediğiniz yere daha hızlı gidersiniz. Eğer "D" ile başlayan birden çok klasör var ise, seçeneklerin listesi için `tab` tuşuna iki kez basın. + +* * * + +### Dizin oluşturun + +Uygulamalı yapmak için masaüstünüzde bir dizin oluşturmaya ne dersiniz? Bu şekilde yapabilirsiniz: + +``` +$ mkdir uygulama +``` + +Windows: + +``` +> mkdir uygulama +``` + +Bu küçük komut masaüstünüzde `uygulama` isimli bir klasör oluşturacaktır. Orada olup olmadığını kontrol etmek için `ls` veya `dir` komutlarını kullanabilirsiniz! Deneyin :) + +> Profesyonel ipucu: Eğer aynı komutları tekrar tekrar yazmak istemiyorsanız, `yukarı ok` ve `aşağı ok` tuşlarına basarak yazdığınız komutlar arasında geçiş yapabilirsiniz. + +* * * + +### Alıştırma! + +Sizin için ufak bir alıştırma: yeni oluşturduğunuz `uygulama` dizininde `test` adında bir dizin oluşturun.`cd` ve `mkdir` komutlarını kullanın. + +#### Çözüm: + +``` +$ cd uygulama +$ mkdir test +$ ls +test +``` + +Windows: + +``` +> cd uygulama +> mkdir test +> dir +05/08/2014 07:28 PM test +``` + +Tebrikler! :) + +* * * + +### Temizlik + +Ortalığı dağınık bırakmak istemeyiz, haydi yaptığımız her şeyi silelim. + +İlk önce masaüstüne geri dönmemiz gerek: + +``` +$ cd .. +``` + +Windows: + +``` +> cd .. +``` + +`cd` komutu ile `..` kullanmak sizi bir üst dizine götürür (Bu sizin şuanki dizininizi tutan ana dizindir). + +Nerede olduğunuzu kontrol edin: + +``` +$ pwd +C:\Users\zeynep\Masaüstü +``` + +Windows: + +``` +> cd +C:\Users\zeynep\Masaüstü +``` + +Şimdi `uygulama` dizinini silme vakti: + +> **Dikkat**: Dosyaları `del`,`rmdir` veya `rm` ile silme işlemi geri alınamaz, bu *silinen dosyalar sonsuza dek yok olur* anlamına gelir! Yani, bu komutları kullanırken çok dikkatli olun. + +``` +$ rm -r uygulama +``` + +Windows: + +``` +> rmdir /S uygulama +uygulama, Emin misiniz ? E +``` + +Bitti! Gerçekten silindiğinden emin olalım: + +``` +$ ls +``` + +Windows: + +``` +> dir +``` + +### Çıkış + +Şimdilik bu kadar! Şimdi komut satırını güvenle kapatabilirsiniz. Bunu "hacker" tarzında yapalım, tamam mı?:) + +``` +$ exit +``` + +Windows: + +``` +> exit +``` + +Harika, değil mi?:) + +## Özet + +İşte bazı yararlı komutların özeti: + +| Komut (Windows) | Komut (Mac OS - GNU/Linux) | Açıklama | Örnek | +| --------------- | -------------------------- | ----------------------- | ------------------------------------------------- | +| exit | exit | pencereyi kapatır | **exit** | +| cd | cd | dizin değiştir | **cd test** | +| dir | ls | dizin/dosyaları listele | **dir** | +| copy | cp | dosya kopyala | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | dosya taşı | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | yeni bir dizin oluştur | **mkdir testdizini** | +| del | rm | bir dosya/dizin sil | **del c:\test\test.txt** | + +Bu kullanabileceğiniz komutlardan sadece birkaçı, fakat bugün bundan daha fazlasını kullanmayacaksınız. + +Eğer meraklı iseniz, [ss64.com][1] adresinden tüm işletim sistemleri için tüm komutların kullanımına ulaşabilirsiniz. + + [1]: http://ss64.com + +## Hazır mısınız? + +Haydi Python'a giriş yapalım! \ No newline at end of file diff --git a/tr/python_installation/README.md b/tr/python_installation/README.md new file mode 100755 index 00000000000..4018e00dfc8 --- /dev/null +++ b/tr/python_installation/README.md @@ -0,0 +1,13 @@ +# Hadi Python ile başlayalım + +Nihayet buradayız! + +Fakat önce, size Python'un ne olduğunu açıklayalım. Python web siteleri, oyunlar, bilimsel yazılımlar, grafikler ve çok daha fazlasını oluşturmak için kullanılan bir programlama dilidir. + +Python'un kökleri 1980'li yılların sonlarına dayanmaktadır ve ana hedefi sadece makineler değil insanlar tarafından da okunabilir olmaktır. Bu yüzden diğer programlama dillerine oranla çok daha basit görünmektedir. Öğrenmesi kolaydır ama merak etmeyin, Python gerçekten güçlüdür! + +# Python kurulumu + +> **Not** Eğer kurulum aşamalarını zaten tamamladıysanız, tekrar yapmanıza gerek yok - direkt olarak diğer aşamaya geçebilirsiniz! + +{% include "/python_installation/instructions.md" %} \ No newline at end of file diff --git a/tr/python_installation/images/add_python_to_windows_path.png b/tr/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/tr/python_installation/images/add_python_to_windows_path.png differ diff --git a/tr/python_installation/instructions.md b/tr/python_installation/instructions.md new file mode 100755 index 00000000000..c610f502331 --- /dev/null +++ b/tr/python_installation/instructions.md @@ -0,0 +1,72 @@ +> Bu bölüm Geek Girls Carrots tarafından yapılan bir eğitime dayanılarak hazırlanmıştır. (http://django.carrots.pl/) + +Django, Python ile yazılmıştır. Django ile bir şey yapmak için Python diline ihtiyacımız var. Hadi Python kurmaya başlayalım! Biz Python 3.4 kurmak istiyoruz, eğer daha düşük bir sürüme sahipseniz, güncellemelisiniz. + +### Windows + +Windows için Python indirmek için resmi siteyi ziyaret edebilirsiniz: https://www.python.org/downloads/release/python-343/. ***.msi** dosyasını indirdikten sonra, dosyayı çalıştırın (çift-tık) ve yönergeleri izleyin. Python kurulumunu yaptığınız dizinin yolunu unutmamanız önemli. Daha sonra lazım olacak! + +Dikkat: Özelleştir (Customize) olarak seçilmiş kurulum sihirbazının ikinci ekranında seçenekleri aşağıya kaydırın ve "Add python.exe to the Path" (python.exe yolunu ekle) seçeneğinin üzerine gelip "Will be installed on local hard drive" seçeneğini seçin: + +![Python'u arama yoluna eklemeyi unutmayın](../python_installation/images/add_python_to_windows_path.png) + +### GNU/Linux + +Muhtemelen sisteminizde Python zaten yüklüdür. Yüklü olup olmadığını (ya da hangi versiyon olduğunu) kontrol etmek için komut satırını açın ve aşağıdaki komutları girin: + +``` +$ python3 --version +Python 3.4.3 +``` + +Python yüklü değilse ya da farklı bir versiyon edinmek istiyorsanız aşağıdaki adımları takip edin: + +#### Debian veya Ubuntu + +Terminale bu komutu girin: + +``` +$ sudo apt-get install python3.4 +``` + +#### Fedora (21'e kadar) + +Terminalde kullanmanız gereken komut: + +``` +$ sudo yum install python3.4 +``` + +#### Fedora (22+) + +Terminalde kullanmanız gereken komut: + +``` +$ sudo dnf install python3.4 +``` + +#### openSUSE + +Terminalde kullanmanız gereken komut: + +``` +$ sudo zypper install python3 +``` + +### OS X + +Python kurulum dosyasını indirmek için resmi siteye gitmelisiniz: https://www.python.org/downloads/release/python-342/: + + * *Mac OS X 64-bit/32-bit yükleyici* dosyasını indirin, + * *python-3.4.3-macosx10.6.pkg* dosyasına çift tıklayarak yükleyiciyi çalıştırın. + +Kurulumun başarılı olup olmadığını kontrol etmek için *Terminal* uygulamasını açın ve aşağıdaki `python3` komutunu çalıştırın: + +``` +$ python3 --version +Python 3.4.3 +``` + +* * * + +Herhangi bir şüpheniz varsa, kurulumda bir şeyler ters gittiyse ya da sonrasında ne yapacağınızı bilmiyorsanız eğitmene sorabilirsiniz! Bazen işler düzgün gitmiyor, bu durumda daha fazla deneyime sahip birinden yardım istemelisiniz. \ No newline at end of file diff --git a/tr/python_introduction/README.md b/tr/python_introduction/README.md new file mode 100755 index 00000000000..85bb8530c24 --- /dev/null +++ b/tr/python_introduction/README.md @@ -0,0 +1,848 @@ +# Python'a Giriş + +> Bu bölümün bazı kısımları Geek Girls Carrots (http://django.carrots.pl/) öğreticisinden alınmıştır. + +Biraz kod yazalım! + +## Python komut istemi (prompt) + +Python'la oynamaya başlamadan önce bilgisayarımızda bir *komut satırı* açmamız gerekiyor. Bunu nasıl yapacağınızı artık biliyorsunuz, [Komut satırına giriş][1] bölümünde öğrenmiştiniz. + + [1]: ../intro_to_command_line/README.md + +Hazır olduğunuzda, aşağıdaki talimatları takip edin. + +Bir Python konsolu açmak istiyoruz; öyleyse Windows'ta `python`, Mac OS/Linux'ta `python3` yazıp, `enter`'a basın. + +``` +$ python3 +Python 3.4.3 (...) +Type "help", "copyright", "credits" or "license" for more information. +>>> +``` + +## İlk Python komutunuz! + +Python komutunu çalıştırdıktan sonra, komut istemi `>>>` şeklinde değişti. Bizim için bu, şimdi yalnızca Python dilinde komutlar kullanabileceğimiz anlamına geliyor. `>>>` yazmanıza gerek yok, Python sizin için bunu yapıyor. + +Eğer herhangi bir zamanda Python komut satırından çıkmak isterseniz, yalnızca `exit()` yazmanız ya da Windows için `Ctrl + Z`, Mac/Linux için `Ctrl + D` kısa yolunu kullanmanız yeterli. Bunu yaptığınız taktirde artık `>>>` yazısını görmeyeceksiniz. + +Şu an için Python komut satırından çıkmak istemiyoruz. Bu konuda daha fazlasını öğrenmek istiyoruz. Gerçekten basit bir şeyle başlayalım. Örneğin, biraz matematik yapmayı deneyip `2 + 3` gibi bir şey yazın ve `enter`'a basın. + +``` +>>> 2 + 3 +5 +``` + +Harika! Cevabın komut satırına geldiğini gördün değil mi? Python matematik biliyor! Şu gibi komutları da deneyebilirsiniz: - `4 * 5` - `5 - 1` - `40 / 2` + +Bunları biraz kurcalayıp eğlen, sonra tekrar burada buluşalım :). + +Gördüğün üzere Python çok iyi bir hesap makinesi. Eğer başka neler yapabileceğini merak ediyorsan... + +## String'ler (dizeler) + +Mesela ismin? İsmini tırnak işaretleri içerisinde şu şekilde yaz: + +``` +>>> "Zeynep" +'Zeynep' +``` + +İlk string'ini oluşturdun! String (katar), bilgisayar tarafından işlenebilen ve karakterlerden oluşan dizilerin genel adıdır. Bir string her zaman aynı özel karakterle başlamalı ve aynı özel karakterle bitmelidir. Tek tırnak (`'`) veya çift tırnak (`"`) olabilir (aralarında herhangi bir fark yok!). Tırnak işaretleri Python'da içlerinde olan şeyin bir string olduğunu ifade eder. + +Stringler birbirlerine eklenebilir. Şunu dene: + +``` +>>> "Merhaba " + "Zeynep" +'Merhaba Zeynep' +``` + +Ayrıca stringleri bir sayı ile çarpabilirsin: + +``` +>>> "Zeynep" * 3 +'ZeynepZeynepZeynep' +``` + +Eğer stringinin içerisine bir tırnak işareti koymak istiyorsan, bunun için iki seçeneğin var. + +Çift tırnak kullanarak: + +``` +>>> "Turgut Uyar'ın dizeleriyiz" +"Turgut Uyar'ın dizeleriyiz" +``` + +veya sola eğik çizgi (``) kullanarak: + +``` +>>> 'Turgut Uyar\'ın dizeleriyiz' +"Turgut Uyar'ın dizeleriyiz" +``` + +Hoş değil mi? İsminin tamamını büyük harf yapmak için, sadece şunu yazman yeterli: + +``` +>>> "Zeynep".upper() +'ZEYNEP' +``` + +Stringin üzerinde `upper` **fonksiyon**unu kullandın! Bir fonksiyon (`upper()` gibi) , çağırıldığında(calling) Python'un bir obje (`"Zeynep"`) üzerinde gerçekleştirmesi gereken bir dizi işleme denilir. + +Eğer ismindeki harflerin sayısını öğrenmek istiyorsan bunun için de bir fonksiyon var! + +``` +>>> len("Zeynep") +6 +``` + +Fonksiyonları bazen string sonunda bir `.` ile (`"Zeynep".upper()` gibi) ve bazen önce fonksiyonu çağırıp sonra parantezler içerisine stringi yerleştirerek kullandığımızı merak ediyor musun? Pekala, bazı durumlarda, fonksiyonlar bir takım nesnelere aittirler, mesela `upper()`, yalnızca stringler üzerinde kullanılabilir. Böyle durumlarda, bu tarz fonksiyonlara biz **method** ismini veriyoruz. Diğer durumlarda, bir fonksiyon özel olarak bir nesneye ait olmayıp, farklı çeşitlerde nesneler üzerinde de kullanılabilir, aynı `len()` gibi. İşte bu nedenle `"Zeynep"` stringini `len` fonksiyonuna bir parametre olarak veriyoruz. + +### Özet + +Tamam, stringlerden yeterince bahsettik. Şu ana kadar şu konuları öğrendin: + +* **konsol-komut istemcisi** - Python komut satırına komut(kod) yazdığında Python cevap veriyor +* **sayılar ve strings(karakter dizinleri)** - Python'da sayılar matematik ve stringler metin nesneleri için kullanılıyor +* **operators(işleçler)** + ve * gibi, değerleri birleştirerek yeni bir değer oluştuyor +* **fonksiyonlar-işlevler** - upper() ve len() gibi, nesneler üzerinde eylemler gerçekleştiriyor. + +Bunlar öğreneceğiniz her programlama dilinin temelleri. Biraz daha zor bir şey için hazır mısın? İddiaya gireriz öylesin! + +## Errors - Hatalar + +Şimdi yeni bir şey deneyelim. Bir sayının uzunluğunu, bir string'in uzunluğunu bulduğumuz gibi bulabilir miyiz? Bu görmek için `len(304023)` yazıp `enter`a basalım: + +``` +>>> len(304023) +Traceback (most recent call last): + File "", line 1, in +TypeError: object of type 'int' has no len() +``` + +İlk hatamızı aldık! Nesne türü "int" (tam sayılar, tüm sayılar) in uzunluğu olmadığını söylüyor. Şimdi ne yapabiliriz? Belki de rakamı bir string olarak yazabiliriz? Stringlerin bir uzunluğu var, değil mi? + +``` +>>> len(str(304023)) +6 +``` + +İşe yaradı! `str` fonksiyonunu `len` fonksiyonunun içinde kullandık. `str` her şeyi string'e çeviriyor. + +* `str` fonksiyonu, değişkenleri **stringe** çeviriyor +* `int` fonksiyonu değişkenleri **integera** çeviriyor + +> Önemli: Tamsayıları yazıya çevirebiliriz, fakat yazıları(text) sayılara çeviremeyiz - `int('selamlar')` bir anlam ifade etmiyor. + +## Değişkenler + +Programlamada en önemli konulardan biri değişkenlerdir. Değişken, daha sonra kullanmak istediğiniz bir yapıya verdiğiniz isimdir. Programcılar değişkenleri verileri tutmak ya da kodlarını daha okunabilir ve anlaşılabilir kılmak için kullanırlar ve böylece her şeyi sürekli akıllarında tutmaya gerek kalmaz. + +`name` adında bir değişken yaratmak istediğimizi varsayalım: + +``` +>>> name = "Ayşe" +``` + +Gördünüz mü? Ne kadar kolay: name değişkeni "Ayşe" oldu. + +Farkettiğiniz gibi, program daha öncekilerinin aksine bu kez hiçbir cevap vermedi. O zaman böyle bir değişkenin gerçekten tanımlı olduğunu nasıl bilebiliriz? Basitçe, `name` yazıp `enter` tuşuna basalım: + +``` +>>> name +'Ayşe' +``` + +İşte bu sizin ilk değişkeniniz! name değişkeninin referansını(içini) istediğiniz zaman değiştirebilirsiniz: + +``` +>>> name = "Suzan" +>>> name +'Suzan' +``` + +Bu değişkeni fonksiyonlar içinde de kullanabilirsiniz: + +``` +>>> len(name) +5 +``` + +Harika değil mi? Tabii ki değişkenler, sayılar da dahil herhangi bir şey olabilir. Şunu deneyin: + +``` +>>> a = 4 +>>> b = 6 +>>> a * b +24 +``` + +Peki ya değişkenin adını yanlış kullanırsak? Ne olacağını tahmin ediyor musunuz? Deneyelim! + +``` +>>> city = "Tokyo" +>>> ctiy +Traceback (most recent call last): + File "", line 1, in +NameError: name 'ctiy' is not defined +``` + +Bir hata! Gördüğünüz gibi, Python bir çok çeşit hata çeşidine sahip ve bu hatanın adı **NameError** , yani İsimlendirme Hatası. Tanımlamadığınız bir değişkenin adını kullanmaya çalışırsanız, Python size bu hatayı verir. Eğer bu hata ile daha sonra karşılaşırsanız, kodunuzdaki değişkenlerin adını doğru yazıp yazmadığınızı kontrol edin. + +Bununla biraz oynayıp, neler yapabildiğinizi görün! + +## Print (yazdır) işlevi + +Şunu deneyin: + +``` +>>> name = 'Merve' +>>> name +'Merve' +>>> print(name) +Merve +``` + +Sadece `name` yazdığınız zaman, Python yorumlayıcısından 'name' değişkeninin dize olarak *temsili* döner, yani tek tırnaklar içine alınmış M-e-r-v-e harfleri. Eğer `print(name)` derseniz Python ekrana değişkenin içeriğini yazdıracaktır, bu kez tırnaklar olmaksızın, daha temiz biçimde. + +Daha ileride göreceğimiz gibi `print()`, işlevlerin içindeyken bir şey yazdırmak istediğimizde ya da bazı şeyleri birden fazla satırda yazdırmak istediğimizde de kullanışlıdır. + +## Listeler + +Python, string ve integerın yanı sıra, çok değişik türlerde nesnelere sahiptir. Şimdi, **liste** türünü tanıtacağız. Listeler tam da düşündüğünüz gibidir: diğer nesnelerin listesi olan nesne :) + +Yeni bir liste yaratmakla devam edelim: + +``` +>>> [] +[] +``` + +Evet, liste boş. Çok kullanışlı sayılmaz, değil mi? Hadi loto numaralarıyla liste oluşturalım. Sürekli kendimizi tekrar etmek istemeyiz, o yüzden listeyi değişkene atayalım: + +``` +>>> lottery = [3, 42, 12, 19, 30, 59] +``` + +Pekala, listeyi oluşturduk! Onunla ne yapabiliriz? Hadi listede kaç tane loto numarası olduğunu görelim. Hangi fonksiyonu kullanman gerektiği hakkında bir fikrin var mı? Zaten bildiğin bir fonksiyon! + +``` +>>> len(lottery) +6 +``` + +Evet! `len()` listedeki nesne sayısını verir. Kullanışlı, değil mi? Belki de şu an listeyi sıralarız: + +``` +>>> lottery.sort() +``` + +Bu hiçbir cevap vermez, sadece listedeki numaraların sırasını değiştirir. Şimdi listeyi yazdıralım ve ne olduğunu görelim: + +``` +>>> print(lottery) +[3, 12, 19, 30, 42, 59] +``` + +Gördüğünüz gibi, listedeki sayılar artık küçükten büyüğe sıralı. Tebrikler! + +Belki de sıralamayı ters çevirmek isteriz? Hadi yapalım! + +``` +>>> lottery.reverse() +>>> print(lottery) +[59, 42, 30, 19, 12, 3] +``` + +Kolay, değil mi? Listeye yeni bir eleman eklemek isterseniz, bu komutu yazarak yapabilirsiniz: + +``` +>>> lottery.append(199) +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +``` + +Sadece listedeki ilk elemanı göstermek isterseniz, **indexes** (indeksler) ile yapabilirsiniz. İndeks elemanın listede nerede olduğunu belirten numaradır. Programcılar sıfırdan başlamayı tercih ederler, bu yüzden listedeki ilk eleman listenin 0. indeksindedir, sonraki 1. indeksindedir ve böyle devam eder. Şunu deneyin: + +``` +>>> print(lottery[0]) +59 +>>> print(lottery[1]) +42 +``` + +Gördüğünüz gibi, Listedeki nesnelere listenin ismi ve köşeli parantez içindeki nesnenin indeksini kullanarak ulaşabilirsin. + +Listeden eleman silmek için yukarıda öğrendiğimiz gibi **indeksleri** ve `pop()` komutunu kullanman gerekir. Bir örnekle öğrendiklerimizi pekiştirelim; listeden ilk numarayı sileceğiz. + +``` +>>> print(lottery) +[59, 42, 30, 19, 12, 3, 199] +>>> print(lottery[0]) +59 +>>> lottery.pop(0) +>>> print(lottery) +[42, 30, 19, 12, 3, 199] +``` + +Kusursuz çalıştı! + +Daha fazla eğlence için diğer indeksleri de deneyin: 6, 7, 1000, -1, -6 veya -1000. Denemeden önce komutların sonuçlarını tahmin etmeye çalışın. Sonuçlar mantıklı mıydı? + +Bütün liste fonksiyonlarını Python dökümantasyonunun bu bölümünde bulabilirsin: https://docs.python.org/3/tutorial/datastructures.html + +## Sözlükler + +Sözlük listeye benzerdir ancak sözlük değerlerine indeks yerine anahtar ile ulaşılır. Anahtar metin veya numara olabilir. Boş bir sözlük oluşturmak için kullanılan söz dizimi şudur: + +``` +>>> {} +{} +``` + +Bu boş bir sözlük oluşturduğunuzu gösterir. Yaşasın! + +Şimdi, bu komutu yazmayı deneyin (kendi bilgilerinle değiştir): + +``` +>>> participant = {'name': 'Ayşe', 'country': 'Türkiye', 'favorite_numbers': [7, 42, 92]} +``` + +Bu komut ile üç anahtar-değer çiftine sahip `participant` isminde bir değişken oluşturdun: + +* Anahtar `name` `'Ayşe'` (`string` nesnesi) değerine işaret eder, +* `country` `Türkiye` (bir diğer `string`) değerine,), +* ve `favorite_numbers` `[7, 42, 92]` (3 numaralı bir `list`) değerine işaret eder. + +Bu söz dizimi ile tek bir anahtarın içeriğini kontrol edebilirsin: + +``` +>>> print(participant['name']) +Ola +``` + +Gördün mü, listeye benzer. Ancak indeksini hatırlamana gerek yok - sadece ismi. + +Python'a olmayan bir anahtarın değerini sorarsak ne olur? Tahmin edebiliyor musun? Hadi deneyip görelim! + +``` +>>> participant['age'] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'age' +``` + +Bir başka hata! **KeyError** hatası. Python yardımseverdir ve sana `'age'` anahtarının sözlükte bulunmadığını söyler. + +Ne zaman sözlük veya liste kullanmalısın? Düşünmek için güzel bir nokta. Sonraki satırdaki cevaba bakmadan önce kafanızda bir çözüm oluşturun. + +* Sıralı elemanlara mı ihtiyacın var? Liste ile devam et. +* İleride hızlıca (anahtarlar ile) değerlere ulaşmak istediğin için anahtarlar ile ilişkilendirilmiş değerlere mi ihtiyacın var? Sözlük kullan. + +Sözlükler de listeler gibi değişebilirdir (*mutable*), yani oluşturulduktan sonra değiştirilebilirler. Oluşturulduktan sonra sözlüklere anahtar/değer çifti ekleyebilirsiniz, aşağıdaki gibi: + +``` +>>> participant['favorite_language'] = 'Python' +``` + +Listeler gibi, `len()` metodu sözlükteki anahtar-değer çiftlerinin sayısını bize verir. Devam edip şu komutu yazın: + +``` +>>> len(participant) +4 +``` + +Umarım şu ana kadar mantıklı gelmiştir :) Sözlüklerle biraz daha eğlenceye hazır mısın? İlginç şeyler için sonraki satıra atla. + +`del` komutunu sözlükten eleman silmek için kullanabilirsin. Mesela, `'favorite_numbers'` anahtarına karşılık gelen elemanı silmek istersen, sadece şu komutu yaz: + +``` +>>> del participant['favorite_numbers'] +>>> participant +{'country': 'Türkiye', 'favorite_language': 'Python', 'name': 'Ayşe'} +``` + +Çıktıdan görebildiğin gibi, 'favorite_numbers' anahtarına karşılık gelen anahtar-değer çifti silindi. + +Bunun yanı sıra, sözlükteki daha önce oluşturulmuş anahtarın değerini değiştirebilirsiniz. Şunu yazın: + +``` +>>> participant['country'] = 'Almanya' +>>> participant +{'country': 'Almanya', 'favorite_language': 'Python', 'name': 'Ayşe'} +``` + +Gördüğün gibi, `'country'` anahtarının değeri `'Türkiye'`den `'Almanya`'ya çevrildi. :) Heyecan verici değil mi? Yaşasın! Bir başka harika şey öğrendin. + +### Özet + +Harika! Şu an programlama hakkında birçok şey biliyorsun. Bu kısımda, şunları öğrendin: + +* **hatalar** - eğer Python yazdığın komutu anlamazsa çıkan hataları nasıl okuyacağını ve anlayacağını artık biliyorsun +* **değişkenler** - daha kolay kod yazmanı sağlayan ve kodunu daha okunabilir yapan nesnelerin isimleri +* **listeler** - belirli bir sırada tutulan nesnelerin listesi +* **sözlükler** - anahtar-değer çifti olarak tutulan nesneler + +Bir sonraki part için heyecanlı mısınız? :) + +## Karşılaştırma + +Programlamanın önemli bir bölümü bir şeyleri karşılaştırmayı içerir. Karşılaştırılabilecek en kolay şey nedir? Tabii ki sayılar. Nasıl çalıştığını görelim (True = "Doğru", False= "Yanlış" demek). + +``` +>>> 5 > 2 +True +>>> 3 < 1 +False +>>> 5 > 2 * 2 +True +>>> 1 == 1 +True +>>> 5 != 2 +True +``` + +Python'a birkaç sayı karşılaştırmasını söyledik. Gördüğünüz gibi, sadece sayıları karşılaştırmakla kalmadı, aynı zamanda metodların sonuçlarını da karşılaştırdı. Güzel değil mi? + +İki sayının eşit olup olmadığını öğrenmek için neden iki tane eşittir işraretini `==` yan yana koyduk? Değişkenlere içerik verirken, tek `=` işaretini kullanıyoruz. İki sayının birbirine eşit olup olmadığını görmek için **her zaman** `==` işaretini kullanmak gerekiyor. Sayıların birbirine eşit olmaması durumunu da kontrol edebiliriz. Bunun için, yukarıdaki örnekteki gibi `!=` sembolünü kullanıyoruz. + +Python' a iki görev daha verin: + +``` +>>> 6 >= 12 / 2 +True +>>> 3 <= 2 +False +``` + +`>` ve `<` işaretleri kolay, fakat `>=` ve `<=` ne anlama geliyor? + +* x `>` y : x büyüktür y +* x `<` y : x küçüktür y +* x `<=` y : x küçük eşittir y +* x `>=` y : x büyük eşittir y + +Harika! Biraz daha ister misiniz? Şunu deneyin: + +``` +>>> 6 > 2 and 2 < 3 +True +>>> 3 > 2 and 2 < 1 +False +>>> 3 > 2 or 2 < 1 +True +``` + +Python'a istediğiniz kadar sayıyı karşılaştırmak için verebilirsiniz, ve size hepsinin cevabını verecek. Çok akıllı değil mi? + +* **and** - Mantıkta kullandığımız "ve" anlamına geliyor, yani iki taraf da True, yani doğruysa, cevap da True olacak +* **or** - Bu da "veya" anlamına geliyor, karşılaştırılan iki taraftan tek bir tanesi bile True ise bize True cevabını verecek + +Portakallarla elmaları karşılaştılaştırabilir miyiz? Bunun Python'daki eşdeğerini deneyelim: + +``` +>>> 1 > 'django' +Traceback (most recent call last): + File "", line 1, in +TypeError: unorderable types: int() > str() +``` + +Gördüğünüz gibi Python tam sayılar(`int`) ve kelimeleri(yani stringleri, `str`) karşılaştıramıyor. Onun yerine, **TypeError** göstererek iki farklı tipteki değişkenin karşılaştırılamayacağını söylüyor. + +## Boolean (Mantıksal) + +Laf arasında, yeni bir Python nesne tipi öğrendiniz. Adı **boolean** olan bu tip çok kolay. + +Sadece iki tane boolean nesnesi var: - True (Doğru) - False (Yanlış) + +Python'un bunu anlaması için her zaman "True" (ilk harf büyük, geri kalanları küçük) yazmanız gerekiyor. **true, TRUE, tRUE işe yaramaz -- sadece True doğru.** (Aynısı "False" için de geçerli.) + +Boolean'lar değişken de olabiliyor! Bakınız: + +``` +>>> a = True +>>> a +True +``` + +Ayrıca bu şekilde de yapabilirsiniz: + +``` +>>> a = 2 > 5 +>>> a +False +``` + +Boolean'lar ile aşağıdaki komutları deneyerek biraz oynayın: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +Tebrikler! Boolean'lar programlamadaki en havalı özelliklerden, ve az önce onları nasıl kullanmanız gerektiğini öğrendiniz! + +# Kaydet! + +Şimdiye kadar kodumuzu bizi sadece tek satır yazmaya limitleyen yorumlayıcı üzerinde yazdık. Normal programlar dosyalar içine kaydedilir ve programlama dilimizin **yorumlayıcısıyla** veya **derleyicisiyle** çalıştırılır. Şimdiye kadar programlarımızı Python **yorumlayıcısında** teker satır teker satır çalıştırdık. Bundan sonraki görevlerde, birden fazla satıra ihtiyacımız olacak, bu yüzden şunlara ihtiyacımız olacak: + +* Python yorumlayıcısından çıkın +* Seçtiğiniz kod düzenleyicisini açın +* Yeni Python dosyasına kod kaydedin +* Çalıştırın! + +Kullandığımız Python yorumlayıcısından çıkmak için sadece ~~~ exit() ~~~ fonksiyonunu yazmanız yeterlidir: + +``` +>>> exit() +$ +``` + +Bu sizi komut satırına geri yönlendirecektir. + +Biraz önce [kod editörü][2] bölümünden bir kod editörü seçmiştik. Şimdi o editörü açmalı ve yeni bir dosya içine kod yazmalıyız: + + [2]: ../code_editor/README.md + +```python +print('Merhaba, Django girls!') +``` + +> **Not** Kod editörlerinin en havalı özelliğini fark etmiş olmalısınız: renkler! Python konsolunda her şey aynı renkteydi, şimdi `print` fonksiyonunun stringden farklı bir renkte olduğunu görüyorsunuz. Bunun ismi "söz dizimi vurgulama" ve kod yazarken gerçekten yararlı bir özellik. Koddaki renkler sana ipucu verecektir, örneğin metin kullanım hatasında veya dildeki anahtar kelimenin yanlış yazımında (mesela fonksiyondaki `def`, aşağıda göreceğiz). Bu kod düzenleyicisi kullanma nedenlerimizden biri :) + +Açıkça, artık oldukça deneyimli Python programcısısın, bu yüzden bugün öğrendiğin kodları yazmaktan çekinme. + +Şimdi dosyayı tanımlayıcı bir isimle kaydetmemiz gerekir. Dosyanın ismine **python_intro.py** diyelim ve masaüstüne kaydedelim. Dosyaya istediğimiz ismi verebiliriz, burada önemli olan kısım dosyanın **.py** uzantısı ile bitmesidir. **.py** uzantısı işletim sistemimize bu dosyanın bir **python çalıştırılabilir dosyası** olduğunu ve Python'un bu dosyayı çalıştırabileceğini belirtiyor. + +Dosyayı kaydettiğimize göre artık çalıştırabiliriz! Konsoldan **Klasör değiştirme** yaparak masaüstüne ulaşın, komut satırı bölümünde öğrendiklerinizi hatırlayın. + +Mac'de bu komut şunun gibi görünecektir: + +``` +$ cd /Users//Desktop +``` + +Linux'ta ise bu şekilde ("Desktop" kelimesi "Masaüstü" olarak da görünebilir): + +``` +$ cd /home//Desktop +``` + +Ve Windows'ta, bu şekilde olacak: + +``` +> cd C:\Users\\Desktop +``` + +Bir problem olursa yardım istemekten çekinmeyin. + +Şimdi dosyadaki komutları çalıştırmak için Python'u kulllanın: + +``` +$ python3 python_intro.py +Merhaba, Django girls! +``` + +Tamam! Bir dosyaya kaydedilen ilk Python programınızı çalıştırdınız. Harika hissediyor musunuz? + +Şimdi programlamanın olmazsa olmaz bir aracını öğrenme zamanı: + +## If...elif...else (Koşullu Akış) + +Kodunuzdaki bir çok şeyi sadece belirli bir durum sağlanıyorsa çalıştırmayı isteyeceksiniz. İşte tam da bu yüzden Python'da **if deyimi** isminde bir yapı bulunuyor. + +**python_intro.py** dosyasındaki kodunuzu şununla değiştirin: + +```python +if 3 > 2: +``` + +Eğer bunu kaydedip çalıştırsaydık şu hatayla karşılaşacaktık: + +``` +$ python3 python_intro.py +File "python_intro.py", line 2 + ^ +SyntaxError: unexpected EOF while parsing +``` + +Python bizden kendisine `3 > 2` durumu (veya `True`) sağlandığında neyi çalıştıracağını söylememizi bekliyor. Python'a "Çalışıyor!" yazmasını söyleyelim. **python_intro.py** dosyanızdaki kodu şununla değiştirin: + +```python +if 3 > 2: + print('Çalışıyor!') +``` + +4 tane boşluk karakteri bıraktığımıza dikkat ettiniz mi? Bunu yaparak if cümlesine yazdığım durum doğru olduğunda neyi çalıştırması gerektiğini Python'a söylemiş oluyoruz. Aslında tek bir boşlukla da yapabilirsiniz, ama hemen hemen bütün Python programcıları kodlarının temiz görünmesi için 4 boşluk bırakıyor. Tek `tab` karakteri de 4 boşluk yerine geçecektir. + +Kaydedip çalıştırmayı deneyelim: + +``` +$ python3 python_intro.py +Çalışıyor! +``` + +### Ya bir koşul True (Doğru) değilse? + +Önceki örneklerde kod sadece koşullar sadece True olduğunda çalışıyordu. Ama Python ayrıca `elif` ve `else` ifadelerine de sahip: + +```python +if 5 > 2: + print('5 gerçekten de 2'den büyüktür') +else: + print('5 2'den büyük değildir') +``` + +Bu kod çalıştığında aşağıdaki çıktıyı verecektir: + +``` +$ python3 python_intro.py +5 gerçekten de 2'den büyüktür +``` + +Eğer 2 5'ten büyük bir sayı olsaydı ikinci komut çalışacaktı. Kolay, değil mi? Şimdi `elif`'in nasıl çalıştığına bakalım: + +```python +name = 'Zeynep' +if name == 'Ayşe': + print('Selam Ayşe!') +elif name == 'Zeynep': + print('Selam Zeynep!') +else: + print('Selam yabancı!') +``` + +ve çalıştırılınca: + +``` +$ python3 python_intro.py +Selam Zeynep! +``` + +Gördünüz mü? Eğer önceki if cümleleriniz doğru olmazsa kontrol edilmek üzere `elif` cümleleri ekleyebilirsiniz. + +`if` cümlenizden sonra istediğiniz kadar `elif` cümlesi ekleyebilirsiniz. Mesela: + +```python +volume = 57 +if volume < 20: + print("Çok sessiz.") +elif 20 <= volume < 40: + print("Güzel bir fon müziği") +elif 40 <= volume < 60: + print("Harika, her notayı duyabiliyorum") +elif 60 <= volume < 80: + print("Parti başlasın") +elif 80 <= volume < 100: + print("Biraz gürültülü!") +else: + print("Kulaklarım ağrıyor! :(") +``` + +Python sırayla her sorguyu çalıştırır ve sonucu ona göre yazar: + +``` +$ python3 python_intro.py +Harika, her notayı duyabiliyorum +``` + +### Özet + +Son üç alıştırmada öğrendikleriniz: + +* **kıyaslama yapmak** - Python'da `>`, `>=`, `==`, `<=`, `<`, `and`, `or` operatörlerini kullanarak kıyaslama yapabiliriz +* **Boolean** - İki farklı değer alabilen bir nesne tipidir: Ya `True` (doğru) olur ya da `False` (yanlış) +* **Dosya kaydetmek** - kodlarımızı dosyalara kaydederek daha büyük programları çalıştırabiliriz. +* **if...elif...else** - cümlelerini sadece belirli durumlar sağlandığında çalıştırmak istediğimiz komutlar için kullanabiliriz. + +Bu bölümün son kısmının zamanı geldi! + +## Kendi fonksiyonlarınız! + +Python'daki `len()` gibi fonksiyonları hatırlıyor musunuz? Haberler iyi - artık kendi fonksiyonlarınızı da yazabileceksiniz! + +Fonksiyon Python tarafından işlenmesi gereken yönergeler dizisidir. Python'da her fonksiyon `def` anahtar kelimesi ile başlar, bir isim verilir ve bazı parameterleri olabilir. Kolay bir tane ile başlayalım. **python_intro.py** içindeki kodu aşağıdaki ile değiştirelim: + +```python +def hi(): + print('Merhaba!') + print('Nasılsın?') + +hi() +``` + +Tamam, ilk fonksiyonumuz hazır! + +Fonksiyon adını neden dosyanın en altına yazdığımızı merak edebilirsiniz. Bunun nedeni, Python'ın dosyayı okuyup, onu yukarıdan aşağı doğru işlemesi. Yani fonksiyonumuzu kullanabilmek için, onu en alt kısımda yeniden yazmalıyız. + +Haydi şimdi bunu çalıştıralım ve neler olacağını görelim: + +``` +$ python3 python_intro.py +Merhaba! +Nasılsın? +``` + +Bu epey kolaydı! Şimdi parametreli bir fonksiyon yazalım. Bir önceki örneği kullanabiliriz - fonksiyonumuz yine 'merhaba' desin - ama bu sefer ismini de söylesin: + +```python +def hi(name): +``` + +Gördüğünüz gibi, fonksiyonumuza `name` (isim) adında bir parametre ekledik: + +```python +def hi(name): + if name == 'Ayşe': + print('Selam Ayşe!') + elif name == 'Zeynep': + print('Selam Zeynep!') + else: + print('Selam yabancı!') + +hi() +``` + +Unutmayın: `if` içerisindeki `print` fonksiyonundan önce dört tane boşluk var. Bunun sebebi sadece durum sağlandığında çalışmasını istememiz. Bakalım nasıl çalışıyor: + +``` +$ python3 python_intro.py +Traceback (most recent call last): +File "python_intro.py", line 10, in + hi() +TypeError: hi() missing 1 required positional argument: 'name' +``` + +Üzgünüz, bir hata. Neyse ki, Python bize oldukça yararlı bir hata mesajı veriyor. `hi()` fonksiyonun (yukarıda tanımladığımız) bir değişken kullanımını gerektirdiğini (`name` isimli) ve bizim o değişkeni fonksiyonu çağırırken iletmeyi unuttuğumuzu söylüyor. Dosyanın alt kısmında hatayı düzeltelim: + +```python +hi("Ayşe") +``` + +Ve tekrar çalıştıralım: + +``` +$ python3 python_intro.py +Selam Ayşe! +``` + +Ve eğer ismi değiştirirsek ne olur? + +```python +hi("Zeynep") +``` + +Ve çalıştırın: + +``` +$ python3 python_intro.py +Selam Zeynep! +``` + +Peki Ayşe veya Zeynep dışında başka bir isim yazdığımızda ne olacağını tahmin edebiliyor musunuz? Deneyin ve tahmininizin doğru olup olmadığını görün. Şunun gibi bir şey yazmalı: + +``` +Selam yabancı! +``` + +Süper değil mi? Böylece fonksiyona göndereceğiniz isim değiştiğinde aynı kodu tekrar tekrar yazmanıza gerek kalmayacak. İşte fonksiyonlara tam da bu yüzden ihtiyacımız var - aynı kodu tekrar yazmaya gerek yok! + +Hadi daha akıllıca bir şeyler yapalım -- tabii ki ikiden fazla isim var ve her isim için bir kontrol yazmak zor olurdu, değil mi? + +```python +def hi(name): + print('Selam ' + name + '!') + +hi("Seda") +``` + +Şimdi kodu çağıralım: + +``` +$ python3 python_intro.py +Selam Seda! +``` + +Tebrikler! Az önce fonksiyonları nasıl yazacağınızı öğrendiniz! :) + +## Döngüler + +Bu da zaten son parça. Hızlı oldu, değil mi? :) + +Programcılar kendilerini tekrar etmeyi sevmezler. Programlama tamamen işleri otomatize etmedir, bu yüzden her insanı ismiyle selam istemeyiz, değil mi? İşte burası döngülerin devreye girdiği yerdir. + +Hala listeleri hatırlıyoruz değil mi? Haydi bir kızlar listesi yapalım: + +```python +girls = ['Seda', 'Gül', 'Pınar', 'Ayşe', 'Sen'] +``` + +Diyelim ki hepsine merhaba demek istiyoruz. Az önce yazdığımız `hi` fonksiyonunu döngü içinde kullanabiliriz: + +```python +for name in girls: +``` + +~~~ for~~~ cümlesi ~~~ if~~~ cümlesine benzer davranır; ikisi için de dört boşluk karakterine ihtiyacımız car. + +Dosyada yer alacak tam kod aşağıdadır: + +```python +def hi(name): + print('Selam ' + name + '!') + +girls = ['Seda', 'Gül', 'Pınar', 'Ayşe', 'Sen'] +for name in girls: + hi(name) + print('Sıradaki') +``` + +Ve onu çalıştırdığımız zaman: + +``` +$ python3 python_intro.py +Selam Seda! +Sıradaki +Selam Gül! +Sıradaki +Selam Pınar! +Sıradaki +Selam Ayşe! +Sıradaki +Selam Sen! +Sıradaki +``` + +Gördüğünüz gibi, `for` cümlesinin içine boşluk karakteri ile koyduğunuz her şey `girls` listesi için tekrarlanıyor. + +Ayrıca `for`'u `range` fonksiyonuyla beraber sayılar üzerinde de kullanabilirsiniz: + +``` +for i in range(1, 6): + print(i) +``` + +Çalıştırırsak: + +``` +1 +2 +3 +4 +5 +``` + +`range` fonksiyonu birbirini takip eden sayılardan bir liste oluşturur (bu sayıları da siz parametre olarak yazarsınız). + +Sizin verdiğiniz ikinci parametrenin listede olmadığına dikkat edin. Yani `range(1, 6)` 1'den 5'e kadar sayıyor, 6 dahil edilmiyor. Çünkü "range" yarı-açık bir aralık ifade ediyor, yani ilk sayı dahil ediliyor ama sondaki sayı dahil edilmiyor. + +## Özet + +İşte bu. **Harikasın, süpersin!** Bu bölüm biraz zordu, kendinle gurur duymalısın. Biz buraya kadar geldiğin için seninle gurur duyuyoruz! + +Bir sonraki bölüme geçmeden önce kısa bir süreliğine başka birşey yapmak isteyebilirsiniz - esneyin, biraz etrafı dolaşın, gözlerinizi dinlendirin :) + +![Kek][3] + + [3]: images/cupcake.png diff --git a/tr/python_introduction/images/cupcake.png b/tr/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/tr/python_introduction/images/cupcake.png differ diff --git a/tr/template_extending/README.md b/tr/template_extending/README.md new file mode 100755 index 00000000000..82ae39b0448 --- /dev/null +++ b/tr/template_extending/README.md @@ -0,0 +1,124 @@ +# Template genişletmek + +Django'nun size sunduğu başka bir güzellik de **template genişletmek**tir. O da ne demek? Şu demek, HTML dosyanızın bazı bölümlerini birden fazla sayfanızda kullanabilirsiniz. + +Böylece aynı bilgi/yerleştirmeyi kullanmak istediğinizde her dosyada kendinizi tekrar etmenize gerek kalmaz. Ve bir değişiklik yapmak istediğinizde bunu bütün template dosyalarında yapmanıza gerek kalmaz, bir kere değiştirmek yeterlidir! + +## Temel template oluşturun + +Temel template web sitenizin bütün sayfalarında genişletebileceğiniz en temel template'inizdir. + +Şimdi `blog/templates/blog/` klasörü içinde `base.html` adlı bir dosya oluşturalım: + +``` +blog +└───templates + └───blog + base.html + post_list.html +``` + +Sonra bunu açalım ve `post_list.html` dosyasındaki her şeyi aşağıdaki gibi bu `base.html`'ye kopyalayalım: + +```html +{% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.yayinlama_tarihi }} +
+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + +Sonra, `base.html` dosyasındaki ``'nizi (`` ve `` arasında kalan her şeyi) şununla değiştirin: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + +Aslında sadece `{% for post in posts %}{% endfor %}` arasındaki her şeyi şununla değiştirmiş olduk: + +```html +{% block content %} +{% endblock %} +``` + +Peki bu ne anlama geliyor? Az önce bir template etiketi olan `block`'u kullanarak bir blok oluşturdunuz. Diğer template'leri bu bloğun içine HTML ekleyerek `base.html`'yi genişletebilirsiniz. Bunun nasıl yapıldığını da hemen göstereceğiz. + +Şimdi bunu kaydedin ve tekrar `blog/templates/blog/post_list.html` dosyanızı açın. Body içinde kalanlar hariç her şeyi silin. Ve ayrıca `` bölümünü de silin. Dosyanız şöyle görünecektir: + +```html +{% for post in posts %} +
+
+ {{ post.yayinlama_tarihi }} +
+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+{% endfor %} +``` + +Ve şimdi şu satırı sayfanın başına ekleyin: + +``` +{% extends 'blog/base.html' %} +``` + +{% raw %}Bu şu anlama geliyor: `post_list.html` dosyasında `base.html` template'i genişletiyoruz. Sadece bir şey kaldı: Her şeyi (en son eklediğimiz satır hariç) `{% block content %}` ve `{% endblock content %}` arasına koyun. Şunun gibi:{% endraw %} + +```html +{% extends 'blog/base.html' %} + +{% block content %} + {% for post in posts %} +
+
+ {{ post.yayinlama_tarihi }} +
+

{{ post.baslik }}

+

{{ post.yazi|linebreaksbr }}

+
+ {% endfor %} +{% endblock content %} +``` + +İşte bu! Sitenizin hala düzgün çalışıp çalışmadığını kontrol edin :) + +> `blog/base.html` dosyası olmadığını söyleyen bir `TemplateDoesNotExists` hatası alıyorsanız, ve `runserver` konsolda çalışmaya devam ediyorsa Ctrl ve C butonlarına aynı anda basarak durdurmaya çalışın. Ve `python manage.py runserver` komutu ile yeniden başlatmayı deneyin. \ No newline at end of file diff --git a/tr/whats_next/README.md b/tr/whats_next/README.md new file mode 100755 index 00000000000..940dcf852f1 --- /dev/null +++ b/tr/whats_next/README.md @@ -0,0 +1,40 @@ +# Sırada ne var? + +Kendini tebrik et! **Kesinlikle harikasın**. Seninle gurur duyuyoruz! <3 + +### Şimdi ne yapmak gerek? + +Bir ara ver ve rahatla. Gerçekten çok büyük bir şey yaptın. + +Bundan sonra şunları yaptığına emin ol: + +* Güncel kalmak için Django Girls'ü [Facebook][1] ya da [Twitter][2] dan takip et + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### Daha geniş kapsamlı kaynaklar önerebilir misiniz? + +Evet! Öncelikle [Django Girls Tutorial: Extensions][3] isimli diğer kitabımızı dene. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Sonra ise aşağıda listelenen diğer kaynakları deneyebilirsin. Hepsini öneriyoruz! + +- [Django'nun resmi eğitimi][4] +- [Kodlamaya Yeni Başlayan (New Coder) eğitimi][5] +- [Code Academy Python kursu][6] +- [Code Academy HTML & CSS kursu][7] +- [Django Carrots eğitimi][8] +- [Learn Python The Hard Way kitabı][9] +- [Getting Started With Django görünütülü dersleri][10] +- [Two Scoops of Django: Best Practices for Django 1.8 kitabı][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: http://django.carrots.pl/en/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 \ No newline at end of file diff --git a/uk/GLOSSARY.md b/uk/GLOSSARY.md new file mode 100644 index 00000000000..21fed491ffc --- /dev/null +++ b/uk/GLOSSARY.md @@ -0,0 +1,2 @@ +# Редактор коду +Редактор коду - це програма, що дозволяє зберегти ваш код, так що можна повернутися до його редагування пізніше. Ви можете дізнатися, звідки його взяти з розділу [про текстовий редактор](./code_editor/README.md) diff --git a/uk/README.md b/uk/README.md old mode 100755 new mode 100644 index 4995458c9bb..39af52cf8d7 --- a/uk/README.md +++ b/uk/README.md @@ -1,53 +1,45 @@ -# Навчальний посібник - Django Girls Tutorial - +# Навчальний посібник Django Girls [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - [1]: https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge - -> Ця робота ліцензована міжнародною ліцензією Creative Commons Attribution-ShareAlike 4.0. Щоб переглянути копію цієї ліцензії, відвідайте http://creativecommons.org/licenses/by-sa/4.0/ +> Ця робота ліцензована міжнародною ліцензією Creative Commons Attribution-ShareAlike 4.0 +International License. Щоб переглянути копію цієї ліцензії, відвідайте +https://creativecommons.org/licenses/by-sa/4.0/ ## Translation -100% of this tutorial has been translated from English by a volunteer: [chupakabra](https://github.com/chupakabra). Special thanks for all the free time you sacrificed to make that happen! <3 +This tutorial has been translated from English by a group of awesome volunteers: [chupakabra](https://github.com/chupakabra), [Oleksandr Redko](https://github.com/alexandear), [Taras Bunyk](https://github.com/bunyk), [msihor](https://crowdin.com/profile/msihor), [Olesia Hrydzhuk](https://github.com/Zlira), [Andriy Kohut](https://github.com/andriykohut), [Artem Suchov](https://crowdin.com/profile/suchov), [Artem Godlevskyi](https://github.com/errno), [Alex Vykalyuk](https://crowdin.com/profile/alekzvik), [Kostyantyn Leschenko](https://crowdin.com/profile/kleschenko). Special thanks for all the free time they sacrificed to make that happen! <3 + ## Вступ -Чи ви колись відчували, що світ крутиться все більше і більше навколо технологій, а ви в певній мірі пасете задніх? Чи вас колись цікавило як створити веб сайт, однак, ніколи не вистачало достатньої мотивації щоб почати? Чи ви колись вважали, що світ програмування є занадто складним для вас, щоб навіть пробувати робити щось самостійно? +Чи ви коли-небудь відчували, що світ крутиться все більше і більше навколо технологій, а ви в певній мірі пасете задніх? Чи вас колись цікавило, як створити веб-сайт, однак, ніколи не вистачало достатньої мотивації, щоб почати? Чи ви колись вважали, що світ програмування є занадто складним для вас, щоб навіть пробувати робити щось самостійно? -Що ж, маємо гарні новини для вас! Програмування це не так складно як може здаватися і ми хочемо вам показати наскільки веселим цей процес може бути. +Що ж, маємо гарні новини для вас! Програмування - це не так складно, як може здатися, і ми хочемо вам показати, наскільки веселим цей процес може бути. -Даний навчальний посібник не перетворить вас магічним чином на програміста. Якщо ви хочете розбиратися у цьому, то вам потрібні будуть для цього місяці або навіть роки теорії та практики. Однак, ми хочемо показати вам, що програмування або створення веб сайтів не є настільки складним, як це здається. Спробуємо пояснити різні поняття настільки, наскільки зуміємо, то ж ви не будете почуватися заляканими технологіями. +Даний навчальний посібник не перетворить вас магічним чином на програміста. Якщо ви хочете розбиратися у цьому, то вам потрібні будуть для цього місяці або навіть роки теорії та практики. Однак ми хочемо показати вам, що програмування або створення веб сайтів не є настільки складним, як це здається. Спробуємо пояснити різні поняття настільки, наскільки зуміємо, то ж ви не будете почуватися заляканими технологіями. -Сподіваємось, що що ми зможемо змусити вас полюбити технології настільки, наскільки любимо їх ми самі! +Сподіваємось, ми зможемо навчити вас полюбити технології настільки, наскільки любимо їх ми самі! ## Що ви вивчите під час освоєння посібника? -По завершенню даного посібника, ви будете мати простий,робочий веб додаток: свій власний блог. Ми покажемо вам як опублікувати його в Інтернеті, то ж інші також зможуть оцінити вашу роботу! +По завершенню даного посібника, ви будете мати простий робочий веб-додаток - свій власний блог. Ми покажемо вам як опублікувати його в Інтернеті, тож інші також зможуть оцінити вашу роботу! Це буде (в більшій чи меншій мірі) виглядати наступним чином: -![Figure 0.1](images/application.png) +![Рисунок 0.1](images/application.png) -> Якщо ви працюєте над матеріалами самостійно і не маєте інструктора, що зміг би допомогти у разі певної проблеми, ми маємо для вас чат: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -. Ми попросили наших інструкторів і попередніх учасників бути там час від часу і допомагати іншим із освоєнням матеріалу! Не бійтеся задавати свої питання! +> Якщо ви працюєте над матеріалами самостійно і не маєте інструктора, що зміг би допомогти у разі певної проблеми, для вас існує чат: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge). Ми попросили наших інструкторів і попередніх учасників бути там час від часу та допомагати іншим із освоєнням матеріалу! Не бійтеся задавати свої питання! -Гаразд, [почнемо з самого початку...][3] - - [3]: ./how_the_internet_works/README.md +Гаразд, [почнемо з самого початку...](./how_the_internet_works/README.md) ## Коротка інформація та вклад -Цей посібник підтримується спільнотою [DjangoGirls][4]. Якщо ви знайдете якісь помилки або захочете зробити певні оновлення, будь ласка, [виконуйте вказівки з частини про вклад][5]. - - [4]: http://djangogirls.org/ - [5]: https://github.com/DjangoGirls/tutorial/blob/master/README.md +Цей посібник підтримується спільнотою [DjangoGirls](https://djangogirls.org/). Якщо ви знайдете якісь помилки або захочете зробити певні оновлення, будь ласка, [виконуйте вказівки з частини про вклад](https://github.com/DjangoGirls/tutorial/blob/master/README.md). ## Чи не бажаєте допомогти нам із перекладом посібника на інші мови? -на даний момент, переклади підтримуються на платформі crowdin.com: +На даний момент, переклади підтримуються на платформі crowdin.com: https://crowdin.com/project/django-girls-tutorial -Якщо ваша мова не перерахована на crowdin, будь ласка, [відкрийте нову тему][6], що інформує про мову, таким чином ми зможемо додати її - - [6]: https://github.com/DjangoGirls/tutorial/issues/new +Якщо ваша мова не перерахована на crowdin, будь ласка, [відкрийте нову тему](https://github.com/DjangoGirls/tutorial/issues/new), що інформує про мову, таким чином ми зможемо додати її. diff --git a/uk/SUMMARY.md b/uk/SUMMARY.md old mode 100755 new mode 100644 index 46b334679ac..ea34bf8e38d --- a/uk/SUMMARY.md +++ b/uk/SUMMARY.md @@ -1,26 +1,26 @@ # Зміст -* [Вступ](README.md) -* [Як працює Інтернет?](how_the_internet_works/README.md) -* [Вступ до командного рядку](intro_to_command_line/README.md) -* [Встановлення Python](python_installation/README.md) -* [Редактор коду](code_editor/README.md) -* [Вступ до Python](python_introduction/README.md) -* [Що таке Django?](django/README.md) -* [Встановлення Django](django_installation/README.md) -* [Запуск Django проекту](django_start_project/README.md) -* [Django моделі](django_models/README.md) -* [Django адміністратор](django_admin/README.md) -* [Розгортання!](deploy/README.md) -* [Django urls](django_urls/README.md) -* [Django відображення - час творити!](django_views/README.md) -* [Вступ до HTML](html/README.md) -* [Django ORM (Querysets)](django_orm/README.md) -* [Динамічні дані в шаблонах](dynamic_data_in_templates/README.md) -* [Django шаблони](django_templates/README.md) -* [CSS - зроби це красиво](css/README.md) -* [Шаблонне розширення](template_extending/README.md) -* [Розширте свою програму](extend_your_application/README.md) -* [Django форми](django_forms/README.md) -* [Домен](domain/README.md) -* [Що далі?](whats_next/README.md) +* [Вступ](README.md) +* [Встановлення](installation/README.md) +* [Як працює Інтернет](how_the_internet_works/README.md) +* [Вступ до командного рядку](intro_to_command_line/README.md) +* [Встановлення Python](python_installation/README.md) +* [Редактор коду](code_editor/README.md) +* [Вступ до Python](python_introduction/README.md) +* [Що таке Django?](django/README.md) +* [Встановлення Django](django_installation/README.md) +* [Ваш перший Django проект!](django_start_project/README.md) +* [Django моделі](django_models/README.md) +* [Django адміністратор](django_admin/README.md) +* [Розгортання!](deploy/README.md) +* [Django urls](django_urls/README.md) +* [Django відображення - час творити!](django_views/README.md) +* [Вступ до HTML](html/README.md) +* [Django ORM (Querysets)](django_orm/README.md) +* [Динамічні дані в шаблонах](dynamic_data_in_templates/README.md) +* [Django шаблони](django_templates/README.md) +* [CSS - зроби це красиво](css/README.md) +* [Шаблонне розширення](template_extending/README.md) +* [Розширте свою програму](extend_your_application/README.md) +* [Django форми](django_forms/README.md) +* [Що далі?](whats_next/README.md) diff --git a/uk/code_editor/README.md b/uk/code_editor/README.md old mode 100755 new mode 100644 index 11880c6a6af..da85dfaae1c --- a/uk/code_editor/README.md +++ b/uk/code_editor/README.md @@ -1,31 +1,7 @@ # Редактор коду -Наближаємось до написання нашого першого рядка коду, отже настав час завантажити редактор коду! +Наближаємось до написання нашого першого рядка коду, отже, настав час завантажити редактор коду! -Існує багато різноманітних редакторів і здебільшого все зводиться до персональних вподобань. Більшість Python програмістів використовують складні, але надзвичайно потужні IDE (англ. Integrated Development Environments - Інтегровані середовища розробки), такі як PyCharm. Однак, вони можливо менш доцільні для початківців; ми пропонуємо не менш потужні, але більш простіші. +> **Примітка** Ви могли зробити це раніше у розділі "Встановлення" - якщо вже завантажили редактор, то можете відразу перейти до наступного розділу! -Нижче наведено перелік наших вподобань, але також можете попросити поради в своїх тренерів - буде простіше отримувати від них допомогу. - -## Gedit - -Gedit є відкритим, безкоштовним редактором, доступним для усіх операційних систем. - -[Завантажити Gedit можна тут][1] - - [1]: https://wiki.gnome.org/Apps/Gedit#Download - -## Sublime Text 2 - -Sublime Text є дуже популярним редактором із безкоштовним пробним періодом. Він легко встановлюється та простий у використанні і, також доступний для усіх операційних систем. - -[Завантажити Sublime Text 2 можна тут][2] - - [2]: http://www.sublimetext.com/2 - -## Atom - -Atom - це найновіший редактор коду створений GitHub. Він є безкоштовним, відкритим, легко встановлюється та простий у користуванні. Доступний для Windows, OSX і Linux. - -[Завантажити Atom можна тут][3] - - [3]: https://atom.io/ \ No newline at end of file +{% include "/code_editor/instructions.md" %} diff --git a/uk/code_editor/instructions.md b/uk/code_editor/instructions.md new file mode 100644 index 00000000000..4f6cce57793 --- /dev/null +++ b/uk/code_editor/instructions.md @@ -0,0 +1,34 @@ +Існує багато різноманітних редакторів і здебільшого все зводиться до персональних вподобань. Більшість Python програмістів використовують складні, але надзвичайно потужні IDE (англ. Integrated Development Environments - інтегровані середовища розробки), такі як PyCharm. Однак, вони менш доцільні для початківців; ми пропонуємо такі ж потужні, але більш простіші інструменти. + +Нижче наведено перелік наших вподобань, але ви також можете попросити поради в своїх тренерів - тоді буде простіше отримувати від них допомогу. + +## Gedit + +Gedit є відкритим, безкоштовним редактором, доступним для усіх операційних систем. + +[Завантажте його можна тут](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3 + +Sublime Text є дуже популярним редактором із безкоштовним пробним періодом. Він легко встановлюється та простий у використанні, а також доступний для усіх операційних систем. + +[Завантажити його можна тут](https://www.sublimetext.com/3) + +## Atom + +Atom - це найновіший редактор коду, створений [GitHub](https://github.com/). Він є безкоштовним, відкритим, легко встановлюється та простий у користуванні. Доступний для Windows, OSX і Linux. + +[Завантажити його можна тут](https://atom.io/) + + + +## Чому ми встановлюємо редактор коду? + +Ви напевне запитуєте себе, чому ми встановлюємо спеціальний редактор для коду, а не використовуємо щось на зразок Word чи Notepad. + +По-перше, код повинен зберігатись як **звичайний текст**, а проблемою таких програм як Word чи Textedit є те, що вони не створюють звичайний текст, вони продукують так званий "збагачений" текст (зі шрифтами та форматуванням), використовуючи спеціальні формати, такі як [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +Другою причиною є те, що редактори коду спеціалізуються саме на редагуванні коду, тому вони можуть запропонувати корисні функції на зразок підсвітки коду залежно від його значення чи автоматичного закривання дужок. + +Ми побачимо все це в дії пізніше. Скоро ви вважатимете свого вірного редактора коду одним із найулюбленіших інструментів :) + diff --git a/uk/css/README.md b/uk/css/README.md index 152818950b1..f84307689ea 100755 --- a/uk/css/README.md +++ b/uk/css/README.md @@ -4,13 +4,13 @@ ## Що таке CSS? -Каскадні таблиці стилів (англ. Cascading Style Sheets або скорочено CSS) - спеціальна мова, що використовується для опису зовнішнього вигляду і форматування сайту написаного мовою розмітки (як HTML). Сприймайте це, як свого роду макіяж для нашої веб-сторінки;). +Каскадні таблиці стилів (англ. Cascading Style Sheets, скорочено CSS) - спеціальна мова, що використовується для опису зовнішнього вигляду і форматування сайту написаного мовою розмітки (як HTML). Сприймайте це, як свого роду макіяж для нашої веб-сторінки;). Але ми ж не хочемо починати знову все з нуля, правда? А візьмемо знову щось, що вже було створене програмістами і опубліковано в Інтернеті для вільного користування. Ви ж знаєте, знову винаходити велосипед зовсім не весело. ## Скористаємось Bootstrap! -Bootstrap - один з найбільш популярних HTML і CSS фреймворків для розробки прекрасних веб-сайтів: http://getbootstrap.com/ +Bootstrap - один з найбільш популярних HTML і CSS фреймворків для розробки прекрасних веб-сайтів: https://getbootstrap.com/ Він був написаний програмістами, які працювали для Twitter'у і на сьогоднішній день удосконалюється волонтерами з усього світу. @@ -18,92 +18,90 @@ Bootstrap - один з найбільш популярних HTML і CSS фре Для встановлення Bootstrap, вам потрібно додати наступні рядки у розділ `` вашого `.html` файлу (`blog/templates/blog/post_list.html`): - - - +```html + + +``` -Це не додасть жодного файлу до вашого проекту. Натомість ці рядки просто вказують на файли опубліковані в інтернеті. Просто рухайтесь вперед, відкрийте ваш веб-сайт і оновіть сторінку. Ось так! +Це не додасть жодного файлу до вашого проекту. Натомість ці рядки просто вказують на файли опубліковані в інтернеті. +Просто рухайтесь вперед, відкрийте ваш веб-сайт і оновіть сторінку. Ось так! ![Рисунок 14.1](images/bootstrap1.png) Вже краще! + ## Статичні файли в Django -Інше поняття, про яке ви дізнаєтесь сьогодні називається **статичні файли**. Статичні файли включають усі ваші CSS файли та малюнки -- файли, які не є динамічними, а отже їхній вміст не залежить від змісту запиту і буде однаковим для усіх користувачів. +Нарешті, ми детальніше розглянемо те, що ми називали __статичними файлами__. Статичні файли включають усі ваші CSS файли та картинки - файли, які не є динамічними, а отже, їхній вміст не залежить від змісту запиту і буде однаковим для усіх користувачів. -CSS -- статичний файл, отже для того щоб налаштувати CSS, нам потрібно спочатку налаштувати статичні файли в Django. Вам потрібно зробити це лише один раз. Почнемо: -### Налаштування статичних файлів в Django +### Де помістити статичні файли для Django -Спочатку, нам потрібно створити папку для зберігання наших статичних файлів. Створимо папку `static` всередині нашої папки `djangogirls` . +Як ви бачили, коли ми запускали `collectstatic` на сервері, Django вже знає, де знайти статичні файли для вбудованого додатку "admin". Тепер нам просто потрібно додати деякі статичні файли для нашого власного додатку `blog`. + +Створимо директорію `static` всередині додатку blog: djangogirls - ├─── static - └─── manage.py - + ├── blog + │ ├── migrations + │ └── static + └── mysite -Відкриємо файл `mysite/settings.py`, опустимося вниз і додамо наступні рядки: +Django автоматично знайде всі "статичні" папки всередині будь-якої з папок з вашими додатками, і він буде мати можливість використовувати їх як статичні файли. - STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "static"), - ) - -Таким чином Django буде знати де можна знайти ваші статичні файли. ## Ваш перший CSS файл! -Що ж, тепер давайте створимо CSS файл для того, щоб додати ваш власний стиль до вашої веб-сторінки. Створіть нову папку з назвою `css` всередині вашої папки `static`. Потім всередині цієї папки`css` створіть новий файл з назвою `blog.css`. Готово? - - static - └─── css - blog.css - - -Настав час написати CSS! Відкрийте файл `static/css/blog.css` в обраному кодовому редакторі. +Що ж, тепер давайте створимо CSS файл для того, щоб додати ваш власний стиль до вашої веб-сторінки. Створіть нову папку з назвою `css` всередині вашої папки `static`. Потім всередині цієї папки`css` створіть новий файл `blog.css`. Готові? -Не будемо тут занурюватись надто глибоко в процес налаштування і вивчення CSS, оскільки це так просто, що ви можете вивчити цей матеріал самостійно після завершення воркшопу. Ми наполегливо рекомендуємо пройти цей курс [Codeacademy HTML & CSS course][2] для того щоб вивчити все, що вам потрібно знати про оформлення веб-сайтів з CSS. + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css - [2]: http://www.codecademy.com/tracks/web +Настав час написати CSS! Відкрийте файл `static/css/blog.css` в редакторі коду. -Але принаймні попрацюємо трохи. Можливо, ми могли б змінити колір заголовка? Щоб зрозуміти кольори, комп'ютери використовують спеціальні коди. Вони починаються з `#` і далі слідують 6 літер (A-F), а також цифри (0-9). Ви можете знайти коди кольорів, наприклад, тут: http://www.colorpicker.com/. Також можете користуватися вже [визначеними кольорами ][3], такими як `red` та `green`. +Не будемо тут занурюватись надто глибоко в процес налаштування і вивчення CSS, оскільки це так просто, що ви можете вивчити цей матеріал самостійно після завершення воркшопу. Ми наполегливо рекомендуємо пройти курс [Codeacademy HTML & CSS course](https://www.codecademy.com/tracks/web) для того, щоб вивчити все, що вам потрібно знати про оформлення веб-сайтів за допомогою CSS. - [3]: http://www.w3schools.com/cssref/css_colornames.asp +Але принаймні попрацюємо трохи. Може ми могли б змінити колір заголовка? +Щоб зрозуміти кольори, комп'ютери використовують спеціальні коди. Вони починаються з `#` і далі слідують 6 літер (A-F), а також цифри (0-9). Ви можете знайти коди кольорів, наприклад, тут: http://www.colorpicker.com/. Також можете користуватися вже [визначеними кольорами](http://www.w3schools.com/colors/colors_names.asp), такими як `red` та `green`. У вашому файлі `static/css/blog.css` потрібно додати наступний код: - h1 a { - color: #FCA205; - } - - -`h1 a` -- CSS селектор. Це означає, що ми застосовуємо наші стилі до кожного елементу `a` всередині елементу `h1` (наприклад, коли ми маємо в коді щось на зразок: `

link

`). У цьому випадку, ми повідомляємо про те, що треба змінити колір на `#FCA205`, тобто помаранчевий. Звичайно, ви можете визначити тут ваш власний колір! +```css +h1 a { + color: #FCA205; +} +``` -В CSS файлі ми визначаємо стилі для елементів файлу HTML. Елементи ідентифікуються іменами (тобто `a`, `h1`, `body`), атрибутом `class` або атрибутом `id`. Class і id -- імена, які ви присвоюєте елементам власноруч. Класи (сlasses) визначають групи елементів, а ідентифікатори (id), в свою чергу, вказують на специфічні елементи. Наприклад, наступний тег може бути ідентифікований CSS з використанням тегового імені `a`, класу `external_link`, або ідентифікатора `link_to_wiki_page`: +`h1 a` - CSS селектор. Це означає, що ми застосовуємо наші стилі до кожного елементу `a` всередині елементу `h1` (наприклад, коли ми маємо в коді щось на зразок: `

link

`). У цьому випадку, ми повідомляємо про те, що треба змінити колір на `#FCA205`, тобто помаранчевий. Звичайно, ви можете визначити тут ваш власний колір! - - +В CSS файлі ми визначаємо стилі для елементів файлу HTML. Елементи ідентифікуються іменами (тобто `a`, `h1`, `body`), атрибутом `class` або атрибутом `id`. +Class і id - імена, які ви присвоюєте елементам власноруч. Класи (сlasses) визначають групи елементів, а ідентифікатори (id), в свою чергу, вказують на специфічні елементи. Наприклад, наступний тег може бути ідентифікований CSS з використанням тегового імені `a`, класу `external_link`, або ідентифікатора `link_to_wiki_page`: -Читайте про CSS селектори в [CSS Selectors in w3schools][4]. +```html + +``` - [4]: http://www.w3schools.com/cssref/css_selectors.asp +Читайте про [CSS селектори на w3schools](http://www.w3schools.com/cssref/css_selectors.asp). -Далі, нам треба також повідомити наш HTML шаблон про те, що ми додали CSS. Відкрийте файл `blog/templates/blog/post_list.html` і цей рядок до самого початку: +Далі, нам треба повідомити наш HTML-шаблон про те, що ми додали CSS. Відкрийте файл `blog/templates/blog/post_list.html` і додайте на початок цей рядок: ```html {% load staticfiles %} ``` - -Тут ми лише завантажуємо статичні файли:). Далі, між `` і ``, після лінків на файли Bootstrap CSS (браузер читає файли за порядком їх слідування, отже код нашого файлу перекриває код в файлах Bootstrap), додайте цей рядок: +Тут лише завантажуються статичні файли :) +Далі, між `` і ``, після посилань на CSS файли Bootstrap додайте цей рядок: ```html ``` - - -Ми щойно повідомили наш шаблон де розташовані наші CSS файли. +Браузер читає файли в порядку їх слідування, тому ми повинні впевнитись, що код написаний в правильному місці. Інакше, код в нашому файлі може перекривати код із файлів Bootstrap. +Ми щойно повідомили наш шаблон, де розташовані наші CSS файли. Тепер ваш файл має виглядати наступним чином: @@ -125,56 +123,60 @@ CSS -- статичний файл, отже для того щоб налашт

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -OK, збережіть файл і перезавантажте сторінку! +Добре, збережіть файл і перезавантажте сторінку! ![Рисунок 14.2](images/color2.png) Чудова робота! Можливо, ми також хотіли б дати нашому веб-сайту трохи повітря і збільшити відступ зліва? Давайте спробуємо! - body { - padding-left: 15px; - } - +```css +body { + padding-left: 15px; +} +``` -Додайте це до вашого CSS, збережіть файл і подивіться як це працює! +Додайте це до вашого CSS, збережіть файл і подивіться, як це працює! ![Рисунок 14.3](images/margin2.png) -Можливо, ми могли б також налаштувати шрифт нашого заголовка? Вставте це всередину розділу `` файлу `blog/templates/blog/post_list.html`: +Може ми могли б також налаштувати шрифт нашого заголовка? Вставте це всередину розділу `` файлу `blog/templates/blog/post_list.html`: - - +```html + +``` -Цей рядок імпортує шрифт із назвою *Lobster* з шрифтів Google (https://www.google.com/fonts). +Цей рядок імпортує шрифт із назвою *Lobster* із колекції шрифтів Google (https://www.google.com/fonts). -Тепер додайте рядок `font-family: 'Lobster';` до файлу `static/css/blog.css` всередині блоку визначення стилю для `h1 a` (код між дужками `{` і `}`) та перезавантажте сторінку: +Знайдіть блок визначення стилю `h1 a` (код між фігурними дужками `{` і `}`) в CSS файлі `blog/static/css/blog.css`. Тепер додайте Тепер додайте рядок `font-family: 'Lobster';` між дужками і перезавантажте сторінку: - h1 a { - color: #FCA205; - font-family: 'Lobster'; - } - +```css +h1 a { + color: #FCA205; + font-family: 'Lobster'; +} +``` ![Рисунок 14.3](images/font.png) Чудово! -Як було зазначено вище, CSS має концепцію класів, котра дозволяє вам іменувати частину HTML коду і застосовувати стилі лише для цієї частини без будь-якого ефекту для інших. Це надзвичайно корисно якщо у вас є скажімо два блоки div, але вони виконують зовсім різні функції (як ваш заголовок і пост), отже, ви не хочете, щоб вони виглядали однаково. -Дайте імена певним частинам HTML коду. Додайте клас із назвою `page-header` до блоку `div`, що містить ваш заголовок, як це зроблено тут: +Як було зазначено вище, CSS має концепцію класів. Вона дозволяє вам іменувати частину HTML коду і застосовувати стилі лише до цієї частини без будь-якого ефекту на інші частини. Це буває надзвичайно корисним. Скажімо, у вас є два блоки div, але вони виконують зовсім різні функції (як ваш заголовок і пост). Клас дозволяє вам зробити їх вигляд різним. - - +Дайте імена певним частинам HTML коду. Додайте клас `page-header` до блоку `div`, що містить ваш заголовок, як це зроблено тут: + +```html + +``` А тепер додайте клас `post` до вашого блоку `div`, що містить сам допис. @@ -182,74 +184,73 @@ OK, збережіть файл і перезавантажте сторінку

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

``` - - -А тепер додамо визначення блоків для різних селекторів. Селектори, які починають із символу `.` стосуються класів. Існує багато хороших довідників про CSS в Інтернеті, які можуть допомогти вам зрозуміти наступний код. Поки що, просто скопіюйте і вставте це у ваш файл `djangogirls/static/css/blog.css`: - - .page-header { - background-color: #ff9400; - margin-top: 0; - padding: 20px 20px 20px 40px; - } - - .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { - color: #ffffff; - font-size: 36pt; - text-decoration: none; - } - - .content { - margin-left: 40px; - } - - h1, h2, h3, h4 { - font-family: 'Lobster', cursive; - } - - .date { - float: right; - color: #828282; - } - - .save { - float: right; - } - - .post-form textarea, .post-form input { - width: 100%; - } - - .top-menu, .top-menu:hover, .top-menu:visited { - color: #ffffff; - float: right; - font-size: 26pt; - margin-right: 20px; - } - - .post { - margin-bottom: 70px; - } - - .post h1 a, .post h1 a:visited { - color: #000000; - } - - -Далі модифікуйте HTML код, що відображує пости. Замініть: + +А тепер додамо визначення блоків для різних селекторів. Селектори, які починаються із символу `.` стосуються класів. Існує багато хороших посібників і пояснень CSS у Вебі, що можуть допомогти вам зрозуміти наступний код. Поки що, просто скопіюйте і вставте це у ваш файл `mysite/static/css/blog.css`: + +```css +.page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; +} + +.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; +} + +.content { + margin-left: 40px; +} + +h1, h2, h3, h4 { + font-family: 'Lobster', cursive; +} + +.date { + float: right; + color: #828282; +} + +.save { + float: right; +} + +.post-form textarea, .post-form input { + width: 100%; +} + +.top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; +} + +.post { + margin-bottom: 70px; +} + +.post h1 a, .post h1 a:visited { + color: #000000; +} +``` + +Далі обгорніть HTML код, що відображає пости, визначеннями класів. Замініть це: ```html {% for post in posts %}

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - в `blog/templates/blog/post_list.html` на: @@ -260,26 +261,27 @@ OK, збережіть файл і перезавантажте сторінку {% for post in posts %}
- {{ post.published_date }} +

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -Збережіть файли і перезавантажте свій сайт. +Збережіть ці файли і перезавантажте веб-сайт. ![Рисунок 14.4](images/final.png) -Юхууу! Виглядає прекрасно, чи не так? Код, який ми щойно вставили насправді не є складним для розуміння і ви маєте бути в змозі зрозуміти більшу його частину просто прочитавши. +Юхууу! Виглядає прекрасно, чи не так? +Код, який ми щойно вставили, насправді не є складним для розуміння і ви в змозі зрозуміти більшу його частину після прочитання. -Не бійтеся трохи повозитися з цим CSS файлом і спробуйте поміняти деякі речі. Якщо щось зламається, не хвилюйтесь, ви завжди можете відмінити попередню дію! +Не бійтеся трохи повозитися з цим CSS файлом і спробуйте поміняти деякий код. Якщо щось зламається, не хвилюйтесь, ви завжди можете відмінити попередню дію! -В будь-якому разі, ми настійно рекомендуємо пройти цей безкоштовний он-лайн курс [Codeacademy HTML & CSS course][2] як своєрідну домашню роботу після воркшопу щоб вивчити усе, що потрібно знати про оформлення ваших веб-сайтів із CSS. +В будь-якому разі, дуже рекомендуємо пройти цей безкоштовний онлайн [Codeacademy HTML & CSS курс](https://www.codecademy.com/tracks/web). Він допоможе вам вивчити усе, що потрібно знати про оформлення веб-сайтів за допомогою CSS. Готові до наступного розділу?! :) + diff --git a/uk/deploy/README.md b/uk/deploy/README.md index f7aa57859b7..99badc01230 100755 --- a/uk/deploy/README.md +++ b/uk/deploy/README.md @@ -1,229 +1,308 @@ # Розгортання! -> **Зауваження** Даний розділ інколи може даватись трохи складно для освоєння. Наполегливо продовжуйте і дійдіть до кінця; розгортання -- важлива частина процесу розробки веб-сайту. Цей розділ розміщено всередині даного практичного посібника, отже ваш наставник зможе допомогти із цим дещо хитрим процесом випуску вашого веб-сайту в Інтернет. Це означає, що ви все ще можете завершити цей курс самостійно, якщо раптом не встигаєте. +> **Зауваження** Цей розділ може бути дещо складним для освоєння. Наполегливо продовжуйте і дійдіть до кінця; розгортання - важлива частина процесу розробки веб-сайту. Цей розділ розташований посередині посібника, щоб ваш наставник зміг допомогти із дещо хитрим процесом випуску веб-сайту в Інтернет. Це означає, що ви все ще можете завершити цей курс самостійно, якщо раптом не встигаєте. -До цього часу ваш веб-сайт був доступний лише локально на вашому комп'ютері, тепер ви дізнаєте як його розгорнути! Розгортання -- це процес публікації вашого додатку в Інтернеті таким чином, що люди можуть зрештою зайти і побачити його :). +До цього часу ваш веб-сайт був доступний лише локально на вашому комп'ютері, тепер ви дізнаєтесь, як його розгорнути! Розгортання - це процес публікації вашого додатку в Інтернеті таким чином, що люди можуть зайти і побачити його :). -Як ви вже знаєте, веб-сайт має бути розміщений на сервері. Існує багато провайдерів, однак ми будемо користуватися таким, що має найпростіший процес розгортання: [Heroku][1]. Heroku є безкоштовним для невеликих додатків, які не мають дуже багато відвідувачів, однозначно наразі цього буде достатньо для вас. +Як ви вже знаєте, веб-сайт має бути розміщений на сервері. В Інтернеті є багато компаній які пропонують такі послуги. Ми будемо використовувати той, який має відносно простий розгортання процес: [PythonAnywhere](https://pythonanywhere.com/). PythonAnywhere безкоштовний для малих додатків, в яких не дуже багато користувачів, тож нам цього точно буде достатньо. - [1]: http://heroku.com/ +Інший зовнішній інструмент, який ми будемо використовувати - це [GitHub](https://www.github.com), платформа для розміщення коду. У нього є альтернативи, але майже кожен програміст зараз має GitHub профіль, і скоро ви будете серед них! -Ми будемо слідувати згідно цього посібника: https://devcenter.heroku.com/articles/getting-started-with-django, але ми розмістили його тут, отже вам буде простіше. +Ці три місця є дуже важливими для вас. Ваш локальний комп'ютер буде місцем, де ви розробляєте і тестуєте. Після того, як впевнитесь в змінах, ви перемістите копію програми на GitHub. Веб-сайт буде на PythonAnywhere і ви оновите його, роблячи нову копію коду з GitHub. -## Файл `requirements.txt` +# Git -Нам потрібно створити файл `requirements.txt` щоб повідомити Heroku які пакети Python повинні бути встановлені на нашому сервері. +Git - це "система контролю версій", яка використовується багатьма розробниками. Ця програма дозволяє відслідковувати зміни у файлах з часом так, що ви можете повернутись до певних версій пізніше. Схоже на функцію "слідкувати за змінами" в Microsoft Word, але набагато потужніше. -Але спочатку, Heroku потребує встановлення декількох пакетів. Перейдіть до вашої консолі із активованою `virtualenv` та наберіть наступне: +## Встановлення Git - (myvenv) $ pip install dj-database-url gunicorn whitenoise - +> **Примітка** Якщо ви вже виконали процес встановлення, немає потреби робити це ще раз, - можете перейти до наступного кроку і почати створення свого Git репозиторію. -По завершенню інсталяції перейдіть до папки `djangogirls` та запустіть цю команду: +{% include "/deploy/install_git.md" %} - (myvenv) $ pip freeze > requirements.txt - +## Створення свого Git репозиторію -Створиться файл із назвою `requirements.txt`, який міститиме список встановлених пакетів (тобто бібліотек Python, якими ви користуєтесь, наприклад Django :)). +Git відслідковує зміни певних файлів в репозиторії коду (коротко – "репо"). Давайте створимо "репо" для нашого проекту. Відкрийте вашу консоль та запустіть наступні команди в папці `djangogirls`: -> **Зауваження**: `pip freeze` виводить список усіх Python бібліотек встановлених у вашому virtualenv, а `>` перенаправляє вихід `pip freeze` до файлу. Спробуйте запустити `pip freeze` без `> requirements.txt` щоб побачити що трапиться! +> **Примітка** Перевірте поточну директорію за допомогою команд `pwd` (OSX/Linux) або `cd` (Windows) перед стартом репозиторію. Ви маєте бути в папці `djangogirls`. -Відкрийте цей файл і додайте наступний рядок в самий кінець: + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com - psycopg2==2.5.4 - +Створення git-репозиторію відбувається тільки один раз на кожен проект (і тобі більше не потрібно буде заново вводити ім'я чи електронну пошту). -Цей рядок потрібен для того, щоб ваш додаток працював на Heroku. +Git стежитиме за змінам всіх файлів у цій директорії, але є певні файли, які ми хочемо ігнорувати. Ми зробимо це шляхом створення файлу з назвою `.gitignore` в базовій директорії. Відкрий свій редактор і створи новий файл з наступним змістом: -## Procfile +``` +*.pyc +__pycache__ +myvenv +db.sqlite3 +/static +.DS_Store +``` -Інша річ, яку ми повинні створити -- Procfile. Це дозволить Heroku знати які команди виконувати для того, щоб запустити наш веб-сайт. Відкрийте кодовий редактор, створіть файл із назвою `Procfile` у папці `djangogirls` і додайте цей рядок: +І збережи його як `.gitignore` в директорії "djangogirls". - web: gunicorn mysite.wsgi - +> **Примітка** Крапка на початку імені файлу важлива! У разі виникнення будь-яких труднощів при створенні (наприклад, Mac не любить, коли через Finder створюють файли, імена яких починаються з крапки), використовуйте "Зберегти як" у редакторі, це повинно спрацювати. -Цей рядок означає що ми збираємось розгорнути `web` додаток, і ми зробимо це шляхом запуску команди `gunicorn mysite.wsgi` (`gunicorn` -- програма на зразок більш потужної версії Django команди `runserver`). +> **Примітка** Одним із файлів, вказаних в `.gitignore` є `db.sqlite3`. Цей файл є вашою локальною базою даних, де зберігаються пости. Ми не хочемо додавати його до нашого репозиторію, тому що веб-сайт на PythonAnywhere використовуватиме іншу базу. Ця база даних може бути SQLite, як на вашій локальній машині, але зазвичай, ми будемо використовувати базу MySQL, яка може обслуговувати набагато більше відвідувачів сайту, ніж SQLite. У всякому разі, ігнорування бази даних SQLite для копії коду на GitHub, означає, що всі створені вами пости залишаться і будуть доступні локально, але ви можете додати їх також і на продакшн. Ви повинні думати про локальну базу як про хороший майданчик, де можна тестувати різні речі і не боятися, що можна видалити реальні пости з блогу. -Далі збережіть файл. Є! +Перед тим, як виконати команду `git add` (також, коли ви просто не впевненні що змінилось) непоганою ідеєю буде виконати `git status`. Це допоможе уникнути сюрпризів, наприклад, додавання чи коміту небажаного файлу. Команда `git status` повертає інформацію про файли у вашому репозиторії: untracked (не додані до репозиторію файли), modified (змінені файли), staged (файл додані до коміту), статус поточної гілки і багато іншого. Вивід повинен бути схожий на: -## Файл `runtime.txt` + $ git status + On branch master -Нам треба повідомити Heroku яку версію Python ми бажаємо використовувати. Це можна зробити створивши файл `runtime.txt` в папці `djangogirls` скориставшись командою редактора "new file", і помістивши в нього наступний текст (і нічого більше!): + Initial commit - python-3.4.2 - + Untracked files: + (use "git add ..." to include in what will be committed) -## mysite/local_settings.py + .gitignore + blog/ + manage.py + mysite/ -Є різниця між локальними налаштуваннями (на вашому комп'ютері) і налаштуваннями для нашого серверу. Heroku використовує одну базу даних, а ваш комп'ютер використовує різні бази даних. Саме тому потрібно створювати окремі файли для налаштувань, котрі будуть доступними лише для нашого локального середовища. + nothing added to commit but untracked files present (use "git add" to track) -Створіть файл `mysite/local_settings.py`. Він має містити налаштування для бази даних `DATABASE` з файлу `mysite/settings.py`. Так як тут: +Зрештою, зберігаємо наші зміни. Перейдіть до консолі і виконайте наступні команди: - import os - BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } - } - - DEBUG = True - + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py -Далі просто збережіть файл! :) -## mysite/settings.py +## Викладемо наш код на GitHub -Інша річ, яку нам потрібно зробити це модифікувати файл налаштувань `settings.py` для нашого веб-сайту. Відкрийте `mysite/settings.py` у вашому редакторі і додайте наступні рядки вкінці файлу: +Відкриємо [GitHub.com](https://www.github.com) і створимо новий безкоштовний обліковий запис. (Ті хто зробили це ще на етапі підготовки - справжні молодці!) - import dj_database_url - DATABASES['default'] = dj_database_url.config() - - SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') - - ALLOWED_HOSTS = ['*'] - - STATIC_ROOT = 'staticfiles' - - DEBUG = False - +Створимо новий репозиторій з назвою "my-first-blog". Залишимо опцію "initialise with a README" не вибраною, .gitignore порожньою (пізніше ми додамо це вручну) і License також залишимо як None. -Вкінці `mysite/settings.py`, скопіюйте та вставте це: + - try: - from .local_settings import * - except ImportError: - pass - +> **Примітка** Ім'я `my-first-blog` важливе - ви можете вибрати щось інше, але воно буде використовуватись багато разів в інструкціях нижче, і потрібно буде замінити його кожного разу. Мабуть легше просто його залишити як `my-first-blog`. -Таким чином, усі ваші локальні налаштування буде імпортовано, якщо такий файл існує. +В наступному екрані ми побачимо посилання для клонування репозиторію - clone URL, скопіюємо його і вставимо у термінал: -Далі збережіть файл. + -## mysite/wsgi.py +Зараз нам потрібно під'єднати Git репозиторій на локальному комп'ютері до щойно створеного на GitHib. -Відкрийте файл `mysite/wsgi.py` та додайте ці рядки вкінці: +Введіть у вашій консолі (замінивши `<ваше-github-ім'я>` іменем користувача, вказаним під час створення облікового запису GitHub, але без кутових дужок): - from whitenoise.django import DjangoWhiteNoise - application = DjangoWhiteNoise(application) - + $ git remote add origin https://github.com/<ваше-github-ім'я>/my-first-blog.git + $ git push -u origin master -Порядок! +Введемо наше ім'я користувача та пароль від GitHub, і побачимо щось на зразок: -## Heroku акаунт + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. -Вам треба встановити Heroku toolbelt, який ви можете знайти тут (можете пропустити цей крок, якщо ви вже виконали встановлення під час налаштування): https://toolbelt.heroku.com/ + -> При запуску інсталяційної програми Heroku toolbelt на Windows оберіть пункт "Custom Installation" коли буде запит на те, які компоненти інсталювати. У списку компонентів, що має з'явитися після цього, перевірте, будь ласка, додатково чи є галочка в пункті "Git and SSH". -> -> На Windows ви також повинні запустити наступну команду щоб додати Git і SSH до змінної `PATH` вашого командного рядку: `setx PATH "%PATH%;C:\Program Files\Git\bin"`. Перезапустіть після цього командний рядок щоб активувати зміни. +Ваш код тепер на GitHub. Ходімо перевіримо! Виявляється, він у хорошій компанії - [Django](https://github.com/django/django), [Цей посібник](https://github.com/DjangoGirls/tutorial) і багато інших чудових проектів з відкритим вихідним кодом також публікуються на GitHub :) -Створіть, будь ласка, також Heroku акаунт на цьому сайті: https://id.heroku.com/signup/www-home-top -Далі активуйте ваш Heroku акаунт на вашому комп'ютері запустивши цю команду: +# Налаштування нашого блогу на PythonAnywhere - $ heroku login - +> **Примітка** Можливо, ви вже створили обліковий запис на PythonAnywhere під час підготовки - якщо це так, немає необхідності робити це знову. -У випадку якщо у вас немає SSH ключа ця команда автоматично його створить. SSH ключі необхідні для того, щоб експортувати код на Heroku. +{% include "/deploy/signup_pythonanywhere.md" %} -## Git -Git -- це система контролю версій, що використовується багатьма програмістами - програмне забезпечення, котре відслідковує зміни у файлах що відбуваються з часом, таким чином ви можете пізніше відкликати специфічні версії. Heroku використовує git репозиторій щоб керувати файлами вашого проекту, отже ми також ним скористаємось. +## Завантажимо наш код на PythonAnywhere -Створіть файл із назвою `.gitignore` в папці `djangogirls` і наступним змістом: +Після входу до PythonAnywhere, ми опинимось на головній панелі або сторінці "Consoles". Виберемо опцію почати нову "bash" консоль (Start a new console - bash) - це PythonAnywhere версія консолі, схожа на ту, що на вашому комп'ютері. - myvenv - __pycache__ - staticfiles - local_settings.py - db.sqlite3 - *.py[co] +> **Примітка** PythonAnywhere побудований на основі Linux, тому, якщо ви на Windows, консоль буде трохи відрізнятись від тієї, що на вашому комп'ютері. -та збережіть його. Крапка на початку імені файлу є важливою! Як можна побачити, ми повідомляємо Heroku про те що треба ігнорувати `local_settings.py` і не завантажувати цей файл, отже він є доступним лише на вашому комп'ютері (локально). +Давайте завантажимо наш код з GitHub у PythonAnywhere, клонувавши наш репозиторій. Наберіть наступне у консолі PythonAnywhere (не забудьте використовувати ім'я користувача GitHub замість `< ваше-github-ім'я>`): -Наступним кроком створимо новий git репозиторій і збережемо наші зміни. Перейдіть до консолі і запустіть ці команди: + $ git clone https://github.com/<ваше-github-ім'я>/my-first-blog.git + +Ця команда завантажить копію вашого коду на PythonAnywhere. Давайте перевіримо, набравши `tree my-first-blog`: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### Створення virtualenv на PythonAnywhere + +Так само як і на власному комп'ютері, створіть virtualenv на PythonAnywhere. У консолі Bash введіть: + +``` +$ cd my-first-blog + +$ virtualenv --python=python3.4 myvenv +Running virtualenv with interpreter /usr/bin/python3.4 +[...] +Installing setuptools, pip...done. + +$ source myvenv/bin/activate + +(mvenv) $ pip install django whitenoise +Collecting django +[...] +Successfully installed django-1.8.2 whitenoise-2.0 +``` + + +> **Примітка** Крок `pip install` може зайняти кілька хвилин. Терпіння і ще раз терпіння! Але якщо він займає більш ніж 5 хвилин, щось пішло шкереберть. Попросіть допомоги у вашого тренера. + + + + +### Збирання статичних файлів. + +Можливо ви поцікавились, що за штука цей "whitenoise"? Це інструмент для обслуговування так званих "статичних файлів". Статичні файли - це файли, які зазвичай не змінюються і не виконують ніякого коду, наприклад, HTML чи CSS файли. На серверах вони працюють інакше, ніж на вашому локальному комп'ютері, щоб сервер міг їх віддавати, нам потрібен спеціальний інструмент, такий як "whitenoise". + +Пізніше, коли ми змінимо CSS для нашого сайту, ми дізнаємось трохи більше про статичні файли. + +Поки що нам просто потрібно виконати додаткову команду `collectstatic` на сервері. Ця команда каже Django про усі статичні файли на сервері, які йому потрібні. На даний момент це в основному файли, що допомагають зробити красивою сторінку адміністрування. + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + +Введемо "yes" і помчали! Чи не прекрасно, коли ми можемо змусити комп'ютер друкувати незрозумілий текст сторінка за сторінкою? Кожного разу я додаю невеликий звуковий супровід: дир-дир-дир... + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### Створимо базу даних на PythonAnywhere + +Ось ще одна річ, яка відрізняється на локальному комп'ютері і на сервері: вони використовують різні бази даних. Так що облікові записи користувачів і статті блогу можуть відрізнятися на сервері і локальному комп'ютері. + +Ми можемо ініціалізувати базу даних на сервері таким самим чином, як і на локальному комп'ютері - з допомогою `migrate` і `createsuperuser`: + + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + +## Опублікуємо наш блог як веб-додаток + +Тепер наш код на PythonAnywhere, віртуальне середовище готове, статичні файли зібрані, база даних встановлена. Ми готові до публікації веб-додатку! + +Перейдемо до панелі керування PythonAnywhere, натиснувши на лого сайту і виберемо вкладку **Web**. Тепер натиснемо **Add a new web app**. + +Після підтвердження нашого доменного імені, виберемо ручне налаштування (**manual configuration**) у діалоговому вікні, зверніть увагу: варіант "Django" нам *не годиться*. Далі виберемо **Python 3.4** і натиснемо Next для завершення. + +> **Примітка** Пересвідчіться, що ви вибрали варіант "Manual configuration", а не "Django". Ми занадто круті для стандартних налаштувань PythonAnywhere для Django ;-) + + +### Налаштуємо virtualenv + +Ми опинились на сторінці налаштувань веб-додатку на PythonAnywhere. Сюди слід переходити, якщо ви хочете зробити якісь зміни до додатку на сервері. + + + + +У розділі "Vitrualenv" натиснемо на червоний текст "Enter the path to a virtualenv" (введіть шлях до virtualenv) і напишемо: `/home//my-first-blog/myvenv/`. Перед тим, як продовжити, натиснемо синю кнопку з галочкою, щоб зберегти шлях. + +> **Примітка** Замініть на своє ім'я користувача. Якщо ви помилитесь, PythonAnywhere покаже вам невеличке попередження. - $ git init - Initialized empty Git repository in ~/djangogirls/.git/ - $ git add . - $ git commit -m "My Django Girls app" - [master (root-commit) 2943412] My Django Girls - 7 files changed, 230 insertions(+) - create mode 100644 .gitignore - create mode 100644 Procfile - create mode 100644 mysite/__init__.py - create mode 100644 mysite/settings.py - create mode 100644 mysite/urls.py - create mode 100644 mysite/wsgi.py - create mode 100644 manage.py - create mode 100644 requirements.txt - create mode 100644 runtime.txt - -## Підберіть ім'я для додатку +### Сконфігуруємо WSGI файл -Зробимо ваш блог доступним в Інтернеті за адресою `[назва блогу].herokuapp.com`, отже потрібно підібрати ім'я, яке ще ніхто не взяв. Це ім'я не повинно бути пов'язаним із Django додатком `blog`, або з `mysite` або з чимось, що ми до цього часу встигли створити. Ім'я може будь-яким на ваш вибір, але Herokuє досить вимогливим щодо допустимих символів: дозволяється використовувати лише прості маленькі літери (жодних прописних літер чи акцентів), чисел, а також дефісів (`-`). +Django використовує у роботі "WSGI протокол" - стандарт взаємодії веб-додатків на Python із веб-серверами. Він підтримується PythonAnywhere. Отже, поредагувавши конфігураційний файл WSGI, ми дозволимо PythonAnywhere розпізнати наш блог на Django. -По тому як ви придумали ім'я (можливо щось щось пов'язане із вашим ім'ям або нікнеймом), запустіть наступну команду, замінивши `djangogirlsblog` на ім'я свого додатку: +Перейдемо за посиланням напроти "WSGI configuration file" (у розділі "Code" близько до початку сторінки - посилання матиме якусь таку назву: `/var/www/_pythonanywhere_com_wsgi.py`). Ми опинились на сторінці з редактором. - $ heroku create djangogirlsblog - +Зітремо весь вміст файлу і замінимо його таким: -> **Зауваження**: Не забудьте замінити `djangogirlsblog` на ім'я вашого додатку на Heroku. +```python +import os +import sys -Якщо ж не можете придумати ім'я, просто можна запустити +path = '/home//my-first-blog' # use your own username here +if path not in sys.path: + sys.path.append(path) - $ heroku create - +os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' -і Heroku підбере для вас невикористовуване ім'я (можливо щось на зразок `enigmatic-cove-2527`). +from django.core.wsgi import get_wsgi_application +from whitenoise.django import DjangoWhiteNoise +application = DjangoWhiteNoise(get_wsgi_application()) +``` -Якщо раптом захочете змінити ім'я вашого Heroku додатку, то це можна зробити у будь-який час за допомогою команди (замінює на бажане нове ім'я `the-new-name`): +> **Примітка** Не забудьте вказати своє ім'я користувача замість `` +> **Примітка** Третій рядок вказує PythonAnywhere, як знайти наш додаток. Дуже важливо, щоб цей шлях був коректним і щоб не було зайвих пробілів. Інакше ви побачите "ImportError" в логах помилок. - $ heroku apps:rename the-new-name - +Завдання цього файлу - розповісти PythonAnywhere, де живе наш веб-додаток і як знайти файл із налаштуванням Django. Також він налаштовує інструмент для статичних файлів "whitenoise". -> **Зауваження**: Пам'ятайте, що після того як ви змінили ім'я додатку, треба відвідати `[the new name].herokuapp.com` щоб побачити ваш сайт. +Натиснемо **Save** і перейдемо назад до вкладки **Web**. -## Розгортання на Heroku! +Готово! Натискаємо на велику зелену **Reload** кнопку і можемо глянути на свій веб-додаток. Посилання на нього вгорі сторінки. -Було багато налаштувань і встановлень, правда ж? Але це треба зробити лише один раз! Тепер можна починати процес розгортання! -Коли ви запускаєте `heroku create`, Heroku об'єкт для нашого додатку автоматично додається до нашого репозиторію. Тепер ми можемо за допомогою простою операції git push розгорнути (опублікувати) наш додаток: +## Підказки для відлагодження (debug) - $ git push heroku master - +Якщо відвідавши ваш сайт, побачили повідомлення про помилку, найперше, куди слід подивитись - це **лог помилок**. Перейти до нього можна із [вкладки Web](https://www.pythonanywhere.com/web_app_setup/) PythonAnywhere. Гляньте, чи є там повідомлення про помилки; найновіші будуть внизу файлу. Найчастіше трапляються такі проблеми: -> **Зауваження**: Можливо під час найпершого запуску в результаті буде багато інформації на виході, оскільки Heroku компілює та встановлює psycopg. Ви дізнаєтеся про успішне завершення команди якщо по завершенню побачите щось на зразок `https://yourapplicationname.herokuapp.com/ deployed to Heroku` в останніх рядках вихідної інформації на консолі. +- Забули ввести одну із команд у консолі: створення віртуального середовища, його активацію, встановлення туди Django, збирання статичних файлів, міграцію бази даних. -## Відвідайте ваш сайт +- Зробили опечатку в шляху до virtualenv на вкладці Web - в такому разі, там можна буде побачити маленьке червоне повідомлення про помилку. -Ви щойно опублікували ваш код на Heroku, і визначили типи процесів у файлі `Procfile` (раніше ми обрали процес типу `web`). А зараз можемо повідомити Heroku, що хочемо розпочати цей процес `web process`. +- Помилились у конфігураційному файлі WSGI - перевірте шлях до своєї директорії my-first-blog. -Щоб це зробити запустіть наступну команду: +- Ви точно вибрали таку ж версію Python для віртуального середовища, як і для веб-додатку? Обидві повинні мати версію 3.4. - $ heroku ps:scale web=1 - +- Ось деякі [загальні підказки для налагодження у PythonAnywhere вікі](https://www.pythonanywhere.com/wiki/DebuggingImportError). -Heroku повідомляється про те, що треба запустити лише одну копію нашого `web` процесу. Оскільки додаток для нашого блогу цілком простий, не треба дуже багато потужностей, а отже буде добре якщо запустимо лише один процес. Цілком можливо попросити Heroku запустити більше процесів (доречі, Heroku називає ці процеси "Dynos"отже не дивуйтесь якщо зустрінете даний термін) але надалі це не буде безкоштовно. +Пам'ятайте, що ваш тренер може допомогти! -А зараз можемо відвідати сайт у нашому браузері за допомогою команди `heroku open`. - $ heroku open - +# Ми вийшли у світ! -> **Зауваження**: ви побачите сторінку із помилкою! Поговоримо про це через хвилину +На сторінці за замовчуванням нашого сайту має бути напис "Welcome to Django" так само, як і на вашому локальному комп'ютері. Спробуємо додати `admin` у кінці URL і опинимось у панелі адміністратора. Використаємо для входу логін і пароль та побачимо, що тут можна додавати нові пости на сервер. -Відкриється сторінка із адресою [https://djangogirlsblog.herokuapp.com/](), і через мить ви мабуть побачите сторінку з помилкою. Оскільки ми створили лише вид для адмінки (admin view), додайте `admin/` до адресного рядку (наприклад, [https://djangogirlsblog.herokuapp.com/admin/]()) щоб побачити робочу сторінку нашого веб додатку. -Помилку, яку ви побачили, викликана тим, що коли ми здійснювали публікацію на Heroku, то створили нову базу даних і вона є наразі пустою. Треба запустити команду ~~~ migrate~~~ як ми вже робили на самому початку коли починали відповідно налаштовувати базу даних для нашого проекту: +*ДОБРЯЧЕ* похваліть себе! Розгортання на сервер - один з найхитромудріших етапів веб-розробки. Зазвичай люди витрачають дні, щоб усе запрацювало. Але вам вдалось вийти у справжній інтернет, запросто! - $ heroku run python manage.py migrate - - $ heroku run python manage.py createsuperuser - -Тепер ви маєте змогу побачити ваш веб-сайт у браузері! Вітаємо :)! diff --git a/uk/deploy/images/github_get_repo_url_screenshot.png b/uk/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/uk/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/uk/deploy/images/new_github_repo.png b/uk/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/uk/deploy/images/new_github_repo.png differ diff --git a/uk/deploy/images/pythonanywhere_web_tab_virtualenv.png b/uk/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/uk/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/uk/deploy/install_git.md b/uk/deploy/install_git.md new file mode 100644 index 00000000000..28dd2f7693a --- /dev/null +++ b/uk/deploy/install_git.md @@ -0,0 +1,33 @@ + +### Windows + +Git можна завантажити з [git-scm.com](https://git-scm.com/). Ви можете натискати "next next next" на всіх кроках окрім одного. На п’ятому кроці, названому "Adjusting your PATH environment", виберіть "Run Git and associated Unix tools from the Windows command-line" (нижня опція). Крім цього, стандартні налаштування добрі. Вимкніть закінчення рядків в стилі Windows, ввімкніть в стилі Unix, вони кращі. + +### Mac OS + +Завантажте Git з [git-scm.com](https://git-scm.com/) і просто слідуйте вказівкам. + + +### Linux + +Якщо Git не встановлений, то він має бути доступний через менеджер пакетів, тому спробуйте: + + +#### Debian або Ubuntu + + $ sudo apt-get install git + + +#### Fedora (до 21) + + $ sudo yum install git + + +#### Fedora (22+) + + $ sudo dnf install git + + +#### openSUSE + + $ sudo zypper install git diff --git a/uk/deploy/signup_pythonanywhere.md b/uk/deploy/signup_pythonanywhere.md new file mode 100644 index 00000000000..12ee7b6ca76 --- /dev/null +++ b/uk/deploy/signup_pythonanywhere.md @@ -0,0 +1,8 @@ + +Тепер час для створення безкоштовного "Beginner" акаунту на PythonAnywhere. + +* [www.pythonanywhere.com](https://www.pythonanywhere.com/) + + +> **Примітка** При виборі імені користувача, пам'ятайте, що URL-адреса блогу матиме вигляд `yourusername.pythonanywhere.com`, так що зупиніться або на вашому ніку, або на імені, пов'язаному з тематикою блогу. + diff --git a/uk/django/README.md b/uk/django/README.md index 7a5fcca6be7..2c30e036c46 100755 --- a/uk/django/README.md +++ b/uk/django/README.md @@ -1,6 +1,6 @@ # Що таке Django? -Django (*/ˈdʒæŋɡoʊ/ джанго*) -- безкоштовний і відкритий фреймворк для створення веб додатків, написаний мовою програмування Python. Веб фреймворк - набір компонентів, які допомагають розробляти веб-сайти швидше і простіше. +Django (_/ˈdʒæŋɡoʊ/ джанго_) - безкоштовний і відкритий фреймворк для створення веб додатків, написаний мовою програмування Python. Веб фреймворк - набір компонентів, які допомагають розробляти веб-сайти швидше і простіше. При побудові веб-сайту, ви завжди потребуєте схожого набору компонентів: спосіб управління авторизацією користувача (створення акаунту, вхід, вихід), панель управління, форми, спосіб завантажити файли, тощо. @@ -16,12 +16,12 @@ Django (*/ˈdʒæŋɡoʊ/ джанго*) -- безкоштовний і відк ## Що трапляється коли хтось надсилає запит на веб-сайт з вашого серверу? -Коли на веб-сервер надходить запит він перенаправляється на Django, котрий намагається з'ясувати на що конкретно був запит. Спочатку береться адреса веб-сторінки і Django намагається з'ясувати що робити. Ця частина роботи здійснюється таким компонентом Django як **urlresolver** (зауважте, що адреса веб-сайту називається URL - Uniform Resource Locator - отже ім'я *urlresolver* має сенс). Це не дуже складний елемент - вилучається список шаблонів і відбуваються спроби знайти підходящий URL. Django перевіряє шаблони у порядку слідування і якщо якийсь із них відповідає адресі веб-сторінки Django надсилає запит до асоційованої функції (котра має назву *view*). +Коли на веб-сервер надходить запит, він перенаправляється на Django, котрий намагається з'ясувати на що конкретно був запит. Спочатку береться адреса веб-сторінки і Django намагається з'ясувати, що робити. Ця частина роботи здійснюється таким компонентом Django як __urlresolver__ (зауважте, що адреса веб-сайту називається URL - Uniform Resource Locator - отже ім'я *urlresolver* має сенс). Це не дуже складний елемент - вилучається список шаблонів і відбуваються спроби знайти підходящий URL. Django перевіряє шаблони у порядку слідування і якщо якийсь із них відповідає адресі веб-сторінки Django надсилає запит до асоційованої функції (котра має назву *view*). -Уявіть собі листоношу з листом. Вона пересувається вулицею і перевіряє номер кожного будинку на відповідність тому, що вказаний у листі. Якщо він відповідає, вона залишає листа на місці. За подібною схемою працює і urlresolver! +Уявіть собі листоношу з листом. Він йде по вулиці і звіряє номер кожного будинку з тим, що вказаний в адресі отримувача. Якщо номер співпадає, він кладе листа в скриньку. Аналогічним чином працює і urlresolver! Всередині функції *view* відбуваються найцікавіші речі: щоб знайти деяку інформацію, ми можемо подивитися в базу даних. Можливо, користувач може попросити зробити певні зміни даних? На зразок листа, що говорить "Будь ласка, змініть опис моєї роботи." Елемент *view* може перевірити чи дозволено вам це зробити, потім оновлює опис роботи для вас і відправляє зворотнє повідомлення: "Виконано!". Далі блок *view* генерує відповідь і Django може відправити її до веб браузера користувача. Звичайно, вище наведені пояснення є трохи спрощеними, але вам не потрібно знати усіх технічних деталей поки що. Достатньо мати загальне уявлення. -Отже замість того, щоб надто занурюватись у деталі, ми просто почнемо щось створювати із використанням Django і вивчимо усі важливі складові на цьому шляху! \ No newline at end of file +Отже замість того, щоб надто занурюватись у деталі, ми просто почнемо щось створювати із використанням Django і вивчимо усі важливі складові на цьому шляху! diff --git a/uk/django_admin/README.md b/uk/django_admin/README.md index 6401705f942..bb011082f0d 100755 --- a/uk/django_admin/README.md +++ b/uk/django_admin/README.md @@ -4,19 +4,20 @@ Відкриймо файл `blog/admin.py` і замінимо його зміст на наступні рядки: - from django.contrib import admin - from .models import Post - - admin.site.register(Post) +```python +from django.contrib import admin +from .models import Post +admin.site.register(Post) +``` Як можна побачити, ми імпортуємо (включаємо) модель посту Post визначену у попередньому розділі. Щоб зробити нашу модель видимою на сторінці адміністратора, потрібно зареєструвати модель за допомогою `admin.site.register(Post)`. -OK, переглянути нашу модель Post. Не забудьте запустити `python manage.py runserver` в консолі щоб запустити веб сервер. Перейдіть до браузера і наберіть адресу: http://127.0.0.1:8000/admin/ Ви побачите сторінку входу наступного зразку: +Гаразд, час поглянути на нашу модель Post. Не забудьте виконати в консолі команду `python manage.py runserver` для того щоб запустити сервер. Відкрийте браузер, введіть адресу http://127.0.0.1:8000/admin/ і ви побачите сторінку входу схожу на цю: ![Сторінка авторизації](images/login_page2.png) -Для того, щоб здійснити вхід потрібно створити суперюзера *superuser* - користувача, котрий контролює сайт. Перейдіть назад до командного рядка і наберіть `python manage.py createsuperuser`, натисніть `enter` і наберіть ваше ім'я користувача (маленькі літери, без пробілів), email адресу і пароль. Вихідний результат має виглядати наступним чином (де ім'я користувача і email повинні містити ваші дані): +Щоб ввійти, потрібно створити *суперкористувача (superuser)* - користувача, котрий може контролювати все на сайті. Поверніться до командного рядка, наберіть `python manage.py createsuperuser`, і натисніть клавішу Enter. Коли вас про це запитають, введіть логін користувача (маленькими буквами без пропусків), адресу email та пароль. Не хвилюйтеся, що ви не можете бачити пароль який вводите – так і повинно бути. Просто введіть його і натисніть `Enter` щоб продовжити. Вихідний результат має виглядати наступним чином (де ім'я користувача і email повинні містити ваші дані): (myvenv) ~/djangogirls$ python manage.py createsuperuser Username: admin @@ -25,17 +26,18 @@ OK, переглянути нашу модель Post. Не забудьте з Password (again): Superuser created successfully. - -Поверніться до вашого браузера і здійсніть вхід використовуючи логін пароль щойно створеного суперюзера, ви маєте побачити робочу панель Django адміністратора. +Поверніться до вашого браузера і здійсніть вхід використовуючи логін та пароль щойно створеного суперкористувача; ви маєте побачити робочу панель адміністратора Django. ![Django адміністратор](images/django_admin3.png) -Перейдіть до постів і трохи поекспериментуйте з ними. Додайте 5-6 блог постів. Не турбуйтесь про їх зміст - можете просто скопіювати і вставити деякий текст з цього навчального посібника в якості поста щоб зберегти час :). +Перейдіть в Posts та поекспериментуйте з ними трошки. Додайте п’ять-шість постів. Не переживайте за вміст, можете просто скопіювати якийсь текст з цього підручника щоб зберегти час :). Переконайтесь у тому, що принаймні два або три поста (але не всі) мають встановлену дату публікації. Це стане у нагоді пізніше. ![Django адміністратор](images/edit_post3.png) -Якщо бажаєте дізнатися про Django адміністратор, зверніться до Django документації: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ +Якщо бажаєте дізнатися більше про Django admin, гляньте документацію Django: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/ + +Це напевне гарний час щоб налити кави (чи чаю) чи з’їсти щось щоб перезарядитися. Ви створили свою першу модель Django і заслуговуєте на короткий тайм-аут! + -Напевно настав вдалий момент прихопити чашку кави (або чаю) і з'їсти трохи солодощів. Ви створили вашу першу Django модель, то ж заслуговуєте на невеличке задоволення! diff --git a/uk/django_forms/README.md b/uk/django_forms/README.md index 09d2795bc7d..8a5d4c09903 100755 --- a/uk/django_forms/README.md +++ b/uk/django_forms/README.md @@ -1,8 +1,8 @@ # Django форми -Остання річ, яку б ми хотіли зробити з нашим сайтом це створити зручний спосіб додавати і редагувати пости. Django адміністратор це звісно круто, але водночас він є досить складним для налаштування. З формами ми будемо мати абсолютний контроль над нашим інтерфейсом - можемо робити майже усе що заманеться! +Остання річ, яку б ми хотіли зробити з нашим сайтом, це створити зручний спосіб додавати і редагувати пости. Django адміністратор - це звісно круто, але водночас він є досить складним для налаштування. З формами ми будемо мати абсолютний контроль над нашим інтерфейсом - можемо робити майже усе, що заманеться! -Що тішить стосовно Django форм так це те, що останні можна визначати як з нуля так і створювати засобами `ModelForm`, що зберігають результат форми всередині моделі. +Що тішить стосовно Django форм, так це те, що останні можна визначати як з нуля, так і створювати засобами `ModelForm`, що зберігають результат форми всередині моделі. Це саме те, що нам потрібно: створимо форму для нашої моделі `Post`. @@ -12,43 +12,42 @@ blog └── forms.py - -Ok, відкриймо цей файл і наберемо наступний код: +Добре, відкриємо цей файл і наберемо наступний код: - from django import forms - - from .models import Post - - class PostForm(forms.ModelForm): - - class Meta: - model = Post - fields = ('title', 'text',) - +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` Спершу потрібно імпортувати Django форми (`from django import forms`) і, очевидно, нашу модель `Post` (`from .models import Post`). -`PostForm`, як ви можливо зазначили, ім'я нашої форми. Ми маємо повідомити Django, що наша форма є `ModelForm` (таким чином Django здійснить для нас певні магічні маніпуляції) і рядок `forms.ModelForm` відповідає за це. +`PostForm`, як ви можливо зазначили, це ім'я нашої форми. Ми маємо повідомити Django, що наша форма є `ModelForm` (таким чином Django здійснить для нас певні магічні маніпуляції) і рядок `forms.ModelForm` відповідає за це. Далі, у нас є `class Meta`, де ми вказуємо для Django котра з моделей має бути використана для створення форми (`model = Post`). -Зрештою, можемо зазначити якими полями має закінчуватись наша форма. В даному сценарії ми би хотіли опублікувати такі параметри як заголовок `title` і зміст `text`, дані про автора `author`, що автоматично встановлюються як дані користувача, який наразі залогінився (тобто ви!), а також дата створення `created_date`, яка автоматично встановлюється при створенні поста (тобто в коді), вірно ж? +Зрештою, можемо зазначити, якими полями має закінчуватись наша форма. В даному сценарії ми би хотіли опублікувати такі параметри, як заголовок `title` і зміст `text`, дані про автора `author`, що автоматично встановлюються як дані користувача, який наразі залогінився (тобто ви!), а також дата створення `created_date`, яка автоматично встановлюється при створенні поста (тобто в коді), вірно ж? І це все! Все що нам потрібно тепер зробити це використати форму в блоці *view* і відобразити її в шаблоні. -Отже знову ми створимо: посилання на сторінку, адресу (URL), вид (view) і шаблон (template). +Отже, знову ми створимо: посилання на сторінку, адресу (URL), вид (view) і шаблон (template). ## Посилання на сторінку з формою Час відкрити `blog/templates/blog/base.html`. Додамо лінк всередині блоку `div` із ім'ям `page-header`: ```html - -``` - + +``` -Зауважте, що ми хочемо запустити наш новий блок view `post_new`. +Зауважте, що ми хочемо запустити наше нове відображення `post_new`. Клас `"glyphicon glyphicon-plus"` постачається bootstrap темою, яку ми використовуємо, і буде відображати знак плюса. Після додавання відповідного рядка, ваш html файл має виглядати наступним чином: @@ -64,7 +63,7 @@ Ok, відкриймо цей файл і наберемо наступний к
@@ -78,44 +77,47 @@ Ok, відкриймо цей файл і наберемо наступний к ``` - -Після збереження і перезапуску сторінки http://127.0.0.1:8000 ви, очевидніше за все, побачите знайому помилку `NoReverseMatch`, вірно? +Після збереження та оновлення сторінки http://127.0.0.1:8000 ви звісно побачите знайому помилку `NoReverseMatch`, правда? ## URL Відкриваємо `blog/urls.py` і додаємо рядок: +```python url(r'^post/new/$', views.post_new, name='post_new'), - +``` Остаточно код буде виглядати так: - from django.conf.urls import include, url - from . import views - - urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - url(r'^post/new/$', views.post_new, name='post_new'), - ] - +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` -Після оновлення сайту бачимо помилку `AttributeError`, оскільки вид `post_new` не є реалізованим. Давайте додамо цей вид прямо зараз. +Після оновлення сайту бачимо помилку `AttributeError`, оскільки відображення `post_new` не реалізоване. Давайте додамо цей вид прямо зараз. -## post_new view +## Відображення post_new Час відкрити файл `blog/views.py` і додати наступні рядки: - from .forms import PostForm - +```python +from .forms import PostForm +``` -і функцію для потрібного відображення: +і функцію для потрібного *відображення*: - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` Щоб створити нову форму `Post`, нам потрібно викликати функцію `PostForm()` і передати її до шаблону. Повернемося пізніше до цього відображення, а зараз давайте створимо шаблон для форми. @@ -123,14 +125,14 @@ Ok, відкриймо цей файл і наберемо наступний к Нам потрібно створити файл `post_edit.html` у папці `blog/templates/blog`. Щоб створити форму нам знадобиться декілька речей: -* ми маємо відобразити форму. Можемо це зробити, наприклад, за допомогою простого `{{ form.as_p }}`. -* верхній рядок має бути розміщений всередині тега HTML для форми: `...` -* нам знадобиться кнопка Зберегти - `Save`. Створимо її в HTML за допомогою: `` -* і врешті-решт одразу після відкриття тегу для форми `
` потрібно додати `{% raw %}{% csrf_token %}{% endraw %}`. Це дуже важливо з міркувань безпеки вашої форми! Django наголосить на цьому, якщо ви раптом забудете вказати згадану вказівку і будете намагатися зберегти форму: +- нам треба показати форму. Можна, наприклад, зробити це за допомогою простого `{% raw %}{{ form.as_p }}{% endraw %}`. +- верхній рядок має бути розміщений всередині тега HTML для форми: `...
` +- нам знадобиться кнопка Зберегти - `Save`. Створимо її в HTML за допомогою: `` +- і нарешті, одразу після відкриваючого тегу `
` ми маємо додати `{% raw %}{% csrf_token %}{% endraw %}`. Це дуже важливо з міркувань безпеки вашої форми! Django наголосить на цьому, якщо ви раптом забудете вказати згадану вказівку і будете намагатися зберегти форму: ![CSFR Forbidden page](images/csrf2.png) -Добре, отже давайте подивимось як має виглядати HTML код в `post_edit.html`: +Добре, отже, давайте подивимось як має виглядати HTML код в `post_edit.html`: ```html {% extends 'blog/base.html' %} @@ -143,15 +145,14 @@ Ok, відкриймо цей файл і наберемо наступний к
{% endblock %} ``` - Час перезавантажитись! Йой! Ваша форма відображується! ![New form](images/new_form2.png) -Але, одну хвилинку! Коли ви набираєте щось в полях `title` і `text` і намагаєтесь зберегти зміни - що ж тоді станеться? +Але, одну хвилиночку! Коли ви набираєте щось в полях `title` і `text`, та намагаєтесь зберегти зміни - що ж тоді станеться? -А нічого! Ми знову опинимося на тій самій сторінці і наш текст зникне... і жодного нового поста. Отже, що ж пішло не так? +А нічого! Ми знову опинимося на тій самій сторінці, і наш текст зникне... і жодного нового поста. Отже, що ж пішло не так? Відповідь: нічого. Мусимо проробити трохи більше роботи з нашим блоком *view*. @@ -159,84 +160,96 @@ Ok, відкриймо цей файл і наберемо наступний к Відкрийте `blog/views.py` знову. Наразі все що ми маємо в `post_new` це: - def post_new(request): - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Коли відбувається зберігання форми, ми повертаємось назад до того ж виду, але цього разу матимемо трохи більше даних в `request`, конкретніше у `request.POST`. Пам'ятайте, що у файлі HTML наше визначення `
` містило атрибут `method="POST"`? Усі поля форми на даний момент знаходитимуться в `request.POST`. Ви не повинні перейменовувати `POST` на щось інше (лише єдине альтернативне прийнятне значення для атрибуту `method` це `GET`, але ми не маємо часу пояснювати в чому різниця). +Коли ми відправляємо форму, ми потрапляємо в той самий view, але цього разу маємо більше даних в `request`, а якщо точніше - в `request.POST` (ця назва не пов’язана з блогерським терміном "пост", вона пов’язана з тим що ми "постимо" дані). Пам'ятайте, що у файлі HTML наше визначення `` містило атрибут `method="POST"`? Усі поля форми на даний момент знаходитимуться в `request.POST`. Ви не повинні перейменовувати `POST` на щось інше (лише єдине альтернативне прийнятне значення для атрибуту `method` це `GET`, але ми не маємо часу пояснювати в чому різниця). Отже, ми маємо дві окремі ситуації, що потребують контролю для нашого блоку вид *view*. Перша: коли ми отримуємо доступ до сторінки вперше і хочемо отримати пусту форму. Друга: коли ми повертаємось назад до виду *view* із усіма нещодавно доданими даними форми. Таким чином, маємо додати умову (використаємо для цього `if`). - if request.method == "POST": - [...] - else: - form = PostForm() - +```python +if request.method == "POST": + [...] +else: + form = PostForm() +``` Час заповнити порожнє місце `[...]`. Якщо метод `method` є методом `POST`, тоді ми захочемо створити `PostForm` з даними форми, вірно? Зробимо це за допомогою: - form = PostForm(request.POST) - +```python +form = PostForm(request.POST) +``` Просто! Наступна річ - перевірити чи коректно заповнена форма (налаштовані усі необхідні поля і не відбулося зберігання жодного некоректного значення). Зробимо це за допомогою `form.is_valid()`. Ми перевіряємо чи є форма прийнятною і якщо це так, то можемо зберегти її! - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - +```python +if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` -В основі, маємо тут два моменти: зберігаємо форму за допомогою `form.save` і додаємо автора (оскільки поле автор `author` було відсутнє в `PostForm` і це поле є необхідним!). `commit=False` означає, що ми не хочемо поки що зберігати модель `Post` - ми хочемо спочатку додати ім'я автора. У більшості випадків ви будете користуватися `form.save()`, без `commit=False`, але в даному випадку, ми маємо це зробити. `post.save()` захистить здійснені зміни (додавання автора) і створиться новий блог пост! +В основі, маємо тут два моменти: зберігаємо форму за допомогою `form.save` і додаємо автора (оскільки поле автор `author` було відсутнє в `PostForm` і це поле є необхідним!). `commit=False` означає, що ми не хочемо поки що зберігати модель `Post` - ми хочемо спочатку додати ім'я автора. У більшості випадків ви будете користуватися `form.save()` без `commit=False`, але в даному випадку, ми маємо це зробити. +`post.save()` захистить здійснені зміни (додавання автора) і створиться новий блог пост! -Зрештою, було б чудово якби ми могли миттєво переходити на сторінку `post_detail` для щойно створеного допису у блозі, чи не так? Щоб зробити це, нам необхідно виконати ще один імпорт: +Зрештою, було б чудово, якби ми могли миттєво переходити на сторінку `post_detail` для щойно створеного допису у блозі, чи не так? Щоб зробити це, нам необхідно виконати ще один імпорт: - from django.shortcuts import redirect - +```python +from django.shortcuts import redirect +``` -Додайте це з самого початку вашого файлу. А тепер можемо повідомити: перейти на сторінку `post_detail` для щойно створеного поста. +Додайте це з самого початку вашого файлу. А тепер можемо сказати: перейти на сторінку `post_detail` для щойно створеного поста. - return redirect('blog.views.post_detail', pk=post.pk) - +```python +return redirect('post_detail', pk=post.pk) +``` -`blog.views.post_detail` -- ім'я виду, до якого ми хочемо перейти. Пам'ятаєте, що цей вид потребує змінної `pk`? Щоб здійснити передачу вище згаданої змінної, скористаємося `pk=post.pk`, де `post` є новоствореним постом! +`blog.views.post_detail` - ім'я виду, до якого ми хочемо перейти. Пам'ятаєте, що цей вид потребує змінної `pk`? Щоб здійснити передачу вище згаданої змінної, скористаємося `pk=post.pk`, де `post` є новим постом! -Але, ок, щось дуже багато балачок, напевно ми хотіли б побачити як відображується даний вид наразі в цілому, правда ж? +Але, щось дуже багато балачок, напевно ми хотіли б побачити, як відображується даний вид наразі в цілому, правда ж? - def post_new(request): - if request.method == "POST": - form = PostForm(request.POST) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm() - return render(request, 'blog/post_edit.html', {'form': form}) - +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` -Подивимося, чи усе працює. Перейдіть на сторінку http://127.0.0.1:8000/post/new/, додайте заголовок `title` і зміст `text`, збережіть зміни... і вуаля! Новий блог пост успішно додано і нас автоматично перенаправило на сторінку `post_detail`! +Подивимося, чи усе працює. Зайдіть на сторінку http://127.0.0.1:8000/post/new/, додайте `title` та `text`, збережіть... і вуаля! Новий блог пост успішно додано і нас автоматично перенаправило на сторінку `post_detail`! -Ви напевно вже зауважили, що ми взагалі не встановлюємо дату публікації. Ми представимо *кнопку публікації* додатково в **Django Girls Tutorial: Extensions**. +Ви могли помітити, що ми встановлюємо дату публікації, перед збереженням поста. Пізніше, ми введемо *кнопку публікації* в **Django Girls Tutorial: Розширте ваш додаток**. Просто чудово! -## Валідація форми +> Оскільки ми нещодавно мали справу з інтерфейсом Django адміністратора система наразі вважає, що ми залогінились. Є декілька ситуацій, які могли призвести до того, що ми вийшли з системи (закриття браузера, перезавантаження бази даних тощо). Якщо раптом виявиться, що при створенні поста з'явиться помилка, пов'язана із відсутністю залогіненого користувача, перейдіть на сторінку адміністратора http://127.0.0.1:8000/admin і залогіньтеся знову. Проблему тимчасово буде вирішено. Безповоротне розв'язання проблеми чекає на вас у розділі __Домашня робота: безпека вашого сайту!__ після освоєння головного посібника. + +![Logged in error](images/post_create_error.png) + + +## Перевірка форми -А тепер, ми покажемо вам наскільки круто використовувати Django форми. Блог пост повинен мати такі поля як заголовок - `title` і зміст - `text`. В нашій моделі `Post` ми не вказали (на відміну від дати публікації - `published_date`), що ці поля не є необхідними, отже Django, за замовчуванням, очікує що вони будуть заповнені. +А тепер ми покажемо вам, наскільки круто використовувати Django форми. Блог пост повинен мати такі поля як заголовок - `title` і зміст - `text`. В нашій моделі `Post` ми не вказали (на відміну від дати публікації - `published_date`), що ці поля не є необхідними, отже, Django, за замовчуванням, очікує що вони будуть заповнені. Спробуйте зберегти форму без атрибутів `title` і `text`. Здогадуємось, що трапиться! -![Form validation](images/form_validation2.png) +![Перевірка форми](images/form_validation2.png) Django турбується про те, щоб усі поля нашої форми були коректно заповнені. Хіба це не круто? -> Оскільки ми нещодавно мали справу з інтерфейсом Django адміністратора система наразі вважає, що ми залогінились. Є декілька ситуацій, які могли призвести до того, що ми вийшли з системи (закриття браузера, перезавантаження бази даних тощо). Якщо раптом виявиться, що при створенні поста з'явиться помилка, пов'язана із відсутністю залогіненого користувача, перейдіть на сторінку адміністратора http://127.0.0.1:8000/admin і залогіньтеся знову. Проблему тимчасово буде вирішено. Безповоротне розв'язання проблеми чекає на вас у розділі **Домашня робота: безпека вашого сайту!** після освоєння головної програми. - -![Logged in error](images/post_create_error.png) ## Редагування форми @@ -244,10 +257,9 @@ Django турбується про те, щоб усі поля нашої фо Відкрийте `blog/templates/blog/post_detail.html` і додайте наступний рядок: -```html +```python ``` - таким чином, шаблон буде виглядати подібним чином: @@ -255,79 +267,135 @@ Django турбується про те, щоб усі поля нашої фо {% extends 'blog/base.html' %} {% block content %} -
- {% if post.published_date %} - {{ post.published_date }} - {% endif %} - +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

-

{{ post.title }}

-

{{ post.text|linebreaks }}

{% endblock %} ``` - В `blog/urls.py` додамо цей рядок: +```python url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), - +``` -Повторно використаємо шаблон `blog/templates/blog/post_edit.html`, отже остання річ, яка лишилась це відображення.. +Повторно використаємо шаблон `blog/templates/blog/post_edit.html`, отже, остання річ, яка лишилась це відображення.. Давайте відкриємо `blog/views.py` і додамо в самому кінці файлу: - def post_edit(request, pk): - post = get_object_or_404(Post, pk=pk) - if request.method == "POST": - form = PostForm(request.POST, instance=post) - if form.is_valid(): - post = form.save(commit=False) - post.author = request.user - post.save() - return redirect('blog.views.post_detail', pk=post.pk) - else: - form = PostForm(instance=post) - return render(request, 'blog/post_edit.html', {'form': form}) - - -Виглядає майже точно так як і наш вид `post_new`, чи не так? Але не зовсім. Перше: ми передаємо додатковий параметр `pk` з адресного рядку. Наступне: ми отримуємо модель `Post`, яку хотіли б відредагувати як `get_object_or_404(Post, pk=pk)` і потім, при створенні форми ми передаємо цей пост як екземпляр `instance` коли зберігаємо форму: - - form = PostForm(request.POST, instance=post) - +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + +Виглядає майже точно так, як і наш вид `post_new`, правда? Не зовсім. Перше: ми передаємо додатковий параметр `pk` з адресного рядку. Наступне: ми отримуємо модель `Post`, яку хотіли б відредагувати як `get_object_or_404(Post, pk=pk)` і потім, при створенні форми ми передаємо цей пост як екземпляр `instance`, коли зберігаємо форму: + +```python +form = PostForm(request.POST, instance=post) +``` а коли ми просто відкриваємо форму з цим постом для редагування: - form = PostForm(instance=post) - +```python +form = PostForm(instance=post) +``` -Добре, давайте протестуємо чи все працює! Перейдімо на сторінку `post_detail`. У верхньому правому кутку має з'явитися кнопка редагування: +Добре, давайте протестуємо, чи все працює! Перейдімо на сторінку `post_detail`. У верхньому правому кутку має з'явитися кнопка редагування: -![Edit button](images/edit_button2.png) +![Кнопка редагування](images/edit_button2.png) Коли ви натиснете на неї, то побачите форму з нашим блог постом: -![Edit form](images/edit_form2.png) +![Редагування форми](images/edit_form2.png) Можете вільно змінити заголовок або текст і зберегти зміни! -Вітаємо! Ваш додаток стає все більше і більше завершеним! +Вітаємо! Ваш додаток стає все більш і більш повним! + +Якщо бажаєте дізнатись більше інформації про форми Django, ознайомтесь із документацією: https://docs.djangoproject.com/en/1.9/topics/forms/ + +## Безпека + +Створювати нові публікації просто клацаючи на посилання класно! Але зараз, будь-хто хто відвідує ваш сайт, буде здатним опублікувати пост, а ви цього напевне не хочете. Давайте зробимо так що кнопка показується для вас, але не показується для всіх інших. + +В `blog/templates/blog/base.html`, знайдіть наш `page-header` `div` і тег посилання який ви додали туди раніше. Вони повинні виглядати якось так: + +```html + +``` + +Ми збираємось додати інший тег `{% if %}` який показуватиме посилання лише користувачам які ввійшли від імені адміністратора. На даний момент, це лише ви! Змініть тег `` щоб він виглядав так: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Цей `{% if %}` зробить так, що посилання буде відправлятись браузеру лише коли користувач, що запитував сторінку, залогований. Це не захищає від створення нових публікацій анонімами повністю, але це непоганий перший крок. Ми розглянемо більше питань безпеки в розширених уроках. -Якщо бажаєте дізнатись більше інформації про Django форми ознайомтесь із документацією: https://docs.djangoproject.com/en/1.8/topics/forms/ +Пам'ятаєте іконку редагування, що ми додали до нашої сторінки з деталями посту? Ми також хочемо додати цю ж зміну сюди, щоб інші люди не могли редагувати існуючі пости. + +Відкрийте `blog/templates/blog/post_detail.html` і знайдіть: + +```html + +``` + +Замініть це на: + +```html +{% if user.is_authenticated %} + +{% endif %} +``` + +Оскільки ви ввійшли до системи, то якщо оновите сторінку, не побачите зміни. Відкрийте сторінку в новому браузері або в анонімному вікні, і тоді ви побачите, що посилання не показується! ## Ще одне: розгортання! -Було б непогано побачити чи ваш сайт все ще працює на Heroku, чи не так? Давайте спробуємо розгорнути його знову. Якщо ви вже забули як це зробити, зверніться до кінцевої частини розділу [Розгортання](../deploy/README.md): +Давайте поглянемо, чи це все працює на PythonAnywhere. Час для ще одного розгортання! + +* Спершу, закомітьте новий код і зробіть push на GitHub -```bash +``` $ git status -... -$ git add -A . +$ git add --all . $ git status -... $ git commit -m "Added views to create/edit blog post inside the site." -... -$ git push heroku master +$ git push ``` - + +* Тоді, в [bash консолі PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* Нарешті, перейдіть на [вкладку Web](https://www.pythonanywhere.com/web_app_setup/) і натисніть **Reload**. + І це все! Вітання :) diff --git a/uk/django_installation/README.md b/uk/django_installation/README.md old mode 100755 new mode 100644 index c05d7ce9547..3d6a14afbfb --- a/uk/django_installation/README.md +++ b/uk/django_installation/README.md @@ -1,113 +1,6 @@ # Встановлення Django -> Частина цього розділу базується на матеріалах Geek Girls Carrots (http://django.carrots.pl/). -> -> Частина цього параграфу базується на матеріалі довідника [django-marcador tutorial][1] ліцензованого Creative Commons Attribution-ShareAlike 4.0 International License. Авторське право на навчальні матеріали django-marcador tutorial належить Markus Zapke-Gründemann та ін. +> **Зауваження:** Якщо ви вже проходили кроки інсталяції, значить все має бути зроблено - можете переходити зразу до наступного розділу! - [1]: http://django-marcador.keimlink.de/ +{% include "/django_installation/instructions.md" %} -## Віртуальне середовище - -Перед тим як встановлювати Django, ми допоможемо вам встановити надзвичайно корисний інструмент, що допоможе підтримувати чистоту середовища з кодом на вашому комп'ютері. Можете пропустити цей крок, але дуже бажано не робити цього, адже стартування із найліпшим чином налаштованою системою вбереже вас від багатьох проблем в майбутньому! - -Отже, створимо віртуальне середовище (англ. **virtual environment** або скорочено *virtualenv*). Це ізолює ваші налаштування для Python/Django для кожного окремого проекту. Іншими словами, будь-які зміни здійснені на одному сайті жодним чином не вплинуть на інші розроблювані вами сайти. Гарно, правда ж? - -Все що вам необхідно зробити це знайти місце, де ви хочете створити віртуальне середовище `virtualenv`; наприклад, ваша домашня папка. На Windows це може виглядати як `C:\Users\Name` (де `Name` - ваш логін). - -В рамках цього навчального посібника будемо використовувати нову директорію `djangogirls` з вашої домашньої папки: - - mkdir djangogirls - cd djangogirls - - -Створимо віртуальне середовище з ім'ям `myvenv`. Загальна команда буде ось в такому форматі: - - python -m venv myvenv - - -### Windows - -Щоб створити нове віртуальне середовище `virtualenv`, вам потрібно відкрити консоль (ми вже розповідали вам про це в одному з попередніх розділів - пам'ятаєте?) і запустити `C:\Python34\python -m venv myvenv`. Це буде виглядати так: - - C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv - - -де `C:\Python34\python` - це папка, в якій ви перед цим встановили Python, а `myvenv` - ім'я вашого віртуального середовища `virtualenv`. Можете використовувати яке завгодно ім'я, але воно має містити лише маленькі літери і не містити пробілів. Також хороша ідея зберігати ім'я в короткому виді, оскільки ви будете багаторазово посилатися на нього! - -### Linux та OS X - -Створення віртуального середовища `virtualenv` як на Linux так і на OS X просто відбувається із запуском `python3 -m venv myvenv`. Виглядає це так: - - ~/djangogirls$ python3 -m venv myvenv - - -`myvenv` - ім'я вашого віртуального середовища `virtualenv`. Можете використовувати яке завгодно ім'я, але воно має містити лише маленькі літери і не містити пробілів. Також хороша ідея зберігати ім'я в короткому виді, оскільки ви будете багаторазово посилатися на нього! - -> **ЗАУВАЖЕННЯ:** Ініціалізація віртуального середовища на Ubuntu 14.04 схожим методом наразі призводить до наступної помилки: -> -> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 -> -> -> Щоб обійти цю проблему, використовуйте натомість команду `virtualenv`. -> -> ~/djangogirls$ sudo apt-get install python-virtualenv -> ~/djangogirls$ virtualenv --python=python3.4 myvenv -> - -## Робота з віртуальним середовищем - -Вищезазначена команда створить папку `myvenv` (або інше вибране вами ім'я), що міститиме наше віртуальне середовище (в основному, набір папок і файлів). Все, що ми хочемо тепер зробити це активувати середовище шляхом запуску: - - C:\Users\Name\djangogirls> myvenv\Scripts\activate - - -для Windows, або: - - ~/djangogirls$ source myvenv/bin/activate - - -для OS X і Linux. - -Не забудьте замість `myvenv` повинно бути вибране вами ім'я для віртуального середовища! - -> **ЗАУВАЖЕННЯ:** іноді використання `source` може бути недоступно. В цьому випадку спробуйте зробити наступне: -> -> ~/djangogirls$ . myvenv/bin/activate -> - -Про активізацію віртуального середовища ви дізнаєтесь коли побачите підказку в командному рядку консолі, котра виглядатиме наступним чином: - - (myvenv) C:\Users\Name\djangogirls> - - -або: - - (myvenv) ~/djangogirls$ - - -Зауважте з'явився префікс `(myvenv)`! - -Під час роботи у віртуальному середовищі, `python` буде автоматичному посилатися на правильну версію, отже ви можете використовувати `python` замість `python3`. - -Добре, маємо усі необхідні залежності. Можемо зрештою встановити Django! - -## Встановлення Django - -Наразі, коли ваше віртуальне середовище активоване, можна встановлювати Django використавши `pip`. В консолі, запустіть `pip install django==1.8` (зазначте, що тут ми користуємося подвійним знаком рівності: `==`). - - (myvenv) ~$ pip install django==1.8 - Downloading/unpacking django==1.8 - Installing collected packages: django - Successfully installed django - Cleaning up... - - -для Windows - -> Якщо виникла помилка під час запуску pip на Windows платформі, будь ласка, перевірте чи шлях до вашого проекту містить пробіли (наприклад, `C:\Users\User Name\djangogirls`). Якщо так, будь ласка, перемістіть проект в інше місце, шлях до якого не буде містити пробілів (наприклад: `C:\djangogirls`). Після переміщення спробуйте запустити вищевказану команду знову. - -для Linux - -> Якщо виникла помилка під час запуску pip на Ubuntu 12.04, будь ласка, запустіть `python -m pip install -U --force-reinstall pip` щоб коректно перевстановити pip у віртуальному середовищі. - -Ось і все! Тепер (нарешті) ви готові до створення Django додатку! diff --git a/uk/django_installation/instructions.md b/uk/django_installation/instructions.md new file mode 100644 index 00000000000..2e261b48e4b --- /dev/null +++ b/uk/django_installation/instructions.md @@ -0,0 +1,102 @@ +> Частина цього розділу базується на матеріалах Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). + +> Частина цього розділу базується на матеріалі [django-marcador tutorial] +(http://django-marcador.keimlink.de/), +який ліцензований Creative Commons Attribution-ShareAlike 4.0 International License. +Авторське право на навчальні матеріали django-marcador tutorial належить Markus Zapke-Gründemann та ін. + + +## Віртуальне середовище + +Перед тим, як встановлювати Django, ми допоможемо вам встановити надзвичайно корисний інструмент, що допоможе підтримувати середовище розробки на вашому комп'ютері чистим. Цей крок можна пропустити, але дуже рекомендується його виконати. Починати найкращим можливим способом дозволить уникнути багатьох клопотів в майбутньому! + +Отже, створимо віртуальне середовище (англ. **virtual environment**, скорочено *virtualenv*). Virtualenv ізолюватиме ваше Python/Django середовище, для кожного проекту. Це означає, що будь-які зміни, внесені на одному сайті не вплинуть на будь-які інші, які ви також розробляєте. Гарно, правда ж? + +Все, що вам необхідно зробити - це знайти місце, де ви хочете створити віртуальне середовище `virtualenv`; наприклад, ваша домашня папка. На Windows це може виглядати як `C:\Users\Name` (де `Name` - ваш логін). + +В рамках цього навчального посібника будемо використовувати нову директорію `djangogirls` з вашої домашньої папки: + + mkdir djangogirls + cd djangogirls + +Створимо віртуальне середовище з ім'ям `myvenv`. Загальна команда буде ось в такому форматі: + + python3 -m venv myvenv + +### Windows + +Щоб створити нове віртуальне середовище `virtualenv`, вам потрібно відкрити консоль (ми вже розповідали вам про це в одному з попередніх розділів - пам'ятаєте?) і запустити `C:\Python34\python -m venv myvenv`. Це буде виглядати так: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + +де `C:\Python34\python` - це папка, в якій ви перед цим встановили Python, а `myvenv` - ім'я вашого віртуального середовища `virtualenv`. Ви можете використовувати будь-яке ім’я, але старайтесь обмежитись маленькими буквами і не використовуйте пробілів, наголосів або спеціальних символів. Тримати ім’я коротким - також гарна ідея, оскільки ви будете часто посилатися на нього! + +### Linux та OS X + +Створення віртуального середовища `virtualenv` як на Linux так і на OS X просто відбувається запуском `python3 -m venv myvenv`. +Виглядає це так: + + $ python3 -m venv myvenv + +`myvenv` - ім'я вашого віртуального середовища `virtualenv`. Можете використовувати яке завгодно ім'я, але воно має містити лише маленькі літери і не містити пробілів. Тримати ім’я коротким - також гарна ідея, оскільки ви будете часто посилатися на нього! + +> __ЗАУВАЖЕННЯ:__ Ініціалізація віртуального середовища на Ubuntu 14.04 і Debian 8 схожим методом наразі призводить до наступної помилки: + +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 + +> Щоб обійти цю проблему, використовуйте натомість команду `virtualenv`. + +> $ sudo apt-get install python-virtualenv +> $ virtualenv --python=python3.4 myvenv + + +## Робота з віртуальним середовищем + +Вище зазначена команда створить папку `myvenv` (або інше вибране вами ім'я), що міститиме наше віртуальне середовище (в основному, набір папок і файлів). + +#### Windows + +Запустіть своє віртуальне середовище, виконавши: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + +#### Linux та OS X + +Запустіть своє віртуальне середовище виконавши: + + $ source myvenv/bin/activate + +Не забудьте, що замість `myvenv` повинно бути вибране вами ім'я для віртуального середовища! + +> __ЗАУВАЖЕННЯ:__ іноді використання `source` може бути недоступно. В цьому випадку спробуйте зробити наступне: + +> $ . myvenv/bin/activate + +Про активацію віртуального середовища ви дізнаєтесь, коли побачите префікс `(myvenv)` в командному рядку консолі + +Під час роботи у віртуальному середовищі, `python` буде автоматичному посилатися на правильну версію, отже ви можете використовувати `python` замість `python3`. + +Добре, маємо усі необхідні залежності. Можемо зрештою встановити Django! + +## Встановлення Django + +Наразі, коли ваш `virtualenv` активований, можна встановлювати Django використавши `pip`. В консолі, запустіть `pip install django==1.9` (зазначте, що тут ми користуємося подвійним знаком рівності: `==`). + + (myvenv) ~$ pip install django==1.9 + Downloading/unpacking django==1.9 + Installing collected packages: django + Successfully installed django + Cleaning up... + +для Windows +> Якщо ви отримуєте помилку коли викликаєте pip на Windows, будь ласка, перевірте чи шлях до вашого проекту не містить пробілів, наголосів чи спеціальних символів (наприклад `C:\Users\User Name\djangogirls`). Якщо містить - перемістіть його в місце шлях до якого не містить таких символів (пропонуємо: `C:\djangogirls`). Після переміщення спробуйте запустити вищевказану команду знову. + +для Windows 8 чи Windows 10 +> Ваш командний рядок може зависнути, після того як ви спробуєте встановити Django. Якщо це сталось, замість вище зазначеної команди використовуйте: + +> C:\Users\Name\djangogirls> python -m pip install django==1.9 + +для Linux +> Якщо виникла помилка під час запуску pip на Ubuntu 12.04, будь ласка, запустіть `python -m pip install -U --force-reinstall pip` щоб коректно перевстановити pip у віртуальному середовищі. + +Оце усе! Зараз ви (нарешті) готові створити додаток Django! diff --git a/uk/django_models/README.md b/uk/django_models/README.md index f37f96beb7a..4adfaf94d38 100755 --- a/uk/django_models/README.md +++ b/uk/django_models/README.md @@ -1,6 +1,6 @@ # Django моделі -Наразі ми б хотіли створити щось, що зберігатиме усі дописи в нашому блозі. Але щоб бути спроможними це зробити нам необхідно трохи обговорити таке поняття як об'єкти - `objects`. +Наразі ми б хотіли створити щось, що зберігатиме усі дописи в нашому блозі. Але щоб бути спроможними це зробити, нам необхідно трохи поговорити про таке поняття, як об'єкти `objects`. ## Об'єкти @@ -21,12 +21,11 @@ purr() scratch() feed(cat_food) - - + + CatFood -------- taste - Отже, основна ідея полягає в тому, щоб описати реальні речі в програмному коді з усіма їх властивостями (так званими властивостями об'єкта `object properties`) і діями (так званими методами `methods`). @@ -43,13 +42,12 @@ author created_date published_date - Якого роду дії можна було б вчиняти з дописом у блозі? Було б непогано мати певний метод, що публікує допис, правда ж? Отже, нам потрібен метод `publish`. -Таким чином, знаючи нарешті чого ми хочемо досягти, можемо почати моделювати це в Django! +Таким чином, знаючи, чого ми хочемо досягти, можемо почати моделювати це в Django! ## Django модель @@ -64,7 +62,6 @@ Щоб підтримувати все у порядку, створимо окремий додаток всередині нашого проекту. Дуже добре зберігати в усьому організованість з самого початку. Щоб створити додаток треба запустити наступну команду в консолі (з директорії `djangogirls`, де знаходиться файл `manage.py`): (myvenv) ~/djangogirls$ python manage.py startapp blog - Ви побачите, що створено нову директорію `blog`, яка містить певну кількість файлів. Директорії та файли в нашому проекті мають виглядати наступним чином: @@ -83,20 +80,20 @@ ├── models.py ├── tests.py └── views.py - Після створення ми також повинні повідомити Django, що він має використовувати цей додаток. Ми робимо це у файлі `mysite/settings.py`. Нам треба знайти `INSTALLED_APPS` та додати рядок `'blog',` зверху над `)`. Таким чином, остаточний результат повинен мати наступний вигляд: - INSTALLED_APPS = ( - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'blog', - ) - +```python +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', +) +``` ### Створення моделі допису у блозі @@ -104,70 +101,71 @@ Відкриємо `blog/models.py`, видалимо все звідси та запишемо наступний код: - from django.db import models - from django.utils import timezone - - class Post(models.Model): - author = models.ForeignKey('auth.User') - title = models.CharField(max_length=200) - text = models.TextField() - created_date = models.DateTimeField( - default=timezone.now) - published_date = models.DateTimeField( - blank=True, null=True) - - def publish(self): - self.published_date = timezone.now() - self.save() - - def __str__(self): - return self.title - - -> Перевірте чи використали ви два знаки підкреслення (`_`) з кожної сторони `str`. Вони часто використовуються в Python і інколи ми називаємо їх "dunder" (скорочено від англ. "double-underscore"). - -Страхіття якесь, правда ж? Але не хвилюйтесь, ми пояснимо що означають ці лінії! +```python +from django.db import models +from django.utils import timezone + + +class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title +``` + +> Двічі перевірте, чи ви використали два знаки підкреслення (`_`) з кожної сторони `str`. Ця домовленість часто використовується в Python й іноді ми називаємо її "dunder" (скорочення від англ. "double-underscore"). + +Страхіття якесь, правда ж? Але не хвилюйтесь, ми пояснимо, що означають ці рядки! Усі лінії, що починаються з `from` або `import` - це лінії, які додають деякі біти з інших файлів. Отже замість того, щоб копіювати і вставляти одне й те ж в кожному файлі,ми можемо включити деякі частини з `from ... import ...`. `class Post(models.Model):` - цей рядок визначає нашу модель (це об'єкт `object`). -* `class` - це спеціальне ключове слово, яке показує що ми визначаємо об'єкт. -* `Post` - це ім'я нашої моделі. Ми можемо давати їй різні імена (але ми повинні уникати використання спеціальних символів та пробілів). Завжди починайте ім'я класу із великої літери. -* `models.Model` означає, що Post є Django моделлю, отже Django знає, що вона повинна бути збережена у базі даних. +- `class` - це спеціальне ключове слово, яке показує що ми визначаємо об'єкт. +- `Post` - це ім'я нашої моделі. Ми можемо давати їй різні імена (але ми повинні уникати використання спеціальних символів та пробілів). Завжди починайте ім'я класу із великої літери. +- `models.Model` означає, що Post є Django моделлю, отже Django знає, що вона повинна бути збережена у базі даних. А зараз визначимо властивості, про які ми говорили перед цим: `title`, `text`, `created_date`, `published_date` і `author`. Щоб це зробити нам необхідно визначити тип поля (чи це текст? Число? Дата? Зв'язок із іншим об'єктом, наприклад, об'єкт користувач - User?). -* `models.CharField` - текст як обмежена кількість символів. -* `models.TextField` - для необмежених довгих текстів. Буде ідеальним для змістової частини допису, правда ж? -* `models.DateTimeField` - дата та час. -* `models.ForeignKey` - зв'язок із іншою моделлю. +- `models.CharField` - для текстових полів з обмеженням кількісті символів. +- `models.TextField` - великі блоки тексту без обмежень. Ідеально підходить для запису блогу, правильно? +- `models.DateTimeField` - дата та час. +- `models.ForeignKey` - зв'язок із іншою моделлю. -Не будемо пояснювати кожен біт коду, оскільки це може зайняти надто багато часу. Якщо хочете дізнатися більше про поля моделей, а також як визначати речі відмінні від вище описаних, то дивіться документацію Django (https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types). +Не будемо пояснювати кожне слово в коді, оскільки це може зайняти надто багато часу. Якщо хочете дізнатися більше про поля моделей, а також як визначати речі відмінні від вище описаних, то дивіться документацію Django (https://docs.djangoproject.com/en/1.9/ref/models/fields/#field-types). -А як щодо `def publish(self):`? Це і є наш метод `publish`, про який ми говорили раніше. `def` означає, що це функція/метод. `publish` - ім'я методу. Ви можете змінити його, якщо бажаєте. Є правило, коли замість пробілів використовуються маленькі літери та знаки підкреслювання (наприклад, якщо ви хочете визначити метод, який обчислює середню ціну, то можна було б назвати його `calculate_average_price`). +А як щодо `def publish(self):`? Це і є наш метод `publish`, про який ми говорили раніше. `def` означає, що це функція/метод, а `publish` - ім'я методу. Ви можете змінити ім'я методу, якщо захочете. Правило іменування: треба використовувати рядкові букви, а пробіли замінювати підкресленнями. Наприклад, метод для розрахунку середньої ціни може бути названий `calculate_average_price`. -Методи дуже часто щось повертають. Приклад цього можна побачити в методі `__str__`. У цьому сценарії, коли ми викликаємо `__str__()`, то отримуємо текст (**string**) із заголовком посту. +Методи часто повертають (`return`) щось. Приклад цього можна побачити в методі `__str__`. У цьому сценарії, коли ми викликаємо `__str__()`, то отримуємо текст (**string**) із заголовком посту. -Якщо вам щось незрозуміло з приводу моделей, не соромтеся запитувати у вашого тренера! Ми знаємо, що це дуже складно, особливо коли одночасно ви вивчаєте, що таке об'єкти і функції. Але сподіваємося наразі це виглядає трохи менш таємничим для вас! +Якщо вам щось незрозуміло з приводу моделей, не соромтеся запитувати у вашого тренера! Ми знаємо, що це дуже складно, особливо коли ви одночасно вивчаєте об'єкти і функції. Але сподіваємося наразі це виглядає трохи менш таємничим для вас! ### Створення таблиць для моделей в базі даних -Останній крок - додати нашу нову модель до нашої бази даних. Спершу ми повинні зробити так, щоб Django знав, що сталися деякі зміни в нашій моделіl (ми щойно її створили), наберіть `python manage.py makemigrations blog`. Це буде виглядати наступним чином: +Останній крок - додати нашу нову модель до нашої бази даних. Спочатку потрібно повідомити Django, що змінилась наша модель (ми щойно створили її!). Наберіть `python manage.py makemigrations blog`. Це буде виглядати так: (myvenv) ~/djangogirls$ python manage.py makemigrations blog Migrations for 'blog': 0001_initial.py: - Create model Post - -Django підготував для нас файл перенесення, який ми повинні тепер застосувати до нашої бази даних, наберіть `python manage.py migrate blog`, на виході отримаємо: +Django підготував для нас файл перенесення, який ми повинні тепер застосувати до нашої бази даних. Наберіть `python manage.py migrate blog`, на виході отримаємо: (myvenv) ~/djangogirls$ python manage.py migrate blog Operations to perform: Apply all migrations: blog Running migrations: + Rendering model states... DONE Applying blog.0001_initial... OK - -Урааа! Наша модель допису Post тепер знаходиться у нашій базі даних, було б добре побачити її, правда ж? Для цього перейдемо до наступного розділу! +Ура! Наша модель допису Post тепер знаходиться у нашій базі даних. Було б добре побачити її, правда ж? Для цього перейдемо до наступного розділу! diff --git a/uk/django_orm/README.md b/uk/django_orm/README.md index 583552159c9..8c0bd3eccfa 100755 --- a/uk/django_orm/README.md +++ b/uk/django_orm/README.md @@ -1,27 +1,28 @@ # Django ORM і QuerySets -У цьому розділі ви дізнаєтесь як Django з'єднується із базою даних і зберігає в ній дані. Почнемо занурення! +У цьому розділі ви дізнаєтесь, як Django з'єднується із базою даних і зберігає в ній дані. Почнемо занурення! + ## Що таке QuerySet? -A QuerySet є, по суті, списком об'єктів заданої Model. QuerySet дозволяє вам считувати дані з бази даних, а також фільтрувати і впорядковувати їх. +A QuerySet є, по суті, списком об'єктів заданої моделі Model. QuerySet дозволяє вам считувати дані з бази даних, а також фільтрувати і впорядковувати їх. Найпростіше показати на прикладі. Давайте спробуємо? + ## Django shell -Відкрийте консоль і наберіть команду: +Відкрийте свій локальний термінал (не PythonAnywhere) і наберіть цю команду: (myvenv) ~/djangogirls$ python manage.py shell - -Результат повинен бути наступним: +Результатом повинно бути: (InteractiveConsole) >>> +Ви опинетесь в інтерактивній консолі Django. Це щось подібне на командний рядок Python, але має додаткову магію Django :). Звичайно, тут ви також можете використовувати усі команди Python. -Ви опинетесь в інтерактивній консолі Django. Це щось подібне на командний рядок із запитом в Python, але має додаткову магію Django:). Звичайно, тут ви також можете використовувати усі команди Python. ### Усі об'єкти @@ -32,108 +33,86 @@ A QuerySet є, по суті, списком об'єктів заданої Mode File "", line 1, in NameError: name 'Post' is not defined - Ой! З'явилась помилка. Вона повідомляє нам, що немає ніяких постів. І це правильно, адже ми забули спочатку імпортувати їх! >>> from blog.models import Post - Усе просто: імпортуємо модель `Post` з `blog.models`. Спробуємо вивести усі пости знову: >>> Post.objects.all() - [] + [, ] +Це список з дописів, з якими ми працювали раніше! Ми створили ці дописи через панель адміністратора Django. Проте, зараз ми хочемо створити нові дописи за допомогою Python, як ми цього доб'ємось? -В результаті отримаємо пустий список. Здається правильно, правда ж? Адже ми ще не додали жодного поста! То ж виправимо це. ### Створення об'єкту -Мова йдеться про те як створити об'єкт Post в базі даних: - - >>> Post.objects.create(author=user, title='Sample title', text='Test') +Мова йдеться про те, як створити об'єкт Post в базі даних: + >>> Post.objects.create(author=me, title='Sample title', text='Test') -Однак, маємо тут один пропущений елемент: користувач -`user`. Ми маємо передати екземпляр моделі `User` як автора. Як це зробити? +Однак, ми пропустили один елемент : `me`. Потрібно передати екземпляр моделі `User` у якості автора. Як це зробити? Спочатку імпортуємо модель User: >>> from django.contrib.auth.models import User - Які користувачі присутні в нашій базі даних? Спробуймо це: - >>> User.objects.all() - [] - - -Жодного користувача! Давайте створимо одного: - - >>> User.objects.create(username='ola') - - - -Яких користувачів ми маємо в нашій базі даних тепер? Спробуйте знову: - >>> User.objects.all() [] +Це суперкористувач, якого ми створили раніше! Нам потрібен його екземпляр: -Круто! Давайте тепер отримаємо екземпляр користувача: - - user = User.objects.get(username='ola') - + me = User.objects.get(username='ola') Як бачимо, ми отримали користувача із іменем, що дорівнює 'ola'. Чудово! Звісно, ви мали б використовувати ваше ім'я. -Тепер зрештою можемо створити наш перший пост: - - >>> Post.objects.create(author = user, title = 'Sample title', text = 'Test') +Тепер ми нарешті можемо створити наш пост: + >>> Post.objects.create(author=me, title='Sample title', text='Test') -Урра! Бажаєте перевірити чи це працює? +Ура! Бажаєте перевірити, чи це працює? >>> Post.objects.all() - [] + [, , ] + +Є, ще один допис в списку! ### Додайте більше постів -А тепер можете трохи побавитися і пододавати більше постів щоб побачити як це працює. Додайте ще 2-3 поста і переходьте до наступної частини. +А тепер можете трохи побавитися і пододавати більше постів, щоб побачити, як це працює. Додайте ще 2-3 поста і переходьте до наступної частини. + ### Фільтрування об'єктів -Великою частиною QuerySets є можливість фільтрувати запити до бази даних. Скажімо, ми хочемо відшукати усі пости, що мають автора ola. Будемо використовувати `filter` замість `all` в `Post.objects.all()`. В дужках ми вказуємо яким умовам повинен відповідати пост щоб завершити наш запит до бази даних. У нашому випадку автор є користувачем. В Django це можна відобразити так: `author=user`. Тепер наш шматок коду виглядає так: +Великою частиною QuerySets є можливість фільтрувати запити до бази даних. Скажімо, ми хочемо відшукати усі пости, що мають автора ola. Будемо використовувати `filter` замість `all` в `Post.objects.all()`. В дужках ми вказуємо яким умовам повинен відповідати пост, щоб завершити наш запит до бази даних. У нашому випадку це автор `author`, що дорівнює `me`. В Django цю умову можна виразити як: `author=me`. Тепер наш шматок коду виглядає так: - >>> Post.objects.filter(author=user) + >>> Post.objects.filter(author=me) [, , , ] - -Чи, можливо, ми хочемо побачити усі пости, що містять слово 'title'в полі `title`? +Чи, можливо, ми хочемо побачити усі пости, що містять слово 'title' в полі `title`? >>> Post.objects.filter(title__contains='title') [, ] - > **Зауваження** Тут використано два знаки підкреслювання (`_`) між `title` і `contains`. Django ORM використовує цей синтаксис щоб відокремити імена полів ("title") і операції або фільтри ("contains"). Якщо ви раптом використаєте одне підкреслювання, то отримаєте помилку на кшталт "FieldError: Cannot resolve keyword title_contains". -Також можна отримати список усіх опублікованих постів. Зробимо це відфільтрувавши усі пости, що мають published_date`: задану в минулому часі - +Ви також можете отримати список всіх опублікованих дописів. Ми робимо це шляхом фільтрації всіх дописів, які мають встановлене поле `published_date`: >>> from django.utils import timezone >>> Post.objects.filter(published_date__lte=timezone.now()) [] +На жаль, доданий з Python консолі допис ще не опублікований. Ми можемо змінити це! Спершу отримаємо екземпляр допису, який хочемо опублікувати: -Нажаль, ще жоден наш пост не було опубліковано. Це можна змінити! Спершу отримаємо екземпляр поста, який ми хочемо опублікувати: - - >>> post = Post.objects.get(id=1) - + >>> post = Post.objects.get(title="Sample title") А далі опублікуємо його за допомогою нашого методу `publish`! >>> post.publish() - -А тепер спробуйте вивести список усіх опублікованих постів знову (натисніть 3 рази кнопку із стрілочкою вверх і після цього - `enter`): +Тепер спробуйте отримати список опублікованих дописів знову (натисніть стрілку вгору 3 рази, а потім `enter`): >>> Post.objects.filter(published_date__lte=timezone.now()) [] @@ -146,13 +125,20 @@ QuerySets також дозволяє впорядковувати список >>> Post.objects.order_by('created_date') [, , , ] - -Також можна здійснити впорядкування у зворотньому напрямку додавши `-` на початку: +Також можна здійснити впорядкування у зворотньому напрямку, додавши `-` на початку: >>> Post.objects.order_by('-created_date') [, , , ] +### З'єднання QuerySets + +QuerySets можна поєднувати, створюючи **ланцюжки**: + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + +Це дуже потужний механізм, що дозволяє вам писати дуже складні запити. + Клас! Тепер ви готові до наступної частини! Щоб закрити командну оболонку, наберіть: >>> exit() diff --git a/uk/django_start_project/README.md b/uk/django_start_project/README.md index 1ff62f34f1e..8b121540a53 100755 --- a/uk/django_start_project/README.md +++ b/uk/django_start_project/README.md @@ -1,31 +1,34 @@ # Ваш перший Django проект! -> Частина цього розділу базується на матеріалах Geek Girls Carrots (http://django.carrots.pl/). -> -> Частина цього розділу базується на матеріалх [django-marcador tutorial][1] ліцензованих Creative Commons Attribution-ShareAlike 4.0 International License. Авторське право на навчальні матеріали django-marcador tutorial належить Markus Zapke-Gründemann та ін. +> Частина цього розділу базується на матеріалах Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). - [1]: http://django-marcador.keimlink.de/ +> Частина цього розділу базується на матеріалх [django-marcador tutorial](http://django-marcador.keimlink.de/) +ліцензованих Creative Commons Attribution-ShareAlike 4.0 International License. +Авторське право на навчальні матеріали django-marcador tutorial належить +Markus Zapke-Gründemann та ін. Ми збираємося створити простий блог! -Перший крок це створити новий Django проект. В основному, це означає що ми будемо запускати певні скрипти Django, які створюватимуть для нас каркас Django проекту: набір папок і файлів, які ми будемо пізніше використовувати. +Перший крок - це почати новий проект Django. По суті, це означає що ми запустимо деякі скрипти, які надає Django, що створять для нас скелет Django проекту. Це просто кілька каталогів та файлів, якими ми користуватимемось пізніше. -Імена деяких файлів і папок є дуже важливими для Django. Не можна перейменовувати файли, які ми зараз будемо створювати. Їх переміщення в різні місця також не є хорошою ідеєю. Django потребує підтримки певної структури, для того щоб бути в змозі знаходити важливі речі. +Імена деяких файлів і папок є дуже важливими для Django. Не можна перейменовувати файли, які ми зараз будемо створювати. Їх переміщення в різні місця також не є хорошою ідеєю. Для того щоб Django міг знаходити важливі речі, потрібно підтримувати задану архітектуру. -В консолі потрібно запустити (пам'ятайте, що не треба набирати `(myvenv) ~/djangogirls$`, OK?): +> Пам'ятайте, що усе треба запускати у віртуальному середовищі. Якщо ви не бачите префікс `(myvenv)` в консолі, то потрібно активувати ваше віртуальне середовище. Ми пояснювали як це зробити у розділі __Встановлення Django__ в частині __Робота з віртуальним середовищем__. +Команда `myvenv\Scripts\activate` на Windows або `source myvenv/bin/activate` на Mac OS / Linux зробить це за вас. -> Пам'ятайте, що усе треба запускати у віртуальному середовищі. Якщо ви не бачите префікс `(myvenv)` в консолі, то потрібно активувати ваше віртуальне середовище. Ми пояснювали як це зробити у розділі **Встановлення Django** в частині **Робота з віртуальним середовищем**. +В терміналі Mac OS або Linux слід запустити наступну команду; **не забудьте додати крапку `.` в кінці**: -Запустіть: + (myvenv) ~/djangogirls$ django-admin startproject mysite . - django-admin startproject mysite . +У Windows; **не забудьте додати крапку `.` в кінці**: -для Windows: + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . - (myvenv) C:\Users\Name\djangogirls> python myvenv\Scripts\django-admin.py startproject mysite . +> Крапка `.` має ключове значення, оскільки вона означає "встанови Django в поточний каталог" (символ крапки `.` використовується, щоб не писати повний шлях) - -> **Зауваження** Переконайтесь, що ви включили (`.`) вкінці команди, це важливо. +> **Примітка** Коли набираете команду вище, пам'ятайте, що потрібно друкувати тільки ту частину, яка починається з `django-admin` або `django-admin.py`. +Частини шляху `~/djangogirls$ (myvenv)` та `(myvenv) C:\Users\Name\djangogirls >`вказані тут лише +як приклад запрошення командного рядка до введення команд. `django-admin.py` - це скрипт, що створить для вас усі необхідні папки і файли. Наразі ви повинні мати структуру, котра виглядає наступним чином: @@ -36,27 +39,39 @@ urls.py wsgi.py __init__.py - + `manage.py` - скрипт, що допомагає керувати сайтом. З його допомогою ми зможемо запускати веб сервер без встановлення чогось іще додатково, серед іншого. Файл `settings.py` містить конфігурацію вашого веб сайту. -Пам'ятаєте, коли ми розмовляли про листоношу, що перевіряє куди треба доправити листа? Файл `urls.py` містить список шаблонів, що використовуються елементом `urlresolver`. +Пам'ятаєте, коли ми розмовляли про листоношу, що перевіряє, куди треба доправити листа? Файл `urls.py` містить список шаблонів, що використовуються елементом `urlresolver`. Проігноруємо поки інші файли, адже ми не будемо їх змінювати. Єдина річ, яку варто пам'ятати - не видалити їх ненароком! + ## Зміна налаштувань Здійснимо деякі зміни в `mysite/settings.py`. Відкриємо файл в текстовому редакторі, який ви мали встановити раніше. -Було б добре мати коректні часові налаштування на нашому веб сайті. Перейдіть на http://en.wikipedia.org/wiki/List_of_tz_database_time_zones і скопіюйте відповідний часовий пояс (TZ). (наприклад, `Europe/Berlin` ) +Було б непогано мати коректний час на нашому сайті. Перейдіть до [списку часових поясів на Вікіпедії](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) та скопіюйте відповідний часовий пояс (TZ). (напр. `Europe/Kiev`) + +У файлі settings.py знайдіть рядок, що містить `TIME_ZONE` і замініть його на ваш часовий пояс: + +```python +TIME_ZONE = 'Europe/Kiev' +``` + +Попередній рядок показує як обрати часовий пояс "Europe/Kiev" -Потрібно знайти рядок, що містить `USE_TZ` і `TIME_ZONE` та модифікувати їх, щоб вони мали наступний вигляд, підставляючи замість `Europe/Berlin` відповідно ваш часовий пояс: - USE_TZ = False - TIME_ZONE = 'Europe/Berlin' - +Нам також необхідно додати шлях для статичних файлів (згодом із посібника ви дізнаетесь все про "статичні файли" та листи стилів (CSS)). Перейдіть *в кінець* файлу та додайте новий запис `STATIC_ROOT` одразу під словом `STATIC_URL`: + +```python +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'static') +``` + ## Налаштування бази даних @@ -64,42 +79,57 @@ Відповідні налаштування вже прописані у файлі `mysite/settings.py`: - DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } +```python +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } - +} +``` Щоб створити базу даних для нашого блогу, давайте запустимо наступне в консолі: `python manage.py migrate` (ми повинні знаходитися всередині директорії `djangogirls`, яка містить файл `manage.py`). Якщо все пройшло успішно, ви маєте побачити щось на кшталт: (myvenv) ~/djangogirls$ python manage.py migrate Operations to perform: - Apply all migrations: admin, contenttypes, auth, sessions + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... Running migrations: + Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK Applying sessions.0001_initial... OK - Ми це зробили! Час запустити веб сервер і перевірити чи працює наш сайт! Ви повинні знаходитися в папці, що містить файл `manage.py` (папка `djangogirls`). В консолі ми можемо активувати веб сервер запустивши `python manage.py runserver`: (myvenv) ~/djangogirls$ python manage.py runserver - -А зараз все, що ви повинні перевірити це чи активований ваш веб сайт. Відкрийте ваш браузер (Firefox, Chrome, Safari, Internet Explorer або будь-який, який ви використовуєте) і введіть адресу: +Якщо ви використовуєте Windows і бачите помилку `UnicodeDecodeError` слід виконати наступну команду: + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +А зараз ви повинні перевірити, чи запущений ваш веб-сайт. Відкрийте браузер (Firefox, Chrome, Safari, Internet Explorer або будь-який інший) і введіть адресу: http://127.0.0.1:8000/ - -Веб сервер буде приймати команду із командного рядка поки ви не зупините її: щоб набрати нову команду відкрийте нове вікно терміналу (і не забудьте всередині цього вікна також активувати ваше віртуальне середовище), або ж зупиніть веб сервер повернувшись до вікна, в котрому він запущений і натиснувши CTRL+C - клавіші Control і C buttons разом (одночасно) (на Windows, ви можете натиснути Ctrl+Break). +Веб-сервер забирає на себе керування командним рядком, доки ви його не зупините. Моб мати можливість виконувати нові команди, поки працює веб-сервер, відкрийте нове вікно командного рядка (терміналу) та активуйте ваш virtualenv. Щоб зупинити веб-сервер, переключіться назад до вікна, в якому він працює і використайте сполучення клавіш CTRL + C (натисніть клавіші разом) (на Windows, можливо, доведеться натиснути клавіші Ctrl + Break). -Вітаємо! Ви щойно створили ваш перший веб сайт і запустили його використовуючи веб сервер! Хіба ж це не круто? +Вітаємо! Ви щойно створили свій перший веб-сайт та запустили його на веб-сервері! Хіба ж це не круто? -![It worked!](images/it_worked2.png) +![Працює!](images/it_worked2.png) -Готові до наступного кроку? Час створити певний контент! +Готові до наступного кроку? Час додати трішки контенту! diff --git a/uk/django_templates/README.md b/uk/django_templates/README.md index d35430013ea..40bd9d9ab87 100755 --- a/uk/django_templates/README.md +++ b/uk/django_templates/README.md @@ -1,12 +1,12 @@ # Django шаблони -Час вивести деякі дані! Django надає нам певні допоміжні, вбудовані шаблонні теги для цього. +Час вивести деякі дані! Django надає нам певні допоміжні, вбудовані __шаблонні теги__ для цього. ## Що таке шаблонні теги? -Як бачите, в HTML, ви не можете помістити Python код, тому що браузери не зрозуміють його. Вони знають лише HTML. Ми знаємо, що HTML більшою мірою є статичним, в той час як Python є більш динамічним. +Як бачите, в HTML, ви не можете помістити Python код, тому що браузери не зрозуміють його. Вони знають лише HTML. Ми знаємо, що HTML більшою мірою є статичною, в той час як Python є більш динамічною мовою. -**Шаблонні теги Django** дозволяють нам передавати Python-подібні речі в HTML, таким чином можна розробляти динамічні веб-сайти швидше і простіше. Ой! +__Шаблонні теги Django__ дозволяють нам передавати Python-подібні речі в HTML, таким чином можна розробляти динамічні веб-сайти швидше і простіше. Ой! ## Шаблон для виведення списку постів @@ -18,29 +18,27 @@ {{ posts }} ``` -Спробуйте це у вашому шаблоні `blog/templates/blog/post_list.html` (замініть усе між другими тегами `
` на рядок `{{ posts }}`), збережіть файл і перезавантажте сторінку щоб побачити результати: +Спробуйте це в шаблоні `blog/templates/blog/post_list.html`. Починаючи з другого `
` до третього `
` замініть все на `{{ posts }}`. Збережіть файл і оновіть сторінку, щоб побачити результат: -![Figure 13.1](images/step1.png) +![Рисунок 13.1](images/step1.png) -Як можна побачити, все що ми отримали це: +Як можна побачити, все що ми отримали, це: [, ] - -Означає, що Django розуміє це як список об'єктів. Пам'ятаєте із розділу **Вступ до Python** як ми можемо виводити списки? Так, за допомогою циклів for! В Django шаблоні, вони реалізуються наступним чином: +Означає, що Django розуміє це як список об'єктів. Пам'ятаєте із розділу __Вступ до Python__ як ми можемо виводити списки? Звичайно, за допомогою циклу __for__! У Django шаблонах ви можете створити їх наступним чином: ```html {% for post in posts %} {{ post }} {% endfor %} ``` - Спробуйте це у вашому шаблоні. -![Figure 13.2](images/step2.png) +![Рисунок 13.2](images/step2.png) -Працює! Однак, бажано щоб вони були виведені як статичні пости, які ми створили раніше у розділі **Вступ до HTML**. Ви можете компонувати теги HTML і шаблонні теги. Наша частина `body` буде виглядати так: +Працює! Однак, бажано, щоб вони були виведені як статичні пости, які ми створили раніше у розділі __Вступ до HTML__. Ви можете компонувати теги HTML і шаблонні теги. Наша частина `body` буде виглядати так: ```html
@@ -51,36 +49,48 @@

published: {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -Усе, що міститься між `{% for %}` і `{% endfor %}` буде повторюватись для кожного об'єкту у списку. Перезавантажте вашу сторінку: +{% raw %}Все, що ви напишете між `{% for %}` та `{% endfor %}` повторюватиметься для кожного об'єкта у списку. Оновіть сторінку:{% endraw %} -![Figure 13.3](images/step3.png) +![Рисунок 13.3](images/step3.png) + +Чи помітили ви, що цього разу ми використали трохи відмінні позначення `{{ post.title }}` або `{{ post.text }}`? Ми маємо доступ до даних, що містяться в кожному полі, визначеному в нашій моделі `Post`. Також `|linebreaksbr` перенаправляє текст посту через фільтр щоб конвертувати розриви ліній в абзаци. -Чи помітили ви, що цього разу ми використали трохи відмінні позначення `{{ post.title }}` або `{{ post.text }}`? Ми маємо доступ до даних, що містяться в кожному полі, визначеному в нашій моделі `Post`. Також `|linebreaks` перенаправляє текст посту через фільтр щоб конвертувати розриви ліній в абзаци. ## Ще одне -Було б непогано побачити чи ваш сайт все ще працює на Heroku, чи не так? Давайте спробуємо розгорнути його знову. Якщо ви вже забули як це зробити, зверніться до кінцевої частини розділу 15: +Було б непогано побачити як ваш сайт буде працювати в інтернеті, так? Давайте спробуєм розгорнути його в PythonAnywhere знову. Ось наступні кроки... + +* По-перше, залийте ваш код на Github -```bash +``` $ git status -... -$ git add -A . +[...] +$ git add --all . $ git status -... -$ git commit -m "Used Django templates instead of static HTML." -... -$ git push heroku master +[...] +$ git commit -m "Modified templates to display posts from database." +[...] +$ git push ``` - -Вітаємо! А тепер спробуйте додати новий пост у вашому Django адміністраторі (не забудьте додати published_date!), потім перезавантажте сторінку щоб переконатись що новий пост з'явився. +* Потім, увійдіть до [PythonAnywhere](https://www.pythonanywhere.com/consoles/) та перейдіть до **Bash консолі** (або запустіть нову) і виконайте команди: + +``` +$ cd my-first-blog +$ git pull +[...] +``` + +* Нарешті, перейдіть на вкладку [Web](https://www.pythonanywhere.com/web_app_setup/) і натисніть **Reload** (перезавантажити) у веб-додатку. + + +Вітаємо! А тепер спробуйте додати новий пост у вашому Django адміністраторі (не забудьте додати published_date!), потім перезавантажте сторінку, щоб переконатись, чи з'явився новий пост. -Працює як заклинання? Ми пишаємось вами! Почастуйте себе чимось солоденьким, ви заслужили :) +Все працює, як годинник? Ми пишаємося! Відійдіть ненадовго від комп'ютера, ви заслуговуєте на перерву. :) -![Figure 13.4](images/donut.png) +![Рисунок 13.4](images/donut.png) diff --git a/uk/django_urls/README.md b/uk/django_urls/README.md index 96910973d14..8977d9b80c8 100755 --- a/uk/django_urls/README.md +++ b/uk/django_urls/README.md @@ -1,51 +1,71 @@ # Django url -Ми збираємося побудувати нашу першу веб сторінку -- домашню сторінку для вашого блогу! Але спочатку, давайте трохи дізнаємось про Django url. +Ми збираємося побудувати нашу першу веб-сторінку - домашню сторінку для вашого блогу! Але спочатку, давайте трохи дізнаємось про Django URL-адреси. ## Що таке URL? -URL -- це просто веб адреса. Ви можете побачити URL кожен раз коли відвідуєте будь-який веб сайт, він видимий в браузерному адресному рядку (так! 127.0.0.1:8000 це URL! І http://djangogirls.com також є URL): +URL - це просто веб-адреса. Відображається URL кожен раз, коли ви відвідуєте веб-сайт - це видно в адресному рядку браузера (так! `127.0.0.1:8000` - це URL! І `https://djangogirls.org` також є URL): ![Url](images/url.png) -Кожна сторінка в Інтернеті потребує свого власного URL. Таким чином ваш додаток знає, що треба показувати користувачу, який відкриває URL. В Django використовується певний елемент, що називається `URLconf` (URL configuration), котрий є набором шаблонів, яким Django намагатиметься відповідати за допомогою отриманого URL щоб віднайти необхідне відображення. +Кожна сторінка в Інтернеті потребує свого власного URL. Таким чином ваш додаток знає, що треба показувати користувачу, який відкриває URL. В Django використовується така річ, яка називається `URLconf` (URL конфігурація). URLconf являє собою набір шаблонів, які Django намагатиметься зіставити з отриманих URL, щоб знайти правильне відображення. ## Як працює URL в Django? -Відкриємо файл `mysite/urls.py` і подивимось як він виглядає: +Давайте відкриємо файл `mysite/urls.py` в редакторі коду і подивимось, як він виглядає: - from django.conf.urls import include, url - from django.contrib import admin - - urlpatterns = [ - # Examples: - # url(r'^$', 'mysite.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), - - url(r'^admin/', include(admin.site.urls)), - ] - +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), +] +``` Як бачите, Django вже щось записав сюди для нас. -Рядки, що починаються з `#` це коментарі, тобто ці рядки не будуть запускатися Python. Досить зручно, чи не так? +Рядки, що починаються з `#` - це коментарі, тобто ці рядки не будуть запускатися Python. Досить зручно, чи не так? -URL адміністратора, котрий ви відвідували у попередньому розділі вже є тут: +URL панелі адміністратора, котрий ви відвідували у попередньому розділі вже є тут: +```python url(r'^admin/', include(admin.site.urls)), - +``` Це означає, що для кожного URL, що починається з `admin/` Django знаходитиме відповідне відображення - *view*. У даному випадку ми включаємо багато адміністраторських URL, отже не все запаковується в цей маленький файл, що є більш читабельним і акуратнішим. ## Regex -Хіба вам не цікаво яким чином Django створює відповідності між URL і відображеннями? Гаразд, ця частина досить хитра. Django використовує `regex` -- регулярні вирази. Regex має багато (багато!) правил, що формують шаблон пошуку. Досить не просто для розуміння, отже не будемо турбуватись про це наразі, а дізнатись про них ви, однозначно, зможете потім. А зараз будемо користуватися лише тими правилами, які нам будуть необхідні. +Хіба вам не цікаво, яким чином Django створює відповідності між URL і відображеннями? Гаразд, ця частина досить хитра. Django використовує `regex`, що є скороченням від "regular expressions" (регулярні вирази). Regex має багато (багато!) правил, що формують шаблон пошуку. Оскільки регулярні вирази є продвинутою темою, ми не будемо вникати в деталі їх роботи. + +Якщо ви все ще хочете зрозуміти, як ми створили шаблони, ось приклад процесу - нам потрібно буде тільки обмежена підмножина правил для того, щоб виразити потрібний шаблон, а саме: + + ^ для початку тексту + $ для кінця тексту + \d для цифри + + щоб позначити, що попередній символ має бути повторений мінімум один раз + () для захоплення частини шаблону + +Все інше у визначенні url буде прийматися як є. + +Тепер уявіть, що у вас є сайт з такою адресою: `http://www.mysite.com/post/12345/`, де `12345` - це номер вашого посту. + +Написання окремих відображень для усіх номерів постів було б дійсно нестерпним. За допомогою регулярних виразів ми можемо створити шаблон, який відповідає url і витягти номер для нас: `^post/(\d+)/$`. Давайте розберемо його по частинах, щоб побачити, що ми тут робимо: + +* **^post/** говорить Django взяти що-небудь, що має `post/` на початку url (зразу після `^`) +* **(\d+)** означає, що буде число (одне або декілька цифр), і ми хочемо, щоб число захопилось і вибралось +* **/** вказує Django, що наступним символом має бути `/` +* **$** далі позначає кінець URL-адреси, а це означає, що під шаблон підходять лише ті рядки, які закінчуються на `/` -Наведемо простий приклад лише для того, щоб на залишити вас у тупиковому положенні на цьому реченні: уявіть, що у вас є сайт із адресою: `http://www.mysite.com/post/12345/`, де `12345` -- номер вашого поста. Написання окремих відображень для усіх номерів постів було б дійсно нестерпно. Django спрощує цей момент дозволяючи писати `http://www.mysite.com/post//`. Django потурбується про решту! ## Ваш перший Django url! -Час створити наш перший URL! Ми хочемо, щоб http://127.0.0.1:8000/ був домашньою сторінкою нашого блогу і виводив список постів. +Час створити наш перший URL! Ми хочемо, щоб 'http://127.0.0.1:8000/' був домашньою сторінкою нашого блогу і виводив список постів. Також ми б хотіли підтримувати порядок у файлі `mysite/urls.py`, отже імпортуємо url з нашого додатку `blog` у файл `mysite/urls.py`. @@ -53,37 +73,43 @@ URL адміністратора, котрий ви відвідували у п Ваш файл `mysite/urls.py` повинен наразі мати такий вигляд: - from django.conf.urls import include, url - from django.contrib import admin - - urlpatterns = [ - url(r'^admin/', include(admin.site.urls)), - url(r'', include('blog.urls')), - ] - +```python +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), +] +``` + +Django тепер перенаправлятиме усе, що надходить на 'http://127.0.0.1:8000/' до `blog.urls` і шукатиме там подальші інструкції. + +Для запису регулярних виразів у Python використовується символ `r` перед стрічкою. Це підказка для інтерпретатора, що рядок може містити спеціальні символи, які використовуються в регулярних виразах. -Django тепер перенаправлятиме усе, що надходить на http://127.0.0.1:8000/ до `blog.urls` і шукатиме там подальші інструкції. ## blog.urls -Створіть новий пустий файл `blog/urls.py`. Добре! Додайте наступні перші два рядки: +Створіть новий порожній файл `blog/urls.py`. Добре! Додайте наступні перші два рядки: - from django.conf.urls import include, url - from . import views - +```python +from django.conf.urls import url +from . import views +``` Тут ми лише імпортуємо методи Django і всі наші відображення з додатку `blog` (у нас ще немає жодного, але ми повернемося до цього через хвилину!) Після цього, ми можемо додати наш перший URL шаблон: - urlpatterns = [ - url(r'^$', views.post_list), - ] - +```python +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), +] +``` -Як бачите, ми присвоюємо відображення із назвою `post_list` значенню URL `^$`. Але що означає `^$`? Це магія регулярних виразів :) Давайте розберемось по порядку: - `^` в регулярному виразі означає "початок"; з цього знаку ми можемо розпочати пошук нашого шаблону - `$` відповідає лише "закінченню" рядка, що означає, що ми будемо тут завершувати наш пошук +Як бачите, ми присвоюємо відображення із назвою `post_list` значенню URL `^$`. Цей регулярний вираз буде перевіряти рядок на `^` (початок рядка) та `$` (кінець) - тому тільки порожній рядок буде відповідати цим вимогам. Це правильно, тому що в механізмі Django URL, вираз ' http://127.0.0.1:8000 /' не є частиною URL-адреси. Цей шаблон показуватиме для Django, що `views.post_list` є правильним місцем для переходу, якщо хтось введе ваш сайт за адресою 'http://127.0.0.1:8000/'. -Якщо ви застосуєте ці два знаки разом, виглядатиме на те, що ми шукаємо пустий рядок! І це правильно, тому що в Django url розпізнавачах (url resolvers), http://127.0.0.1:8000/ не є частиною URL. Цей шаблон показуватиме Django, що `views.post_list` є правильним місцем для переходу, якщо хтось введе ваш сайт за адресою http://127.0.0.1:8000/. +На останок, `name='post_list'` - це назва URL, який використовуватиметься для ідентифікації потрібного відображення (в'ю). Це може бути ім'ям потрібного нам відображення (в'ю), або взагалі чимось іншим. Ми буде використовувати іменовані URL-адреси, протягом всього проекту, тому важливо, давати ім'я кожному URL у застосунку. Ми також повинні намагатися давати URL-адресам якомога простіші та унікальні імена, і так, щоб їх було легко запам'ятати. Усе гаразд? Відкрийте http://127.0.0.1:8000/ у браузері, щоб побачити результат. @@ -91,6 +117,6 @@ Django тепер перенаправлятиме усе, що надходит Що, тут більше немає повідомлення "It works"? Не хвилюйтесь, це просто сторінка із помилкою, нічого боятися! Вони є насправді дуже корисними: -Можете прочитати тут: **no attribute 'post_list'**. Чи *post_list* не нагадує вам про щось? Це назва нашого відображення! Це означає, що усе на місці, ми просто ще не створили відповідне відображення. Не переймайтесь, ми його отримаємо. +Можете прочитати тут: __no attribute 'post_list'__. Чи *post_list* не нагадує вам про щось? Це назва нашого відображення! Це означає, що все знаходиться на місці, але ми просто ще не створили наше *відображення*. Не переймайтесь, ми його отримаємо. -> Якщо бажаєте дізнатися більше про Django URLconf, зверніться до офіційної документації: https://docs.djangoproject.com/en/1.8/topics/http/urls/ +> Якщо бажаєте дізнатися більше про Django URLconf, зверніться до офіційної документації: https://docs.djangoproject.com/en/1.9/topics/http/urls/ diff --git a/uk/django_views/README.md b/uk/django_views/README.md index eba06a6d087..1bff20240f6 100755 --- a/uk/django_views/README.md +++ b/uk/django_views/README.md @@ -1,28 +1,30 @@ -# Django відображення - час створювати! +# Django відображення - час творити! -Час позбутися помилки, створеної в останньому розділі :) +Час позбутися помилки, створеної в попередньому розділі :) -Відображення - *view* -- це місце, в якому ми закладаємо "логіку" нашої програми. Воно надсилає запит на інформацію з моделі, яку ви перед цим створили і передає його шаблону, який ви створюватиме в наступному розділі. Відображення є просто методами Python, трохи складнішими, ніж речі які ми робили у розділі **Вступ до Python**. +Відображення - *view* - це місце, в якому ми закладаємо "логіку" нашої програми. Воно запитує інформацію з `моделі`, яку ми створили раніше і передає його до `шаблону`. Ми створимо шаблон в наступному розділі. Відображення - це просто методи Python, трохи складніші за ті, які ми робили у розділі __Вступ до Python__. Відображення розташовані у файлі `views.py`. Додамо наші відображення до файлу `blog/views.py`. ## blog/views.py -OK, давайте відкриємо цей файл подивимось що тут: +OK, давайте відкриємо цей файл і подивимось що тут: - from django.shortcuts import render - - # Create your views here. - +```python +from django.shortcuts import render -Не так багато поки що. Найпростіший вид може мати наступний вигляд. +# Create your views here. +``` - def post_list(request): - - return render(request, 'blog/post_list.html', {}) - +Не так багато поки що. Найпростіший вид може бути таким. -Як бачимо, ми створили метод (`def`) із назвою `post_list`, що у якості аргументу бере запит - `request` і повертає метод `render`, що активує (компілює) наш шаблон `blog/post_list.html`. +```python +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` + + +Як бачимо, ми створили метод (`def`) із назвою `post_list`, що приймає як аргумент запит - `request` і повертає метод `render`, що активує (компілює) наш шаблон `blog/post_list.html`. Збережіть файл, перейдіть до http://127.0.0.1:8000/ і подивіться, що ми отримали. @@ -32,4 +34,4 @@ OK, давайте відкриємо цей файл подивимось що Цього разу усе просто: *TemplateDoesNotExist*.Виправимо це і створимо шаблон в наступному розділі! -> Дізнатися більше про Django відображення можна звернувшись до офіційної документації: https://docs.djangoproject.com/en/1.8/topics/http/views/ +> Дізнатися більше про Django відображення можна, звернувшись до офіційної документації: https://docs.djangoproject.com/en/1.9/topics/http/views/ diff --git a/uk/domain/README.md b/uk/domain/README.md deleted file mode 100755 index 587b0d3dc61..00000000000 --- a/uk/domain/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Домен - -Heroku надає вам домен, але він надто довгий, важкий для запам'ятовування, і ... потворний. Було б чудово мати доменне ім'я, яке було б коротким і легко запам'ятовувалось, чи не так? - -У поточному розділі ми навчимо вас як купувати домен і направити його на Heroku! - -## Де зареєструвати домен? - -Звичайний домен коштує близько $15 на рік. Існують дешевші і дорожчі варіанти, в залежності від провайдера. Є багато компаній, у яких ви можете придбати домен: простий [google search][1] дасть вам сотні варіантів. - - [1]: https://www.google.com/search?q=register%20domain - -Наш найулюбленіший -- [I want my name][2]. Вони рекламують себе як "безболісне управління доменом", і це насправді безболісно. - - [2]: https://iwantmyname.com/ - -## Як зареєструвати домен на IWantMyName? - -Зайдіть на [iwantmyname][3] і наберіть домен, який би ви хотіли мати в рядку пошуку. - - [3]: http://iwantmyname.com - -![](images/1.png) - -Після чого має з'явитися список усіх доступних доменів зі словом, яке ви набрали в рядку пошуку. Як бачимо, усміхнене обличчя свідчить про те, що домен є доступним для купівлі, а сумне обличчя про те, що домен вже зайнятий. - -![](images/2.png) - -Ми вирішили купити `djangogirls.in`: - -![](images/3.png) - -Давайте перевіримо. Ви повинні зареєструватись на iwantmyname, якщо ще досі цього не зробили. Після цього, надайте інформацію про вашу розрахункову картку і можете купувати домен! - -Далі, натисніть `Domains` в меню і оберіть щойно придбаний домен. Далі клікніть на посилання `manage DNS records`: - -![](images/4.png) - -Тепер вам потрібно знайти цю форму: - -![](images/5.png) - -І заповнити її наступними деталями: - Hostname: www - Type: CNAME - Value: ваш домен на Heroku (наприклад, djangogirls.herokuapp.com) - TTL: 3600 - -![](images/6.png) - -Натисніть кнопки Додати і Зберегти внизу. - -Процес активації вашого домену може зайняти до пари годин, отже будьте терплячими! - -## Нлаштування домену на Heroku - -Ви також повинні повідомити Heroku, що хочете використовувати ваш замовлений домен. - -Зайдіть на [Heroku Dashboard][10], залогіньтесь і оберіть ваш додаток. Далі перейдіть до налаштувань вашого додатку (пункт меню - Settings), вкажіть ваш домен у розділі `Domains` і збережіть зміни. - - [10]: https://dashboard.heroku.com/apps - -Ось і все! \ No newline at end of file diff --git a/uk/domain/images/1.png b/uk/domain/images/1.png deleted file mode 100644 index 97a06e28f2a..00000000000 Binary files a/uk/domain/images/1.png and /dev/null differ diff --git a/uk/domain/images/2.png b/uk/domain/images/2.png deleted file mode 100644 index 604fd5b02c8..00000000000 Binary files a/uk/domain/images/2.png and /dev/null differ diff --git a/uk/domain/images/3.png b/uk/domain/images/3.png deleted file mode 100644 index c941c0d231d..00000000000 Binary files a/uk/domain/images/3.png and /dev/null differ diff --git a/uk/domain/images/4.png b/uk/domain/images/4.png deleted file mode 100644 index dcbe145b271..00000000000 Binary files a/uk/domain/images/4.png and /dev/null differ diff --git a/uk/domain/images/5.png b/uk/domain/images/5.png deleted file mode 100644 index 778765053e5..00000000000 Binary files a/uk/domain/images/5.png and /dev/null differ diff --git a/uk/domain/images/6.png b/uk/domain/images/6.png deleted file mode 100644 index 52a0bb87c4c..00000000000 Binary files a/uk/domain/images/6.png and /dev/null differ diff --git a/uk/dynamic_data_in_templates/README.md b/uk/dynamic_data_in_templates/README.md index 95d308359c3..077e02e353d 100755 --- a/uk/dynamic_data_in_templates/README.md +++ b/uk/dynamic_data_in_templates/README.md @@ -1,4 +1,4 @@ -# Django Querysets +# Динамічні дані в шаблонах Маємо різні шматочки на своїх місцях: модель `Post` визначено в `models.py`, маємо `post_list` у `views.py`, а також відповідний шаблон. Однак, яким чином ми змусимо наші пости з'явитися в HTML шаблоні? Оскільки це те, чого ми хочемо: взяти деякий контент (моделі збережені в базі даних) і вивести його в гарному вигляді на нашому шаблоні, правда ж? @@ -8,61 +8,65 @@ Нам треба відкрити наш `blog/views.py`. Таким чином, відображення `post_list` виглядає на кшталт: - from django.shortcuts import render - - def post_list(request): - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render -Пам'ятаєте як ми говорили про включення коду написаного в різних файлах? Тепер настав момент, коли ми повинні включити модель написану в `models.py`. Додаймо рядок `from .models import Post`: +def post_list(request): + return render(request, 'blog/post_list.html', {}) +``` - from django.shortcuts import render - from .models import Post - +Пам'ятаєте, як ми говорили про включення коду написаного в різних файлах? Тепер настав момент, коли ми повинні включити модель написану в `models.py`. Додаймо рядок `from .models import Post`: + +```python +from django.shortcuts import render +from .models import Post +``` Крапка після `from` означає *поточна директорія* або *поточний додаток*. Оскільки `views.py` і `models.py` розташовані в одній і тій же папці, можемо просто використовувати `.` і ім'я файлу (без `.py`). Далі імпортуємо ім'я моделі (`Post`). -А що далі? Щоб вилучити реальні пости з моделі `Post` нам потрібно певна річ, що називається `QuerySet`. +А що далі? Щоб вилучити реальні пости з моделі `Post`, нам потрібна певна річ, що називається `QuerySet`. ## QuerySet -Ви маєте вже бути ознайомлені із роботою QuerySets. Ми говорили про це у розділі [Django ORM (QuerySets)][1]. - - [1]: ../django_orm/README.md +Ви маєте вже бути ознайомлені із роботою QuerySets. Ми говорили про це у розділі [Django ORM (QuerySets)](../django_orm/README.md). Отже, наразі ми зацікавлені у списку опублікованих і відсортованих за параметром `published_date` блог постів, чи не так? Ми вже робили це у розділі QuerySets! Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - А тепер вставимо цей шматок коду у файл `blog/views.py` додавши його до функції `def post_list(request)`: - from django.shortcuts import render - from django.utils import timezone - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - return render(request, 'blog/post_list.html', {}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) +``` Зазначте, будь ласка, що ми створюємо *змінну* для нашого QuerySet: `posts`. Сприймайте її як ім'я для QuerySet. З цього моменту ми можемо посилатися на неї через це ім'я. -Остання пропущена частина - передача QuerySet `posts` шаблону (розглянемо як це вивести в наступному розділі). +Крім того, код використовує функцію `timezone.now()`, а значить, ми повинні імпортувати `timezone`. -У функції `render` ми вже маємо параметр `request` (тобто усе, що ми отримуємо від користувача через Інтернет) і файл шаблону `'blog/post_list.html'`. Останній параметр, котрий виглядає як: `{}` - це місце, в якому ми можемо додавати певні речі для використання у шаблоні. Ми повинні дати їм імена (ми обмежились ім'ям `'posts'` наразі :)). Це має виглядати як: `{'posts': posts}`. Зауважте, будь ласка, що частина перед `:` береться в лапки `''`. +Остання пропущена частина - передача QuerySet `posts` шаблону (розглянемо, як це вивести в наступному розділі). + +У функції `render` ми вже маємо параметр `request` (тобто усе, що ми отримуємо від користувача через Інтернет) і файл шаблону `'blog/post_list.html'`. Останній параметр, котрий виглядає як: `{}` - це місце, в якому ми можемо додавати певні речі для використання у шаблоні. Ми повинні дати їм імена (ми обмежились ім'ям `'posts'` наразі :)). Це має виглядати як: `{'posts': posts}`. Прохання звернути увагу, що частина перед `:` є рядком; вам необхідно взяти це у лапки `''`. Отже, врешті-решт наш файл `blog/views.py` матиме наступний вигляд: - from django.shortcuts import render - from django.utils import timezone - from .models import Post - - def post_list(request): - posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') - return render(request, 'blog/post_list.html', {'posts': posts}) - +```python +from django.shortcuts import render +from django.utils import timezone +from .models import Post + +def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) +``` Це все! Час повернутись назад до нашого шаблону і вивести QuerySet! -Якщо бажаєте дізнатись трохи більше про QuerySets в Django, зазирніть сюди: https://docs.djangoproject.com/en/1.8/ref/models/querysets/ +Якщо бажаєте дізнатись трохи більше про QuerySets в Django, зазирніть сюди: https://docs.djangoproject.com/en/1.9/ref/models/querysets/ + diff --git a/uk/extend_your_application/README.md b/uk/extend_your_application/README.md index a27eed82f4a..a052ace1398 100755 --- a/uk/extend_your_application/README.md +++ b/uk/extend_your_application/README.md @@ -1,17 +1,16 @@ -# Розширте ваш додаток +# Розширте свою програму -Ми вже завершили усі кроки необхідні для створення нашого сайту: знаємо як написати модель, url, відображення та шаблон. А також знаємо про те, як зробити наш сайт гарнішим. +Ми вже завершили усі кроки, необхідні для створення нашого сайту: знаємо як написати модель, url, відображення та шаблон. А також знаємо про те, як зробити наш сайт гарнішим. Час попрактикуватись! Перша потрібна для нашого блогу річ це, очевидно, сторінка для відображення одного посту, чи не так? -У нас вже є модель `Post`, отже не треба нічого додавати до `models.py`. +У нас вже є модель `Post`, отже? не треба нічого додавати до `models.py`. -## Створимо посилання в шаблоні +## Створюємо в шаблоні посилання на сторінку посту Почнемо із додавання посилання в `blog/templates/blog/post_list.html`. Таким чином, матимемо: - ```html {% extends 'blog/base.html' %} @@ -22,101 +21,103 @@ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} {% endblock content %} + ``` - -Ми хочемо мати посилання на сторінку із деталями про окремий пост, яке міститиметься в заголовку поста. Змінимо `

{{ post.title }}

` на посилання: +{% raw %}Ми хочемо, щоб в списку постів заголовок посилався на сторінку детальної інформації про пост. Давайте змінимо `

{{ post.title }}

` так, щоб вийшло посилання на пост:{% endraw %} ```html -

{{ post.title }}

+

{{ post.title }}

``` - -Час пояснити містичне `{% url 'blog.views.post_detail' pk=post.pk %}`. Як можна було очікувати, `{% %}` означає, що ми використовуємо шаблонні теги Django. Цього разу скористаємось таким, що створить для нас URL! +{% raw %}Саме час пояснити цей дивний запис `{% url 'post_detail' pk=post.pk %}`. Як можна було очікувати, `{% %}` означає, що ми використовуємо шаблонні теги Django. Цього разу ми використаєм один з них, який створить URL для нас!{% endraw %} -`blog.views.post_detail` - це шлях до відображення `post_detail`, яке ми бажаємо створити. Зауважте, будь ласка: `blog` -- це ім'я нашого додатку (папка `blog`), `views` взято з імені файлу `views.py` і остання частина - `post_detail` - це ім'я відображення. +`blog.views.post_detail` - це шлях до відображення `post_detail`, яке ми бажаємо створити. Зауважте, будь ласка, що: `blog` - це ім'я нашого додатку (папка `blog`), `views` взято з імені файлу `views.py` і остання частина - `post_detail` - це ім'я відображення. -Тепер коли ми зайдемо на: http://127.0.0.1:8000/ то отримаємо помилку (як і очікувалось, оскільки у нас немає URL або відображення для `post_detail`). Це буде виглядати як: +Тепер, коли перейдемо на: http://127.0.0.1:8000/, отримаємо помилку (як і очікувалось, оскільки у нас немає URL або потрібного *вигляду* (в'ю) для `post_detail`). Він буде виглядати наступним чином: ![NoReverseMatch error](images/no_reverse_match2.png) +## Створюєм адресу URL для деталей запису + Давайте створимо URL в `urls.py` для нашого відображення `post_detail`! -### URL: http://127.0.0.1:8000/post/1/ +Ми хочемо, щоб наш перший пост був доступний за такою **URL-адресою**: http://127.0.0.1:8000/post/1/ -Ми бажаємо створити URL щоб направляти Django до відображення, що називається `post_detail`, що в свою чергу має відобразити введений пост. Додамо рядок `url(r'^post/(?P[0-9]+)/$', views.post_detail),` у файл `blog/urls.py`. Це буде виглядати наступним чином: +У файлі `blog/urls.py` вкажемо Django, де взяти відображення для запису блогу, яке називається `post_detail`. Додамо рядок `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),`у файл `blog/urls.py`. Це має виглядати якось так: - from django.conf.urls import include, url - from . import views - - urlpatterns = [ - url(r'^$', views.post_list), - url(r'^post/(?P[0-9]+)/$', views.post_detail), - ] - +```python +from django.conf.urls import url +from . import views -Виглядає жахливо, але не хвилюйтесь - ми пояснимо вам: - усе починається із `^` знову -- "початок" - `post/` лише означає, що після початку, URL має містити слово **post** і **/**. Все йде добре. - `(?P[0-9]+)` - ця частина хитріша. Це означає, що Django візьме усе, що ви тут розмістите і передасть це до відображення як змінну із ім'ям `pk`. `[0-9]` також повідомляє нас про те, що це може бути лише цифрою, не літерою (будь-яке значення між 0 та 9). `+` означає, що тут має бути один або більше символів. Таким чином, щось на зразок `http://127.0.0.1:8000/post//` є неприйнятним, однак `http://127.0.0.1:8000/post/1234567890/` цілком! - `/` - далі нам потрібно знову**/** - `$` - "кінець"! +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` -Це означає, що якщо ви введете http://127.0.0.1:8000/post/5/, Django зрозуміє, що ви шукаєте відображення із назвою `post_detail` і передає цьому відображенню інформацію, що `pk` дорівнює `5`. +Ця частина `^post/(?P[0-9]+)/$` виглядає страшно, але не хвилюйтеся - зараз ми все пояснимо: +- вона починається з `^` - цей символ означає "початок", +- далі `post/` означає, що після початку, URL-адреса має містити слова **post** та **/**. Все йде добре. +- `(?P[0-9]+)` - ця частина хитріша. Вона означає, що Django візьме усе, що ви тут розмістите і передасть це до відображення як змінну із ім'ям `pk`. `[0-9]` також повідомляє нам про те, що це може бути лише цифрою, а не літерою (будь-яке значення між 0 та 9). `+` означає, що тут має бути один або більше символів. Таким чином, щось на зразок `http://127.0.0.1:8000/post//` є неприйнятним, однак `http://127.0.0.1:8000/post/1234567890/` цілком! +- `/` - далі нам потрібно знову __/__ +- `$` - "кінець"! -`pk` -- скорочення для первинного ключа - `primary key`. Це ім'я часто використовується в Django проектах. Однак, можете назвати вашу змінну як вам до вподоби (пам'ятайте: маленькі літери і `_` замість пробілів!). Наприклад, замість `(?P[0-9]+)` можемо мати змінну `post_id`, і, таким чином, ця частина буде виглядати як: `(?P[0-9]+)`. +Це означає, що якщо введете `http://127.0.0.1:8000/post/5/`, Django зрозуміє, що ви шукаєте відображення із назвою `post_detail` і передає цьому відображенню інформацію, що `pk` дорівнює `5`. -Гаразд! Давайте перезавантажимо сторінку: http://127.0.0.1:8000/ - +`pk` - скорочення для первинного ключа - `primary key`. Це ім'я часто використовується в Django проектах. Однак, можете назвати вашу змінну як вам до вподоби (пам'ятайте: маленькі літери і `_` замість пробілів!). Наприклад, замість `(?P[0-9]+)` можемо мати змінну `post_id`, і, таким чином, ця частина буде виглядати як: `(?P[0-9]+)`. -Бум! Ще одна помилка! Як і варто було очікувати! +Добре, ми додали новий шаблон URL для `blog/urls.py`! Давайте перезавантажимо сторінку: http://127.0.0.1:8000/ Опаньки! Знову помилка! Як ми і очікували. ![AttributeError](images/attribute_error2.png) -Пам'ятаєте яким є наступний крок? Звісно: треба додати відображення! +Пам'ятаєте наступний крок? Звісно: треба додати відображення! -## post_detail view +## Додамо деталі для відображення запису -Цього разу наше відображення отримує ще додатковий параметр - `pk`. Наше відображення має вилучити його, правда ж? Отже, визначимо нашу функцію як `def post_detail(request, pk):`. Зауважте, що треба використовувати точно таке ж ім'я як ми визначили в urls (`pk`). Неправильно нехтувати цією змінною, це призведе до помилки! +Цього разу наше відображення отримує додатковий параметр - `pk`. Наше відображення має вилучити його, правда ж? Отже, визначимо нашу функцію як `def post_detail(request, pk):`. Зауважте, що треба використовувати точно таке ж ім'я, як ми визначили в urls (`pk`). Неправильно нехтувати цією змінною, це призведе до помилки! -А тепер, ми би хотіли додати один-єдиний пост. Щоб зробити це можемо скористатися наступним запитом до бази даних: +А тепер, ми хотіли б додати один-єдиний пост. Щоб зробити, це можемо скористатися наступним запитом до бази даних: Post.objects.get(pk=pk) - -Однак, цей код містить проблеми. Якщо немає жодного поста із заданим первинним ключем (`pk`), ми отримаємо мега жахливу помилку! +Однак, цей код містить проблеми. Якщо немає жодного поста із заданим первинним ключем (`pk`), ми отримаємо мегажахливу помилку! ![DoesNotExist error](images/does_not_exist2.png) -Ми цього не хочемо! Але, звичайно, Django надає деякі інструменти, що будуть обробляти це для нас: `get_object_or_404`. У випадку, якщо немає постів із заданим `pk`, виведеться більш приємна сторінка (так звана сторінка `Page Not Found 404`). +Ми цього не хочемо! Звичайно, Django надає деякі інструменти, що будуть обробляти це для нас: `get_object_or_404`. У випадку, якщо немає постів із заданим `pk`, виведеться більш приємна сторінка (так звана сторінка `Page Not Found 404`). ![Page not found](images/404_2.png) -Хороші новини полягають в тому, що можна створити свою власну сторінку `Page not found` і зробити її настільки гарною, наскільки ви захочете. Однак, це не є надто важливим на даний момент, отже, пропустимо цей крок. +Хороші новини полягають в тому, що можна створити свою власну сторінку `Page not found` і зробити її настільки гарною, наскільки ви захочете. Однак, це не є надто важливим на даний момент, тому пропустимо цей крок. Добре, час додати відображення у наш файл `views.py`! Нам треба відкрити `blog/views.py` і додати наступний код: from django.shortcuts import render, get_object_or_404 - -Поряд із іншими рядками `from`. А вкінці файлу додаймо наше відображення: +Поряд із іншими рядками `from`. А в кінці файлу додамо наше відображення: def post_detail(request, pk): post = get_object_or_404(Post, pk=pk) return render(request, 'blog/post_detail.html', {'post': post}) - -Так. Настав час перезавантажити нашу сторінку: http://127.0.0.1:8000/ - +Так. Прийшла пора оновити сторінку: http://127.0.0.1:8000 / ![Post list view](images/post_list2.png) -Спрацювало! Але що ж трапиться коли ви клікните на посилання в заголовку поста? +Спрацювало! Але що ж трапиться, коли ви натиснете на посилання в заголовку поста? ![TemplateDoesNotExist error](images/template_does_not_exist2.png) -О ні! Інша помилка! Але ж ми вже знаємо як із цим поводитись, чи не так? Потрібно додати шаблон! +О, ні! Інша помилка! Але ж ми вже знаємо, як із цим поводитись, чи не так? Потрібно додати шаблон! + +## Створюємо шаблон для деталей запису Створимо файл в `blog/templates/blog` і назвемо його `post_detail.html`. @@ -126,22 +127,23 @@ {% extends 'blog/base.html' %} {% block content %} - {% if post.published_date %} -
- {{ post.published_date }} -
- {% endif %} -

{{ post.title }}

-

{{ post.text|linebreaks }}

+
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
{% endblock %} ``` - -Знову розширюємо `base.html`. Всередині блоку `content` ми хотіли б відобразити такі параметри як: published_date (якщо існує), title і text. Але, мусимо обговорити певні важливі речі, правда ж? +Знову розширюємо `base.html`. Всередині блоку `content` ми хотіли б відобразити такі параметри як: published_date (якщо існує), title і text. Але мусимо обговорити певні важливі речі, правда ж? -`{% if ... %} ... {% endif %}` -- це шаблонний тег, який можна використовувати, коли ми бажаємо перевірити дещо (пам'ятаєте `if ... else ..` з розділу **Вступ до Python**?). В цьому сценарії ми хотіли б дізнатися чи параметр `published_date` не пустий. +{% raw %}`{% if ... %} ... {% endif %}` - це шаблонний тег, який можна використовувати, коли ми бажаємо перевірити дещо (пам'ятаєте `if ... else ..` з розділу __Вступ до Python__?). У цьому випадку ми хочемо перевірити, чи дата запису `published_date` не порожня.{% endraw %} -Ok, можемо перезавантажити нашу сторінку і побачити чи `Page not found` зникло тепер. +Окей, можемо перезавантажити нашу сторінку і побачити, чи повідомлення `Page not found` тепер зникло. ![Post detail page](images/post_detail2.png) @@ -149,18 +151,27 @@ Ok, можемо перезавантажити нашу сторінку і п ## Ще одне: розгортання! -Було б непогано побачити чи ваш сайт все ще працює на Heroku, чи не так? Давайте спробуємо розгорнути його знову. Якщо ви вже забули як це зробити, зверніться до кінцевої частини розділу [Розгортання](../deploy/README.md): +Було б добре переконатись, що ваш сайт буде працювати на PythonAnywhere, вірно? Спробуймо зробити розгортання ще раз. -```bash +``` $ git status -... -$ git add -A . +$ git add --all . $ git status -... -$ git commit -m "Added more views to the website." -... -$ git push heroku master +$ git commit -m "Added view and template for detailed blog post as well as CSS for the site." +$ git push ``` - + +* Тоді в [Bash консолі PythonAnywhere](https://www.pythonanywhere.com/consoles/): + +``` +$ cd my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +* Нарешті, перейдіть на [вкладку Web](https://www.pythonanywhere.com/web_app_setup/) і натисніть **Reload**. І це все! Вітання :) diff --git a/uk/extend_your_application/images/no_reverse_match2.png b/uk/extend_your_application/images/no_reverse_match2.png index db65a5dc70a..306926206f8 100644 Binary files a/uk/extend_your_application/images/no_reverse_match2.png and b/uk/extend_your_application/images/no_reverse_match2.png differ diff --git a/uk/how_the_internet_works/README.md b/uk/how_the_internet_works/README.md old mode 100755 new mode 100644 index bc3b212dbd9..61cc68f8363 --- a/uk/how_the_internet_works/README.md +++ b/uk/how_the_internet_works/README.md @@ -2,44 +2,47 @@ > На створення цього розділу нас надихнула розмова "Як працює Інтернет" Джесіки Маккеллар (http://web.mit.edu/jesstess/www/). -Б'ємось об заклад, ви використовуєте Інтернет кожного дня. Однак, чи знаєте ви насправді, що трапляється коли ви набираєте адресу на зразок http://djangogirls.org у вашому браузері та натискаєте `enter`? +Б'ємось об заклад, ви використовуєте Інтернет кожного дня. Однак, чи знаєте ви насправді, що трапляється, коли ви набираєте адресу на зразок https://djangogirls.org у браузері та натискаєте `enter`? -Перша річ, яку вам необхідно зрозуміти це те, що веб сайт є лише набором файлів на жорсткому диску. Просто як фільми, музика або зображення. Проте, є одна річ унікальна для веб сайтів: вони включають комп'ютерний код, що називається HTML. +Перша річ, яку вам необхідно зрозуміти - це те, що веб-сайт є лише набором файлів на жорсткому диску. Просто як фільми, музика або зображення. +Проте, є одна унікальна річ для веб-сайтів: вони містять комп'ютерний код, що називається HTML. -Якщо ви не знайомі із програмуванням, спочатку може бути складно вловити що таке HTML, але ваші веб браузери (такі як Chrome, Safari, Firefox, тощо) люблять це. Веб браузери розроблені спеціальним чином, щоб розуміти цей код, слідувати його інструкціям і представляти усі файли, з яких створений ваш веб сайт точно в такому вигляді, як ви того забажаєте. +Якщо ви не знайомі із програмуванням, спочатку може бути складно зрозуміти, що таке HTML, але веб-браузери (такі як Chrome, Safari, Firefox тощо) його люблять. +Веб-браузери розроблені спеціально, щоб розуміти цей код, виконувати його інструкції та показувати файли, з якого складається ваш сайт, саме так, як ви того забажаєте. -Як і з кожним файлом, нам потрібно зберігати HTML файли в певному місці на жорсткому диску. Для Інтернету, ми використовуємо спеціальні, потужні комп'ютери, що називаються *серверами*. Вони не мають екрану, мишки чи клавіатури, тому що їхня основна ціль -- зберігати і обробляти дані. Саме тому ці комп'ютерами назвали *серверами*, тому що вони обробляють (англ. to *serve* - обробляти) ваші дані. +Як і звичайні файли, нам потрібно зберігати HTML-файли в певному місці на жорсткому диску. В Інтернеті ми використовуємо спеціальні потужні комп'ютери, що називаються *серверами*. +Вони не мають екрану, мишки чи клавіатури, тому що їхня основна ціль - зберігати і обробляти дані. Саме тому ці комп'ютери назвали *серверами*, вони обробляють (англ. to *serve* - обробляти) ваші дані. -OK, але ж ви хочете дізнатися як виглядає Інтернет, чи не так? +Гаразд, але ж ви хочете дізнатися як виглядає Інтернет, чи не так? Ми намалювали для вас картинку! Вона виглядає наступним чином: -![Figure 1.1](images/internet_1.png) +![Рисунок 1.1](images/internet_1.png) -Виглядає як суцільний безлад, чи не так? Фактично, це мережа з'єднаних машин (вище зазначених *серверів*). Сотні тисяч машин! Багато-багато кілометрів кабелю по усьому світу! Можете відвідати веб сайт Submarine Cable Map (http://submarinecablemap.com/), щоб побачити, наскільки складною є мережа. Тут наведено скріншот з веб-сайту: +Суцільний безлад, правильно? Фактично, це мережа з'єднаних машин (вище зазначених *серверів*). Сотні тисяч машин! Багато-багато кілометрів кабелю по усьому світу! Можете відвідати веб-сайт Submarine Cable Map (http://submarinecablemap.com/), щоб побачити, наскільки складною є мережа. Тут наведено знімок з веб-сайту: -![Figure 1.2](images/internet_3.png) +![Рисунок 1.2](images/internet_3.png) -Вражаюче, чи не так? Але однозначно, неможливо мати проводи між кожною машиною підключеною до Інтернету. Отже, щоб досягти машини (наприклад, ту на якій збережено http://djangogirls.org), ми повинні передати запит через багато-багато різних машин. +Вражаюче, чи не так? Але однозначно, неможливо мати проводи між кожною машиною, підключеною до Інтернету. Отже, щоб досягти машини (наприклад, ту на якій збережено https://djangogirls.org), ми повинні передати запит через багато-багато різних машин. Це виглядатиме так: -![Figure 1.3](images/internet_2.png) +![Рисунок 1.3](images/internet_2.png) -Уявіть, що коли ви набираєте http://djangogirls.org, ви відправляєте листа, що говорить: "Шановні Django Girls, я хочу побачити веб сайт djangogirls.org. Відправте мені його, будь ласка!" +Уявіть, що коли ви набираєте https://djangogirls.org, ви відправляєте листа, що говорить: "Шановні Django Girls, я хочу побачити веб-сайт djangogirls.org. Відправте мені його, будь ласка!" -Ваш лист надійде до найближчого поштового віділення. Далі він надходить до іншого, що знаходиться трохи ближче до вашого адресата, далі до іншого і так далі поки не буде досягнуто остаточного пункту призначення. Єдина унікальна річ це те, що ви відправляєте листи (*пакетні дані*) часто в одне й те ж місце, і кожен лист може проходити загалом через різні поштові відділення (*роутери*), в залежності яким чином вони розподіляються в кожному відділенні. +Ваш лист надійде до найближчого поштового віділення. Далі він надходить до іншого, що знаходиться трохи ближче до вашого адресата, далі до іншого і так далі, поки не буде досягнуто остаточного пункту призначення. Єдина відмінність в тому, що при відправці багатьох листів (*пакетів даних*) в однакове місце, кожен з них може піти через абсолютно різні поштові відділення (*маршрутизатори*). Це залежить від того, як їх розподілили в кожному відділенні. -![Figure 1.4](images/internet_4.png) +![Рисунок 1.4](images/internet_4.png) Так, це так само просто. Ви відправляєте повідомлення і очікуєте певної відповіді. Звісно, замість паперу і ручки ви використовуєте байти даних, але ідея та сама! -Замість адрес із назвами вулиці, міста, індексом і назвою країни, ми використовуємо IP адреси. Ваш комп'ютер спочатку запитує про DNS (англ. Domain Name System - Система доменних імен) для переводу djangogirls.org в IP адресу. Це працює трохи подібно до старомодних телефонних записників, де ви могли б знайти ім'я особи, з якою бажаєте зв'язатися і знайти її номер телефону та адресу. +Замість адрес із назвами вулиці, міста, індексом і назвою країни, ми використовуємо IP адреси. Ваш комп'ютер спочатку запитує про DNS (англ. Domain Name System - система доменних імен) для переводу djangogirls.org в IP-адресу. Це працює подібно до старомодних телефонних довідників, де ви могли б знайти ім'я особи, з якою бажаєте зв'язатися і знайти її номер телефону та адресу. -Коли ви відправляєте листа, це потребує наявності певних властивостей для коректної доставки: адреса, штамп тощо. Також ви використовуєте мову, котру розуміє отримувач, правда ж? Те ж саме із *пакетними даними*, котрі ви відправляєте, щоб побачити веб сайт: використовується протокол, що називається HTTP (англ. Hypertext Transfer Protocol - протокол передачі гіпертексту). +Коли ви відправляєте листа, це потребує наявності певних речей для коректної доставки: адреса, штамп тощо. Також ви використовуєте мову, котру розуміє отримувач, правда ж? Те ж саме стосується і *пакетів даних*, які ви відправляєте, щоб побачити веб-сайт. Ми використовуємо протокол, який називається HTTP (англ. Hypertext Transfer Protocol, протокол передачі гіпер-текстових документів). -Отже, по суті, коли у вас є веб сайт вам треба мати *сервер* (машину), де він житиме. *Сервер* очікує на вхідні *запити* (листи, котрі просять сервер відправити ваш веб сайт) і відправляє у відповідь ваш веб сайт (у іншому листі). +Отже, по суті, коли у вас є веб-сайт, вам треба мати *сервер* (машину), де він житиме. Коли *сервер* отримує вхідний *запит* (в листі), він відправляє назад ваш веб-сайт (в іншому листі). -Оскільки це є навчальний посібник з Django, ви запитаєте що ж робить Django. Коли ви відправляєте відповідь, то не завжди бажаєте відправляти одне й те саме кожному. Набагато краще якщо ваші листи є персоналізованими, особливо для осіб, які щойно вам написали, правда ж? Django допомагає вам зі створенням цих персоналізованих, цікавих листів :). +Оскільки ви читаєте навчальний посібник з Django, ви запитаєте, що ж робить Django. Коли ви відправляєте відповідь, то не завжди бажаєте відправляти одне й те саме кожному. Набагато краще, якщо ваші листи є персоналізованими, особливо для осіб, які щойно вам написали, еге ж? Django допомагає вам зі створенням цих персоналізованих цікавих листів :). Досить розмов, час творити! diff --git a/uk/how_the_internet_works/images/internet_4.png b/uk/how_the_internet_works/images/internet_4.png index 05f1aed562f..2661cec1b61 100644 Binary files a/uk/how_the_internet_works/images/internet_4.png and b/uk/how_the_internet_works/images/internet_4.png differ diff --git a/uk/html/README.md b/uk/html/README.md old mode 100755 new mode 100644 index a9b91f044c1..ab871101e16 --- a/uk/html/README.md +++ b/uk/html/README.md @@ -2,15 +2,15 @@ Ви можете запитати, що таке шаблон? -Шаблон -- це файл, який ми можемо повторно використовувати для представлення різноманітної інформації в послідовному форматі. Наприклад, ви можете використовувати шаблон для допомоги у написанні листа, бо, хоча кожен лист може містити різне повідомлення та бути адресованим різним особам, усі листи поширюватимуться у однаковому форматі. +Шаблон - це файл, який ми можемо повторно використовувати для представлення різноманітної інформації в послідовному форматі. Наприклад, ви можете використовувати шаблон для допомоги у написанні листа, бо, хоча кожен лист може містити різне повідомлення та бути адресованим різним особам, усі листи поширюватимуться у однаковому форматі. Формат Django шаблону описаний мовою, що називається HTML (це HTML, зазначений у першому розділі **Як працює Інтернет**). ## Що таке HTML? -HTML -- це простий код, що інтерпретується вашим веб браузером ( таким як Chrome, Firefox чи Safari) для відображення веб сторінки для користувача. +HTML - це простий код, що інтерпретується вашим веб браузером (таким як Chrome, Firefox чи Safari) для відображення веб сторінки для користувача. -HTML відповідає "HyperText Markup Language" (з англ мова розмітки гіпертексту). **HyperText** (гіпертекст) -- це тип тексту, що підтримує гіперпосилання між сторінками. **Markup** (розмітка) означає, що ми отримали документ із розміченим кодом для того, щоб повідомити дещо (у даному випадку, браузер) як треба інтерпретувати сторінку. HTML код побудований за допомогою **тегів**, кожен з яких починається із `<` і закінчується `>`. Ці теги розмічують **елементи**. +HTML розшифровується як "Мова розмітки гіпертексту". __Гіпертекст__ означає тип тексту, який підтримує гіперпосилання між сторінками. __Розмітка__ (англ. markup) означає, що ми отримали документ із розміченим кодом для того, щоб повідомити комусь (у даному випадку, браузеру) як треба інтерпретувати сторінку. HTML код побудований за допомогою __тегів__, кожен з яких починається із `<` і закінчується на `>`. Теги представляють __елементи розмітки__. ## Ваш перший шаблон! @@ -21,156 +21,174 @@ HTML відповідає "HyperText Markup Language" (з англ мова ро blog └───templates └───blog - (Вас може здивувати, для чого нам потрібно дві папки із однаковим ім'ям `blog` - як виявиться пізніше, це всього лише зручне узгодженість із найменування, котра спрощує життя, коли речі починають ускладнюватися.) -А тепер створіть файл `post_list.html` (просто залиште його поки що пустим) всередині папки `blog/templates/blog`. +А тепер створіть файл `post_list.html` (просто залиште його поки що порожнім) всередині папки `blog/templates/blog`. -Погляньте як тепер виглядає ваш веб сайт: http://127.0.0.1:8000/ +Погляньте, як тепер виглядає ваш веб сайт: http://127.0.0.1:8000/ -> Якщо помилка `TemplateDoesNotExists` досі не зникла, спробуйте перезапустити ваш сервер. Перейдіть до командного рядка, зупиніть сервер натиснувши Ctrl+C (кнопки Control і C разом) і активуйте його знову запустивши команду `python manage.py runserver`. +> Якщо помилка `TemplateDoesNotExists` досі не зникла, спробуйте перезапустити ваш сервер. Перейдіть до командного рядка, зупиніть сервер, натиснувши Ctrl+C (клавіші Control і C разом) та активуйте його знову, запустивши команду `python manage.py runserver`. -![Figure 11.1](images/step1.png) +![Рисунок 11.1](images/step1.png) Більше ніяких помилок! Вітання :) Однак, ваш сайт насправді не публікує нічого, окрім пустої сторінки, оскільки ваш шаблон також пустий. Ми маємо це виправити. Додайте наступне у ваш файл шаблону: - -

Hi there!

-

It works!

- - +```html + +

Hi there!

+

It works!

+ +``` -То як тепер виглядає ваш веб сайт? Натисніть щоб з'ясувати: http://127.0.0.1:8000/ +То як тепер виглядає ваш веб-сайт? Натисніть, щоб з'ясувати: http://127.0.0.1:8000/ -![Figure 11.2](images/step3.png) +![Рисунок 11.2](images/step3.png) Спрацювало! Гарна робота :) -* Самий основний тег, ``, завжди є початком будь-якої веб сторінки і `` - завжди є кінцем. Як бачите, увесь контент сайту розміщений між початковим тегом `` і закриваючим тегом `` -* `

` - тег для елементів абзацу; `

` закриває кожен абзац +- Базовий тег `` завжди є початком будь-якої веб сторінки і `` - завжди є кінцем. Як бачите, увесь контент сайту розміщений між початковим тегом `` і закриваючим тегом ``. +- `

` - тег для елементів абзацу; `

` закриває кожен абзац. -## Head & body +## Голова і тіло (Head & body) -Кожну сторінку HTML також можна поділити на два елементи: **head** - (голова) і **body** - (тіло). +Кожну сторінку HTML також можна поділити на два елементи: __head__ - (голова) і __body__ - (тіло). -* **head** - елемент, що містить інформацію про документ, яка не відображається на екрані. +- __head__ - елемент, що містить інформацію про документ, яка не відображається на екрані. -* **body** - елемент, що містить усе інше, що відображається як частина веб сторінки. +- __body__ - елемент, що містить усе інше, що відображається як частина веб сторінки. -Ми використовуємо `` щоб повідомити браузер про конфігурацію сторінки, а `` щоб повідомити браузер, що у дійсності знаходиться на сторінці. +Ми використовуємо `` щоб повідомити браузер про конфігурацію сторінки, а ``, щоб повідомити браузер, що у дійсності знаходиться на сторінці. -Наприклад, ви можете розмістити заголовок веб сторінки всередині `` наступним чином: +Наприклад, ви можете розмістити заголовок веб-сторінки всередині `` наступним чином: - - - Ola's blog - - -

Hi there!

-

It works!

- - - +```html + + + Ola's blog + + +

Hi there!

+

It works!

+ + +``` Збережіть файл і перезавантажте вашу сторінку. -![Figure 11.3](images/step4.png) +![Рисунок 11.3](images/step4.png) -Зауважте як браузер зрозумів , що "Ola's blog" це заголовок вашої сторінки? Він інтерпретував `Ola's blog` і розмістив текст у рядку заголовка вашого браузера (він також буде використаний для закладок чи інших речей). +Зауважте, як браузер зрозумів , що "Ola's blog" - це заголовок вашої сторінки? Він інтерпретував `Ola's blog` і розмістив текст у рядку заголовка вашого браузера (він також буде використаний для закладок чи інших речей). -Можливо, ви також зауважили, що кожен відкриваючий тег відповідає *закриваючому тегу*, із `/`, і ці елементи є *вкладеними* (тобто ви не можете закрити окремий тег поки усі теги, що містяться всередині не будуть також закриті). +Можливо, ви також звернули увагу, що кожен відкриваючий тег відповідає *закриваючому тегу*, із `/`, і ці елементи є *вкладеними* (тобто ви не можете закрити окремий тег поки усі теги, що містяться всередині не будуть також закриті). Це щось на кшталт як покласти речі всередину ящиків. У вас є один великий ящик, ``; всередині цього ящика є ``, що містить ще менші ящики: `

`. -Ви повинні керуватися цими правилами *закриваючих* тегів, і *вкладених* елементів - якщо ви цього не робитимите, браузер може бути не в змозі інтерпретувати їх правильно і ваша сторінка буде відображуватись некоректно. +Ви повинні керуватися цими правилами _закриваючих_ тегів, і _вкладених_ елементів - якщо ви цього не робитимите, браузер може бути не в змозі інтерпретувати їх правильно і ваша сторінка буде відображатись некоректно. ## Налаштуйте ваш шаблон А тепер можете трохи побавитися і спробувати налаштувати ваш шаблон! Тут наведено декілька корисних тегів для цього: -* `

Заголовок

` - для найважливішого заголовка -* `

Підзаголовок

` для заголовків наступного рівня -* `

Підпідзаголовок

` ... і так далі, аж до `
` -* `текст` робить акцент на вашому тексті -* `текст` робить сильний акцент на вашому тексті -* `
` переходить на наступну лінію (ви не можете нічого розмістити всередині br) -* `link` створює посилання -* `
  • перший елемент
  • другий елемент
` створює список, такий як цей! -* `
` визначає блок сторінки +- `

Заголовок

` - для найважливішого заголовка +- `

Підзаголовок

` для заголовків наступного рівня +- `

Підпідзаголовок

` ... і так далі, аж до `
` +- `текст` робить акцент на вашому тексті +- `текст` робить сильний акцент на вашому тексті +- `
` переходить на наступну лінію (ви не можете нічого розмістити всередині br) +- `link` створює посилання +- `
  • перший елемент
  • другий елемент
` створює список, такий як цей! +- `
` визначає блок сторінки Тут наведено повний приклад шаблону: - - - Django Girls blog - - - - -
-

published: 14.06.2014, 12:14

-

My first post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

-
- -
-

published: 14.06.2014, 12:14

-

My second post

-

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

-
- - - +```html + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + +``` Тут було створено три блоки `div`. -* Перший `div` елемент містить заголовок нашого блог посту - а точніше, заголовок і посилання -* Два інших `div` елементи містять наші пости із датою публікації, `h2` із заголовком поста, який можна клікнути і два `p` (абзаци) тексту, один для дати, а інший для нашого блог посту. +- Перший `div` елемент містить заголовок нашого блогу - а точніше, заголовок і посилання +- Два інших `div` елементи містять наші пости із датою публікації, `h2` із заголовком поста, який можна клікнути і два `p` (абзаци) тексту, один для дати, а інший для нашого блог посту. Отримуємо наступний ефект: -![Figure 11.4](images/step6.png) +![Рисунок 11.4](images/step6.png) + +Йой! Але досі, наш шаблон лише незмінно відображає точно __таку ж інформацію__ - тоді як раніше йшлося про шаблони, що дозволяють нам відображувати __різну__ інформацію в __однаковому форматі__. -Йой! Але досі, наш шаблон лише незмінно відображає точно **таку ж інформацію** - тоді як раніше йшлося про шаблони, що дозволяють нам відображувати **різну** інформацію в **однаковому форматі**. +Що б ми дійсно хотіли зробити, так це відобразити реальні пости, додані в нашій панелі адміністратора Django - це те, до чого ми перейдемо далі. -Що б ми дійсно хотіли зробити, так це відобразити реальні пости, додані в нашому Django адміністраторі. І це те, до чого ми перейдемо далі. +## Ще одна річ: розгортання! -## Ще одне +Було б добре побачити все це в Інтернеті, правда? Давайте зробимо ще одне розгортання на PythonAnywhere: -Було б добре чи ваш сайт все ще працює на Heroku, правда ж? Спробуємо повторити процедуру розгортання знову. +### Фіксування (commit) і завантаження (push) коду на GitHub -Спершу, давайте подивимось які файли було модифіковано з часу нашого останнього розгортання: +По-перше, давайте подивимося, які файли були змінені після розгортання (виконайте ці команди локально, не на PythonAnywhere): $ git status - -Повідомимо `git` про те, що треба включити усі зміни з поточної папки: +Переконайтеся, що ви перебуваєте в директорії `djangogirls`, далі давайте скажемо для `git` включити всі зміни в рамках цього каталогу: - $ git add -A . - + $ git add --all . -> **Зауваження** `-A` (коротко усі - "all") означає, що `git` також розпізнає якщо раптом ви видалили файли (за замовчуванням, він розпізнає лише нові/змінені файли). Також пам'ятайте (з розділу 3), що `.` означає поточну директорію. +> __Зауваження__ `-A` (коротко усі - "all") означає, що `git` також розпізнає якщо раптом ви видалили файли (за замовчуванням, він розпізнає лише нові/змінені файли). Також пам'ятайте (з розділу 3), що `.` означає поточну директорію. Перед тим як завантажити усі файли, давайте перевіримо що ж буде завантажувати `git` (усі файли, які буде завантажувати `git` повинні тепер з'явитися і бути позначеними зеленим кольором): $ git status - Майже на місці, а тепер час повідомити йому про те, що треба зберегти ці зміни в його історії. Ми збираємося задати "commit message" що ж ми змінили. На цьому етапі можна набрати будь-що, що вважатимете за потрібне, однак, має сенс надрукувати щось дійсно зрозуміле, щоб, таким чином, ви могли згадати що ви зробили у майбутньому. $ git commit -m "Changed the HTML for the site." - -> **Зауваження** Переконайтеся, що ви використали подвійні лапки навколо повідомлення про здійснену фіксацію. +> __Зауваження__ Переконайтеся, що ви використали подвійні лапки навколо повідомлення про здійснену фіксацію. + +Після того, як ми це зробили, завантажимо (push) наші зміни до GitHub: + + git push + + +### Завантаження (pull) нового коду на PythonAnywhere і перезапуск веб-додатку + +* Відкрийте [сторінку з терміналами на PythonAnywhere](https://www.pythonanywhere.com/consoles/) і переключіться на вже запущений **Bash термінал** (або запустіть новий). Далі, наберіть команди: + +``` +$ cd ~/my-first-blog +$ source myvenv/bin/activate +(myvenv)$ git pull +[...] +(myvenv)$ python manage.py collectstatic +[...] +``` + +Подивіться, що ваш код почав завантажуватись. Якщо ви хочете перевірити успішність процедури, відкрийте вкладку **Files** і подивіться на свій код на PythonAnywhere. -По тому як ми це зробили, можна зрештою завантажити (push) наші зміни на веб сайт на heroku: - git push heroku master - +* Зрештою, переключіться на вкладку [Web](https://www.pythonanywhere.com/web_app_setup/) і натисніть **Reload**. -І цього має бути достатньо! По тому як Heroku завершить, ви можете перезавантажити ваш веб сайт в браузері. Зміни мають бути видимими! \ No newline at end of file +Оновлення повинні відобразитись на вашому веб-сайті! Переключись на нього і онови сторінку. Ви повинні побачити зміни :) diff --git a/uk/installation/README.md b/uk/installation/README.md new file mode 100644 index 00000000000..ae2cd0a743a --- /dev/null +++ b/uk/installation/README.md @@ -0,0 +1,48 @@ +# Якщо ви проходите цей підручник вдома + +Якщо ви проходите цей посібник вдома, а не на одному з [майстер-класів Django Girls](https://djangogirls.org/events/), ви можете повністю пропустити цей розділ і перейти до розділу [Як працює Інтернет?](../how_the_internet_works/README.md). + +Справа в тому, що ми все одно розглядаємо ці речі в посібнику, а цей розділ - лише додаткова сторінка, де зібрані разом всі інструкції по встановленню. Зустріч Django Girls включає в себе "Вечір налаштувань", коли ми встановлюємо все потрібне, щоб не витрачати на це час під час воркшопу, це дуже зручно для нас. + +Якщо ви вважаєте це корисним, можете пройти цей розділ також. Але якщо бажаєте почати вчитися без встановлення купи речей на ваш комп'ютер, пропустіть цей розділ і ми пояснимо як ставити програми пізніше. + +Успіхів! + +# Встановлення +На воркшопі ви будете створювати блог, і в посібнику є кілька підготовчих задач по встановленню, які було б добре виконати заздалегідь, так щоб на воркшопі ви були відразу готові програмувати. + +# Встановіть Python +{% include "/python_installation/instructions.md" %} + +# Налаштуйте virtualenv та встановіть Django +{% include "/django_installation/instructions.md" %} + +# Встановіть редактор коду +{% include "/code_editor/instructions.md" %} + +# Встановіть Git +{% include "/deploy/install_git.md" %} + +# Створіть аккаунт на GitHub +Зайдіть на [GitHub.com](https://www.github.com) і зареєструйте новий безкоштовний аккаунт користувача. + +# Створіть аккаунт на PythonAnywhere +{% include "/deploy/signup_pythonanywhere.md" %} + + +# Почніть читати + +Вітання, ви все зробили і готові йти вперед! Якщо ви все ще маєте час перед воркшопом, буде корисно, якщо ви почнете читати кілька вступних розділів: + + * [Як працює Інтернет](../how_the_internet_works/README.md) + + * [Знайомство з командним рядком](../intro_to_command_line/README.md) + + * [Вступ до Python](../python_introduction/README.md) + + * [Що таке Django?](../django/README.md) + + +# Насолоджуйтесь подією! + +Після початку воркшопу, можете відразу перейти до [вашого першого Django проекту!](../django_start_project/README.md), тому що ви пройшли матеріал із попередніх розділів. diff --git a/uk/intro_to_command_line/README.md b/uk/intro_to_command_line/README.md old mode 100755 new mode 100644 index 3320f3864f5..01859a6c4e5 --- a/uk/intro_to_command_line/README.md +++ b/uk/intro_to_command_line/README.md @@ -1,14 +1,16 @@ # Вступ до інтерфейсу командного рядка -Що, це захоплює, чи не так?! Ви напишете свій перший рядок коду просто через декілька хвилин :) +Це захоплює, чи не так?! Ви напишете свій перший рядок коду через декілька хвилин :) -**Дозвольте нам представити вас вашому новому другові: командний рядок!** +__Дозвольте нам представити вас вашому новому другові: командний рядок!__ -Наступні кроки покажуть вам як користуватися чорним вікном, яким користуються усі хакери. Спочатку це може видаватися трохи жахливим, однак насправді це лише командна підказка, що очікує певних команд від вас. +Наступні кроки покажуть вам, як користуватися чорним вікном хакерів. Спочатку це може видаватися трохи жахливим, однак насправді - це лише командна підказка, що очікує від вас певних команд. + +> **Примітка.** Зауважте, що в цій книзі ми використовуємо терміни 'директорія', 'каталог' та 'папка' взаємозамінно, ці слова означають одне й те саме. ## Що таке командний рядок? -Вікно, котре зазвичай називають **командним рядком** або **інтерфейсом командного рядку**, є текстовою програмою для відображення і керування файлами на вашому комп'ютері (так само як, наприклад, Windows Explorer або Finder на Mac, але без графічного інтерфейсу). Інші назви командного рядка: *cmd*, *CLI*, *prompt*, *console* або *terminal*. +Вікно, яке зазвичай називають __командним рядком__ або __інтерфейсом командного рядка__, є текстовою програмою для перегляду, обробки і управління файлами на вашому комп'ютері. Як Провідник на Windows чи Finder на Mac, але без графічного інтерфейсу. Інші назви командного рядка: *cmd*, *CLI*, *prompt*, *console* або *terminal*. ## Відкриваємо інтерфейс командного рядка @@ -34,15 +36,17 @@ $ - На Windows, це знак `>`: > - Кожній команді буде передувати цей знак і один пробіл, але ви не мусите набирати їх. Ваш комп'ютер робитиме це для вас сам :) -> Просто маленьке зауваження: у вашому випадку ви, мабуть, побачите, щось на кшталт `C:\Users\ola>` або `Olas-MacBook-Air:~ ola$` перед знаком командного рядка і це є на 100% правильним. У даному навчальному матеріалі ми лише спростимо цей момент, щоб вилучити певний мінімум. +> Просто маленьке зауваження: у вашому випадку ви побачите щось на кшталт `C:\Users\ola>` або `Olas-MacBook-Air:~ ola$` перед знаком командного рядка і це на 100% є правильним. + +Частина до `$` або `>` включно називається *запрошенням командного рядка* або скорочено *командним рядком*. Вона запрошує вас ввести туди щось. + +У посібнику, коли нам потрібно, щоб ви набрали щось в командний рядок, ми включатимемо `$` або `>`, а іноді й більше символів зліва. Ви можете ігнорувати ліву частину і друкувати в командний рядок лише те, що починається після `$`. ## Ваша перша команда (ЙОЙ!) @@ -50,18 +54,15 @@ $ whoami - або > whoami - Далі натисніть `enter`. Це наш результат: $ whoami olasitarska - Як бачимо, комп'ютер лише виводить ваше ім'я користувача. Файно, еге ж?:) > Спробуйте набирати кожну команду, а не копіювати і вставляти. Таким чином ви більше запам'ятаєте! @@ -72,23 +73,21 @@ ### Поточна директорія -Було б чудово знати де ми наразі знаходимось, хіба ні? Давайте подивимось. Введіть цю команду і натисніть `enter`: +Було б чудово знати, де ми перебуваємо зараз, чи не так? Давайте подивимося. Введіть цю команду і натисніть `enter`: $ pwd /Users/olasitarska - Якщо ви працюєте на Windows: > cd C:\Users\olasitarska - -Можливо, ви побачите щось схоже на вашій машині. По тому як ви відкрили командний рядок, то зазвичай ви починаєте зі своєї домашньої папки. +Можливо, ви побачите щось схоже на вашій машині. Після того, як ви відкрили командний рядок, ви зазвичай починаєте зі своєї домашньої папки. > Зауваження: 'pwd' відповідає 'print working directory' (англ. надрукувати робочу папку). -* * * +--- ### Список файлів і папок @@ -101,7 +100,6 @@ Music ... - Windows: > dir @@ -112,95 +110,84 @@ Windows: 05/08/2014 07:28 PM Music ... - -* * * +--- ### Змінити поточну директорію -Можливо, тепер ми можемо перейти до нашої папки Робочий стіл? +Тепер давайте перейдемо до директорії робочого столу: $ cd Desktop - Windows: > cd Desktop - -Перевірте чи дійсно щось змінилось: +Перевірте, чи дійсно щось змінилось: $ pwd /Users/olasitarska/Desktop - Windows: > cd C:\Users\olasitarska\Desktop - Ось! -> ПРОФІ хитрощі: якщо ви наберете `cd D` і потім натиснете `tab` на клавіатурі, командний рядок автоматично заповнить решту імені, таким чином можна оперувати швидше. Якщо папок, що починаються з "D" більше однієї, натисніть кнопку `tab` двічі щоб отримати список варіантів. +> ПРОФІ хитрощі: якщо ви наберете `cd D` і потім натиснете `tab` на клавіатурі, командний рядок автоматично заповнить решту імені, таким чином можна переходити швидше. Якщо папок, що починаються з "D" більше однієї, натисніть кнопку `tab` двічі для отримання списку варіантів. * * * ### Створити директорію -Як щодо створення папки Django Girls на вашому робочому столі? Ви можете це зробити наступним чином: - - $ mkdir djangogirls +Як щодо створення каталогу `practice` на вашому робочому столі? Ви можете зробити це таким чином: + $ mkdir practice Windows: - > mkdir djangogirls - + > mkdir practice -Ця коротка команда створить папку з іменем `djangogirls` на вашому робочому столі. Може перевірити чи є вона там, просто глянувши на свій Робочий стіл або запустивши команду `ls`/`dir`! Спробуйте :) +Ця коротка команда створить папку з іменем `practice` на вашому робочому столі. Може перевірити чи є вона там, просто глянувши на свій Робочий стіл або запустивши команду `ls` або `dir`! Спробуйте :) > ПРОФІ хитрощі: Якщо ви не хочете кожного разу набирати одну й ту ж команду, спробуйте натиснути кнопки `стрілка вгору` та `стрілка вниз` на своїй клавіатурі щоб повторити нещодавно використовувані команди. -* * * +--- ### Вправа! -Невеличкий виклик для вас: в щойно створеній папці `djangogirls` створіть папку `test`. Використайте команди `cd` та `mkdir`. +Невеличке випробування для вас: в щойно створеній директорії `practice` створіть папку `test`. Використайте команди `cd` та `mkdir`. #### Розв'язання: - $ cd djangogirls + $ cd practice $ mkdir test $ ls test - Windows: - > cd djangogirls + > cd practice > mkdir test > dir 05/08/2014 07:28 PM test - Вітаємо! :) -* * * +--- ### Прибираємо -Ми не хочемо залишити безлад, то ж давайте видалимо усе, що ми до цього моменту створили. +Ми не хочемо залишити безлад, то ж давайте видалимо усе, що ми створили до цього моменту. -Спочатку, нам потрібно повернутися назад до директорії Робочий стіл: +Спочатку нам потрібно повернутися назад до директорії Робочий стіл: $ cd .. - Windows: > cd .. - Використання `cd` із `..` змінить вашу поточну директорію на батьківську (тобто папка, що містить вашу поточну папку). Перевірте де ми: @@ -208,48 +195,40 @@ Windows: $ pwd /Users/olasitarska/Desktop - Windows: > cd C:\Users\olasitarska\Desktop +Тепер час видалити директорію `practice`: -А тепер час видалити папку `djangogirls`. - -> **Увага**: Видалення файлів за допомогою `del`, `rmdir` або `rm` є безповоротнім, тобто *файли будуть видалені назавжди*! То ж, будьте конче обережними із цією командою. - - $ rm -r djangogirls +> __Увага__: Видалення файлів за допомогою `del`, `rmdir` або `rm` є безповоротнім, тобто *файли будуть видалені назавжди*! То ж, будьте конче обережними із цими командами. + $ rm -r practice Windows: - > rmdir /S djangogirls - djangogirls, Are you sure ? Y - + > rmdir /S practice + practice, Are you sure ? Y Виконано! Щоб переконатися, що папку дійсно видалена, давайте перевіримо: $ ls - Windows: > dir - ### Вихід Це все наразі! Можна тепер спокійно закрити командний рядок. Давайте зробимо це хакерським методом, добре?:) $ exit - Windows: > exit - Круто, га?:) ## Підсумок @@ -266,11 +245,9 @@ Windows: | mkdir | mkdir | створити нову директорію | **mkdir testdirectory** | | del | rm | видалити директорію/файл | **del c:\test\test.txt** | -Тут наведено лише невелика кількість команд, котрі можна запускати у вашому командному рядку, однак, на даний момент ми не збираємося використовувати щось більше. - -Якщо вас цікавить, [ss64.com][1] містить повний список посилань на команди для усіх операційних систем. +Тут наведено лише невелику кількість команд, котрі можна запускати у вашому командному рядку, однак, на даний момент ми не збираємося використовувати щось більше. - [1]: http://ss64.com +Якщо вас цікавить, [ss64.com](http://ss64.com) містить повний список посилань на команди для усіх операційних систем. ## Готові? diff --git a/uk/python_installation/README.md b/uk/python_installation/README.md old mode 100755 new mode 100644 index 42ab05953db..48b6f8aabae --- a/uk/python_installation/README.md +++ b/uk/python_installation/README.md @@ -2,65 +2,13 @@ Нарешті ми тут! -Але спершу, дозвольте нам розказати вам що ж таке Python. Python -- це дуже популярна мова програмування, що може використовуватися для створення веб сайтів, ігор, наукових продуктів, графіки та багато-багато іншого. +Але спершу, дозвольте нам розказати вам що ж таке Python. Python - це дуже популярна мова програмування, що може використовуватися для створення веб сайтів, ігор, наукових програм, графіки та багато-багато іншого. -Python розроблено наприкінці 1980-х і його основна мета бути читабельним для людських істот (не тільки для машин!), саме тому ця мова виглядає набагато простіше, ніж інші мови програмування. Це привносить простоту у процес вивчення, але не турбуйтеся, Python також є дуже потужнимl! +Python розроблено наприкінці 80-х, і його головною ціллю є читабельність для людей (не тільки для машин!). Саме тому ця мова виглядає набагато простіше, ніж інші мови програмування. Це привносить простоту у процес вивчення, але не турбуйтеся, Python водночас є дуже потужним! # Встановлення Python -> Цей розділ базується на навчальних матеріалах Geek Girls Carrots (http://django.carrots.pl/) +> **Примітка** Якщо ви вже прошли розділ установки, немає потреби робити це знову - можна пропустити і перейти відразу до наступного розділу! -Django написаний на Python. Нам потрібен Python, щоб робити усе, що заманеться на Django. Почнемо з його інсталяції! Ми хочемо встановити Python 3.4, отже якщо ви вже маєте якусь більш ранню версію, то необхідно її оновити. +{% include "/python_installation/instructions.md" %} -### Windows - -Python для Windows можна завантажити з сайту https://www.python.org/downloads/release/python-343/. Після завантаження файлу ***.msi**, ви повинні запустити його (натисніть по ньому двічі) і виконувати усі подальші інструкції. Важливо пам'ятати шлях (директорію), де ви встановили Python. Це знадобиться пізніше! - -### Linux - -Цілком ймовірно, що у вас вже є Python встановлений разом із системою. Щоб перевірити це (а заодно й версію), відкрийте консоль і наберіть наступну команду: - - $ python3 --version - Python 3.4.2 - - -Якщо Python не встановлено або ви бажаєте встановити іншу версію, то можете виконати встановлення наступним чином: - -#### Debian або Ubuntu - -Наберіть наступну команду в консолі: - - $ sudo apt-get install python3.4 - - -#### Fedora (<=21) - -Скористайтеся наступною командою в консолі: - - $ sudo yum install python3.4 - - -#### Fedora (22+) - -Скористайтеся наступною командою в консолі: - - $ sudo dnf install python3.4 - - -### OS X - -Вам необхідно перейти на веб сайт https://www.python.org/downloads/release/python-342/ і завантажити Python інсталятор: - -* завантажте файл *Mac OS X 64-bit/32-bit installer* *DMG*, -* натисніть двічі, щоб відкрити його, -* клікніть двічі по *Python.mpkg*, щоб запустити інсталятор. - -Підтвердіть, що інсталяція пройшла успішно відкривши програму *Terminal* і запустивши команду `python3`: - - $ python3 --version - Python 3.4.2 - - -* * * - -Якщо маєте певні сумніви або щось пішло не так і ви без поняття що робити далі - будь ласка, зверніться до свого тренера! Інколи не все йде гладко і краще звернутись по допомогу до когось, хто має більше досвіду. diff --git a/uk/python_installation/images/add_python_to_windows_path.png b/uk/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/uk/python_installation/images/add_python_to_windows_path.png differ diff --git a/uk/python_installation/instructions.md b/uk/python_installation/instructions.md new file mode 100644 index 00000000000..861c3e7d614 --- /dev/null +++ b/uk/python_installation/instructions.md @@ -0,0 +1,67 @@ + +> Цей розділ базується на навчальних матеріалах Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) + +Django написаний на Python. Нам потрібен Python, щоб робити усе, що заманеться на Django. Почнемо з його інсталяції! Ми хочемо встановити Python 3.4, отже якщо ви вже маєте якусь більш ранню версію, то необхідно її оновити. + + +### Windows + +Python для Windows можна завантажити з сайту https://www.python.org/downloads/release/python-343/. Після завантаження файлу ***.msi**, ви повинні запустити його (натисніть по ньому двічі) і виконувати усі подальші інструкції. Важливо пам'ятати шлях (директорію), де ви встановили Python. Це знадобиться пізніше! + +Зверніть увагу на другу сторінку "Customize" майстера установки, вам потрібно пролистати вниз і вибрати опцію "Add python.exe to the Path" (додати python.exe в системну змінну Path), як показано тут: + +![Не забудьте додати Python до змінної Path](../python_installation/images/add_python_to_windows_path.png) + +### Linux + +Цілком ймовірно, що у вас вже є Python встановлений разом із системою. Щоб перевірити це (а заодно й версію), відкрийте консоль і наберіть наступну команду: + + $ python3 --version + Python 3.4.3 + +Якщо Python не встановлено або ви бажаєте встановити іншу версію, то можете виконати встановлення наступним чином: + + +#### Debian або Ubuntu + +Наберіть наступну команду в консолі: + + $ sudo apt-get install python3.4 + + +#### Fedora (до версії 21) + +Скористайтеся наступною командою в консолі: + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +Скористайтеся наступною командою в консолі: + + $ sudo dnf install python3.4 + + +#### openSUSE + +Скористайтеся наступною командою в консолі: + + $ sudo zypper install python3 + + +### OS X + +Вам необхідно перейти на веб сайт https://www.python.org/downloads/release/python-343/ і завантажити Python інсталятор: + +* завантажте файл *Mac OS X 64-bit/32-bit installer*, +* Двічі клацніть на *python 3.4.3 macosx10.6.pkg*, щоб запустити інсталятор. + +Підтвердіть, що інсталяція пройшла успішно відкривши програму *Terminal* і запустивши команду `python3`: + + $ python3 --version + Python 3.4.3 + +---- + +Якщо маєте певні сумніви, або щось пішло не так і ви без поняття, що робити далі - будь ласка, зверніться до свого тренера! Інколи не все йде гладко і краще звернутись по допомогу до когось, хто має більше досвіду. diff --git a/uk/python_introduction/README.md b/uk/python_introduction/README.md old mode 100755 new mode 100644 index 1cba003e8f8..6b780694b25 --- a/uk/python_introduction/README.md +++ b/uk/python_introduction/README.md @@ -1,25 +1,22 @@ # Вступ до Python -> Частина цього розділу базується на матеріалах Geek Girls Carrots (http://django.carrots.pl/). +> Частина цього розділу базується на матеріалах Geek Girls Carrots (https://github.com/ggcarrots/django-carrots). Давайте напишемо якийсь код! ## Командний рядок Python -Щоб розпочати роботу із Python нам необхідно відкрити *командний рядок*. Ви вже повинні знати як це зробити, адже ознайомились із цим у розділі [Вступ до командного рядка](../intro_to_command_line/README.md). +Щоб розпочати роботу із Python, нам необхідно відкрити *командний рядок*. Ви вже повинні знати як це зробити, адже ознайомились із цим у розділі [Вступ до командного рядка](../intro_to_command_line/README.md). +Як тільки будете готові, виконайте наведені нижче інструкції. - -Так як ви готові, виконаємо наведені нижче інструкції. - -Ми хочемо відкрити консоль Python, то ж наберіть `python3` та натисніть `enter`. +Ми хочемо відкрити консоль Python, тому введіть `python` на Windows або `python3` на Mac OS/Linux та натисніть `Enter`. $ python3 - Python 3.4.2 (...) - Type "copyright", "credits" or "license" for more information. + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. >>> - ## Ваша перша команда на Python! Після запуску команди Python командний рядок зміниться на `>>>`. Для нас це означає, що відтепер ми можемо користуватися лише командами мови Python. Вам не доведеться друкувати `>>>` - Python зробить це для вас сам. @@ -31,8 +28,10 @@ >>> 2 + 3 5 - -Чудово! Бачите, яким чином здійснено вивід відповіді? Python знає математику! Можна спробувати інші команди, наприклад: - `4 * 5` - `5 - 1` - `40 / 2` +Чудово! Бачите, яким чином здійснено вивід відповіді? Python знає математику! Можна спробувати інші команди, наприклад: +- `4 * 5` +- `5 - 1` +- `40 / 2` Поки що можете трохи побавитися із математикою, а далі повертайтесь назад :). @@ -40,26 +39,23 @@ ## Рядки -Як щодо вашого імені? Наберіть ваше ім'я в лапках як тут: +Як щодо вашого імені? Наберіть ваше ім'я в лапках, як тут: >>> "Ola" 'Ola' - -Щойно ви створили свій перший рядок! Це є набір символів, що може оброблятися комп'ютером. Рядок має постійно починатися і закінчуватися одним і тим же символом. Це можуть бути одинарні (`'`) або подвійні (`"`) лапки - вони повідомляють Python, що всередині них міститься рядок. +Щойно ви створили свій перший рядок! Це послідовність символів, що може бути оброблена комп'ютером. Рядок має постійно починатися і закінчуватися одним і тим же символом. Це може бути одинарна (`'`) або подвійна (`"`) лапка (немає ніякої різниці)! Лапки вказують Python, що всередині них рядок. Рядки можна об'єднувати. Спробуйте: >>> "Hi there " + "Ola" 'Hi there Ola' - Також можна множити рядки на число: >>> "Ola" * 3 'OlaOlaOla' - Якщо вам раптом треба поставити апостроф всередині рядка, то існує два шляхи це зробити. Використавши подвійні лапки: @@ -67,62 +63,56 @@ >>> "Runnin' down the hill" "Runnin' down the hill" - -або ж конвертувати апостроф за допомогою бекслеша (``): +або ж екранувати апостроф за допомогою оберненої косої риски (англ. backslash `\`): >>> 'Runnin\' down the hill' "Runnin' down the hill" - -Гарно, еге ж? Щоб побачити своє ім'я написане великими літерами, просто наберіть: +Гарно, еге ж? Щоб побачити своє ім'я, написане великими літерами, наберіть: >>> "Ola".upper() 'OLA' - -Ви щойно застосували до свого рядка **функцію** `upper`! Функція (така як `upper()`) - це набір інструкцій, які повинен виконувати Python над заданим об'єктом (`"Ola"`) з моменту як ви викликали її. +Ви щойно застосували до свого рядка `upper` __функцію__! Функція (така як `upper()`) - це набір інструкцій, які повинен виконувати Python над заданим об'єктом (`"Ola"`) з моменту її виклику. Якщо ви раптом забажаєте дізнатися про число літер, що містяться у вашому імені, то для цього також існує функція! >>> len("Ola") 3 - -Здивовані чому іноді ви викликаєте функції із `.` наприкінці рядка (на зразок `"Ola".upper()`), а іноді ви спочатку викликаєте функцію і вказуєте рядок у дужках? Що ж, в деяких випадках, функції належать об'єктам, як `upper()`, котра може бути виконана лише над рядком. У цьому випадку, ми називаємо функцію **методом**. Іншого разу, функції не належать до жодного об'єкту і можуть використовуватись стосовно різних типів об'єктів, як `len()`. Саме тому ви використовуємо `"Ola"` у якості параметра для функції `len`. +Здивовані, чому іноді ви викликаєте функції із `.` наприкінці рядка (на зразок `"Ola".upper()`), а іноді ви спочатку викликаєте функцію і вказуєте рядок у дужках? Що ж, в деяких випадках, функції належать об'єктам, як `upper()`, котра може бути виконана лише над рядком. У цьому випадку, ми називаємо функцію __методом__. Іншого разу, функції не належать до жодного об'єкту і можуть використовуватись стосовно різних типів об'єктів, як `len()`. Саме тому ви використовуємо `"Ola"` у якості параметра для функції `len`. ### Підсумок Гаразд, досить стосовно рядків. Отже, ви вже ознайомилися із такими поняттями як: -* **командний рядок** - набір команд (коду) в командному рядку Python дає результат у відповідях на Python -* **числа і рядки** - в Python числа використовуються для математичних розрахунків, а рядки - для текстових об'єктів -* **оператори** - на зразок + та \*, комбінують значення і продукують нове -* **функції** - на зразок upper() та len(), виконують дії над об'єктами. +- __командний рядок__ - набір команд (коду) в командному рядку Python дає результат у відповідях на Python +- __числа і рядки__ - в Python числа використовуються для математичних розрахунків, а рядки - для текстових об'єктів +- __оператори__ - на зразок + та \*, комбінують значення і продукують нове +- __функції__ - на зразок upper() та len(), виконують дії над об'єктами. Це є основи кожної мови програмування, яку ви вивчатимете. Готові приступити до чогось складнішого? Б'ємось об заклад, що так! ## Помилки -Спробуємо щось нове. Чи можемо ми отримати довжину числа тим же методом як ми це робили для нашого імені? Наберіть `len(304023)` та натисніть `enter`: +Спробуємо щось нове. Чи можемо ми отримати довжину числа тим же методом, як ми це робили для нашого імені? Наберіть `len(304023)` та натисніть `Enter`: >>> len(304023) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'int' has no len() - -Ми отримали нашу першу помилку! Вона говорить про те, що об'єкт типу "int" (integers, цілі числа) не мають довжини. І що ж нам тепер робити? Можливо, можна записати наше число у формі рядка? Рядки ж мають довжину, правда? +Ми отримали нашу першу помилку! Вона говорить про те, що об'єкт типу "int" (integers, цілі числа) не має довжини. І що ж нам тепер робити? Можливо, можна записати наше число у формі рядка? Рядки ж мають довжину, правда? >>> len(str(304023)) 6 - Спрацювало! Ми використали функцію `str` всередині функції `len`. `str()` перетворює будь-що на рядки. -* Функція `str` перетворює речі на **рядки** -* Функція `int` перетворює речі на **цілі числа** +- Функція `str` перетворює речі на __рядки__ +- Функція `int` перетворює речі на __цілі числа__ -> Важливо: ми можемо перетворювати числа на текст, однак, не можемо перетворити текст на числа - чому б могло дорівнювати `int('hello')`? +> Важливо: ми можемо перетворювати числа на текст, однак, не можемо перетворити текст на числа - чому б дорівнювало `int('hello')`? ## Змінні @@ -132,37 +122,32 @@ >>> name = "Ola" - Бачите? Це просто! Просто: name дорівнює Ola. -Як ви зауважили, ваша програма не повернула нічого як вона це робила до того. Отже, як ми можемо бути певні, що змінна насправді існує? Просто введіть `name` і натисніть `enter`: +Як ви зауважили, ваша програма не повернула нічого як вона це робила до того. Отже, як ми впевнимось, що змінна насправді існує? Просто введіть `name` і натисніть `enter`: >>> name 'Ola' - Урра! Ваша перша змінна :)! Ви завжди можете змінити значення, на яке вона посилатиметься: >>> name = "Sonja" >>> name 'Sonja' - Також можна використовувати її у функціях: >>> len(name) 5 - -Файно, хіба ні? Звісно, змінні можуть представляти будь-що, числами також! Спробуйте: +Файно, хіба ні? Звісно, змінні можуть представляти будь-що, числа також! Спробуйте: >>> a = 4 >>> b = 6 >>> a * b 24 - -Але що, якщо ми використали неправильне ім'я? Чи можете ви передбачити, що станеться? Спробуймо! +А якщо ми використали неправильне ім'я? Чи можете ви передбачити, що станеться? Спробуймо! >>> city = "Tokyo" >>> ctiy @@ -170,10 +155,10 @@ File "", line 1, in NameError: name 'ctiy' is not defined +Помилка! Як бачите, Python має різні типи помилок і дана помилка називається **NameError**. Python виведе для вас цю помилку, якщо ви спробуєте використати досі не визначену змінну. Якщо ж ви зіткнетеся із цією помилкою пізніше, перевірте свій код, чи не зробили ви помилки в написанні імен змінних. -Помилка! Як бачите, Python має різні типи помилок і дана помилка називається **NameError**. Python виведе для вас цю помилку, якщо ви спробуєте використати досі не визначену змінну. Якщо ж ви зіткнетеся із цією помилкою пізніше, перевірте свій код щоб побачити чи не пропустили ви часом якоїсь змінної. +Поекспериментуйте із цим усім і подивіться, що можна робити! -Поекспериментуйте із цим усім поки що і подивіться що можна робити! ## Функція print @@ -185,43 +170,38 @@ >>> print(name) Maria - Коли ви просто набираєте `name`, Python інтерпретує відповіді за допомогою рядкового *представлення* змінної 'name', котра є набором літер M-a-r-i-a, взятим в одинарні лапки, ''. Коли ви повідомляєте `print(name)`, Python "надрукує" значення змінної на екран, без лапок, що є більш акуратним. Як ми потім побачимо, `print()` є також корисним коли ми хочемо надрукувати речі з внутрішніх функцій, або ж коли хочемо надрукувати речі в декілька рядків. + ## Списки -Окрім рядків та чисел, Python має усі види різних типів об'єктів. Наразі ми збираємося представити вашій увазі один із них, що називається **список**. Списки є саме тим, про що ви й подумали: це є об'єкти, що є списками інших об'єктів :) +Окрім рядків та чисел, Python має усі види різних типів об'єктів. Наразі ми збираємося представити вашій увазі один із них, що називається __список__. Списки є саме тим, про що ви й подумали: це об'єкти, що є списками інших об'єктів :) Створимо список: >>> [] [] - -Так, цей список пустий. Не дуже корисно, чи не так? Створимо список лотерейних чисел. Ми не бажаємо увесь час повторюватись, то ж покладемо усе до змінної, також: +Так, цей список пустий. Не дуже корисно, чи не так? Створимо список лотерейних чисел. Ми не бажаємо увесь час повторюватись, тож покладемо усе до змінної: >>> lottery = [3, 42, 12, 19, 30, 59] - -Гаразд, маємо список! Що ми можемо із цим робити? Давайте глянемо скільки лотерейних номерів міститься у списку. Не маєте жодного уявлення яку функцію для цього можна використати? Ви вже це знаєте! +Гаразд, маємо список! Що ми можемо із цим робити? Давайте глянемо скільки лотерейних номерів міститься у списку. Не маєте жодного уявлення, яку функцію для цього можна використати? Ви вже це знаєте! >>> len(lottery) 6 - Так! `len()` може дати вам кількість об'єктів у списку. Зручно, правда ж? Може, тепер здійснимо сортування: >>> lottery.sort() - -Ця функція нічого не повертає, вона лише змінює порядок, в якому з'являються числа у списку. Давайте надрукуємо список знову і подивимось що ж трапилося: +Ця функція нічого не повертає, вона лише змінює порядок, в якому з'являються числа у списку. Давайте надрукуємо список знову і подивимось, що ж трапилося: >>> print(lottery) [3, 12, 19, 30, 42, 59] - Як бачимо, числа у вашому списку тепер відсортовано починаючи з найменшого і закінчуючи найбільшим значенням. Вітаємо! Можливо, ми хочемо відсортувати числа у зворотньому порядку? Давайте це зробимо! @@ -230,25 +210,34 @@ >>> print(lottery) [59, 42, 30, 19, 12, 3] - Просто, чи не так? Якщо ви забажаєте щось додати до свого списку, то можете це зробити за допомогою наступної команди: >>> lottery.append(199) >>> print(lottery) [59, 42, 30, 19, 12, 3, 199] - -Якщо захочете показати лише перше число, то можете зробити це використавши **індекси**. Індекс - це номер, що повідомляє про те, звідки у списку взято елемент. Комп'ютерщики люблять починати відлік з 0, отже перший об'єкт з вашого списку буде мати індекс 0, наступний - 1, і так далі. Спробуйте наступне: +Якщо захочете показати лише перше число, то можете зробити це використавши __індекси__. Індекс - це номер, що повідомляє про те, звідки у списку взято елемент. Програмісти вважають за краще рахувати з 0, таким чином, перший об'єкт у списку має індекс 0, наступний - 1 і так далі. Спробуйте наступне: >>> print(lottery[0]) 59 >>> print(lottery[1]) 42 - Як бачимо, ви можете отримати доступ до різних об'єктів списку використавши ім'я списку та індекс об'єкта всередині квадратних дужок. -Для додаткового задоволення, спробуйте деякі індекси: 6, 7, 1000, -1, -6 або -1000. Подивіться чи здатні ви передбачити результат команди перед її застосуванням. Чи мають ці результати якийсь смисл? +Для того, щоб видалити що-небудь із списку, вам потрібно використовувати вище вивчені __індекси__ і команду `pop()`. Давайте спробуємо на прикладі та нагадаємо, що ми вивчили раніше; ми будемо видаляти перший елемент з нашого списку. + + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + +Працює чудово! + +Для додаткового задоволення, спробуйте деякі індекси: 6, 7, 1000, -1, -6 або -1000. Подивіться, чи здатні ви передбачити результат команди перед її застосуванням. Чи мають ці результати якийсь смисл? Список усіх доступних методів для списку міститься у цьому розділі документації з Python: https://docs.python.org/3/tutorial/datastructures.html @@ -259,88 +248,82 @@ >>> {} {} - Це показує, що ви просто створили пустий словник. Урра! -А тепер, спробуйте набрати наступну команду (спробуйте також замінити вашу власну інформацію): - - >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +А тепер спробуйте набрати наступну команду (спробуйте також замінити на вашу власну інформацію): +```python +>>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} +``` -За допомогою вказаної команди, ви щойно створили змінну із назвою `participant` і трьома парами ключ-значення: +За допомогою вказаної команди ви щойно створили змінну із назвою `participant` і трьома парами ключ-значення: -* ключ `name` вказує на значення `'Ola'` (об'єкт `string` - рядок), -* `country` вказує на `'Poland'` (інший об'єкт `string` - рядок), -* і `favorite_numbers` вказує на `[7, 42, 92]` (об'єкт `list` - список з трьома числами всередині). +- ключ `name` вказує на значення `'Ola'` (об'єкт `string` - рядок), +- `country` вказує на `'Poland'` (інший об'єкт `string` - рядок), +- і `favorite_numbers` вказує на `[7, 42, 92]` (об'єкт `list` - список з трьома числами всередині). Можна перевірити значення індивідуальних ключів, використовуючи наступний синтаксис: >>> print(participant['name']) Ola - Бачите, усе подібно до списку. Але вам не треба пам'ятати індекс - лише ім'я. -Що трапиться якщо запитати Python про значення ключа, що не існує? Не здогадуєтесь? Давайте спробуємо і подивимось! +Що трапиться, якщо запитати Python про значення ключа, якого не існує? Не здогадуєтесь? Давайте спробуємо і подивимось! >>> participant['age'] Traceback (most recent call last): File "", line 1, in KeyError: 'age' - Погляньте, інша помилка! Цього разу - **KeyError**. Python допомагає і підказує вам про те, що ключа `'age'` не існує в даному словнику. Коли ж варто використовувати словник, а коли список? Що ж, гарне питання. Просто вирішимо його подумки перед тим, як подивитися відповідь у наступному рядку. -* Вам необхідна лише впорядкована послідовність елементів? Користуйтеся списком. -* Вам потрібні значення асоційовані із ключами, так що ви можете ефективно переглядати їх (за допомогою ключа) пізніше? Користуйтеся словником. +- Вам необхідна лише впорядкована послідовність елементів? Користуйтеся списком. +- Вам потрібні значення асоційовані із ключами, так що ви можете ефективно переглядати їх (за допомогою ключа) пізніше? Користуйтеся словником. -Словники, як і списки, є *змінними*, це означає, що їх можна змінювати після створення. Можна додати нову пару ключ/значення до словника після того, як він створений, на зразок: +Словники, як і списки, є *змінюваними*, це означає, що вони можуть бути змінені після створення. Ви можете додати нові пари ключ/значення до словника після того, як він був створений, наприклад: >>> participant['favorite_language'] = 'Python' - Як і для списків, використання методу `len()` для словників, повертає значення пар ключ-значення в словнику. Наберіть команду: >>> len(participant) 4 - Сподіваюся, це наразі має сенс. :) Готові до ще більшого задоволення від роботи зі словниками? Перейдіть на наступний рядок, щоб побачити дещо дивовижне. -Можна використовувати команду `del` для видалення елементів зі словника. Скажімо, якщо ви бажаєте видалити значення, що відповідає ключу `'favorite_numbers'`, просто наберіть наступну команду: +Можна використовувати команду `pop()` для видалення елементів зі словника. Скажімо, якщо ви бажаєте видалити значення, що відповідає ключу `'favorite_numbers'`, просто наберіть наступну команду: - >>> del participant['favorite_numbers'] + >>> participant.pop('favorite_numbers') >>> participant {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} - Як бачимо з результатів, пару ключ-значення, що відповідає ключу 'favorite_numbers' було видалено. -Таким же чином можна також змінювати значення асоційоване із вже існуючим ключем зі словника. Наберіть: +Аналогічно можна змінювати значення, асоційоване з уже існуючим ключем зі словника. Наберіть: >>> participant['country'] = 'Germany' >>> participant {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} - Як бачимо, значення ключа `'country'` було змінено із `'Poland'` на `'Germany'`. :) Вражаюче? Ура! Ви щойно освоїли іншу дивовижну річ. ### Підсумок -Чудово! Тепер ви знаєте багато про програмування. У цій останній частині ви дізналися про такі поняття як: +Чудово! Тепер ви знаєте багато про програмування. У цій останній частині ви дізналися про такі поняття, як: -* **помилки** - тепер ви знаєте як читати та розуміти помилки, що з'являються якщо Python не розуміє отриманої команди -* **змінні** - імена для об'єктів, що дозволяють вам спростити процес написання коду і робить його більш читабельним -* **списки** - списки певним чином впорядкованих об'єктів -* **словники** - об'єкти, що зберігають пари ключ-значення +- __помилки__ - тепер ви знаєте як читати та розуміти помилки, що з'являються якщо Python не розуміє отриманої команди +- __змінні__ - імена для об'єктів, що дозволяють вам спростити процес написання коду і робить його більш читабельним +- __списки__ - списки певним чином впорядкованих об'єктів +- __словники__ - об'єкти, що зберігають пари ключ-значення Не дочекаєтеся переходу до наступної частини? :) ## Порівняння -Велика частина програмування включає речі пов'язані із порівнянням. Що є найпростішою річчю для порівняння? Звісно, числа. Давайте подивимось як це працює: +Велика частина програмування включає речі, пов'язані із порівнянням. Що є найпростішою річчю для порівняння? Звісно, числа. Давайте подивимось як це працює: >>> 5 > 2 True @@ -350,11 +333,12 @@ True >>> 1 == 1 True + >>> 5 != 2 + True +Ми надали Python деякі числа для порівняння. Як бачимо, Python вміє порівнювати не лише числа, а й результати операцій. Гарно, еге ж? -Ми надали Python деякі числа для порівняння. Як бачимо, Python can порівнює не лише числа, але також може порівнювати результати. Гарно, еге ж? - -Цікаво чому ми використали два однакові знаки `==` щоб порівняти чи є рівними числа? Ми використовуємо `=` для присвоєння значень змінним. Завжди, **завжди** треба писати `==` якщо ви бажаєте здійснити перевірку двох чисел на рівність одне одному. +Цікаво, чому ми використали два однакові знаки `==`, щоб порівняти на рівність числа? Ми використовуємо `=` для присвоєння значень змінним. Завжди, __завжди__ треба писати `==`, якщо ви бажаєте здійснити перевірку двох чисел на рівність одне одному. Ми також можемо перевіряти, чи два об'єкти є нерівними. Для цього ми використовуємо символ `!=`, як показано в прикладі вище. Задайте для Python ще дві задачі: @@ -363,13 +347,12 @@ >>> 3 <= 2 False - щодо `>` та `<` - усе просто, але що означають `>=` і `<=`? Читайте їх як: -* x `>` y означає x більше ніж y -* x `<` y означає: x менше ніж y -* x `<=` y означає: x менше або дорівнює y -* x `>=` y означає: x більше або дорівнює y +- x `>` y означає x більше ніж y +- x `<` y означає x менше ніж y +- x `<=` y означає x менше або дорівнює y +- x `>=` y означає x більше або дорівнює y Чудово! Хочете ще? Спробуйте це: @@ -380,11 +363,10 @@ >>> 3 > 2 or 2 < 1 True - Ви можете задавати для Python стільки чисел для порівння скільки заманеться, і він дасть вам результат! Дуже розумно, чи не так? -* **and** - якщо ви використовуєте оператор `and`, обидва порівнюваних значення мають бути істинними - True для того, щоб і уся команда була істинною - True -* **or** - якщо ви використовуєте оператор `or`, лише одне із порівнюваних значень мають бути істинними - True для того, щоб і уся команда була істинною - True +- __and__ - якщо ви використовуєте оператор `and`, обидва порівнюваних значення мають бути істинними - True для того, щоб і уся команда була істинною - True +- __or__ - якщо ви використовуєте оператор `or`, лише одне із порівнюваних значень мають бути істинними - True для того, щоб і уся команда була істинною - True Чи чули ви про вираз "порівняння яблук і апельсинів"? Давайте спробуємо Python еквівалент: @@ -393,16 +375,18 @@ File "", line 1, in TypeError: unorderable types: int() > str() - -Бачимо тут, що як і у виразі, Python не в змозі порівняти число (`int`) та рядок (`str`). Натомість, виводиться **TypeError** і повідомляє нас про те, що ці два типи не можна порівнювати між собою. +Бачимо тут, що як і у виразі, Python не в змозі порівняти число (`int`) та рядок (`str`). +Натомість, виводиться **TypeError** і повідомляє нас про те, що ці два типи не можна порівнювати між собою. ## Логічні типи -Між іншим, ви щойно дізналися про новий типу об'єкту в Python. Він називається логічним - **Boolean** -- і, можливо, це найпростіший тип. +Між іншим, ви щойно дізналися про новий типу об'єкту в Python. Він називається логічним - __Boolean__ - і, можливо, це найпростіший тип. -Існує лише два логічних об'єкти: - Істинне - True - Хибне - False +Існує лише два логічних об'єкти: +- Істинне: True +- Хибне: False -Але для того, щоб Python міг це зрозуміти, треба завжди писати True (перша літера - велика, а решта - маленькі). **true, TRUE, tRUE не працюють -- лише True є правильним.** (Те ж саме стосується і False також.) +Але для того, щоб Python міг це зрозуміти, треба завжди писати 'True' (перша літера - велика, а решта - маленькі). __true, TRUE, tRUE не працюють - лише True є правильним.__ (Те ж саме стосується і 'False' також.) Логічні значення також можуть бути змінними! Погляньте: @@ -410,86 +394,84 @@ >>> a True - -Можна також зробити теж саме по іншому: +Можна також зробити теж саме по-іншому: >>> a = 2 > 5 >>> a False - Практикуйте із логічними типами спробувавши запустити наступні команди: -* `True and True` -* `False and True` -* `True or 1 == 1` -* `1 != 2` +- `True and True` +- `False and True` +- `True or 1 == 1` +- `1 != 2` -Вітання! Логічними типи одна із найкрутіших властивостей програмування, і ви щойно освоїли як їх застосовувати! +Вітання! Логічними типи - одна із найкрутіших властивостей програмування, і ви щойно освоїли, як їх застосовувати! # Збережіть! -Досі, ми писали увесь наш python код в інтерпретаторі, котрий обмежує нас до одного рядку коду одночасно. Нормальні програми зберігаються в файлах і виконуються **інтерпретаторами** або **компіляторами** наших мов програмування. Досі ми запускали наші програми одним рядком в Python **інтерпретаторі**. Для наступних задач нам знадобиться більше, ніж один рядок коду, отже нам потрібно: +Досі ми писали увесь наш Python код в інтерпретаторі, що обмежує нас написанням лише одного рядка за раз. Зазвичай програми зберігаються у файлах і виконуються __інтерпретатором__ або __компілятором__ нашої мови програмування. Досі ми запускали наші програми одним рядком в Python __інтерпретаторі__. Для наступних задач нам знадобиться більше, ніж один рядок коду, отже, нам потрібно: -* Закрити Python інтепретатор -* Відкрити наш текстовий редактор на вибір -* Зберегти певний код в python файлі -* Запустити його! +- Закрити Python інтепретатор +- Відкрити наш вибраний текстовий редактор +- Зберегти певний код в python файлі +- Запустити його! -Щоб вийти з Python інтерпретатора, яким ми користувалися до цього, просто наберіть функцію ~~~ exit()~~~: +Щоб вийти з Python інтерпретатора, яким ми користувалися до цього, просто наберіть функцію ```exit()```: >>> exit() $ - Ви повернетеся назад до командного рядка. -Раніше, ми вже обрали для себе редактор коду. А тепер ми маємо відкрити цей редактор і написати певний код в новому файлі: +Раніше ми вже обрали для себе редактор коду в розділі [редактор коду](../code_editor/README.md). А тепер ми маємо відкрити цей редактор і написати якийсь код в новому файлі: - print('Hello, Django girls!') +```python +print('Hello, Django girls!') +``` +Очевидно, ви тепер є досить досвідченим Python програмістом, отже, можете написати у ваш код усе, що ви до цього часу вивчили. -Очевидно, ви тепер є досить досвідченим python програмістом, отже можете написати у ваш код усе, що ви до цього часу вивчили. +А тепер треба зберегти файл і дати йому описове ім'я. Назвімо файл **python_intro.py** і збережемо його на вашому робочому столі. Ви можете називати файл як завгодно, тільки важливо, щоб назва закінчувалась на __.py__. Закінчення __.py__ говорить нашій операційній системі, що це **виконуваний файл Python** і Python може його запускати. -А тепер треба зберегти файл і дати йому описове ім'я. Назвімо файл **python_intro.py** і збережемо його на вашому робочому столі. Можемо назвати файл як нам заманеться, важливим тут є переконатися, що файл закінчується на **.py**, це повідомляє нашому комп'ютеру, що це **виконуваний python файл** і Python може його запускати. +> **Примітка** Ви повинні помітити одну з найкрутіших фіч редакторів коду: кольори! У консолі Python все було одного кольору, тепер ви повинні побачити, що функція `print` має інший колір, ніж рядок, який вона друкує. Це називається "підсвіткою синтаксису", і це справді корисна функція для програміста. Різний колір слів дає вам підказку щодо правильності набору тексту чи орфографічної помилки (згодом зверніть увагу на колір слова `def` в тілі функції). Це одна з вагомих причин, чому ми використовуємо редактор коду :) -По тому як файл успішно збережено, час запустити його! Використовуючи навики отримані під час освоєння розділу, що стосувався командного рядка, скористайтеся терміналом, щоб **змінити директорію** на робочий стіл. -Для Mac, команда буде виглядати так: +По тому, як файл успішно збережено, час запустити його! Використовуючи навики отримані під час освоєння розділу, що стосувався командного рядка, скористайтеся терміналом, щоб **змінити директорію** на робочий стіл. - cd /Users//Desktop +Для Mac, команда буде виглядати так: + $ cd /Users//Desktop Для Linux, вона буде на зразок (слово "Desktop" може бути перекладене вашою мовою): - cd /home//Desktop - - -І для windows, це буде так: + $ cd /home//Desktop - cd C:\Users\\Desktop +І для Windows, це буде так: + > cd C:\Users\\Desktop -Якщо ви застрягли, просто попросіть допомогти. +Якщо ви застрягли, просто попросіть допомоги. -і потім використайте Python щоб виконати код у файлі як тут: +Використовуйте Python, щоб виконати код у файлі, таким чином: $ python3 python_intro.py Hello, Django girls! - -Гаразд! Ви щойно запустили вашу першу pythonпрограму, яка була збережена у файлі. Чудові відчуття? +Гаразд! Ви щойно запустили вашу першу Python програму, яка була збережена у файлі. Чудові відчуття? Тепер ви можете переходити до важливого інструменту у програмуванні: ## If...elif...else -Багато речей в програмі мають бути виконані лише коли виконуються задані умови. Саме тому Python має інструмент, що називається **умовою if - якщо**. +Багато речей в програмі мають бути виконані лише тоді, коли виконуються задані умови. Саме тому Python має інструмент, що називається __умовою if - якщо__. Замініть код вашого файлу **python_intro.py** на наступне: - if 3 > 2: - +```python +if 3 > 2: +``` Якщо ми збережемо зміни і запустимо цей файл, то побачимо наступну помилку: @@ -498,110 +480,134 @@ ^ SyntaxError: unexpected EOF while parsing +Python очікує від нас подальших інструкцій, які повинні бути виконані, якщо умова `3 > 2` виявляється істинною (тобто `True`). Спробуємо змусити Python надрукувати “It works!”. Змініть код у файлі **python_intro.py** на наступне: -Python очікує від нас подальших інструкцій, які повинні бути виконані якщо умова `3 > 2` виявляється істинною (тобто `True`). Спробуємо змусити Python надрукувати “It works!”. Змініть код у файлі **python_intro.py** на наступне: - - if 3 > 2: - print('It works!') +```python +if 3 > 2: + print('It works!') +``` - -Зауважили яким чином ми зробили відступ в 4 пробіли для наступного рядка коду? Це необхідно робити для того, щоб Python знав який шматок коду запускати, якщо результати умови істинні. Можна зробити відступ і в один пробіл, але майже усі Python програмісти роблять відступ у 4 пробіли, щоб було акуратніше. Один знак табуляції також буде рахуватися як 4 пробіли. +Зауважили, яким чином ми зробили відступ в 4 пробіли для наступного рядка коду? Це необхідно робити для того, щоб Python знав, який шматок коду запускати, якщо результати умови істинні. Можна зробити відступ і в один пробіл, але майже усі Python програмісти роблять відступ у 4 пробіли, щоб було акуратніше. Один `tab` також рахується як 4 пробіли. Збережіть і запустіть знову: $ python3 python_intro.py It works! +### Що ж, якщо ні? -### Що ж якщо ні? - -У попередніх прикладах, код виконувався лише коли умови були істинними - True. Однак, Python також має умови `elif` та `else`: - - if 5 > 2: - print('5 is indeed greater than 2') - else: - print('5 is not greater than 2') +У попередніх прикладах код виконувався лише, коли умови були істинними - True. Однак, Python також має умови `elif` та `else`: +```python +if 5 > 2: + print('5 is indeed greater than 2') +else: + print('5 is not greater than 2') +``` -Коли це все запустити, то отримаємо на виході: +Коли запустимо це, буде виведено: $ python3 python_intro.py 5 is indeed greater than 2 - Якщо 2 було числом більшим за 5, то далі буде виконуватися друга команда. Просто, правда ж? Подивимося як працює `elif`: - name = 'Sonja' - if name == 'Ola': - print('Hey Ola!') - elif name == 'Sonja': - print('Hey Sonja!') - else: - print('Hey anonymous!') - +```python +name = 'Sonja' +if name == 'Ola': + print('Hey Ola!') +elif name == 'Sonja': + print('Hey Sonja!') +else: + print('Hey anonymous!') +``` і в результаті: $ python3 python_intro.py Hey Sonja! +Бачите, що тут відбуваеться? `Elif` вказує додаткові умови для перевірки, якщо результат попередніх умов є невдалим. + +Ви можете додати стільки виразів `elif`, скільки вам до вподоби одразу після виразу `if`. Наприклад: + +```python +volume = 57 +if volume < 20: + print("It's kinda quiet.") +elif 20 <= volume < 40: + print("It's nice for background music") +elif 40 <= volume < 60: + print("Perfect, I can hear all the details") +elif 60 <= volume < 80: + print("Nice for parties") +elif 80 <= volume < 100: + print("A bit loud!") +else: + print("My ears are hurting! :(") +``` -Бачите, що сталося? +Python послідовно виконує всі перевірки та друкує: + + $ python3 python_intro.py + Perfect, I can hear all the details ### Підсумок -В останніх трьох вправах ви освоїли такі поняття як: +В останніх трьох вправах ви освоїли такі поняття, як: -* **порівняння** - в Python можна порівнювати елементи використовуючи `>`, `>=`, `==`, `<=`, `<` та оператори `and`, `or` -* **Логічний тип - Boolean** - тип об'єкту, що може дорівнювати лише одному з двох значень: `True`- Істинне або `False` - Хибне -* **Збереження файлів** - зберігання коду в файлах дозволяє виконувати більші програми. -* **if...elif...else** - умови, що дозволяють виконувати код лише коли виконуються певні умови. +- __порівняння__ - в Python можна порівнювати елементи використовуючи `>`, `>=`, `==`, `<=`, `<` та оператори `and`, `or` +- __Логічний тип - Boolean__ - тип об'єкту, що може дорівнювати лише одному з двох значень: `True`- Істинне або `False` - Хибне +- __Збереження файлів__ - зберігання коду в файлах дозволяє виконувати більші програми. +- __if...elif...else__ - умови, що дозволяють виконувати код лише коли виконуються певні умови. Час для останньої частини цього параграфу! ## Ваші власні функції! -Пам'ятаєте функції на зразок `len()`, що можна виконувати в Python? Що ж, гарні новини, зараз ви дізнаєтесь як писати свої власні функції! +Пам'ятаєте функції на зразок `len()`, що можна виконувати в Python? Що ж, гарні новини - зараз ви дізнаєтесь, як писати свої власні функції! Функція - це набір інструкцій, які Python повинен виконати. Кожна функція в Python починається із ключового слова `def`, отримує ім'я і може містити певні параметри. Почнемо з простого. Перепишемо код в **python_intro.py** наступним чином: - def hi(): - print('Hi there!') - print('How are you?') - - hi() +```python +def hi(): + print('Hi there!') + print('How are you?') +hi() +``` Окей, наша перша функція готова! -Ви можете запитати для чого ми написали ім'я функції наприкінці файлу. Це тому, що Python зчитує файл і виконує його згори донизу. Отже, для того, щоб скористатися нашою функцією, ми повинні написати її знову унизу. +Ви можете запитати, для чого ми написали ім'я функції наприкінці файлу. Це тому, що Python зчитує файл і виконує його згори донизу. Отже, для того, щоб скористатися нашою функцією, ми повинні написати її знову унизу. -А тепер запустимо і подивимось що станеться: +А тепер запустимо і подивимось, що станеться: $ python3 python_intro.py Hi there! How are you? - Це було просто! Побудуємо нашу першу функцію з параметрами. Скористаємося попереднім прикладом - функцією, що говорить 'hi' особі, що її запускає - з іменем: - def hi(name): - +```python +def hi(name): +``` Як бачимо, зараз ми задали для нашої функції параметр, який назвали `name`: - def hi(name): - if name == 'Ola': - print('Hi Ola!') - elif name == 'Sonja': - print('Hi Sonja!') - else: - print('Hi anonymous!') - - hi() +```python +def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') +hi() +``` -Як бачимо, перед функцією `print` потрібно було зробити два відступи, оскільки `if` має знати, що повинно трапитися якщо умова виконується. Поглянемо тепер як це працює: +Пам'ятайте: функція `print` відділена відступами від команди `if` на чотири пробіли. Це тому, що функція запускається, коли виконується умова. Давайте подивимося, як це відбувається зараз: $ python3 python_intro.py Traceback (most recent call last): @@ -609,82 +615,85 @@ Python очікує від нас подальших інструкцій, як hi() TypeError: hi() missing 1 required positional argument: 'name' +Ой, помилка. На щастя, Python надає нам дуже корисне повідомлення про помилку. +Воно повідомляє нас про те, що функція `hi()` (та, яку ми визначили) має один необхідний аргумент (`name`) і що ми забули передати його, коли здійснювали виклик функції. +Виправимо це наприкінці файлу: -Ой, помилка. На щастя, Python надає нам дуже корисне повідомлення про помилку. Воно повідомляє нас про те, що функція `hi()` (та, яку ми визначили) має один необхідний аргумент (`name`) і що ми забули передати його коли здійснювали виклик функції. Виправимо це наприкінці файлу: +```python +hi("Ola") +``` - hi("Ola") - - -і запустимо знову: +І запустимо знову: $ python3 python_intro.py Hi Ola! - А якщо ми змінимо ім'я? - hi("Sonja") +```python +hi("Sonja") +``` - -запустіть: +Запустимо: $ python3 python_intro.py Hi Sonja! - -А тепер що ви думаєте про те, що станеться якщо ми вкажемо тут інше ім'я? (Не Ola і не Sonja) Спробуємо і подивимося чи ви маєте рацію. Маємо отримати на виході: +А тепер що ви думаєте про те, що станеться, якщо ми вкажемо тут інше ім'я? (Не Ola і не Sonja) Спробуємо і подивимося, чи ви маєте рацію. Маємо отримати на виході: Hi anonymous! - Чудово, чи не так? Таким чином вам не потрібно повторюватись кожного разу, коли ви захочете змінити ім'я особи, з якою має вітатися наша функція. І саме тому нам потрібні функції - ви ж бо ніколи не хочете повторювати свій код! -Виконаємо дещо складніші маніпуляції -- існує безліч імен, набагато більше, ніж лише два, і написати умови для кожного з них буде досить складно, правда ж? +Виконаємо дещо складніші маніпуляції - існує безліч імен, набагато більше, ніж лише два, і написати умови для кожного з них буде досить складно, правда ж? - def hi(name): - print('Hi ' + name + '!') - - hi("Rachel") +```python +def hi(name): + print('Hi ' + name + '!') +hi("Rachel") +``` А тепер виконаємо програму: $ python3 python_intro.py Hi Rachel! - -Вітаємо! Ви щойно розібралися з тим як писати функції :)! +Вітаємо! Ви щойно розібралися з тим, як писати функції :) ## Цикли Це вже остання частина. Усе було швидко, чи не так? :) -Як ми зазначали, програмісти народ лінивий, вони не бажають повторюватись. Під програмування мається на увазі усе, що пов'язане із автоматизацією, то ж, ми не хочемо вітати кожну окрему особу за допомогою імені вручну, правда ж? Саме тут і стаються в нагоді цикли. +Програмісти не люблять повторюватись. Програмування - це процес автоматизації всього, тому ми не хочемо вітати кожну людину по імені вручну, правильно? Тут пригодяться цикли. Ще пам'ятаєте про списки? Давайте створимо список дівчат: - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] - +```python +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +``` -Ми б хотіли привітатися із кожною з них персонально. Щоб це зробити у нас є функція `hi`, отже, використаємо її в циклі: +Ми б хотіли привітатися із кожною з них персонально. Щоб це зробити, у нас є функція `hi`, отже, використаємо її в циклі: - for name in girls: +```python +for name in girls: +``` - -Вираз ~~~ for~~~ поводиться подібно до виразу ~~~ if~~~ , а код, наведений нижче повинен мати відступи в чотири пробіли. +Вираз ```for``` поводиться подібно до виразу ```if```, а код, наведений нижче повинен мати відступи в чотири пробіли. Тут наведено повну версію коду у файлі: - def hi(name): - print('Hi ' + name + '!') - - girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] - for name in girls: - hi(name) - print('Next girl') +```python +def hi(name): + print('Hi ' + name + '!') +girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] +for name in girls: + hi(name) + print('Next girl') +``` -а коли ми запустимо усе це: +А коли ми запустимо усе це: $ python3 python_intro.py Hi Rachel! @@ -698,15 +707,13 @@ Python очікує від нас подальших інструкцій, як Hi You! Next girl - Як бачимо, все, що міститься всередині виразу `for` із відступом буде повторюватися для кожного елементу зі списку `girls`. -Також можна використовувати `for` стосовно чисел із застосуванням методу `range`: +Також можна використовувати `for` для чисел, використовуючи функцію `range`: for i in range(1, 6): print(i) - Що виведе на екран: 1 @@ -715,15 +722,14 @@ Python очікує від нас подальших інструкцій, як 4 5 - `range` - це функція, що створює список чисел, що йдуть одне за одним ці числа задаються вами як параметри). -Зауважте, що друге з цих двох чисел, не входить до списку, що виводиться на екран Python (тобто `range(1, 6)` рахує від 1 до 5, але не включає число 6). +Зауважте, що друге з цих двох чисел, не входить до списку, що виводиться на екран Python (тобто `range(1, 6)` рахує від 1 до 5, але не включає число 6). Це тому, що "діапазон" є напіввідкритим, і під цим ми розуміємо, що він включає перше значення, але не останнє. ## Підсумок -Ось і все. **Ви молодці** Це насправді не було так просто, то ж, ви мусите пишатися собою. Ми однозначно пишаємося вами за все, що тут було пророблено! +Ось і все. __Ви молодці!__ Це був складнуватий розділ, тому ви можете пишатися собою. Ми ж безумовно пишаємося вами, адже ви вже багато чого досягли! -А тепер захопіть собі шматок кексу і переходьте до наступного розділу :) +Ви можете зробити коротку перерву - можливо потрібний відпочинок для ваших очей, розминка, невелика прогулянка, перш ніж перейдете до наступного розділу. :) ![Cupcake](images/cupcake.png) diff --git a/uk/template_extending/README.md b/uk/template_extending/README.md index 3e20849054a..81769f1efd0 100755 --- a/uk/template_extending/README.md +++ b/uk/template_extending/README.md @@ -1,12 +1,12 @@ -# Шаблонне розширення +# Розширення шаблону -Інша хороша річ, яку має Django в своєму арсеналі це **шаблонне розширення**. Що це означає? А це означає, що ви можете використовувати одні й ті ж частини свого HTML коду для різних сторінок веб сайту. +Інша хороша річ, яку має Django в своєму арсеналі - це __розширення шаблону__. Що це означає? Це значить, що ви можете використовувати одні й ті ж частини свого HTML коду для різних сторінок веб-сайту. -Таким чином, вам не доведеться повторюватись у кожному файлі, коли ви захочете використати одну й ту ж інформацію/схему. І якщо ви захочете щось змінити, то не доведеться це робити в кожному шаблоні, а лише один раз! +Шаблони допомогають у випадку, коли ви хочете використати однакову інформацію/схему. Вам не потрібно повторюватись в кожному файлі. І якщо ви захочете щось змінити, то не доведеться це робити в кожному шаблоні, а лише один раз! ## Створення базового шаблону -Базовий шаблон - це основний шаблон, який ви будете розширювати для кожної сторінки вашого веб сайту. +Базовий шаблон - це основний шаблон, який ви будете розширювати для кожної сторінки вашого веб-сайту. Створимо файл `base.html` в `blog/templates/blog/`: @@ -15,7 +15,6 @@ └───blog base.html post_list.html - Відкрийте його і скопіюйте усе з `post_list.html` до файлу `base.html`, як тут: @@ -43,7 +42,7 @@ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} @@ -52,9 +51,8 @@ ``` - -Далі для `base.html`, перепишіть усю частину для `` (усе між `` і ``) на наступне: +Далі для `base.html`, замініть ціле тіло `` (все між `` і ``) цим: ```html @@ -71,19 +69,17 @@ ``` - -В основному ми замінили усе між `{% for post in posts %}{% endfor %}` на: +{% raw %}Зауважте, це замінило все, починаючи від `{% for post in posts %}` до `{% endfor %}`, цим: {% endraw %} ```html {% block content %} {% endblock %} ``` - +Що це означає? Ви щойно створили блок `block`! Використали шаблонний тег `{% block %}` для того, щоб створити місце, в яке буде вставлено HTML. Цей HTML міститиметься в інших шаблонах, які розширюють цей шаблон (`base.html`). Скоро ми покажемо вам, як це зробити. -Що це означає? Ви щойно створили блок - `block`, котрий є шаблонним тегом, що дозволяє вам вставляти в нього HTML в інших шаблонах, які розширюють `base.html`. Скоро ми покажемо вам як це зробити. - -А тепер збережіть зміни і відкрийте знову свій `blog/templates/blog/post_list.html`. Видаліть усе інше, що міститься всередині блоку body і потім також видаліть ``, таким чином файл виглядатиме так: +А тепер збережіть зміни і відкрийте знову свій `blog/templates/blog/post_list.html`. +{% raw %}Видаліть усе, що вище `{% for post in posts %}` і нижче `{% endfor %}`. Коли ви закінчите, файл виглядатиме так:{% endraw %} ```html {% for post in posts %} @@ -92,21 +88,31 @@ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} ``` - -А тепер додайте цей рядок на початок файлу: +Ми хочемо використати це як частина нашого шаблону для всіх блоків контенту. +Час додати теги блоків до цього файлу! -```html -{% extends 'blog/base.html' %} -``` - +{% raw %}Ви хочете, щоб ваший тег блоку підходив до тегу у файлі `base.html`. Ви такоже хочете, щоб він включав в себе весь код, що належить вашим блокам з контентом. Щоб зробити це, розмістіть все між `{% block content %}` і `{% endblock content %}`. Як тут: {% endraw %} -Це означає, що ми розширюємо шаблон `base.html` у файлі `post_list.html`. Залишився лише один момент: розмістіть усе (окрім щойно доданого рядку) між `{% block content %}` та `{% endblock content %}`. Як тут: +```html +{% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +{% endblock %} +``` +Залишився один момент. Нам потрібно поєднати ці два шаблони разом. Це і є розширенням шаблонів. Ми зробимо це додаванням на початок файлу тегу розширення. Як тут: ```html {% extends 'blog/base.html' %} @@ -117,13 +123,12 @@ {{ post.published_date }}

{{ post.title }}

-

{{ post.text|linebreaks }}

+

{{ post.text|linebreaksbr }}

{% endfor %} -{% endblock content %} +{% endblock %} ``` - -Ось і все! Перевірте чи ваш сайт все ще працює коректно :) +Ось і все! Перевірте, чи ваш сайт все ще коректно працює :) -> Якщо з'явилася помилка `TemplateDoesNotExists`, то це говорить про те, що файлу `blog/base.html` не існує і ви маєте в консолі активований `runserver`, спробуйте зупинити його (натиснувши Ctrl+C - кнопки Control і C buttons разом) і перезавантажити запустивши команду `python manage.py runserver`. +> Якщо з'явилася помилка `TemplateDoesNotExists`, то це говорить про те, що файлу `blog/base.html` не існує і ви маєте в консолі запущений `runserver`, спробуйте зупинити його (натиснувши Ctrl+C - кнопки Control і C buttons разом) і перезавантажити командою `python manage.py runserver`. diff --git a/uk/whats_next/README.md b/uk/whats_next/README.md index 20cf6044221..cc03b625155 100755 --- a/uk/whats_next/README.md +++ b/uk/whats_next/README.md @@ -1,40 +1,26 @@ # Що далі? -Привітайте себе! **Ви абсолютно неймовірні**. Ми пишаємося вами! <3 +Привітайте себе! __Ви абсолютно неймовірні.__ Ми пишаємося вами! <3 ### Що тепер робити? -Перепочиньте і розслабтеся. Ви щойно створили дещо дійсно велике. +Перепочиньте і розслабтеся. Ви щойно створили щось дійсно велике. Після цього переконайтеся, що ви: -* Підписалися на Django Girls у [Facebook][1] або на [Twitter][2] щоб бути в курсі усіх подій - - [1]: http://facebook.com/djangogirls - [2]: http://twitter.com/djangogirls +- Підписалися на Django Girls у [Facebook](http://facebook.com/djangogirls) або в [Twitter](https://twitter.com/djangogirls), щоб бути в курсі усіх подій ### Чи можете ви порекомендувати інші джерела? -Так! Спершу, спробуйте нашу іншу книгу, що називається [Django Girls Tutorial: Extensions][3]. - - [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ - -Пізніше, можете спробувати наведені нижче джерела. Дуже рекомендуємо! - -- [Django's official tutorial][4] -- [New Coder tutorials][5] -- [Code Academy Python course][6] -- [Code Academy HTML & CSS course][7] -- [Django Carrots tutorial][8] -- [Learn Python The Hard Way book][9] -- [Getting Started With Django video lessons][10] -- [Two Scoops of Django: Best Practices for Django][11] book - - [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ - [5]: http://newcoder.io/tutorials/ - [6]: http://www.codecademy.com/en/tracks/python - [7]: http://www.codecademy.com/tracks/web - [8]: http://django.carrots.pl/en/ - [9]: http://learnpythonthehardway.org/book/ - [10]: http://gettingstartedwithdjango.com/ - [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6 +Так! Спершу, спробуйте нашу іншу книгу [Django Girls Tutorial: Extensions](http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/). + +Пізніше, ви можете спробувати джерела, перелічені нижче. Дуже рекомендуємо! +- [Django's official tutorial](https://docs.djangoproject.com/en/1.8/intro/tutorial01/) +- [New Coder tutorials](http://newcoder.io/tutorials/) +- [Code Academy Python course](https://www.codecademy.com/en/tracks/python) +- [Code Academy HTML & CSS course](https://www.codecademy.com/tracks/web) +- [Django Carrots tutorial](https://github.com/ggcarrots/django-carrots) +- [Learn Python The Hard Way book](http://learnpythonthehardway.org/book/) +- [Getting Started With Django video lessons](http://gettingstartedwithdjango.com/) +- [Two Scoops of Django: Best Practices for Django 1.8 book](https://twoscoopspress.com/products/two-scoops-of-django-1-8) +- [Hello Web App: Learn How to Build a Web App](https://hellowebapp.com/) diff --git a/zh/GLOSSARY.md b/zh/GLOSSARY.md new file mode 100755 index 00000000000..17ceeab9b1e --- /dev/null +++ b/zh/GLOSSARY.md @@ -0,0 +1,3 @@ +# 代码编辑器 + +代码编辑器是应用程序,允许您将保存您的代码,这样您可以稍后再打开它。 你可以从[代码编辑器](./code_editor/README.md)这一章节了解 \ No newline at end of file diff --git a/zh/README.md b/zh/README.md new file mode 100644 index 00000000000..f676385fa73 --- /dev/null +++ b/zh/README.md @@ -0,0 +1,82 @@ +# Django Girls 教程 + + [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> 这项工作是根据公共创意贡献署名国际协议4.0的要求完成的。若要查看本许可证的副本,请访问https://creativecommons.org/licenses/by-sa/4.0/ + +## 介绍 + +你有没有觉得世界越来越多的是关于技术,而你已经在某种程度上被甩在了后面? 你有没有想去做一个网站,但是却从未有过足够的动力去开始吗? 你有没有想过软件世界太过复杂,即使你想做一些属于自己的东西? + +好的,我们跟你讲一个好消息!编程没有看上去那么复杂,我们将给你展示它是多么的有趣。 + +本教程不会神奇地将你转变为程序员。 如果你想变得擅长于此,你需要数月乃至数年的时间去学习和练习。 但是我们想展示给你编程和创建网站没有看起来那么复杂。 我们试着用深入浅出的方法解释,所以你不会觉得被技术吓到。 + +我们希望我们可以让你变得更爱技术,像我们一样! + +## 在本教程里你会学到什么? + +一旦你完成本教程,你会有一个简单可用的web应用:你自己的博客。我们会教你怎么把它放到网上,这样别人就能看到你的作品! + +它将(或多或少)看起来像这个样子: + +![图0.1][2] + + [2]: images/application.png + +> 如果你独自学习这个教程而苦于没有一位能帮你答疑解惑的的教练,我们给你提供交流的平台:[![Gitter](https://badges.gitter.im/Join Chat.svg)][1]。 我们要求我们的教练以及之前的参与者时不时到那里去,帮助其他人参与本教程! 不要担心什么,尽管大胆地提问吧! + +好嘞,[我们从头开始...][3] + + [3]: ./how_the_internet_works/README.md + +## 关于和贡献 + +这个教程由[DjangoGirls][4]维护。 如果你发现本网有任何错误或想更新教程,请按照 [贡献指导][5]行动. + + [4]: https://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/Contributing.md + +## 中文版的项献者 + +本教程的中文版由下列人员参与翻译,按名字首字母排名: +- Abraham Kan (abrahamkan) +- adv_zxy +- BigBagBOOM +- c2j +- classicalmu (zhanyanqiao) +- cnbabylinke +- Javen (javen_liu) +- jeff kit (bbmyth) +- Joker Qyou (Joker_Qyou) +- Kate Chan (kateismex0) +- liuzhongjun +- meelo +- neal1991 +- neoblackcap +- olasitarska +- pchnet +- rurong (defrur) +- Shit_JinP +- suusatoshigi (SuuSatoshigi) +- wangjiaxi +- wangshunping +- wly522 +- yinhm +- yobo (yfrancesc) +- Yue Du (ifduyue) +- zhangyi2099 +- Zhiheng Lin (onlyice0328) +- 刘奕聪(MrLYC) +- 芝加哥中文Meetup (chicagochinesemeetup) +- 陈艺虹(laceychen1993) + +## 你愿意帮我们翻译将本教程至其他语言吗? + +目前,所有的翻译都储存于crowdin.com的平台,网址是: + +https://crowdin.com/project/django-girls-tutorial + +如果你在crowdin的列表里没看到自己的语言,请以[新开issue][6]的方式通知我们,以便我们加进去。 + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/zh/SUMMARY.md b/zh/SUMMARY.md new file mode 100755 index 00000000000..fafedd53db0 --- /dev/null +++ b/zh/SUMMARY.md @@ -0,0 +1,26 @@ +# 摘要 + +* [介绍](README.md) +* [安装](installation/README.md) +* [互联网是如何工作的?](how_the_internet_works/README.md) +* [命令行介绍](intro_to_command_line/README.md) +* [Python的安装](python_installation/README.md) +* [代码编辑器](code_editor/README.md) +* [Python 简介](python_introduction/README.md) +* [Django 是什么?](django/README.md) +* [Django安装](django_installation/README.md) +* [你的第一个Django 项目 !](django_start_project/README.md) +* [Django模型](django_models/README.md) +* [Django管理](django_admin/README.md) +* [部署!](deploy/README.md) +* [Django urls](django_urls/README.md) +* [Django视图 - 抓紧时间去创建!](django_views/README.md) +* [HTML简介](html/README.md) +* [Django ORM (查询集)](django_orm/README.md) +* [模板中的动态数据](dynamic_data_in_templates/README.md) +* [Django模板](django_templates/README.md) +* [CSS - 让其更漂亮](css/README.md) +* [模板扩展](template_extending/README.md) +* [扩展您的应用](extend_your_application/README.md) +* [Django表单](django_forms/README.md) +* [接下来呢?](whats_next/README.md) diff --git a/zh/code_editor/README.md b/zh/code_editor/README.md new file mode 100755 index 00000000000..aa5f317f017 --- /dev/null +++ b/zh/code_editor/README.md @@ -0,0 +1,7 @@ +# 代码编辑器 + +你马上就要写下第一行代码,现在该下载一个代码编辑器了! + +> **注意**在之前章节你可能已经完成了这一步,如果那样的话,你可以直接进入下一章节。 + +{% include "/code_editor/instructions.md" %} diff --git a/zh/code_editor/instructions.md b/zh/code_editor/instructions.md new file mode 100755 index 00000000000..25efbabebf6 --- /dev/null +++ b/zh/code_editor/instructions.md @@ -0,0 +1,31 @@ +有很多不同的编辑器,通常根据个人偏好选择。 大部分 Python程序员使用像 PyCharm这样复杂但是功能强大的IDE (集成开发环境)。 然而,这可能不太适合初学者。我们建议使用同样强大但是更为简单的编辑器。 + +下面是我们的建议,但是你可以随时咨询你的教练。那样会更容易得到他们的帮助。 + +## Gedit文本编辑器 + +Gedit 是开源、免费的编辑器,支持所有操作系统。 + +[在这里下载](https://wiki.gnome.org/Apps/Gedit#Download) + +## Sublime Text 3编辑器 + +Sublime Text 是一个很受欢迎的、免费试用的编辑器。它很容易安装和使用,并且支持所有操作系统。 + +[在这里下载](https://www.sublimetext.com/3) + +## Atom编辑器 + +Atom 是 [GitHub](https://github.com/) 最新发布的代码编辑器。它开源、免费并且容易安装和使用。它可用于Windows、OSX和 Linux。 + +[在这里下载](https://atom.io/) + +## 我们为什么要安装代码编辑器? + +你可能会疑惑为什么我们要安装代码编辑器软件,而不是使用如 Word 或记事本这样的软件。 + +第一个理由是代码应该是 **纯文本**,如 Word 和Textedit的程序实际上不能产生纯文本,它们产生富文本 (含有字体和格式),使用自定义的格式,如 [RTF (Rich Text Format)](https://en.wikipedia.org/wiki/Rich_Text_Format). + +第二个原因是代码编辑器专长于编辑代码,因此它们可以提供一些有用的功能,比如代码高亮,比如自动闭合引用号。 + +以上这些我们将在实践中具体体会。很快你将会觉得,似乎过时的老文本编辑器正是最得心应手的工具!:) \ No newline at end of file diff --git a/zh/css/README.md b/zh/css/README.md new file mode 100644 index 00000000000..24f4b2e9e73 --- /dev/null +++ b/zh/css/README.md @@ -0,0 +1,313 @@ +# CSS - 让它更好看! + +我们的博客看起来仍然很丑吧?是时候来让它变得更好看了!为此,我们将引入CSS。 + +## 什么是 CSS? + +层叠样式表(Cascading Style Sheets)是一种语言,用来描述使用标记语言(如HTML)写成的网站的外观和格式。把它当做我们网站的化妆 ;)。 + +但我们不想总是从零开始,对吧? 我们将会再一次采用程序们编写并发布到互联网上的免费玩意。 重新发明轮子十分无趣,你懂的。 + +## 让我们用 Bootstrap 吧! + +Bootstrap是最流行的HTML和CSS框架之一,它可以用来开发炫酷的网站:https://getbootstrap.com/ + +起初,它由Twitter的程序员编写,现在由来自世界各地的志愿者写的。 + +## 安装 Boostrap + +若要安装Bootstrap,您需要将它添加到你的 `.html` 文件的 `` 中: + +{% filename %}blog/templates/blog/post_list.html{% endfilename %} +```html + + +``` + +这不会向你的项目添加任何文件。它只是指向在互联网上存在的文件。只需要继续打开您的网站并刷新页面。你瞧! + +![图 14.1][1] + + [1]: images/bootstrap1.png + +已经变得更好看了! + +## Django 中的静态文件 + +最后我们来看看这些我们叫做**静态文件**的东西。 静态文件是指你所有的CSS文件和图片文件,这些文件不是动态的,对所有用户都是一样,不会因为请求内容而发生变化。 + +### Django的静态文件放在哪儿呢? + +Django已经知道到何处找到内建“admin”应用的静态文件。现在我们只需要给我们的`blog`应用添加一些静态文件。 + + +我们在blog应用的目录下创建一个名为`static`的文件夹,创建后目录结构如下: + +``` + djangogirls + ├── blog + │ ├── migrations + │ └── static + └── mysite +``` + + +Django会自动找到你应用文件夹目录下所有名字叫“static”的文件夹,并能够使用其中的静态文件。 + +## 你的第一个 CSS 文件! + +现在让我们创建一个 CSS 文件,为了在您的 web 页中添加你自己的风格。 在`static` 的目录下创建一个新的目录称为 `css` 。 然后,在这个 `css` 目录里创建一个新的文件,称为 `blog.css` 。 准备好了吗? + +``` + djangogirls + └─── blog + └─── static + └─── css + └─── blog.css +``` + + +是时候来写一些CSS了!首先用你的代码编辑器打开`blog/static/css/blog.css`。 + +在这里我们不会太深入学习自定义和关于 CSS的内容 ,因为这些内容很容易而且您可以在本教程结束后自行学习。这页的最后会推荐一个免费课程来学习更多相关的内容。 + +但至少要做一点吧。 也许我们可以改变我们标题的颜色? 计算机使用特殊的编码来了解颜色。 它们以 `#`开始,后面跟着 6 个字母 (A 到 F) 或数字 (0-9)。例如,蓝色的的编码是`#0000FF` 你在这里可以发现许多颜色的编码: http://www.colorpicker.com/。 你也可以使用 [预先定义的颜色][3],如 `red` 和 `green`。 + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +在你的`blog/static/css/blog.css`文件中添加下面的代码: + +```css + h1 a { + color: #FCA205; + } +``` + + +`h1 a`是CSS选择器。 这意味着我们要将我们的样式应用于在 `h1` 元素的任何 `a` 元素 。所以,当我们的代码中有类似`

link

`的代码, 上述的样式就会被应用。在这种情况下,我们会告诉它要改变其颜色为 `#FCA205`,它是橙色的。 当然,你可以把自己的颜色放在这里! + +在 CSS 文件中,我们决定HTML 文件中元素的样式。我们标识元素的第一种方式是用元素名。你可能把来自于HTML段落的这些元素名当做了标签记忆。 例如`a`,`h1`,`body`,这些都是元素名。我们也用属性去标识元素,如 `class` 或属性 `id` 。 类和 id 是你自己给该元素的命名。 类定义元素组,并指向特定元素的 id。 例如,可以使用标记名称 `a`、 类 `external_link` 或 id `link_to_wiki_page` 标识以下标签: + + +```html + +``` + + +可以在 [CSS Selectors in w3schools][4]了解更多. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +我们还需要告诉我们的 HTML 模板,我们添加了一些 CSS。打开 `blog/templates/blog/post_list.html` 文件并在文件最开始的地方添加以下代码: + +```html + {% load staticfiles %} +``` + + +我们刚刚加载了静态文件到这里(译者注:这里实际上是为模板引入staticfiles相关的辅助方法):)。 然后,在`` 和 ``之间,在Bootstrap的CSS文件的引导之后添加以下行: + +```html + +``` + +浏览器按照给定文件的顺序读取文件,所以我们需要确保代码在正确的位置,否则我们文件中的代码可能会覆盖Bootstrap文件中的代码。我们只是告诉我们的模板我们的 CSS 文件所在的位置。 + +现在,您的文件应该像这样: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + + +``` + + +好的保存该文件并刷新网站 ! + +![图 14.2][5] + + [5]: images/color2.png + +干得好 !我想,也许我们也给我们的网站一点空间并增加左边缘。让我们来试试这个 ! + +```css + body { + padding-left: 15px; + } +``` + + +将它添加到你的 css 代码,保存该文件并查看它如何工作 ! + +![图 14.3][6] + + [6]: images/margin2.png + +也许我们可以在我们的头中自定义字体吗?粘贴到你的 `< head >` 在 `blog/templates/blog/post_list.html` 文件中: + +```html + +``` + + +这行将从谷歌的字体 (https://www.google.com/fonts) 中导入称为 *龙虾*的字体 。 + +现在添加一行 `font-family: 'Lobster';` 到CSS文件 `blog/static/css/blog.css` 的 `h1 a` 声明块中(花括弧 `{` 与 `}` 之间的代码),然后刷新页面: + +```css + h1 a { + color: #FCA205; + font-family: 'Lobster'; + } +``` + + +![图 14.3][7] + + [7]: images/font.png + +太棒了! + +如上文所述,CSS 有一个概念叫做类,其中基本上允许您命名的 HTML 代码的一部分并只对这部分应用样式,不会影响其他部分。 它是超级有用的如果你有两个 div,但他们有些很多不一样 (如您的标题和你的帖子)。类可以帮你让它们看起来不同。 + +继续命名部分HTML 代码。添加一个称为 `page-header` 的类到您的 `div`中,其中包含您的标题,像这样: + +```html + +``` + + +和现在将包含一篇博客文章的类`post`添加到您的 `div` 。 + +```html +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+``` + + +现在,我们将向不同的选择器添加声明块。 选择器以 `.` 开始,关联到类。 网络上有很多很棒的CSS教程以及相关解释,帮助您理解下面的代码。 至于现在,就简单地复制粘贴到你的 `blog/static/css/blog.css` 文件中吧。 + +```css + .page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; + } + + .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; + } + + .content { + margin-left: 40px; + } + + h1, h2, h3, h4 { + font-family: 'Lobster', cursive; + } + + .date { + float: right; + color: #828282; + } + + .save { + float: right; + } + + .post-form textarea, .post-form input { + width: 100%; + } + + .top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; + } + + .post { + margin-bottom: 70px; + } + + .post h1 a, .post h1 a:visited { + color: #000000; + } +``` + + +然后将文章的HTML代码用类声明包裹起来。替换以下内容: + +```html + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + + +在 `blog/templates/blog/post_list.html` 是这样的: + +```html +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+``` + + +保存这些文件并刷新您的网站。 + +![图 14.4][8] + + [8]: images/final.png + +呜呼 !看起来棒极了,是吧?看看我们刚在HTML粘贴加入的类以及在CSS中使用的代码。如果你想要时间变成绿松石色,你该在哪里做改变呢? + +不要害怕摆弄这个 CSS,并试图去改变一些东西。调整CSS可以帮你搞明白不同的东西怎样工作。如果你做错了什么东西,别担心,您总是可以撤消它 ! + +我们非常建议在线免费学习这个 [Codeacademy HTML 和 CSS 课程][2] 。它可以帮你学到一切你需要知道的有关如何通过CSS使你的网站更漂亮。 + + [2]: https://www.codecademy.com/tracks/web + +准备好下一章了吗?:) diff --git a/zh/css/images/bootstrap1.png b/zh/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/zh/css/images/bootstrap1.png differ diff --git a/zh/css/images/color2.png b/zh/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/zh/css/images/color2.png differ diff --git a/zh/css/images/final.png b/zh/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/zh/css/images/final.png differ diff --git a/zh/css/images/font.png b/zh/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/zh/css/images/font.png differ diff --git a/zh/css/images/margin2.png b/zh/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/zh/css/images/margin2.png differ diff --git a/zh/deploy/README.md b/zh/deploy/README.md new file mode 100755 index 00000000000..d20d8e4e930 --- /dev/null +++ b/zh/deploy/README.md @@ -0,0 +1,314 @@ +# 部署! + +> **注** 这一章可以有时有点难打通。 坚持并完成它 ;部署是在网站开发过程的重要组成部分。 这一章放在本教程的中部,因此你的指导者可以帮助你在使网站上线中的一些小困难。 这意味着如果您花大量的时间,你仍然能独立完成这个教程。 + +到目前为止您的网站只是在您的计算机上可用,现在您将了解如何部署它 ! 部署是在互联网上发布你的应用程序的一系列过程,因此人们最终可以一起去看看你的应用程序。 + +正如你所学习的,一个网站必须要放到一个服务器上。 在互联网上你可以找到很多的服务器供应商。 我们将使用一个相对简单的部署过程: [PythonAnywhere][1]。 PythonAnywhere 对于一些没有太多访问者的小应用是免费的,所以它对你来说绝对是足够使用的。 + + [1]: https://pythonanywhere.com/ + +其它我们将使用到的外部服务是[GitHub][2],它是一个代码托管服务。 还有其它的一些服务,但当今几乎所有的程序员都有 GitHub 帐户,并且现在你也会有的! + + [2]: https://www.github.com + +我们将使用 GitHub 作为基石,以和 PythonAnywhere 互相传输我们的代码。 + +# Git + +Git是一个被大量程序员使用的"版本控制系统"。 此软件可以跟踪任何时间文件的改变,这样你以后可以随时召回某个特定版本。 有点像Microsoft Word 的"跟踪更改"功能 ,但更强大。 + +## 安装Git + +> **注意** 如果你已经做过安装步骤了,你可以直接跳过这个步骤开始创建你自己的Git版本库。 + +{% include "/deploy/install_git.md" %} + +## 开始我们自己的Git版本库 + +Git跟踪一组特定的在代码仓库(或简称“仓库”)中文件的更改。 我们开始用git管理自己的项目吧。 打开你的终端,进入 `djangogirls` 文件夹运行以下的命令: + +> **注意** 在初始化仓库之前,请使用 `pwd`命令 (OSX/Linux) 或者 `cd` (Windows) 命令检查你当前的工作目录。 你应该是在 `djangogirls` 文件夹下运行命令。 + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config --global user.name "Your Name" + $ git config --global user.email you@example.com + + +每个项目我们只需要初始化一次Git仓库(而且你从此不需要重新输入用户名和邮箱)。 + +Git会追踪这个目录下所有文件和文件夹的更改,但是有一些文件我们希望Git忽略它。 为此,我们可以在系统根目录下创建一个命名为 `.gitignore` 的文件。 打开编辑器,创建新文件并写入以下内容: + + *.pyc + __pycache__ + myvenv + db.sqlite3 + .DS_Store + + +然后在djangogirls项目根目录下保存为 `.gitignore`文件。 + +> **注意** 在文件名最前面的"."很重要。 如果你在创建文件的时候有困难(例如,Macs不能通过Finder创建开头为"."的文件), 可以在编辑器里点击"另存为", 这个没问题的。 + +在执行git操作之前,最好使用 `git status` 命令查看一下当前的状态,尤其是在执行 `git add`或者在你不确定哪些文件被改动的情况下。 这有助于阻止各种意外发生,例如错误的文件被添加或提交。 `git status` 命令会返回所有未追踪/修改/暂存的文件,还有分支状态等信息。 输出会是这样: + + $ git status + On branch master + + Initial commit + + Untracked files: + (use "git add ..." to include in what will be committed) + + .gitignore + blog/ + manage.py + mysite/ + + nothing added to commit but untracked files present (use "git add" to track) + + +最后保存我们的更改。转到你的控制台并运行这些命令: + + $ git add --all . + $ git commit -m "My Django Girls app, first commit" + [...] + 13 files changed, 200 insertions(+) + create mode 100644 .gitignore + [...] + create mode 100644 mysite/wsgi.py + + +## 推送我们的代码到Github上 + +跳转到[GitHub.com][2]网站,注册一个新的免费账号。(如果你在看线下活动之前就已经有账号的话,那就太好了!) + +现在,创建一个新的仓库,命名为“my-first-blog”。 保持 "initialise with a README" 复选框未选中状态,.gitignore 选项为无 (我们已经手动创建了) ,让License设置为无。 + +![][3] + + [3]: images/new_github_repo.png + +> **注意** `my-first-blog`这个名字很重要 — 你可以用其它的,但是这个名字会在教程中出现多次,你需要确保每次都替换掉它。 保持用 `my-first-blog` 这个名字可能更为简单. + +在下一屏中,你将看到你的仓库克隆 URL。选择“HTTPS”版本,拷贝地址,我们马上要把它粘贴到终端: + +![][4] + + [4]: images/github_get_repo_url_screenshot.png + +现在我们需要把你电脑上的Git仓库和Github上的挂接。 + +在控制台输入以下内容(替换 `` 为你的 github 用户名 ,不包含尖括号): + + $ git remote add origin https://github.com//my-first-blog.git + $ git push -u origin master + + +输入你的Github账号名和密码,然后你会看到这样: + + Username for 'https://github.com': hjwp + Password for 'https://hjwp@github.com': + Counting objects: 6, done. + Writing objects: 100% (6/6), 200 bytes | 0 bytes/s, done. + Total 3 (delta 0), reused 0 (delta 0) + To https://github.com/hjwp/my-first-blog.git + * [new branch] master -> master + Branch master set up to track remote branch master from origin. + + + + +你的代码已经在Github上了。 快去确认一下吧! 你会发现这些好家伙们 — [Django][5], [Django Girls Tutorial][6],还有很多其它优秀的开放源代码软件项目同样也在Github上 :) + + [5]: https://github.com/django/django + [6]: https://github.com/DjangoGirls/tutorial + +# 在 PythonAnywhere 设置我们的博客 + +> **注意** 你可能在之前的安装步骤中已经创建 PythonAnywhere 账户 — 如果是的话,那么无需再来一次。 + +{% include "/deploy/signup_pythonanywhere.md" %} + +## 在 PythonAnywhere 上拉取我们的代码 + +当然注册完 PythonAnywhere,你讲会转到仪表盘或“控制台”页面。 选择启动“Bash”控制台这一选项 — 这是 PythonAnywhere 版的控制台,就像你本地电脑上的一样。 + +> **注意** PythonAnywhere 基于 Linux,因此如果你使用 Windows,控制台将会和你本地电脑上的略有不同。 + +让我们通过创建一个我们仓库的 “Clone” 以便从 Github 拉取代码到 PythonAnywhere。 在 PythonAnywhere 控制台输入以下 (不要忘记使用 Github 用户名替换 ``): + + $ git clone https://github.com//my-first-blog.git + + +这将会拉取一份你的代码副本到 PythonAnywhere 上。通过键入`tree my-first-blog` 查阅: + + $ tree my-first-blog + my-first-blog/ + ├── blog + │ ├── __init__.py + │ ├── admin.py + │ ├── migrations + │ │ ├── 0001_initial.py + │ │ └── __init__.py + │ ├── models.py + │ ├── tests.py + │ └── views.py + ├── manage.py + └── mysite + ├── __init__.py + ├── settings.py + ├── urls.py + └── wsgi.py + + +### 在 PythonAnywhere 上创建 virtualenv + +如同你在自己电脑上做的,你可以在 PythonAnywhere 上创建 virtualenv 虚拟环境。在 Bash 控制台下,键入: + + $ cd my-first-blog + + $ virtualenv --python=python3.4 myvenv + Running virtualenv with interpreter /usr/bin/python3.4 + [...] + Installing setuptools, pip...done. + + $ source myvenv/bin/activate + + (mvenv) $ pip install django whitenoise + Collecting django + [...] + Successfully installed django-1.8.2 whitenoise-2.0 + + +> **注意** `pip 安装` 步骤可能需要几分钟。 耐心,耐心!但是如果超过 5 分钟,就不对劲了。 问问你的教练。 + + + +### 收集静态文件。 + +你可曾好奇,什么是"whitenoise"白噪音? 它是用来服务所谓的“static files”静态文件的工具。 静态文件是很少改动或者并非可运行的程序代码的那些文件,比如 HTML 或 CSS 文件。 在我们的计算机上,它们以不同的方式工作,我们需要比如“whitenoise”这样的工具来为其服务。 + +在教程后续编辑网站 CSS 章节会介绍更多有关静态文件的内容。 + +暂且我们只需要在服务器上运行一个额外的命令,就是 `collectstatic`。 它告诉 Django 去收集服务器上所有需要的静态文件。 就眼下来说主要是使admin管理界面看起来更漂亮的文件。 + + (mvenv) $ python manage.py collectstatic + + You have requested to collect static files at the destination + location as specified in your settings: + + /home/edith/my-first-blog/static + + This will overwrite existing files! + Are you sure you want to do this? + + Type 'yes' to continue, or 'no' to cancel: yes + + +键入 "yes", 然后它会自行运转!你可喜欢让计算机打印一页一页令人费解的文本? 我总会弄点噪音作为伴奏。Brp, brp brp... + + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/actions.min.js' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/js/inlines.min.js' + [...] + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/changelists.css' + Copying '/home/edith/my-first-blog/mvenv/lib/python3.4/site-packages/django/contrib/admin/static/admin/css/base.css' + 62 static files copied to '/home/edith/my-first-blog/static'. + + +### 在 PythonAnywhere 上创建数据库 + +服务器与你自己的计算机不同的另外一点是:它使用不同的数据库。因此用户账户以及文章和你电脑上的可能会有不同。 + +我们可以像在自己的计算机上一样在服务器上初始化数据库,使用 `migrate` 以及 `createsuperuser`: + + (mvenv) $ python manage.py migrate + Operations to perform: + [...] + Applying sessions.0001_initial... OK + + + (mvenv) $ python manage.py createsuperuser + + Context | Request Context + + + +## 将我们的博客发布为一个网络应用程序 + +现在我们的代码已在PythonAnywhere上,我们的 virtualenv 已经准备好,静态文件已收集,数据库已初始化。我们准备好发布网络应用程序! + +通过点击 logo 返回到 PythonAnywhere 仪表盘,然后点击 **Web** 选项卡。最终,点 **Add a new web app**. + +在确认你的域名之后,选择对话框中 **manual configuration** (注 *不是* "Django" 选项) : 下一步选择 **Python 3.4**,然后点击 Next 以完成该向导。 + +> **注意** 确保你选中 "Manual configuration" 选项,而不是 "Django" 那个。我们太牛逼,所以不要用 PythonAnywhere Django 默认设置 ;-) + +### 设置 virtualenv + +你将会被带到 PythonAnywhere 上你的Web 应用程序的配置屏,那个页面是每次你想修改服务器上你的应用程序时候要去的页面。 + +![][7] + + [7]: images/pythonanywhere_web_tab_virtualenv.png + +在 “Virtualenv” 一节,点击红色文字 “Enter the path to a virtualenv",然后键入: `/home//my-first-blog/myvenv/`。 前进之前,先点击有复选框的蓝色框以保存路径。 + +> **注意** 替换你自己的用户名。如果你犯了错,PythonAnywhere 会显示一个小警告。 + +### 配置 WSGI 文件 + +Django 使用 “WSGI 协议”,它是用来服务 Python 网站的一个标准。PythonAnywhere 支持这个标准。 PythonAnywhere 识别我们 Django 博客的方式是通过配置 WSGI 配置文件。 + +点击 “WSGI configuration file” 链接(在 "Code" 一节,接近页面上方 — 它将被命名为如 `/var/www/_pythonanywhere_com_wsgi.py`),然后跳转到一个编辑器。 + +删除所有的内容并用以下内容替换: + + import os + import sys + + path = '/home//my-first-blog' # use your own username here + if path not in sys.path: + sys.path.append(path) + + os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' + + from django.core.wsgi import get_wsgi_application + from whitenoise.django import DjangoWhiteNoise + application = DjangoWhiteNoise(get_wsgi_application()) + + +> **注意** 当看到 ``时,别忘了替换为你自己的用户名。 + +这个文件的作用是告诉 PythonAnywhere 我们的Web应用程序在什么位置,Django 设置文件的名字是什么。它也设置 "whitenoise" 静态文件工具。 + +点击 **Save** 然后返回到 **Web** 选项卡。 + +一切搞定!点击大大的绿色 **Reload** 按钮然后你将会看到你的应用程序。页面的顶部可以看到它的链接。 + +## 调试小贴士 + +如果你在访问你的网站时候看到一个错误,首先要去 **error log** 中找一些调试信息。 你可以在 PythonAnywhere [Web 选项卡][8] 中发现它的链接。 检查那里是否有任何错误信息,底部是最新的信息。 常见问题包括: + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +* 忘记我们在控制台中的步骤之一:创建 virtualenv,激活它,安装 Django 进去,运行 collectstatic,迁移数据库。 + +* 在 Web 选项卡中,virtualenv 路径设置错误 — 如果真是这样,这通常会是一个红色错误消息。 + +* WSGI 文件设置错误 — 你的 my-first-blog 目录地址设置是否正确? + +* 你是否为你的 virtualenv 选择了同样的 Python 版本,如同 Web 应用程序里的那样?两个应该都是 3.4。 + +* 有一些常见的调试小贴士在 [general debugging tips on the PythonAnywhere wiki][9] 里. + + [9]: https://www.pythonanywhere.com/wiki/DebuggingImportError + +记住,你的教练会在这里帮你! + +# 你上线了! + +你网站的默认页面说 “Welcome to Django”,如同你本地计算机上的一样。 试着添加 `/admin/`到URL的末尾,然后你会到达管理者的页面。 输入用户名和密码登录,然后你会看到服务器上的 add new Posts 。 + +给你自己一个*超大*的鼓励! 服务器部署是web开发中最棘手的部分之一, 它通常要耗费人们几天时间才能搞定。 但你的网站已经上线,运转在真正的互联网上,就是这样! diff --git a/zh/deploy/images/github_get_repo_url_screenshot.png b/zh/deploy/images/github_get_repo_url_screenshot.png new file mode 100644 index 00000000000..44412f84823 Binary files /dev/null and b/zh/deploy/images/github_get_repo_url_screenshot.png differ diff --git a/zh/deploy/images/new_github_repo.png b/zh/deploy/images/new_github_repo.png new file mode 100644 index 00000000000..6e19174ec88 Binary files /dev/null and b/zh/deploy/images/new_github_repo.png differ diff --git a/zh/deploy/images/pythonanywhere_web_tab_virtualenv.png b/zh/deploy/images/pythonanywhere_web_tab_virtualenv.png new file mode 100644 index 00000000000..cafa22c2d97 Binary files /dev/null and b/zh/deploy/images/pythonanywhere_web_tab_virtualenv.png differ diff --git a/zh/deploy/install_git.md b/zh/deploy/install_git.md new file mode 100755 index 00000000000..5751a997d5f --- /dev/null +++ b/zh/deploy/install_git.md @@ -0,0 +1,17 @@ +### Windows系统 + +你可以从 [git-scm.com](https://git-scm.com/) 下载Git。 你可以在所有的安装步骤中点击"next next next",除了第5步"Adjusting your PATH environment",需要选择"Run Git and associated Unix tools from the Windows command-line"(底部的选项)。 除此之外,默认值都没有问题。 签出时使用 Windows 风格的换行符,提交时使用 Unix 风格的换行符,这样比较好。 + +### MacOS系统 + +从[git-scm.com](https://git-scm.com/)下载Git,根据说明操作。 + +### Linux系统 + +如果git还没有被安装的话,你可以从你的软件包管理器中下载git, 请试试下面命令: + + sudo apt-get install git + # or + sudo yum install git + # or + sudo zypper install git diff --git a/zh/deploy/signup_pythonanywhere.md b/zh/deploy/signup_pythonanywhere.md new file mode 100755 index 00000000000..d9aa35e29d6 --- /dev/null +++ b/zh/deploy/signup_pythonanywhere.md @@ -0,0 +1,5 @@ +下一步,在PythonAnywhere注册一个“Beginner”账户。 + + * [www.pythonanywhere.com](https://www.pythonanywhere.com/) + +> **注意** 在这里选择的用户名会出现在博客链接的地址当中`yourusername.pythonanywhere.com` ,因此最好选择你自己的绰号或者是与博客内容相关的名字。 \ No newline at end of file diff --git a/zh/django/README.md b/zh/django/README.md new file mode 100755 index 00000000000..0a67bddd664 --- /dev/null +++ b/zh/django/README.md @@ -0,0 +1,27 @@ +# Django 是什么? + +Django (*/ˈdʒæŋɡoʊ/jang-goh*) 是用 Python 写的一个自由和开放源码 web 应用程序框架。 web框架是一套组件,能帮助你更快、更容易地开发web站点。 + +当你开始构建一个web站点时,你总需要一些相似的组件:处理用户认证(注册、登录、登出)的方式、一个管理站点的面板、表单、上传文件的方式,等等。 + +幸运的是,其他人很早就注意到web开发人员会面临一些共同的问题。所以他们联手创建了 web 框架(Django 是其中一个)来让你使用。 + +由于框架的存在,你无需重新发明轮子就能建立新的站点。 + +## 你为什么需要一个框架? + +要理解什么是Django, 我们需要更仔细的看一下服务器。 服务器需要知道的第一件事就是你希望它为你的网页做什么。 + +想象一个用来监控接收邮件(请求)的邮箱(端口)。 这就是网站服务器做的事情。 网站服务器读这封信,然后将响应发送给网页。 但是当你想发送一些东西的时候,你必须要有一些内容。 而Django就是可以帮助您创建内容的工具。 + +## 当有人向您的服务器请求一个网站,会发生什么呢? + +当一个请求到达网站服务器,它会被传递到Django,试图找到实际上什么是被请求的。 它首先会拿到一个网页的地址,然后试图去弄清该做什么。 这个部分是由Django的**urlresolver**(url解析器。注意一个网站的地址被叫做URL,统一资源定位器,所以*url解析器*是有意义的)。 它并不十分聪明,他接受一个模式列表,然后试图去匹配 URL。 Django从顶到底检查模式,如果有匹配上的,那么Django会将请求传递给相关的函数(这被称作*视图*)。). + +想象一个邮递员拿着一封信。 她沿着街区走下去,检查每一个房号与信件地址是否对应。 如果匹配上了,她就把信投在那里。 这也是url解析器的工作方式! + +在*视图*函数里做了很多有趣的事情:我们能在数据库中寻找到一些信息。 如果用户要求修改数据呢? 就像一封信里说,“请修改我的工作描述”,*视图* 将检查是否你允许它这么干,然后更新工作描述并发回一个消息:“做完了”。 然后*视图*生成响应,并且Django能够发送给用户的web浏览器。 + +当然,上述的描述是有一些简化的,但是你不需要去知道所有的技术的东西。有一个大概的想法就够了。 + +所以不要太过深入细节,我们会简单用Django创建一些东西,然后我们会在学习的路上学到所有重要的部分! \ No newline at end of file diff --git a/zh/django_admin/README.md b/zh/django_admin/README.md new file mode 100755 index 00000000000..ed5e27ba0f9 --- /dev/null +++ b/zh/django_admin/README.md @@ -0,0 +1,48 @@ +# Django admin 管理后台 + +我们将使用 Django admin 添加,编辑和删除我们刚刚创建的帖子。 + +让我们打开`blog/admin.py`文件,并替换其中的文件像这样: + +```python +from django.contrib import admin +from .models import Post + +admin.site.register(Post) +``` + +如你所见,我们导入(包括)了前一章定义的Post模型。 为了让我们的模型在admin页面上可见,我们需要使用`admin.site.register(Post)`来注册模型. + +OK, 现在来看看我们的 Post 模型。 记得先在控制台输入`python manage.py runserver`启动服务器。 然后打开浏览器,输入地址http://127.0.0.1:8000/admin/你会看到登录界面像这样: + +![登录页面][1] + + [1]: images/login_page2.png + +为了登录, 你需要创建一个掌控整个网站所有东西的*超级用户*。 回到刚才的命令行,输入`python manage.py createsuperuser`,按下Enter。 然后输入你的用户名(英文小写,不保护空格), 邮箱和密码。 你输密码的时候看不见输入?别担心,它就是这样的。 你就输入要输得到然后按`Enter`继续就好了。 输出应该长得像这样(用户名和邮箱应该是你自己的): + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +返回到你的浏览器,用你刚才的超级用户来登录,然后你应该能看到Django admin的管理面板。 + +![Django管理][2] + + [2]: images/django_admin3.png + +到 Posts 页面多试几次,发布5、6条博客文章,不用担心你的文章内容,你可以复制粘贴这个教程的一些文字,这样比较节约时间 :)。 + +请确保至少有两到三个帖子(但不是全部)具有设置的发布日期。它在以后会有用。 + +![Django管理][3] + + [3]: images/edit_post3.png + +如果你想更多地了解Django admin模块,你可以查看Django 的官方文档:https://docs.djangoproject.com/en/1.8/ref/contrib/admin/ + +现在你可以来杯咖啡(或者是茶) 或吃点东西给自己充下电,你刚刚创建了你的第一个Django模型,你应该休息一下。 diff --git a/zh/django_admin/images/django_admin3.png b/zh/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/zh/django_admin/images/django_admin3.png differ diff --git a/zh/django_admin/images/edit_post3.png b/zh/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/zh/django_admin/images/edit_post3.png differ diff --git a/zh/django_admin/images/login_page2.png b/zh/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/zh/django_admin/images/login_page2.png differ diff --git a/zh/django_forms/README.md b/zh/django_forms/README.md new file mode 100755 index 00000000000..36bf57356ae --- /dev/null +++ b/zh/django_forms/README.md @@ -0,0 +1,426 @@ +# Django表单 + +我们最后一件关于我们的网站的事情就是创建一个漂亮的方式来增加和编辑博客文章。 Django的`管理`是很酷,但是它很难去自定义,变得更漂亮。 通过`forms`,我们可以拥有对我们界面绝对的权利—我们能够做几乎我们能想象到的所有事情! + +Django表单的一个好处就是我们既可以从零开始自定义,也可以创建`ModelForm`,它将表单的结果保存到模型里。 + +这正是我们想做的:我们将为我们自己的`Post`模型创建一个表单。 + +就像所有Django的重要部分一样,表单有他们自己的文件`forms.py`。. + +我们需要创建一个文件,把它的名字放在`blog`目录下。 + +``` + blog + └── forms.py +``` + + +好吧,让我们打开它,然后键入以下代码: + +```python +from django import forms + +from .models import Post + +class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) +``` + + +首先我们需要导入Django表单(`from django import forms`)然后,显然是我们的`Post`模型(`from .models import Post

+ +

PostForm`, 正如你所猜想的,是我们表单的名字。 我们需要告诉Django,这个表单是一个`ModelForm`(所以Django将会为我们变一些魔法)—`forms.ModelForm`对此负责。 + +下面,我们有`class Meta`,在这里我们告诉Django哪个模型会被用来创建这个表单(`model=Post`)。). + +最后,我们可以说哪些字段会在我们的表单里出现。 在这个场景里,我们只想要`title`和`text`显示出来—`author`应该是当前登录的人(你!)然后`created_date`应该是我们创建文章时自动分配的(比如,在代码里),对吗? + +就是这样!现在我们所有要做的就是在*视图*里使用表单,然后展现在在模板里。 + +所以下次我们将会创建:一个指向页面的链接,一个URL,一个视图和一个模板。 + +## 指向页面表单的链接 + +是时候打开`blog/templates/blog/base.html`了。我们将添加一个链接到`div`,命名为`page-header`: + +```html + +``` + + +请注意我们想要调用我们的新视图`post_new`. + +添加了新的行后,你的html文件现在应该看起来像这样: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + +

+
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + +``` + + +然后保存,刷新http://127.0.0.1:8000页面,你可以明显地看到一个熟悉的`NoReverseMatch`错误信息,是吧? + +## URL + +我们打开`blog/urls.py`然后添加一个新行: + +```python + url(r'^post/new/$', views.post_new, name='post_new'), +``` + + +最终代码会看起来像这样: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), + url(r'^post/new/$', views.post_new, name='post_new'), +] +``` + + +刷新网页后,我们看到一个`AttributeError`,因为我们没有实现`post_new`视图。让我们现在把它加上吧。 + +## post_new视图 + +现在打开`blog/views.py`文件,加入下面的各行到`from`行下: + +```python +from .forms import PostForm +``` + + +还有我们的*view*: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + + +为了创建一个新的`Post`表单,我们需要调用`PostForm()`,然后把它传递给模板。 我们会回到这个*视图*,但是现在,让我们为这个表单快速创建一个模板。 + +## 模板 + +我们需要在`blog/templates/blog`目录下创建一个文件`post_edit.html`。为了创建一个表单,我们需要几件事情: + +* 要展示表单,我们只需要很简单地加上`{% raw %}{{ form.as_p }}{% endraw %}`. +* 上面的这行需要被HTML表单标签包裹:`...` +* 我们需要一个`Save`按钮。我们通过使用一个HTML按钮来完成:`` +* 最后在`
`标签后,我们需要加上`{% raw %}{% csrf_token %}{% endraw %}`。 这个非常重要,因为他会让你的表单变得更安全! Django会提醒你,当你试图保存表单而你又恰巧忘了这一点: + +![CSFR Forbidden page][1] + + [1]: images/csrf2.png + +好,让我们看看HTML 在`post_edit.html`里应该看起来什么样: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +

New post

+ {% csrf_token %} + {{ form.as_p }} + +
+ {% endblock %} +``` + + +现在刷新!哇!你的表单显示出来了! + +![新表单][2] + + [2]: images/new_form2.png + +但是,请等一下!当你键入诸如`title`和`text`字段,然后视图保存它—下面会发生什么? + +什么都没有!我们再一次回到了同一个页面,然而我们的文本已经消失了...同时没有新的文章被发布。所以错在哪里了呢? + +答案是:没有错误。我们需要在我们的*视图*里做更多的工作. + +## 保存表单 + +再一次打开`blog/views,py`。我们在看到`post_new`中的视图内容是: + +```python +def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + + +当我们提交表单,我们都回到相同的视图,但是这个时候我们有一些更多的数据在 `request`,更具体地说在 `request.POST` (命名和博客后缀"post"无关,它只是用来帮我们"上传"数据)。 还记得在HTML文件里,我们的`
`定义有一个方法`method="POST"`? 现在所有从表单来的东西都在`request.POST`. 你不应该重命名`POST`为其他任何东西(其他唯一有效的`method`值是`GET`,但是我们没有时间去解释它们两者的区别是什么)。 + +所以在我们的*视图*里,我们有了两种不同的情况去处理。 首先:当我们首次访问一个页面,我们想要得到一个空白的页面。 第二:当我们回到*视图*,要有我们所有我们刚刚键入的数据。 所以我们需要添加一个条件判断(我们为此使用`if`)。 + +```python + if request.method == "POST": + [...] + else: + form = PostForm() +``` + + +现在去填写`[...]`。如果`method` 是 `POST`,那么我们要用表单里的数据构建`PostForm`,对吗?我们会这样做: + +```python + form = PostForm(request.POST) +``` + + +很容易吧!下一件事情就是去检查表单是否正确(所有必填字段都要被设置并且不会保存任何不正确的值)。我们将使用`form.is_valid()`来实现. + +我们检查表单是否正确,如果是我们就保存它! + +```python + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() +``` + + +基本上,我们这里有两件事情:我们使用`form.save`保存表单,我们添加一个作者(因为 `PostForm` 中没有`author`字段,然而这个字段是必须的!)。 `commit=False`意味着我们还不想保存`Post`模型—我们想首先添加作者。 大多数情况下,当你使用`form.save()`时,不会使用`commit=False`,但是在这种情况下,我们需要这样做。 `post.save()`会保留更改(添加作者),并创建新的博客文章! + +最后,如果我们能够立即去`post_detail`页面创建新的博客内容,那将很酷,对吗?为了做到这点,我们需要再导入一个: + +```python + from django.shortcuts import redirect +``` + + +把它添加到你文件的最开始处。现在我们可以说:创建完新帖子我们就转去`post_detail`页面。 + +```python + return redirect('blog.views.post_detail', pk=post.pk) +``` + + +`blog.views.post_detail` 是我们想去的视图的名字。 还记得这个*视图* 需得具有一个 `pk` 变量吗? 为了把它传递给视图我们使用`pk=post.pk`, 其中 `post` 就是我们刚刚创立的博客帖子! + +好吧,我们已经说了很多了,但可能我们想看到整个*视图*现在看起来什么样,对吗? + +```python +def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) +``` + + +让我们看看它是否正常工作。 转到页 http://127.0.0.1:8000//post/new/,添加 `title` 和 `text`,将它保存... 看! 新博客文章已经加进来了,我们被重定向到`post_detail`页面! + +你可能已经注意到在保存博客文章之前我们设置发布日期。稍后,我们讲介绍一个在 **Django Girls 教程:扩展**中介绍 *publish button* 。. + +太棒了! + +## 表单验证 + +现在,我们将给你展现Django表单是多么酷。 一篇博客文章需要有`title`和`title`字段。 在我们的`Post`模型中我们并没有说(和`发布日期`恰恰相反)这些字段不是必须的,所以Django,默认期望他们是有存储数据的。 + +尝试不带`title`和`text`内容保存表单。猜猜,会发生什么! + +![表单验证][3] + + [3]: images/form_validation2.png + +Django会处理验证我们表单里的所有字段都是正确的。这不是很棒? + +> 因为我们最近使用过Django管理界面,系统目前认为我们已经登录了。 有几种情况可能导致我们被登出(关闭浏览器,重新启动数据库等等)。 如果你发现当你创建一个文章时得到了一个指向未登录用户错误的时候,前往管理页面`http://127.0.0.1:8000/admin`,再登录。 这会暂时解决问题。 有一个一劳永逸的方法在等着你,可以看看只要教程后的**Homework: add security to your website!** 章节。 + +![记录错误][4] + + [4]: images/post_create_error.png + +## 编辑表单 + +现在我们知道如何添加一个新的表单。 但是如果我们想编辑一个现有的呢? 这和我们刚才做的非常相似。 让我们快速创建一些重要的东西(如果你还不清楚他们,你应该问问你的教练或者看看前面的章节,因为我们已经覆盖了所有的这些步骤)。 + +打开 `blog/templates/blog/post_detail.html` 并添加以下行: + +```html + +``` + + +所以模板看起来像这样: + +```html + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} + +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + + +在`blog/urls.py`里我们添加这行: + +```python + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), +``` + + +我们将复用模板`blog/templates/blog/post_edit.html`,所以最后缺失的东西就是 *view*. + +让我们打开`blog/views.py`,并在文件的最后加入: + +```python +def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.published_date = timezone.now() + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) +``` + + +这看起来几乎完全和我们的`post_new`视图一样,对吗? 但是不完全是。 第一件事:我们从urls里传递了一个额外的`pk`参数。 然后:我们得到了`Post`模型,我们想编辑`get_object_or_404(Post, pk=pk)`,然后当我们创建了一个表单我们用一个`实例`来传递这篇文章,当我们想保存它: + +```python + form = PostForm(request.POST, instance=post) +``` + + +当我们只是打开这篇文章的表单来编辑时: + +```python + form = PostForm(instance=post) +``` + + +好,让我们来试试它是否可以工作!让我们先去`post_detail`页面。在右上角应该有一个编辑按钮: + +![编辑按钮][5] + + [5]: images/edit_button2.png + +当你点击它的时候,你会看到我们博客文章的表单。 + +![编辑表单][6] + + [6]: images/edit_form2.png + +随意修改标题和内容,然后保存更改! + +祝贺你!你的应用程序正在变得越来越完整! + +如果你需要更多关于Django表单的信息,你应该阅读文档: https://docs.djangoproject.com/en/1.8/topics/forms/ + +## 安全性 + +能够通过点击一条连接进行发布确实不错。 但是现在,任何访问你网站的人都能够发布一条新博客日志,这可能不是你想要的。 那让我们来让这个发布按钮只显示给你,对其他人则不显示。 + +在 `blog/templates/blog/base.html`中,找到我们 `page-header` `div` 和你早些时候在放那里锚点标记。看起来应该像这样: + +```html + +``` + + +我们要将另一个 `{% if %}` 标记到这, 这会使链接仅在以管理者身份登录的用户访问时显示。现在来说,管理员就是你! 像这样修改 `` 标记: + +```html + {% if user.is_authenticated %} + + {% endif %} +``` + + +这个 `{% if %}` 会使得链接仅仅发送到哪些已经登陆的用户的浏览器。 这并不能完全保护发布新文章,不过这是很好的第一步。 我们将在扩展课程中包含更多安全部分。 + +你应已登录,如果你刷新页面,你不会看到有什么不同。不过,在新的浏览器或隐身窗口中加载页,你会看不到这个链接! + +## 还有一件事:部署时刻! + +我们来看看这一切能否运行在 PythonAnywhere 上。另一次部署的时间到了! + +* 首先,提交你的新代码,然后将它推送到 Github 上 + + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added views to create/edit blog post inside the site." + $ git push +``` + + +* 然后,在一个 [PythonAnywhere 的 Bash 终端][7]里运行: + + [7]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + + +* 最后,跳到 [Web 标签页][8] 并点击**重新载入**. + + [8]: https://www.pythonanywhere.com/web_app_setup/ + +就是这样!祝贺你:) diff --git a/zh/django_forms/images/csrf2.png b/zh/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/zh/django_forms/images/csrf2.png differ diff --git a/zh/django_forms/images/drafts.png b/zh/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/zh/django_forms/images/drafts.png differ diff --git a/zh/django_forms/images/edit_button2.png b/zh/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/zh/django_forms/images/edit_button2.png differ diff --git a/zh/django_forms/images/edit_form2.png b/zh/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/zh/django_forms/images/edit_form2.png differ diff --git a/zh/django_forms/images/form_validation2.png b/zh/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/zh/django_forms/images/form_validation2.png differ diff --git a/zh/django_forms/images/new_form2.png b/zh/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/zh/django_forms/images/new_form2.png differ diff --git a/zh/django_forms/images/post_create_error.png b/zh/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/zh/django_forms/images/post_create_error.png differ diff --git a/zh/django_installation/README.md b/zh/django_installation/README.md new file mode 100755 index 00000000000..03e24e663cb --- /dev/null +++ b/zh/django_installation/README.md @@ -0,0 +1,5 @@ +# Django安装 + +> **注意**如果你已完成了安装步骤,可以直接进入下一章。 + +{% include "/django_installation/instructions.md" %} diff --git a/zh/django_installation/instructions.md b/zh/django_installation/instructions.md new file mode 100755 index 00000000000..611e7a79b88 --- /dev/null +++ b/zh/django_installation/instructions.md @@ -0,0 +1,113 @@ +> 本节部分内容基于 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) 教程而来。 +> +> 本章的部分内容基于 [django-marcador 教程](http://django-marcador.keimlink.de/) ,使用知识共享署名-4.0 国际许可协议许可。 Django-marcador 教程的版权归 Markus Zapke-Gründemann 所有。 + +## 虚拟环境 + +在安装 Django 之前,我们会让你安装一个非常实用的工具,它可以让你计算机上的编码环境保持整洁。 这个步骤可以跳过,但我们强烈建议你跟着做。 从最佳实践设置开始将会在未来为你省去无数的烦恼! + +所以,让我们创建一个 **虚拟环境** (也称为 *virtualenv*)。 虚拟环境会以项目为单位将你的 Python/Django 安装隔离开。 这意味着对一个网站的修改不会影响到你同时在开发的其他任何一个网站。 优雅吧? + +你需要做的就是找到您想创建 `虚拟环境`的一个目录 ;比如您的主目录。 在 Windows 上,它可能看起来像 `C:\Users\Name` (其中 `Name` 是您的登录名)。 + +在本教程中我们将使用您的 home 目录下的一个新目录 `djangogirls` : + + mkdir djangogirls + cd djangogirls + + +我们将虚拟环境称为 `myvenv`。一般的命令格式是: + + python3 -m venv myvenv + + +### Windows系统 + +若要创建新的 `虚拟环境`,您需要打开的控制台 (我们在前几章里已经告诉过你了,还记得吗?),然后运行 `C:\Python34\python -m venv myvenv`。 它看起来会像这样: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + +`C:\Python34\python` 是您之前安装Python的目录, `myvenv` 是您`虚拟环境` 的名字。 你可以使用其他任何名字,但请坚持使用小写,并不要使用空格、重音符号或特殊字符。 始终保持名称短小是个好主意 — — 你会大量引用它 ! + +### Linux 和 OS X + +在 Linux 和 OS X 上创建的 `虚拟环境` 就和运行 `python3 -m venv myvenv` 一样简单。看起来像这样: + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` 是您 `虚拟环境` 的名字。 您可以使用其他任何名称,但请始终使用小写以及不要有空格。 始终保持名称短小是个好主意,因为你会大量引用它! + +> **注意:** 在Ubuntu 14.04上启动虚拟环境会报以下错误: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> 为了解决这个问题,请使用 `virtualenv` 命令。 +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## 使用虚拟环境 + +上面的命令将创建一个名为 `myvenv` 目录 (或任何你选择的名字),其中包含我们的虚拟环境 (基本上是一堆的目录和文件)。 + +#### Windows系统 + +运行如下命令进入你的虚拟环境: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +#### Linux 和 OS X + +运行如下命令进入你的虚拟环境: + + ~/djangogirls$ source myvenv/bin/activate + + +记住要将 `myvenv` 替换成你选择的 `虚拟环境`的 名字 ! + +> **注:** 有时 `source` 可能不可用。在这些情况下试着做这面这些事情: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +当你看到在您的控制台中有如下提示就知道你已经进入 `虚拟环境` : + + (myvenv) C:\Users\Name\djangogirls> + + +或: + + (myvenv) ~/djangogirls$ + + +注意 `(myvenv)`前缀的出现 ! + +当在一个虚拟的环境中工作时,`python` 将自动指向正确的版本,因此您可以使用 `python` 代替 `python3`. + +好的现在所有重要的依赖关系已经就位。最后,我们可以安装 Django ! + +## 安装 Django + +既然你有了`虚拟环境` ,您可以使用 `pip`安装 Django 。在控制台中,运行 `pip install django==1.8` (注意我们使用双等于号: `==`). + + (myvenv) ~$ pip install django==1.8 + Downloading/unpacking django==1.8 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +在 Windows上 + +> 如果你在 Windows 平台上调用 pip 时得到一个错误,请检查是否您项目的路径名是否包含空格、 重音符号或特殊字符 (如:`C:\Users\User Name\djangogirls`)。 若的确如此,请尝试移动它到另外一个没有空格、重音符号或特殊字符的目录,(例如:`C:\djangogirls`)。 在移动之后,请重试上面的命令。 + +在 Linux 上 + +> 如果你在Ubuntu 12.04上得到一个错误,请运行 `pip python -m pip install -U --force-reinstall pip`来修复虚拟环境中的pip安装。 + +就是这样!你现在(终于)准备好创建一个 Django 应用程序! diff --git a/zh/django_models/README.md b/zh/django_models/README.md new file mode 100755 index 00000000000..fcbd9a95bea --- /dev/null +++ b/zh/django_models/README.md @@ -0,0 +1,175 @@ +# Django模型 + +我们现在将要创建的是一个能存储我们博客所有文章的东西。为了达到这个目的,我们将要讲解一下一个被称为`objects(对象)`的东西. + +## 对象 + +在编程中有一个概念叫做 `面向对象编程` 。 它的思想是,与其用无聊的一连串的程序指令方式写程序,我们不如为事物建立模型,然后定义他们是怎样互相交互的。 + +那什么是对象呢?它是一个属性和操作的集合。它听起来很奇怪,但我们会给你一个例子。 + +如果我们想塑造一只猫的模型,我们会创建一个名为`Cat`的对象,它含有一些属性例如:`color`, `age`, `mood`(又比如:good, bad, sleepy ;)),还有`owner(主人)` (那是一个`Person`对象或者假若是流浪猫,这个属性可以为空)。 + +然后这个`Cat`会有一些行为: `purr`, `scratch`, 或者`feed` (在这其中我们会给这只猫一些 `CatFood`,这个`CatFood`可以是单独的一个包含比如<0>taste属性的对象). + + Cat + -------- + color + age + mood + owner + purr() + scratch() + feed(cat_food) + + + CatFood + -------- + taste + + +所以基本思想就是用包含属性的代码来描述真实的东西(称为 `对象属性`)和操作 (称为 `方法`). + +我们将如何为博客帖子建立模型呢?我们想要建立一个博客,对吗? + +我们需要回答一个问题:什么是一篇博客文章?它应该含有什么样的属性? + +嗯,肯定我们的博客文章需要一些文本,包括内容与标题,对吗? 我们也需要知道是谁写的 — — 所以我们需要一位作者。 最后,我们想要知道什么时候该文章创建并发布。 + + Post + -------- + title + text + author + created_date + published_date + + +一篇博客文章需要做什么样的事情?应该有一些正确的 `方法` 来发布文章,对吗? + +因此我们需要一个`publish`的方法 + +既然我们已经知道什么是我们想要实现的,让我们开始在Django里面为它建模! + +## Django模型 + +知道什么是对象,我们可以为我们的博客文章创建一个 Django 模型。 + +Django 里的模型是一种特殊的对象 — — 它保存在 `数据库` 中。 数据库是数据的集合。 这是您存储有关用户、 您的博客文章等信息的地方。 我们将使用SQLite 数据库来存储我们的数据。 这是默认的 Django 数据库适配器 — — 对于我们现在的需求而言它是足够的。 + +您可以将数据库中的模型看作是电子表格中的列 (字段) 和行 (数据)。 + +### 创建应用程序 + +为了让一切保持整洁,我们将我们的项目内部创建单独的应用程序。 如果一开始就让每一件东西井然有序,那就太好了。 为了创建一个应用程序,我们需要在命令行中执行以下命令 (从`manage.py` 文件所在的`djangogirls` 目录): + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +你会注意到一个新的 `blog` 目录被创建,它现在包含一些文件。我们的目录和我们的项目中的文件现在应该看起来像这样: + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +创建应用程序后,我们还需要告诉 Django 它应该使用它。 我们是在 `mysite/settings.py`文件中这样做的。 我们需要找到 `INSTALLED_APPS` 并在它下面添加一行`'blog'` 。 所以最终的代码应如下所示: + + INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', + ) + + +### 创建一个博客文章模型 + +我们在 `blog/models.py` 文件中,定义所有的 `Models` 对象— — 我们将在其中都定义我们的博客文章。 + +让我们打开 `blog/models.py`,从中删除一切并编写这样的代码: + + from django.db import models + from django.utils import timezone + + + class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title + + +> 当你在`str`的两端使用两个下划线字符(`_`)的时候务必三思而后行。 这是Python编程里面的一种常见的约定写法,有时我们也叫这个做"dunder"("double-underscore"的缩写)。 + +这看起来太吓人了,对吧?不过不用担心,我们会解释这几行是什么意思! + +所有以 `from` 或 `import` 开始的所有行,都是需要从其他文件中添加一些内容。 所以与其复制和粘贴同样的内容,我们可以用 `from...... import......`来导入这些文件. + +`class Post(models.Model):` - 这行是用来定义我们的模型 (这是一个 `对象`). + +* `class` 是一个特殊的关键字,表明我们在定义一个对象。 +* `Post`是我们模型的一个名字。我们可以给它取另外一个不同的名字(但是我们必须避免使用特殊字符或者空格符)。总是以首字面大写来作为类名。 +* `models.Model` 表明Post是一个Django模型,所以Django知道它应该被保存在数据库中。 + +现在我们定义了我们曾经提及到的那些属性:`title`, `text`, `created_date`, `published_date`和`author`。 为了做到那样我们需要为我们每个字段定义一个类型(它是文本吗? 是数字? 是日期? 到另一个对象的关联,比如用户吗?)。 + +* `models.CharField` - 这是你如何用为数有限的字符来定义一个文本。 +* `models.TextField` - 这是没有长度限制的长文本。这听起来用在博客文章的内容上挺适合的,对吧? +* `models.DateTimeField` - 这是日期和时间。 +* `models.ForeignKey` - 这是指向另一个模型的连接。 + +我们不会对这里的代码解释得面面俱到因为那会花太多时间了。 如果你想了解更多有关模型字段以及如何定义除上面描述以外的东西,那你应该去看看Django的官方文档(https://docs.djangoproject.com/en/1.8/ref/models/fields/#field-types)。 + +`def publish(self):`又怎样呢? 这正是我们之前提及到的`publish`方法。 `def`表明这是一个函数或者方法,`publish`是这个方法的名字。 如果你喜欢的话你可以改变方法名。 命名的规则是使用小写字母以及下划线而非空白符。 举个例子,一个计算平均价格的方法可以叫做`calculate_average_price`. + +方法通常会`return`一些东西。 例如在 `__str__` 方法中就有这个。 在这种情况下,当我们调用 `__str__()` 我们将得到文章标题的文本 (**字符串**)。 + +如果关于模型尚有不清楚的,请随时问你的教练 ! 我们知道它很复杂,特别是当你同时学习对象和函数的时候。 但希望它在你看来没有那么神奇! + +### 在你的数据库中为模型创建数据表 + +在这里的最后一步是将我们新的模型添加到我们的数据库。 首先我们必须让Django知道我们在我们的模型(我们刚刚创建的!) 有一些变更。 输入`python manage.py makemigrations blog`。 它看起来会像这样: + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +Django为我们准备了我们必须应用到我们数据库的迁移文件。输入`python manage.py migrate blog`,然后对应的输出应该是: + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Rendering model states... DONE + Applying blog.0001_initial... OK + + +万岁! 我们的Post模型现在已经在我们的数据库里面了! 它看起来很不错, 对吧? 跳转到下一个章节,看看你博客文章的样子! diff --git a/zh/django_orm/README.md b/zh/django_orm/README.md new file mode 100755 index 00000000000..72376c3aba1 --- /dev/null +++ b/zh/django_orm/README.md @@ -0,0 +1,155 @@ +# Django ORM 和 QuerySets(查询集) + +在这一章中,你将学习 Django 如何连接到数据库,并将数据存储在里面。一探究竟吧! + +## QuerySet 是什么呢? + +从本质上说,QuerySet 是给定模型的对象列表(list)。QuerySet 允许您从数据库中读取数据,对其进行筛选以及排序。 + +用例子来学习最容易的了。让我们试试这个,好吗? + +## Django shell + +打开你本地的终端(不是在Python解析器里面) 然后输入这个命令: + + (myvenv) ~/djangogirls$ python manage.py shell + + +效果应该像这样: + + (InteractiveConsole) + >>> + + +你现在在 Django 的交互式控制台中。它是就像 Python 提示符,但有一些额外神奇的 Django 特性:)。你当然也可以在这里使用所有的 Python 命令。 + +### 所有对象 + +首先让我们尝试显示所有我们的文章。你可以用下面的命令: + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +哎呀 !出现了一个错误。它告诉我们没有文章。这是正确的 — — 我们忘了首先导入它 ! + + >>> from blog.models import Post + + +这很简单: 我们从 `blog.models` 导入 `Post` 的模型。让我们试着再一次显示所有的帖子: + + >>> Post.objects.all() + [, ] + + +这是我们之前创建的文章的 list 列表!我们通过使用Django admin界面创建了这些文章。但是我们现在想通过Python来创建新的文章,那么我们应该如何做呢? + +### 创建对象 + +这就是你如何在数据库创建一个新的Post对象的方法: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +但是我们这里有一个遗漏的要素: `me`。我们需要传递 `User` 模型的实例作为作者。如何做到这一点? + +让我们首先导入用户模型: + + >>> from django.contrib.auth.models import User + + +我们在数据库中有哪些用户?试试这个: + + >>> User.objects.all() + [] + + +这是一个我们之前创建的超级用户!让我们现在获取一个用户实例: + + me = User.objects.get(username='ola') + + +正如你所看到的,我们现在 `get` 一个 `username` 等于 'ola' 的`User` 。简单吧!当然,你必须将其改为你所使用的用户名。 + +现在我们终于可以创建我们的文章了: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +哈哈!要检查是否有效吗? + + >>> Post.objects.all() + [, , ] + + +就是这样,又一个文章在列表里面! + +### 添加更多文章 + +你现在可以找点乐子,并添加更多的帖子,看它是如何工作。添加 2-3 个并前进到下一个部分。 + +### 筛选对象 + +QuerySets的很大一部分功能是对它们进行筛选。 譬如,我们想要发现所有都由用户ola编写的文章。 我们将使用 `filter`,而不是 `all` 在 `Post.objects.all()`。 我们需要在括号中申明哪些条件,以在我们的 queryset 结果集中包含一篇博客文章。 在我们的情况是 `author`,它等于 `me`。 把它写在 Django 的方式是: `author = me`。 现在我们的代码段如下所示: + + >>> Post.objects.filter(author=me) + [, , , ] + + +或者,也许我们想看到包含在 `title` 字段标题的所有帖子吗? + + >>> Post.objects.filter(title__contains='title') + [, ] + + +> **注**在`title` 与 `contains` 之间有两个下划线字符 (`_`)。 Django 的 ORM 使用此语法来分隔字段名称 ("title") 和操作或筛选器 ("contains")。 如果您只使用一个下划线,您将收到类似"FieldError: 无法解析关键字 title_contains"的错误。 + +你也可以获取一个所有已发布文章的列表。我们通过筛选所有含`published_date`为过去时间的文章来实现这个目的: + +> > > from django.utils import timezone Post.objects.filter(published_date__lte=timezone.now())[] + +不幸的是,通过Python终端添加的文章还没发布。我们可以改变它!首先获取一个我们想要发布的文章实例: + + >>> post = Post.objects.get(title="Sample title") + + +然后将它与我们 `publish` 的方法一起发布 ! + + >>> post.publish() + + +现在再一次尝试获取已发布的文章(按向上箭头按钮三次,然后按回车): + + >>> Post.objects.filter(published_date__lte=timezone.now()) + [] + + +### 对象排序 + +Queryset 还允许您排序结果集对象的列表。让我们试着让它们按 `created_date` 字段排序: + + >>> Post.objects.order_by('created_date') + [, , , ] + + +我们也可以在开头添加 `-` 来反向排序: + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +### 链式 QuerySets + +你可以通过**链式调用**连续组合QuerySets + + >>> Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +这真是强而有力,而且可以让你写较复杂的的查询 + +酷 !现在,你准备下一个部分 !若要关闭shell程序,请键入这: + + >>> exit() + $ \ No newline at end of file diff --git a/zh/django_start_project/README.md b/zh/django_start_project/README.md new file mode 100755 index 00000000000..a9bb208565d --- /dev/null +++ b/zh/django_start_project/README.md @@ -0,0 +1,135 @@ +# 你的第一个Django 项目 ! + +> 本章的部分内容基于 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) 的教程。 +> +> 本章的部分是基于知识共享署名-4.0 国际许可协议许可的 [django marcador 教程][1]。 Django marcador 教程的版权由Markus Zapke-Gründemann 持有。 + + [1]: http://django-marcador.keimlink.de/ + +我们将要创建一个简单的博客 ! + +第一步是创建一个新的 Django 项目。 首先,我们需要运行一些由 Django 提供的脚本,为我们即将开始的项目建立主要骨架。 它会生成一系列的文件夹和文件,在后面的项目中我们会需要修改和使用到它们。 + +某些名称的文件和目录在 Django 起着至关重要的作用。 你不应该重命名我们将要创建的文件。 将它们移动到一个不同的地方也不是一个好主意。 Django 需要固定的系统结构,以便 Django 能够找到重要的东西。 + +> 记住在虚拟环境中运行的一切。 如果您没有看到您的控制台中的前缀 `(myvenv)`,您需要激活您的虚拟环境。 我们在 **Django 安装**这一节内的 **在虚拟环境下工作** 部分中解释过了。 在windows下面运行命令:myvenv\Scripts\activate,在苹果或linnux环境下运行命令:source myvenv/bin/activate + +在苹果或Linux系统下,你需要运行下面的命令,**记得不要漏掉命令后面的小点(.)**: (myvenv) ~/djangogirls$ django-admin startproject mysite . + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +在windows环境下也不要忘了下面命令最后的小点。 + + (myvenv) C:\Users\Name\djangogirls> django-admin startproject mysite . + + +> 此时,符号"`.`"很重要,它将告诉脚本程序自动安装Django到你当前选择的目录中(所以这个“`.`”是告诉脚本执行时的一种参考点) +> +> **注意**:当敲入前面命令时,记住你是从 `django-admin` 或 `django-admin.py`开始。 而命令串前面的`(myvenv) ~/djangogirls$` 和 `(myvenv) C:\Users\Name\djangogirls>`则是由系统提示用户输入命令的光标位置,这部分不用用户输入。 + +`django-admin.py`是一个脚本,将自动为您创建目录和文件。前面的命令正确的话,你现在就应该有一个目录结构,看起来像下面这样: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + 它是一个Django的项目文件夹,为即将开始的项目准备好了必要的资源文件和文件夹 + + +`manage.py` 是一个帮助管理站点的脚本。在它的帮助下我们将能够在我们的计算机上启动一个 web 服务器,而无需安装任何东西。 + +`settings.py` 文件包含的您的网站的配置数据。 + +还记得当我们谈到一名邮差在决定何处交付一封信时的例子吗?`urls.py` 文件包含`urlresolver`所需的模型的列表。. + +现在让我们忽略其他文件, 现在我们不会改变它们。要记住的唯一一点是不要不小心删除他们! + +## 更改设置 + +让我们在 `mysite/settings.py` 中进行一些更改。使用您前面安装了的代码编辑器打开文件。 + +在我们的站点上有正确的时间是非常不错的。 访问[wikipedia timezones list][2]复制你所在地区的时区 (TZ). (eg. `Europe/Berlin` ) + + [2]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + +然后在 settings.py文件中, 找到包含`TIME_ZONE字段的这行,并将时区改为你所在地区的时区。即:

+ +
python
+TIME_ZONE = 'Europe/Berlin'
+`
+适当的修改"Europe/Berlin" ps:中国大陆地区可修改为 Asia/Shanghai + +我们还需要添加 (我们会找出在教程后面所提到的静态文件和 CSS文件) 静态文件的路径。 我们下拉到文件的*最底部*, 就是在`STATIC_URL` 条目的下面。添加新的一行内容为 `STATIC_ROOT`: + + STATIC_URL = '/static/' + STATIC_ROOT = os.path.join(BASE_DIR, 'static') + + +## 设置数据库 + +有很多的不同的数据库软件,可以用来存储你的网站数据。我们将使用默认的那个, `sqlite3`. + +这已经在您的 `mysite/settings.py` 文件中设置了: + + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } + + +若要为我们的博客创建一个数据库,,让我们运行以下命令在控制台中: `python manage.py migrate` (我们需要`djangogirls` 目录中包含 `manage.py` 文件)。 如果一切顺利,您应该看到这样: + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Synchronize unmigrated apps: messages, staticfiles + Apply all migrations: contenttypes, sessions, admin, auth + Synchronizing apps without migrations: + Creating tables... + Running deferred SQL... + Installing custom SQL... + Running migrations: + Rendering model states... DONE + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying contenttypes.0002_remove_content_type_name... OK + Applying auth.0002_alter_permission_name_max_length... OK + Applying auth.0003_alter_user_email_max_length... OK + Applying auth.0004_alter_user_username_opts... OK + Applying auth.0005_alter_user_last_login_null... OK + Applying auth.0006_require_contenttypes_0002... OK + Applying sessions.0001_initial... OK + + +我们完成了 !现在去启动网站服务器,看看是否我们的网站正在工作! + +你必须要进入包含`manage.py` 文件的目录 (`djangogirls` 目录)。 在控制台中,我们可以通过运行 `python manage.py runserver` 开启 web 服务器: + + (myvenv) ~/djangogirls$ python manage.py runserver + + +如果你在Windows系统遇到UnicodeDecodeError这个错误,用这个命令来代替 + + (myvenv) ~/djangogirls$ python manage.py runserver 0:8000 + + +现在,你需要做的就是检测你的站点的服务器是否已经在运行了。打开你的浏览器(火狐,Chrome,Safari,IE 或者其他你惯用的浏览器)输入这个网址: + + http://127.0.0.1:8000/ + + +Web服务器将接管你的命令行提示符,直到我们停止它。 为了尝试更多命令,我们应该同时打开一个新的终端,并激活虚拟环境。 想要停止web服务器,我们应该切换到刚才在运行程序的窗口,并且按下 CTRL+C - 同时按下CTRL键和字母C键(如果你的操作系统是windows,那么应当按下 Ctrl+Break)。 + +祝贺你 !你已经创建您的第一个网站,并使用 web 服务器运行它!这超级赞吧? + +![它工作了!][3] + +准备好下一步了吗?现在来创建一些内容 ! + + [3]: images/it_worked2.png diff --git a/zh/django_start_project/images/it_worked2.png b/zh/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/zh/django_start_project/images/it_worked2.png differ diff --git a/zh/django_templates/README.md b/zh/django_templates/README.md new file mode 100755 index 00000000000..6d291d9b891 --- /dev/null +++ b/zh/django_templates/README.md @@ -0,0 +1,114 @@ +# Django模板 + +是时候把数据展示出来了!Django提供了一个非常有用的内置来实现\---|-**模板标签** + +## 什么是模板标签呢? + +正如你在前面章节中所了解的那样, 我们并不能将python代码嵌入到HTML中。 因为浏览器不能识别python代码, 它只能解析HTML。 我们知道,HTML是静态页面,而python则显得更加动态。 + +**Django模板标签**允许我们将Python之类的内容翻译成HTML,所以你可以更快更简单的建立动态网站。哈哈! + +## 展现文章列表模板 + +在之前的章节,我们给我们的模板一系列文章在`post`变量里。现在我们将在HTML里展现它。 + +为了用模板标签在HTML中显示变量, 我们会使用两个大括号, 并将变量包含在里面,正如这样 + +```html + {{ posts }} +``` + + +在你的 `blog/templates/blog/post_list.html` 文件中进行如下的操作。 将所有 `
` to the third `
` 中的 to the third 用 `{{ posts }}` 代替。 并保存文件,刷新页面后去看看我们做的那些改变。 + +![图 13.1][1] + + [1]: images/step1.png + +如你所见,我们得到如下: + +``` + [, ] +``` + + +这意味着Django视它为对象的列表。 还记得在 **Python入门介绍** 里我们怎么展现列表的吗? 是的, 我们可以使用循环! 在dajngo模板中使用循环去遍历它们。如下所示: + +```html + {% for post in posts %} + {{ post }} + {% endfor %} +``` + + +在你的模板里试试这个。 + +![图 13.2][2] + + [2]: images/step2.png + +它工作了! 但是想让他们展现的像我们之前在**HTML介绍**章节里创建的静态文章一样 你可以混合HTML和模板标签。 我们的`body`将长得像这样: + +```html + + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + + +{% raw %}所有的在`{% for %}` 和 `{% endfor %}` 之间的内容将会被Django对象列表中的每个对象所代替。刷新页面去看看:{% endraw %} + +![图 13.3][3] + + [3]: images/step3.png + +你注意到这次我们使用了一个明显不同的标记`{{ post.title }}` 或 `{{ post.text }}`? 我们正在访问定义在`Post`模型中的每一个域。 此外,`|linebreaksbr`通过一个过滤器,使得行间隔编程段落。 + +## 还有一件事 + +如果我们将我们的网站放在互联网上运行,那将是一件很不错的事情,难道不是吗? 让我们试着再次部署到 PythonAnywhere。简单部署步骤如下... ... + +* 首先,我们将我们的代码放到Github + +``` + $ git status + [...] + $ git add --all . + $ git status + [...] + $ git commit -m "Modified templates to display posts from database." + [...] + $ git push +``` + + +* 然后,重新登陆 [PythonAnywhere][4] 并进入**Bash 控制台** (或重开一个),并运行: + + [4]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ git pull + [...] +``` + + +* 最后, 我们返回 [Web tab][5] 重新加载我们的应用程序, 此时我们应该可以看到更新后的程序运行情况了。 + + [5]: https://www.pythonanywhere.com/web_app_setup/ + +祝贺你!现在往前走,尝试在你的Django管理中添加一篇新文章(记得添加发布日期!),然后刷新你的页面看看是否文章正常显示了。 + +这一定是个让人沉醉的作品?为此我们应当骄傲, 在计算机学科的一点儿进步,都是自我的一次突破 :)。 + +![图 13.4][6] + + [6]: images/donut.png diff --git a/zh/django_templates/images/donut.png b/zh/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/zh/django_templates/images/donut.png differ diff --git a/zh/django_templates/images/step1.png b/zh/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/zh/django_templates/images/step1.png differ diff --git a/zh/django_templates/images/step2.png b/zh/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/zh/django_templates/images/step2.png differ diff --git a/zh/django_templates/images/step3.png b/zh/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/zh/django_templates/images/step3.png differ diff --git a/zh/django_urls/README.md b/zh/django_urls/README.md new file mode 100755 index 00000000000..4e0ef147725 --- /dev/null +++ b/zh/django_urls/README.md @@ -0,0 +1,117 @@ +# Django urls + +我们将要建立第一个网页:你博客的主页!但是首先,让我们先学习一点 Django 的 url 知识。 + +## 什么是 URL? + +简单地说,URL 是一个网页地址。 每当你访问一个网站时,你都能在浏览器的地址栏里看到一个 URL。(是的! `127.0.0.1:8000` 是一个URL! 同时 `https://djangogirls.org` 也是一个 URL): + +![URL][1] + + [1]: images/url.png + +每一个互联网的网页都需要自己的 URL。 这样当用户打开一个 URL 时,你的应用程序才知道应该展现什么内容。 在 Django 中,我们使用一种叫做 `URLconf` (URL 配置)的机制 。 URLconf 是一套模式,Django 会用它来把 URL 匹配成相对应的 View。 + +## URL 在 Django 中如何工作? + +使用你喜欢的编辑器打开 `mysite/urls.py` 就能看到它长什么样子了: + + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + ] + + +正如你所看到的,Django 已经为我们放了一些东西在里面。 + +以 `#` 开头的行是注释,这些行都不会被Python运行。是不是很方便呢? + +你在上一章节中学到的 admin 的 URL 已经在里面了: + + url(r'^admin/', include(admin.site.urls)), + + +这表示对于每一个以 `admin` 开头的 URL,Django 都会找到一个相对应的 *view*。 在这行代码中,我们包含了许多 admin URL 进来,所以这些 URL 不需要都被打包进这个小文件中。这使得代码更具可读性和简洁性。 + +## 正则表达式 + +你知道 Django 是如何将 URL 匹配到 view 的吗? 好吧,这部分很棘手。 Django 使用了 `regex`,这是“正则表达式”的缩写。 正则表达式有很多(非常多!)规则用来形成一个搜索模式。 由于正则表达式是一个比较深入的话题,我们不会太深入讲解它的运行机制。 + +如果你还是想要了解怎样创建这些模式,下面有一个例子。我们只需要有限的规则的子集,就可以表达出想要的模式,比如: + + ^ 表示文本的开始 + $ 表示文本的结束 + \d 表示数字 + + 表示前面的元素应该重复至少一次 + () 用来捕捉模式中的一部分 + + +其他定义在模式中的部分会保留原本的含义。 + +现在,想象你有一个网站,其中有一个 URL 类似这样:`http://www.mysite.com/post/12345/`。其中 `12345` 是帖子的编号。 + +为每一个帖子都写一个单独的视图是一件会让人恼火的事情。 用正则表达式,我们可以创建一种模式,用来匹配 URL 并提取出帖子编号:`^post/(\d+)/$`。 让我们一步一步将它分解,看看里面做了什么: + + +* **^post/** 告诉 Django 在 URL 的开头匹配 `post/` (后于 `^`) +* **(\d+)** 表示 URL 中会有一个数(一位或者多位数字),并且我们想提取出这个数 +* **/** 告诉 Django 后面紧跟着一个 `/` 字符 +* **$** 表示 URL 的末尾,即以 `/<1>` 结尾的 URL 才会被匹配到 + +## 你的第一个 Django url! + +是时候创建第一个 URL 了!我们想用 'http://127.0.0.1:8000/' 作为博客的首页,并展示一个帖子列表。 + +我们也想保持 `mysite/urls.py` 文件简洁,所以我们从 `blog` 应用导出 urls 到主 `mysite/urls.py` 文件。 +来吧,删除被注释掉的那行(以 `#` 开头的行),然后添加一行代码用于把 `blog.urls` 导入到主 url (`''`). + +你的 `mysite/urls.py` 文件现在应该看起来像这样: + + from django.conf.urls import include, url + from django.contrib import admin + + urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), + ] + + +现在,Django 会把访问 'http://127.0.0.1:8000/' 的请求转到 `blog.urls`,并看看那里面有没有进一步的指示。 + +写正则表达式时,记得把一个 `r` 放在字符串的前面。 这告诉 Python,这个字符串中的特殊字符是为正则表达式准备的,而不是为 Python 自身准备的。 + +## blog.urls + +现在我们创建一个新的 `blog/urls.py` 空文件。好了!加入以下两行: + + from django.conf.urls import url + from . import views + +我们仅仅把 Django 的方法以及 `blog` 应用的全部 `views` 导入了进来。(目前什么都没有,但是不超过一分钟就能搞好!) 然后,我们可以加入第一个 URL 模式: + + urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + ] + + +正如你所见,我们现在分配了一个叫作 `post_list` 的 `view` 到 `^$` 的 URL 上。 这个正则表达会会匹配 `^`(表示开头)并紧随 `$` (表示结尾),所以只有空字符串会被匹配到。 这是正确的,因为在 Django 的 URL 解析器中,'http://127.0.0.1:8000/' 并不是 URL 的一部分。(译注:即只有 'http://127.0.0.1:8000/' 后面的部分会被解析。如果后面的部分为空,即是空字符串被解析。) 这个模式告诉了 Django,如果有人访问 'http://127.0.0.1:8000' 地址,那么 `views.post_list` 是这个请求该去到的地方。 + +最后的部分,`name='post_list'` 是 URL 的名字,用来唯一标识对应的 view。 它可以跟 view 的名字一样,也可以完全不一样。 在项目后面的开发中,我们将会使用命名的 URL ,所以在应用中为每一个 URL 命名是重要的。我们应该尽量让 URL 的名字保持唯一并容易记住。 + +一切都搞定了?在浏览器里打开 http://127.0.0.1:8000/ ,看看结果。 + +![错误][2] + +"It works" 不见了,啊?不要担心,这只是个错误页面,不要被吓到了。它们实际上是非常有用的: + +你会发现有一个 **no attribute 'post_list'** (没有 'post_list' 属性)的错误。 *post_list* 提醒你什么东西了吗? 这是我们的 view 的名字! 这表示其他的一切正常,但是我们还没创建这个 *view* 。 不要担心,我们将会抵达那里。 + +> 如果你想知识更多关于 Django URLconf 的知识,去官方文档看一看:https://docs.djangoproject.com/en/1.8/topics/http/urls/ + + [2]: images/error1.png diff --git a/zh/django_urls/images/error1.png b/zh/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/zh/django_urls/images/error1.png differ diff --git a/zh/django_urls/images/url.png b/zh/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/zh/django_urls/images/url.png differ diff --git a/zh/django_views/README.md b/zh/django_views/README.md new file mode 100755 index 00000000000..53b1cfd7b62 --- /dev/null +++ b/zh/django_views/README.md @@ -0,0 +1,36 @@ +# Django视图 - 是时候去创建! + +是是候去解决我们在上一章所制造的Bug了:) + +*view*是存放应用逻辑的地方。 它将从你之前创建的 `模型`中获取数据,并将它传递给 `模板`。 我们将在下一章创建 tempalte 模板。 视图就是Python方法,只不过比我们在**Python简介**章节中所做的事情稍复杂。 + +视图都被置放在`views.py`文件中。我们将加入我们自己的*views*到`blog/views.py`文件。 + +## blog/views.py + +好,让我们打开这个文件,看看里面有什么: + + from django.shortcuts import render + + # Create your views here. + + +这里没有太多的东西。一个最简单的*view*就长得这个样子。 + + def post_list(request): + return render(request, 'blog/post_list.html', {}) + + +如你所见, 我们创建一个方法 (`def`) ,命名为 `post_list` ,它接受 `request` 参数作为输入, 并 `return` (返回)用 `render` 方法渲染模板 `blog/post_list.html` 而得到的结果. + +保存文件,转到 http://127.0.0.1:8000/ 然后看看我们现在得到什么了。 + +另一个错误!读读现在发生了什么: + +![错误][1] + + [1]: images/error.png + +这个错误很直白:*TemplateDoesNotExist*。让我们修复这个bug,然后在下一个章节里创建一个模板! + +> 阅读更多关于 Django views 的内容请参阅官方文档: https://docs.djangoproject.com/en/1.8/topics/http/views/ diff --git a/zh/django_views/images/error.png b/zh/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/zh/django_views/images/error.png differ diff --git a/zh/dynamic_data_in_templates/README.md b/zh/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..74e9d908022 --- /dev/null +++ b/zh/dynamic_data_in_templates/README.md @@ -0,0 +1,70 @@ +# 模板中的动态数据 + +我们已有的几件: `Post` 模型定义在 `models.py` 中,我们有 `post_list` `views.py` 和添加的模板中。 但实际上我们如何使我们的帖子出现在我们的 HTML 模板上呢? 因为那是我们所想要的: 获取一些内容 (保存在数据库中的模型) 然后在我们的模板中很漂亮的展示,对吗? + +这就是 *views* 应该做的: 连接模型和模板。 在我们的 `post_list` *视图* 中我们需要获取我们想要显示的模型,并将它们传递到模板中去。 所以基本上在 *视图* 中,我们决定什么 (模型) 将显示在模板中。 + +好吧,我们将如何实现它呢? + +我们需要打开我们的 `blog/views.py`。到目前为止 `post_list` *view* 看起来像这样: + + from django.shortcuts import render + + def post_list(request): + return render(request, 'blog/post_list.html', {}) + + +还记得当我们谈论过导入在不同文件中编写的代码吗? 现在是我们必须导入我们已经写在 `models.py` 里的模型的时候了。 我们将添加这行 `from .models import Post`,像这样: + + from django.shortcuts import render + from .models import Post + + +`from` 后面的点号意味着 *当前目录* 或 *当前的应用程序*。 因为 `views.py` 和 `models.py` 是在同一目录中,我们只需要使用 `.` 和 文件的名称(无 `.py`) 。 然后我们导入模型(`Post`). + +但接下来是什么呢?为了让实际的博客帖子从 `Post` 模型里获取,我们需要一种叫做 `QuerySet`的东西. + +## QuerySet 查询集 + +您应该已经熟悉 Queryset 是如何工作的。我们在 [Django ORM (Queryset) 章节][1]谈论过它. + + [1]: ../django_orm/README.md + +所以现在我们对已经发表并进行由 `published_date`排序的博客列表感兴趣,对吗?我们已经在 QuerySets 查询集一节里这么干过! + + Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + + +现在我们把这段代码插入 `blog/views.py` 文件,添加到函数 `def post_list(request)`里去: + + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {}) + + +请注意我们为这里的 QuerySet查询集创建了一个 *变量*: `posts`。将此视为我们的 QuerySet 的名字。从现在开始我们可以通过这个名字引用它。 + +同时,代码中使用了 `timezone.now()` 函数,因此我们需要添加一个导入 `timezone`. + +最后还没有完成的部分是传递 `posts` 查询集到模板中 (我们将在下一章中介绍如何显示它)。 + +在`render` 函数中我们已经有了 `请求` (因此我们通过互联网从用户接收的一切) 和模板文件 `'blog/post_list.html'` 参数。 最后一个参数,看起来像这样: `{}` ,我们可以在其中添加一些模板要使用的东西。 我们需要给它们起名字 (我们暂且沿用 `'posts'` :))。 它应该看起来像这样: `{'posts': posts}`。 请注意,`:` 之前的部分是字符串;你需要将它用引号包围 `''`. + +所以最后我们的 `blog/views.py` 文件应如下所示: + + from django.shortcuts import render + from django.utils import timezone + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) + + +就是它 !现在回到我们的模板并显示此QuerySet查询集! + +如果你想了解更多关于QuerySert的内容,那么你可在这里得到帮助:https://docs.djangoproject.com/en/1.8/ref/models/querysets/ diff --git a/zh/extend_your_application/README.md b/zh/extend_your_application/README.md new file mode 100755 index 00000000000..23d4675e148 --- /dev/null +++ b/zh/extend_your_application/README.md @@ -0,0 +1,206 @@ +# 扩展您的应用 + +我们已经完成了所有创建网站的各项不同必须的步骤:我们知道如何写一个模型,url,视图和模板。我们同样知道如何让我们网站更漂亮。 + +现在来练习吧! + +我们网站里的第一件事情就是,一个展现一篇博客的页面,对吗? + +我们已经有了`Post`模型,所以我们不需要再添加任何内容到`models.py`文件中。. + +## 创建一个模板链接,跳转到博文的内容页 + +我们将从在`blog/templates/blog/post_list.html`里添加一个链接开始。目前它应该看起来像这样: + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + + + +{% raw %}我们在博文列表的博文标题处添加一个链接用于跳转到该博文的详细页面。 让我们编辑 `

{{ post.title }}

` 使得它能链接到博文详情页面:。{% endraw %} + +```html +

{{ post.title }}

+``` + + +{% raw %}是解释神秘的 `{% url 'post_detail' pk=post.pk %}` 时候了。 正如你所猜想的,`{% %}`标记意味着我们正在使用Django模板标签。 这一次我们将使用一个能为我们创建URL的!{% endraw %} + +`blog.views.post_detail` 是我们想创建的 `post_detail` *view* 的路径。 请注意:`blog` 是我们应用的名字 (`blog`目录), `views` 是表单 `views.py` 文件的名字同时最后一个部分 - `post_detail` - 是 *view*的名字。. + +现在当我们访问:http://127.0.0.1:8000/ 我们会得到一个错误(这是预料之中的,因为我们没有名为`post_detail` 的 URL 或 *视图*)。看起来会像这样: + +![NoReverseMatch 错误][1] + + [1]: images/no_reverse_match2.png + +## 创建文章详细页面的URL + +让我们在`urls.py`里为我们的 `post_detail` *view* 创建一个URL! + +我们希望我们的第一条文章详细页面显示在类似这样的**URL**: http://127.0.0.1:8000/post/1/ + +让我们在 `blog/urls.py` 文件中增加一个 URL 来指引 Django 到名为 `post_detail` 的 *view*,它将用来显示整篇博客文章。 增加这行 `url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'),` 到 `blog/urls.py` 文件。 文件应当如下所示: + +```python +from django.conf.urls import url +from . import views + +urlpatterns = [ + url(r'^$', views.post_list, name='post_list'), + url(r'^post/(?P[0-9]+)/$', views.post_detail, name='post_detail'), +] +``` + + +`^post/(?P[0-9]+)/$` 部分看上去很骇人,请勿担心—我们来解释给你听: - 还是起始自 `^` — "开头部分" - `post/` 只是表示,紧接着开头,URL应当包含 **post** 和 **/**。 到目前为止,一切都好。 - `(?P[0-9]+)` - 这部分很棘手。 这表示Django会把所有你放到这里的东西转变成一个称作`pk`的变量并传递给视图。 `[0-9]`也告诉我们它只能由数字,而不是字母(所以是取值范围是介于0和9之间)。 `+` 意味着需要一个或更多的数字。 所以诸如`http://127.0.0.1:8000/post//`是无效的,但是像`http://127.0.0.1:8000/post/1234567890/`是完全OK的! - `/` - 然后我们再次需要 **/** - `$` - "结尾"! + +这意味着如果你键入`http://127.0.0.1:8000/post/5/`到你的浏览器里, Django 明白你在寻找一个叫做 `post_detail` 的 *视图*,然后传递`pk` 等于 `5` 到那个 *视图*. + +`pk` 是 `primary key(主键)`的缩写。 在Django项目中常常用到这个名字。 但是你可以使用你想要的变量(记住:使用小写以及`_`而不是空格!)。 比如与其说 `(?P[0-9]+)` 我们可以有`post_id`, 所以这个就像: `(?P[0-9]+)`. + +好吧,我们已经向 `blog/urls.py` 添加了一个新的 URL 模式!让我们刷新页面: http://127.0.0.1:8000/ Duang!还有另一个错误!果然! + +![属性错误][2] + + [2]: images/attribute_error2.png + +你还记得下面应该怎么做吗?当然:添加一个视图! + +## 增加文章详细页面的视图 + +这次我们的*视图*提供了一个额外的参数`pk`。 我们的*视图*需要能捕获它,对吗? 所以我们将定义我们的函数为`def post_detail(request, pk):`。 注意我们需要使用我们在urls里指定的(`pk`)。 省略这个变量是不正确的,将会导致一个错误! + +现在,我们想要有一个并且只有一个博客帖子。为了做到这一点,我们需要使用下面的请求集合: + +```python + Post.objects.get(pk=pk) +``` + + +但是这段代码有一个问题。如果没有`Post`和给定`主键`(`pk`)我们将有一个非常丑陋的错误! + +![对象不存在错误][3] + + [3]: images/does_not_exist2.png + +我们不希望那样! 但是,当然,Django已经为我们处理好了这些:`get_object_or_404`。 万一没有`Post`和给定的`pk`,它将展现更多有趣的页面(称作`Page Not Found 404`页面)。 + +![找不到页面][4] + + [4]: images/404_2.png + +好消息是你实际上可以创建你自己 `Page not found` 的页面和使它漂亮如你所愿。但现在它不是超级重要的,所以我们将跳过它。 + +好吧,是时候将 *视图* 添加到我们的 `views.py` 文件了! + +我们应该打开 `blog/views.py` 并添加以下代码: + +```python + from django.shortcuts import render, get_object_or_404 +``` + + +在 `from`附近 行。并在文件的末尾,我们将增加我们的 *view*: + +```python +def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) +``` + + +好了。是时候刷新页面了: http://127.0.0.1:8000/ + +![文章列表][5] + + [5]: images/post_list2.png + +它工作了 !但是,当您单击博客文章标题中的某个链接时,会发生什么呢? + +![模板不存在的错误][6] + + [6]: images/template_does_not_exist2.png + +哦不 !另一个错误 !但我们已经知道如何处理它,对吗?我们需要添加一个模板 ! + +## 为文章详细页面增加模板 + +我们将在`blog/templates/blog` 中创建一个文件,叫做 `post_detail.html` . + +它看起来会像这样: + +```python + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} +
+ {{ post.published_date }} +
+ {% endif %} +

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endblock %} +``` + + +现在,我们要扩展 `base.html`。 在`content` 块中,我们想要显示一篇文章的published_date (如果存在的话), 标题和文本。 但我们应该讨论一些重要的东西,对不对吗? + +{% raw %}`{% if ... %} ... {% endif %}` 是当我们想检查某样东西(还记得Python简介里的 if ... else ... 吗?)的时候的一种模板记号 。 在这个例子中,我们想要检查文章的 `published_date` 不是空的。{% endraw %} + +好的,我们可以刷新我们的页面并查看是否 `Page not found` 是不是没有了。 + +![文章细节页面][7] + + [7]: images/post_detail2.png + +耶 !它工作了! + +## 还有一件事:部署时刻! + +你的网站如果还能在 PythonAnywhere 正常运转就好了,对吧?让我们再次部署。 + +``` + $ git status + $ git add --all . + $ git status + $ git commit -m "Added view and template for detailed blog post as well as CSS for the site." + $ git push +``` + + +* 然后,在一个 [PythonAnywhere 的 Bash 终端][8]里运行: + + [8]: https://www.pythonanywhere.com/consoles/ + +``` + $ cd my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] +``` + + +* 最后,跳到 [Web 标签页][9] 并点击**重新载入**. + + [9]: https://www.pythonanywhere.com/web_app_setup/ + +就是这样!祝贺你:) diff --git a/zh/extend_your_application/images/404_2.png b/zh/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/zh/extend_your_application/images/404_2.png differ diff --git a/zh/extend_your_application/images/attribute_error2.png b/zh/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/zh/extend_your_application/images/attribute_error2.png differ diff --git a/zh/extend_your_application/images/does_not_exist2.png b/zh/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/zh/extend_your_application/images/does_not_exist2.png differ diff --git a/zh/extend_your_application/images/no_reverse_match2.png b/zh/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..306926206f8 Binary files /dev/null and b/zh/extend_your_application/images/no_reverse_match2.png differ diff --git a/zh/extend_your_application/images/post_detail2.png b/zh/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/zh/extend_your_application/images/post_detail2.png differ diff --git a/zh/extend_your_application/images/post_list2.png b/zh/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/zh/extend_your_application/images/post_list2.png differ diff --git a/zh/extend_your_application/images/template_does_not_exist2.png b/zh/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/zh/extend_your_application/images/template_does_not_exist2.png differ diff --git a/zh/how_the_internet_works/README.md b/zh/how_the_internet_works/README.md new file mode 100644 index 00000000000..e8d4be41600 --- /dev/null +++ b/zh/how_the_internet_works/README.md @@ -0,0 +1,53 @@ +# 互联网是如何工作的? + +> 本章内容衍生自Jessica McKellar的演讲“互联网是怎么工作的”(http://web.mit.edu/jesstess/www/)。 + +我们猜你每天在使用互联网。但是当你在浏览器里输入一个像 https://djangogirls.org 的地址并按 `回车键`的时候,你真的知道背后发生了什么吗? + +你需要了解的第一件事是一个网站只是一堆保存在硬盘上的文件。 就像你的电影、 音乐或图片一样。 然而,网站的唯一的不同之处是: 网站包含一种称为 HTML 的代码。 + +如果你不熟悉编程,一开始你会很难理解HTML。你的浏览器 (如Chrome、 Safari、 Firefox 等) 却很喜欢它。 Web浏览器懂得这些代码,遵循它的指令并如你所想的那样展示这些文件。 + +就像我们对待每个电脑文件一样,我们需要把HTML文件存储在硬盘的某个位置。 对于互联网,我们使用特定而功能强大的电脑,我们称之为*服务器*。 它们没有屏幕、鼠标或者键盘,因为它们的主要目的是存储数据,并用它来提供服务。 这就是为什么它们被称作*服务器*--因为他们用数据*服务*你。 + +好了,但是你想知道互联网看起来是什么样子的,对吗? + +我们给你画了一幅画!它看起来像这样: + +![图1.1][1] + + [1]: images/internet_1.png + +看起来很糟糕,对吗? 事实上,它是一个由互相连通的机器 (上面提到的*服务器*) 组成的网络。 数以十万计的机器! 很多,很多数以公里长的电缆分布在全世界! 你能访问一个海底电缆地图网站(http://submarinecablemap.com/)来看这个网络有多么复杂。 这是一个网站上的截屏: + +![图1.2][2] + + [2]: images/internet_3.png + +它很迷人,对吧? 但是很明显,我们不太可能用电缆去连接任何两台上网的电脑。 我们需要将请求通过很多很多不同的机器传递,以便连接一台机器 (比如存储https://djangogirls.org的机器)。 + +它看起来像这样: + +![图1.3][3] + + [3]: images/internet_2.png + +想象一下当你键入https://djangogirls.org,你会发送一封信说:“亲爱的Django Girls,我想看看djangogirls.org网站,请将它发送给我!” + +你的信件去了离你最近的邮局。 然后它去离你的收件人稍近一点的邮局,然后再去另一个,以此类推地到达它的目的地。 唯一的事情是,如果你将许多信件 (*数据包*) 发送到同一个地方,他们可以通过完全不同邮政局 (*路由器*)。 这取决于每个办公室的分布情况。 + +![图1.4][4] + + [4]: images/internet_4.png + +是的,就这么简单。你发送信息,然后期望一些回复。当然,你使用的不是纸笔,而是比特数据,但是思想是一样的! + +我们使用的地址叫做IP地址,这种地址却不包含街道、城市、邮编和城市。 你的电脑首先要求DNS(域名服务器)去解析djangogirls.org成为IP地址。 他工作起来有点像老式的电话簿,在那里你可以找到你想联系的人的名字,并且找到他们的电话号码和地址。 + +当你发送一封信时,它需要确切的功能以便正确的传递:地址,邮票等等。 你使用一种接收者同样能够理解的语言,对吗? 你送到网站的*数据包*也类似如此。 我们使用一个名为 HTTP (Hypertext Transfer Protocol:超文本传输协议) 的协议。 + +所以,基本上,当你有一个网站你需要有一台*服务器*用于网站的托管。 当*服务器*接收到一个访问*请求*(一封信),它把网站内容发送回去(回信)。 + +既然这是Django教程,你会问Django做什么。 当你发送一个响应时,你通常不会发送同样的东西给每一个人。 如果你信件的内容是个性化的必然更好,尤其是对于那个刚刚给你写信的人,对吗? Django帮助你创建这些个性化,有趣的信件:)。 + +废话少说,抓紧时间创造! \ No newline at end of file diff --git a/zh/how_the_internet_works/images/internet_1.png b/zh/how_the_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/zh/how_the_internet_works/images/internet_1.png differ diff --git a/zh/how_the_internet_works/images/internet_2.png b/zh/how_the_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/zh/how_the_internet_works/images/internet_2.png differ diff --git a/zh/how_the_internet_works/images/internet_3.png b/zh/how_the_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/zh/how_the_internet_works/images/internet_3.png differ diff --git a/zh/how_the_internet_works/images/internet_4.png b/zh/how_the_internet_works/images/internet_4.png new file mode 100644 index 00000000000..2661cec1b61 Binary files /dev/null and b/zh/how_the_internet_works/images/internet_4.png differ diff --git a/zh/html/README.md b/zh/html/README.md new file mode 100755 index 00000000000..5334811bc80 --- /dev/null +++ b/zh/html/README.md @@ -0,0 +1,206 @@ +# HTML简介 + +什么是模板,你可能会问? + +模板是一个文件,它可以让我们使用一致的格式来展示不同的信息— —例如,您可以使用模板来帮助你写一封信,虽然每封信可以包含不同的消息和发送给不同的人,但他们使用相同的格式。 + +Django模板的格式是由HTML(也就是我们在第一章 **互联网是如何工作的** 中提到的 HTML )语言来描述的。). + +## HTML 是什么? + +HTML 是一种简单的代码,由 Web 浏览器解释—如 Chrome、 火狐或Safari—为用户显示一个网页。 + +HTML代表“HyperText Markup Language(超文本标记语言)”。 **超文本** 是指它是一种支持网页之间的超链接的文本。 **标记** 是指我们将一份文件用代码标记组织起来,然后告诉某个东西(在这种情况下,浏览器中) 如何解释网页。 HTML 代码是由 **标记**构成的,每一个都是由 `<` 开始,由结束 `>`. 这些标签表示标记 **元素**. + +## 你的第一个模板 ! + +创建一个模板是指创建一个模板文件。一切都是文件,对吧?你可能已经注意到这点了。 + +模板保存在 `blog/templates/blog` 目录中。 因此,首先在您的 blog 目录内创建一个称为 `templates` 的目录。 然后创建另一个称为 `blog` 的目录到你的 templates 目录: + + blog + └───templates + └───blog + + +(你可能会疑惑为什么我们需要两个目录都叫的 `blog` — 你以后会发现这是简单有效的命名规则,使生活更容易,当事情开始变得更加复杂的时候。) + +现在创建一个叫做 `post_list.html` 的文件 (现在是空的,别管它)到 `blog/templates/blog` 目录下。 + +看看你的网站现在是什么样子: http://127.0.0.1:8000/ / + +> 如果您仍然有错误 `TemplateDoesNotExists`,尝试重新启动您的服务器。 转到命令行,按 Ctrl + C (同时按Control和 C 按钮) 停止服务,并通过执行 `python manage.py runserver` 命令再次启动它。 + +![图 11.1][1] + + [1]: images/step1.png + +再也没有错误了 !祝贺:)然而,您的网站实际上并没有展现任何东西出了一个空白页,因为您的模板也是空。我们需要解决这个问题。 + +在您的模板文件中添加以下内容: + + +

Hi there!

+

It works!

+ + + +你的网站现在看这样怎么样?单击去查找: http://127.0.0.1:8000/ / + +![图 11.2][2] + + [2]: images/step3.png + +它工作了 !很好地完成了:) + +* 最基本的标记,``,始终是任何网页的开始, `` 始终是最后。 正如你所看到的,整个网站的内容是在 `` 开始标记和结束标记之间 ``的 +* `

` 一种用于段落元素标记 ;`

` 关闭每个段落 + +## Head & body + +每个 HTML 页面也分为两个元素: **head** 和 **body**. + +* **head** 是一个包含有关文档且未显示在屏幕上的信息元素。 + +* **body** 是包含 web 页中所有显示的元素。 + +我们使用 `` 告诉浏览器这个页面的配置,以及 `` 来告诉它什么实际上是在页面上。 + +例如,你可以把网页标题元素放到 ``里,像这样: + + + + Ola's blog + + +

Hi there!

+

It works!

+ + + + +保存该文件并刷新您的网页。 + +![图 11.3][3] + + [3]: images/step4.png + +注意浏览器怎么理解"Ola's blog"是你的网页的标题的呢? 它解释了 ` Ola's blog ` 并将其放置到您的浏览器 (它也用于书签,等等) 的标题栏中。 + +可能你也注意到每个开始标记匹配的 *结束标记*,用 `/`) 和元素是 *嵌套* (即只有您不能关闭特定标记,直到在里面的所有标记都关闭了)。 + +这就像把东西放进盒子里。 你有一个大箱子里,`` ;在它里面还有 ``,并包含更小盒: `

`. + +你需要遵循这些规则即 *关闭* 标签和 *嵌套* 的元素 — — 如果你不这样做,浏览器可能不能正确地解释它们以及您的页面将显示不正确。 + +## 自定义您的模板 + +现在,你可以找点乐子,尝试自定义您的模板 !为此这里有几个有用的标签: + +* `

A heading

` -为你最重要的标题 +* `

A sub-heading

` 为下一层级的标题! +* `

A sub-sub-heading

` ... 同样,直到 `
` +* `text` 强调您的文本 +* `text` 强烈强调您的文本 +* `
` 跳转到下一行(你不能放任何东西在br里面) +* `link` 创建一个链接 +* `
  • first item
  • second item
` 产生一个列表,就像这样! +* `
` 定义页面上的一个段 + +下面是模板的一个完整示例: + + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + + + +我们已经创建了三个不同的 `div` 部分。 + +* 第一个 `div` 元素包含我们的博客的标题 — — 这是一个标题和链接 +* 另两个 `div` 元素包含我们博客文章发表的日期,`h2` 是可点击文章标题和两个 `p` (段落) 的文本、 日期和我们的博客。 + +它给了我们这种效果: + +![图 11.4][4] + + [4]: images/step6.png + +耶! 但到目前为止,我们的模板永远只显示完全 **相同的信息** — — 而我们早些时候谈到模板作为使我们能够以 **相同的格式** 显示 **不同** 的信息. + +我们想要的真正想要做的是的显示实际添加到我们Django admin里面的文章:这是我们接下来要做的。 + +## 还有一件事:部署! + +我们把这些成果放到网上一定很棒,对吧?让我们再来一次 PythonAnywhere 部署: + +### 提交并推送代码到Github + +首先,让我们看看上次部署之后什么文件改变了(运行这些本地命令,不是在 PythonAnywhere 上): + + $ git status + + +请确保你在 `djangogirls` 目录中,让我们告诉 `git` 包括此目录内的所有更改: + + $ git add --all . + + +> **注**`-A`(简称"全部") 意味着,`git` 也会认识到如果你已经删除的文件 (默认情况下,它只能识别新的/已修改的文件)。 此外记得 (在第 3 章)`.` 意味着当前目录。 + +在我们上传的所有文件之前,让我们检查`git` 将上传什么(所有`git` 将上传的文件现在应以绿色显示): + + $ git status + + +我们已经差不多完成了,现在是时候告诉它要在它的历史记录中保存此更改。 我们将要给它附上一条"提交消息"用来描述我们做了什么改动。 您可以在这个阶段键入任何您想要的东西,但写一些描述性的东西更有用,因为它能在将来使你记起你做了什么。 + + $ git commit -m "Changed the HTML for the site." + + +> **注意** 请确保您使用双引号括提交消息。 + +做完这些,我们上传(push)改动到 Github: + + git push + + +### Pull 把你的新代码拉到 PythonAnywhere,然后重新加载你的 web 应用程序 + +* 打开 [PythonAnywhere consoles page][5] 并转到你的 **Bash console**(或启动一个新的)。然后,运行: + + [5]: https://www.pythonanywhere.com/consoles/ + + $ cd ~/my-first-blog + $ source myvenv/bin/activate + (myvenv)$ git pull + [...] + (myvenv)$ python manage.py collectstatic + [...] + + +然后观察你的代码被下载下来。如果你想要检查他是否正确下载,你可以跳转到**Files Tab** 并在PythonAnywhere上查看代码。 + +* 最后,跳到 [Web tab][6] 并点击对应你的 Web 应用程序的 **Reload** 。 + + [6]: https://www.pythonanywhere.com/web_app_setup/ + +你的更新应已上线!刷新你的浏览器,看到更新了吧 :) diff --git a/zh/html/images/step1.png b/zh/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/zh/html/images/step1.png differ diff --git a/zh/html/images/step3.png b/zh/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/zh/html/images/step3.png differ diff --git a/zh/html/images/step4.png b/zh/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/zh/html/images/step4.png differ diff --git a/zh/html/images/step6.png b/zh/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/zh/html/images/step6.png differ diff --git a/zh/images/application.png b/zh/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/zh/images/application.png differ diff --git a/zh/installation/README.md b/zh/installation/README.md new file mode 100755 index 00000000000..c697ade6ce2 --- /dev/null +++ b/zh/installation/README.md @@ -0,0 +1,49 @@ +# 如果你在家做这个练习 + +如果你在家做这个练习,而不是在一个 [Django Girls 活动](https://djangogirls.org/events/)中,你现在完全可以跳过这一章,直接阅读[互联网是如何工作的?](../how_the_internet_works/README.md)一章。 + +这是因为下面的这些步骤包含在整个教程当中,这只是一个额外的页面,把所有的安装说明收集在了一起。 Django Girls活动有一个“开学礼”环节,活动中会一次性安装完成所有的软件,因而在之后的线下活动中就无需再进行安装,这对我们很有帮助。 + +如果你觉得很有帮助,你也可以跟着阅读这一章。 但是如果你想在安装一堆软件以前就开始学习一些东西,最好跳过这一章,我们会稍后解释安装的部分。 + +祝你好运! + +# 安装 + +在线下教程中,你会建立一个博客,有一些配置任务最好能够在之前完成,那样你就可以在那一天直接开始编程。 + +# 安装Python + +{% include "/python_installation/instructions.md" %} + +# 配置 virtualenv 与安装 Django + +{% include "/django_installation/instructions.md" %} + +# 安装一个代码编辑器 + +{% include "/code_editor/instructions.md" %} + +# 安装 Git + +{% include "/deploy/install_git.md" %} + +# 创建一个 Github 账户 + +前往 [GitHub.com](https://www.github.com) 并注册一个新的账号。 + +# 创建一个 PythonAnywhere 帐户 + +{% include "/deploy/signup_pythonanywhere.md" %} + +# 开始阅读 + +恭喜你,你配置好了全部的软件,可以准备正式开始了!如果你仍然在线下活动之前有一些时间,阅读一些入门章节会有一些帮助: + + * [互联网是如何工作的?](../how_the_internet_works/README.md) + + * [命令行介绍](../intro_to_command_line/README.md) + + * [Python 简介](../intro_to_command_line/README.md) + + * [Django 是什么?](../django/README.md) diff --git a/zh/intro_to_command_line/README.md b/zh/intro_to_command_line/README.md new file mode 100755 index 00000000000..3fe4b30df4e --- /dev/null +++ b/zh/intro_to_command_line/README.md @@ -0,0 +1,279 @@ +# 命令行界面简介 + +哈,这是令人兴奋,不是吗?:) 仅几分钟内你会写你第一行代码 + +**让我们把你介绍给你的第一个新朋友: 命令行 !** + +以下步骤将显示你如何使用所有的黑客都使用的黑色窗口。它可能刚开始看上去有点吓人,但事实上它只是等待你的命令提示符。 + +> **注意** 请注意,在本书中我们使用术语“目录”和“文件夹”完全可以互换,它们指的是同一个东西。 + +## 什么是命令行? + +这个窗口通常被称为 **命令行** 或 **命令行界面**,是一个基于文本的用来查看、 处理、 和操作您的计算机上的文件的应用程序。 就像 Windows 资源管理器或 Mac 上的 Finder,但没有图形界面。 命令行的其他名字是: *cmd*,*CLI*、 *提示符*、 *控制台* 或 *终端*. + +## 打开命令行界面 + +为了进行一些实验,我们需要首先打开我们的命令行界面。 + +### Windows系统 + +转到开始菜单 → 所有程序 → 附件 → 命令提示符。 + +### Mac OS X 系统 + +应用程序 → 实用工具 → 终端。 + +### Linux系统 + +它可能是根据应用程序 → 附件 → 终端,但这可能取决于您的版本系统。如果它不存在,只需谷歌一下 :) + +## 提示符 + +你现在应该看到一个白色或黑色的窗口,正等待着你的命令。 + +如果你是在 Mac 或 Linux 上,您可能看到 `$`,就像这样: + + $ + + +在 Windows 上,它是一个 `>` 标志,像这样: + + > + + +每个命令将前缀由这个符号和一个空格组成,但您不必键入它。您的计算机将为您完成这个:) + +> 温馨提示: 你的提示符前可能是一些类似 `C:\Users\ola >` 或 `Ola-MacBook-Air:~ola$` 这样的符号,这都是正确的。 在本教程中我们将只是简化它到最低限度。 + +## 你的第一个命令 (耶 !) + +让我们从简单的东西开始。键入以下命令: + + $ whoami + + +或 + + > whoami + + +然后键入 `enter`。这是我们的结果: + + $ whoami + olasitarska + + +正如你所看到的计算机刚刚打印了你的用户名。棒吧,呵呵?:) + +> 尝试键入每个命令,请不要复制粘贴。你会通过这种方式记得更多东西! + +## 基础知识 + +每个操作系统都有一组略有不同的适用于相应命令行的命令,所以请务必按照您的操作系统说明来做。我们试试这个,好吗? + +### 当前目录: + +知道身在何处让人高兴,对不对?让我们看看。输入命令并键入`enter`: + + $ pwd + /Users/olasitarska + + +如果你在 Windows 操作系统上: + + > cd + C:\Users\olasitarska + + +在你的机器上你可能会看见类似的东西。一旦你打开命令行工具你通常开始于用户主目录。 + +> 注: 'pwd' 代表 '打印工作目录'。 + +* * * + +### 列出文件和目录 + +那么它是什么?它一定很酷,找出。让我们看看: + + $ ls + Applications + Desktop + Downloads + Music + ... + + +Windows系统 + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### 更改当前目录 + +现在,让我们去我们桌面目录: + + $ cd Desktop + + +Windows系统 + + > cd Desktop + + +请检查它是否真的发生改变了: + + $ pwd + /Users/olasitarska/Desktop + + +Windows系统 + + > cd + C:\Users\olasitarska\Desktop + + +它在这儿 ! + +> 进阶提示: 如果你键入 `cd D`,然后在点击`tab`键,命令行将自动填充剩下的名称以便你可以更快地导航。 如果有多个文件夹以"D"开头,按下 `tab` 按钮两次以获取选项的列表。 + +* * * + +### 创建目录 + +在你的桌面上创建一个practice目录怎么样?你可以这样做: + + $ mkdir practice + + +Windows系统 + + > mkdir practice + + +这小小的命令将在桌面上为你创建名为`practice` 的目录。 你可以查看桌面文件夹或者通过运行 `ls` 或 `dir` 命令检查它是否存在! 试试:) + +> 进阶提示: 如果你不想要一遍又一遍地键入相同的命令,试着按 `向上箭头键` 和 `向下箭头` 下循环查看最近你使用过的命令。 + +* * * + +### 练习 + +给你一个小挑战: 在您新创建的 `practice` 目录下创建一个名为 `test`的目录。使用 `cd` 和 `mkdir` 命令。 + +#### 解决方法 + + $ cd practice + $ mkdir test + $ ls + test + + +Windows系统 + + > cd practice + > mkdir test + > dir + 05/08/2014 07:28 PM test + + +恭喜 !:) + +* * * + +### 清理 + +我们不想留下一个烂摊子,所以让我们删除所有的东西,直到达到目的。 + +首先,我们需要回到桌面: + + $ cd .. + + +Windows系统 + + > cd .. + + +使用 `..` 和 `cd` 命令将改变你的当前目录到父目录(包含当前目录的目录)。 + +检查你在哪里: + + $ pwd + /Users/olasitarska/Desktop + + +Windows系统 + + > cd + C:\Users\olasitarska\Desktop + + +现在删除 `practice` 目录: + +> **注意**: 删除文件使用 `del`,`rmdir` 或 `rm` 后便不能挽回,意思就是*已删除的文件会一去不复返了* ! 因此,要十分小心地使用此命令。 + + $ rm -r practice + + +Windows系统 + + > rmdir /S practice + practice, Are you sure ? Y + + +完成了 !为了肯定它真的已经删除了,让我们检查一下: + + $ ls + + +Windows系统 + + > dir + + +### 退出 + +暂时就到这里!你可以安全的关闭命令行。让我们以黑客的方式,好吗?:) + + $ exit + + +Windows系统 + + > exit + + +很酷吧?:) + +## 摘要 + +这里是一些有用的命令摘要: + +| 命令 (Windows) | 命令 (Mac OS / Linux) | 说明: | 示例: | +| ------------ | ------------------- | -------- | ------------------------------------------------- | +| exit | exit | 关闭窗口 | **exit** | +| cd | cd | 更改目录 | **cd test** | +| dir | ls | 列出的目录文件 | **dir** | +| copy | cp | 复制文件 | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | 移动文件 | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | 创建一个新目录 | **mkdir testdirectory** | +| del | rm | 删除文本文件目录 | **del c:\test\test.txt** | + +这些不过是你在你的命令行中可以运行的少量命令,但你今天不会用到比这里更多的了。 + +如果你好奇,[ss64.com][1] 包含用于所有操作系统命令的完整引用。 + + [1]: http://ss64.com + +## 准备好了吗? + +让我们深入到 Python ! \ No newline at end of file diff --git a/zh/python_installation/README.md b/zh/python_installation/README.md new file mode 100755 index 00000000000..399fa3d1182 --- /dev/null +++ b/zh/python_installation/README.md @@ -0,0 +1,13 @@ +# 让我们从学习Python开始 + +我们终于要开始了! + +但首先,让我们告诉你什么是 Python。Python 是一种非常流行的编程语言,可以用来创建网站、 游戏、 科学软件、 图形和很多很多其他的东西。 + +Python 起源于 1980 年代后期,该语言的重要目标是源代码的人类可读性 (而不是机器!)。 这就是为什么它看起来比其他编程语言简单得多。 这使得它易于学习,但不要担心,Python 也是真的很强大 ! + +# Python的安装 + +> 需要说明的是,如果你已经熟悉Python的安装步骤,那你就无需看这章,直接跳到下一章好了。 + +{% include "/python_installation/instructions.md" %} diff --git a/zh/python_installation/images/add_python_to_windows_path.png b/zh/python_installation/images/add_python_to_windows_path.png new file mode 100644 index 00000000000..9510d6f2176 Binary files /dev/null and b/zh/python_installation/images/add_python_to_windows_path.png differ diff --git a/zh/python_installation/instructions.md b/zh/python_installation/instructions.md new file mode 100755 index 00000000000..bb56316be22 --- /dev/null +++ b/zh/python_installation/instructions.md @@ -0,0 +1,66 @@ +> 本节基于 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots)的教程 + +Django 是用 Python 写的。 在 Django 中,我们需要使用 Python 语言去做所有的事情。 让我们从安装开始 ! 我们希望您能安装 Python 3.4,所以如果你有任何以前的版本,你将需要将其升级。 + +### Windows系统 + +您可以从 https://www.python.org/downloads/release/python-343/ 网站上下载 Windows版的Python。 下载 * **.msi** 文件完成之后,你应该运行它 (双击它),并按照那里的指示。 重要的是记住 Python 的安装位置的路径 (目录)。 它以后将会被需要 ! + +需要注意一件事情:在安装向导的第二步,选中“Customize”,向下滚动并确保选中“Add python.exe to the Path”选项,如下所示: + +![别忘了增加 Python 到 Path](../python_installation/images/add_python_to_windows_path.png) + +### Linux系统 + +很有可能你的系统已经默认安装了Python。要检查你是否安装了 (并且它是哪一个版本),打开控制台,并键入以下命令: + + $ python3 --version + Python 3.4.3 + + +如果你未曾安装过 Python 或者你想要一个不同的版本,你可以按如下所示安装它: + +#### Debian 或 Ubuntu + +在控制台中键入此命令: + + $ sudo apt-get install python3.4 + + +#### Fedora (up to 21) + +在您的控制台中使用此命令: + + $ sudo yum install python3.4 + + +#### Fedora (22+) + +在您的控制台中使用此命令: + + $ sudo dnf install python3.4 + + +#### openSUSE + +在您的控制台中使用此命令: + + $ sudo zypper install python3 + + +### OS X + +你需要去到网站 https://www.python.org/downloads/release/python-343/ 然后下载 Python 安装程序: + + * 下载 *Mac OS X 64-bit/32-bit installer* 文件, + * 双击 *python-3.4.3-macosx10.6.pkg* 以运行安装程序。 + +验证安装成功,请打开 *终端* 应用,运行 `python3` 命令: + + $ python3 --version + Python 3.4.3 + + +* * * + +如果您有任何疑问,或如果出了错,你根本不知道该怎么办下一步-请询问你的指导 ! 有时事情都不顺利,这时寻求其他更多经验的人的帮助会更好。 diff --git a/zh/python_introduction/README.md b/zh/python_introduction/README.md new file mode 100755 index 00000000000..cd2d26057e5 --- /dev/null +++ b/zh/python_introduction/README.md @@ -0,0 +1,775 @@ +# Python 简介 + +> 本章的部分内容基于 Geek Girls Carrots (https://github.com/ggcarrots/django-carrots) 的教程。 + +让我们现在就开始写代码 ! + +## Python 提示符 + +要玩转 Python,首先需要打开您的计算机上的 *命令行* 。 这一点,你应该已经掌握了——你在 [命令行入门][1]这一章已经学习过。 + + [1]: ../intro_to_command_line/README.md + +如果你准备好了,那么请按照以下说明进行操作。 + +在 Windows 下输入 `python` 或在 Mac OS/Linux 上输入`python3` 并敲下 `回车键`。. + + $ python3 + Python 3.4.3 (...) + Type "help", "copyright", "credits" or "license" for more information. + >>> + + +## 第一条 Python 命令 ! + +完成运行 Python 命令后,提示符变为 `>>>`。 这就意味着,现在我们只能使用符合 Python 语法的命令。 你不必键入 `>>>` —— Python会为你做的。 + +如果你想在任何时候退出 Python 控制台,只需要键入 `exit()` 或者在 Windows 下使用快捷键 `Ctrl+Z` ,在 Mac/Linux 下使用 `Ctrl+D` 快捷键。 这时候你就不会再看到 `>>>`。 + +但是现在,我们不需要退出 Python 控制台。 我们往下要继续了解 Python 。 让我们从最简单的开始。 例如,试着输入一些数学运算,如 `2 + 3` 并敲下 `回车`. + + >>> 2 + 3 + 5 + + +好的!看到答案是如何显示出来的吗? Python 懂数学!你可以试试其他命令: - `4 * 5` - `5 - 1` - `40 / 2` + +好好的玩一会儿,然后回到这里 :)。 + +正如你所看到的,Python 是一个不错的计算器。如果你想知道你还能用它做什么…… + +## 字符串 + +比试试你的名字?把你的名字用引号括起来,就像这样: + + >>> "Ola" + 'Ola' + + +现在你创建了第一个字符串! 字符串是一个可以由计算机处理的字符序列。 该字符串的开始和结束位置必须用同一个字符标志。 可以由单引号(`'`) 或双引号(`"`)来 包裹(两者是没有区别的!),让 Python 知道,这中间是一个字符串。 + +字符串可以用加号连接在一起。像这样: + + >>> "Hi there " + "Ola" + 'Hi there Ola' + + +你也可以将字符串与数字相乘: + + >>> "Ola" * 3 + 'OlaOlaOla' + + +如果你的字符串中需要表示一个单引号,你有两种方法: + +用双引号来包裹字符串: + + >>> "Runnin' down the hill" + "Runnin' down the hill" + + +或者使用反斜杠(``)来转义单引号 + + >>> 'Runnin\' down the hill' + "Runnin' down the hill" + + +表现得不错,是吧?如果想把字符串变成大写,只需要输入: + + >>> "Ola".upper() + 'OLA' + + +你刚刚在你的字符串上使用了 `upper` **函数**! 像 (`upper()`)这样的函数是告诉Python运行某个给定对象如(`"Ola"`)上的一些列指令。 + +如果你想获取你名字里字母的个数,这里也有一个函数! + + >>> len("Ola") + 3 + + +不知道为什么有时候你调用函数会在字符串尾部是用`.`(就像`"Ola".upper()`)而有时候你会在一开始就调用函数,然后将字符串置于括号中吗? 好吧,在某些情况下,函数属于对象,就像 `upper()`,它只可以被应用于字符串上。 在这种情况下,我们将此函数称为**方法(method)**。 其他时候,函数不隶属于任何一个特定的对象,可以用在不同类型的对象上,例如 `len()` 。 这就是为什么我们使用`"Ola"`作为`len`函数的一个参数。 + +### 摘要 + +好的,关于字符串就学到这里。现在你已经学习到了以下这些内容: + +* **提示符**-键入命令行(代码)到 Python 提示符中,将在 Python 中得到回答。 +* **数字和字符串**-在 Python 里数字用于数学运算,而字符串被用作文本对象。 +* **运算符** - 例如 + 和 *, 将对赋值进行结合,并产生新的值。 +* **函数**-例如 upper() 和 len() ,对对象执行操作。 + +这些都是学习每种编程语言中最基本的东西。想学点更难的东东了吗?我们敢打赌你想! + +## 错误 + +让我们试试一些新东西,我们能够像得到名称长度一样的方式来得到一个数字的长度吗?输入 `len(304023)` 然后敲下 `回车键`: + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +我们得到了第一个错误!它说"int"(整数)的对象类型没有长度。所以我们现在该做什么呢?或许我们能够把我们的数字写成字符串?字符串有长度,对吗? + + >>> len(str(304023)) + 6 + + +它成功了!我们将 `str` 函数插入到 `len` 函数内。`str` 将所有东西转换成字符串。 + +* `str` 函数将对象转换成**字符串** +* `int` 函数将对象转换为**整数** + +> 重要提示:我们能够将所有的数字都转换成文本,但我们不能将所有的文本转换成数字,否则 `int("hello")` 究竟是什么意思? + +## 变量 + +变量是编程中的一个重要概念。 变量只不过是一个待会儿你可以使用的一个东西的名称。 程序员是用这些变量去存储数据,让他们的代码变得更具可读性,所以他们不需要一直记住东西是什么。 + +假设我们想创建一个新变量,叫做 `name` : + + >>> name = "Ola" + + +你看到了吗?这很容易!原因很简单:名字等于Ola。 + +正如你所注意到的,你的程序不会像以前那样返回任何东西。那么我们怎么知道这个变量确实存在?简单键入 `name` 然后按下`回车`。 + + >>> name + 'Ola' + + +耶!你的第一个变量:)!你随时可以改变它指代的内容: + + >>> name = "Sonja" + >>> name + 'Sonja' + + +你还可以这样使用函数: + + >>> len(name) + 5 + + +太棒了,对吗?当然,变量可以是任何东西,比如数字!试试这个: + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +但是如果我们使用了错误的名字?你能猜出来会发生什么吗?试试吧! + + >>> city = "Tokyo" + >>> ctiy + Traceback (most recent call last): + File "", line 1, in + NameError: name 'ctiy' is not defined + + +一个错误! 正如你所见,Python有不同种类的错误,这一种称作**NameError**。 Python将会在你尝试使用未定义的变量时产生这种错误。 如果你以后再次遇到这种错误,检查你的代码,看看你是不是错误输入了任何名称。 + +玩一会儿,然后看看你能做什么! + +## 打印功能 + +试试这个: + + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + + +当你键入 `name`,Python 解释器会打印变量'name'*表示*的字符串,单引号包裹的:'Maria'。 当你调用 `print(name)` 的时候,Python 将会“打印”内容到屏幕上,没有引号,更加整洁。 + +我们稍后会看到的,当我们想打印一些东西,或者想打印一些多行的东西,`print()` 是一个对我们很有用的函数。 + +## 列表 + +除了字符串和整数,Python提供了各种不同类型的对象。 现在我们要介绍一个叫做**列表**的东西。 列表和你想的一样:一个容纳着其他对象的列表对象: ) + +继续,创建一个列表: + + >>> [] + [] + + +是的,这个列表是空的。并不是十分有用,对吗?让我们创建一个彩票号码的列表。我们不想总是重复我们的工作,所以我们也将它置于一个变量中: + + >>> lottery = [3, 42, 12, 19, 30, 59] + + +好吧,我们有了一个列表!我们能为它做什么呢?让我们看一看在列表中有多少个彩票数字。你知道什么方法什么函数你可以使用的吗?你已经知道了! + + >>> len(lottery) + 6 + + +是的!`len()`可以给你列表中对象的个数。很方便,对吗?也许我们可以将它排序: + + >>> lottery.sort() + + +这不会返回任何东西,它仅仅改变了数字出现在列表里的顺序。让我们再一次把它打印出来,看看发生了什么: + + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + + +正如你所看到的,你的列表里的数字现在从最小到最大排序。祝贺! + +也许我们想要将顺序倒序呢?让我们开始做吧! + + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + + +很简单,对吧?如果你想给你的列表里加入些东西,你可以通过简入以下命令: + + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + + +如果你只想要显示第一个数字,你可以通过使用**索引**完成。 索引就是列表中出现一个项的位置。 程序员一般习惯从0开始计数,所以列表中的第一个对象的索引是0,下一个是1,依此类推。 试试这个: + + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + + +正如你所见,你可以通过使用列表名和置于方括号中的对象索引来访问列表中的不同元素。 + +如果需要从列表中删除元素,需要使用 **索引** 和上面学到的 `pop()` 语句来完成。 我们看个例子,删除列表中的第一个数字,以加强我们之前学到的知识。 + + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + >>> print(lottery[0]) + 59 + >>> lottery.pop(0) + >>> print(lottery) + [42, 30, 19, 12, 3, 199] + + +干得漂亮! + +出于额外的乐趣,试试其他的索引:6,7,1000,-1,-6或者-1000。看看你是否能预测出命令尝试的结果。这些结果有意义吗? + +你可以找到本章中所有关于列表的方法的Python文档:https://docs.python.org/3/tutorial/datastructures.html + +## 字典 + +字典类似与列表,但是你通过查找键来获取值,而不是通过访问索引。一个键可以是任何字符串或者数字。定义一个空字典的语法是: + + >>> {} + {} + + +这表明你刚创建了一个空字典。加油! + +现在,试着写下下面的命令(试着也替换你自己的信息): + + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + + +通过这个命令,你刚创建了一个名为`participant`的变量,有三个键值对: + +* 键 `name` 指向 `'Ola'` (一个`字符串` 对象), +* `country` 指向`'Poland'` (另一个 `字符串`), +* 和`favorite_numbers` 指向`[7, 42, 92]` (一个有三个数字的 `列表` ). + +你可以通过下面的语法检查每个键的内容: + + >>> print(participant['name']) + Ola + + +看,这就和列表很相似了。但是你不需要记住索引-仅仅需要记住名字。 + +如果我们问Python一个不存在的键呢?能猜到吗?让我们试一试,看看! + + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + + +看,另一个错误!这是一个 **KeyError** 。Python 会告诉你键`'age'`并不存在于这个字典里。 + +那么什么时候使用字典或者列表呢?好吧,这是一个值得思考的点。在查看下一行答案前先在脑子里面设想一个答案。 + +* 你需要一个有序的元素排列吗?使用列表。 +* 你需要将键值相关联,这样你可以在后面更有效的查找他们?使用字典。 + +字典,就像列表,是*可变的*,意味着他们在创建之后可以被改变。你可以在字典被创建之后,增加新的键/值对,就像: + + >>> participant['favorite_language'] = 'Python' + + +像列表,使用`len()`方法,返回字典中键值对数目。继续输入命令: + + >>> len(participant) + 4 + + +我希望你能觉得到目前为止这些都合情合理。:)准备享受更多字典的乐趣吗?跳到下一行去做一些更有趣的事情。 + +你可以使用`del`命令去删除字典里的元素。 比如,如果你想删除键`'favorite_numbers'`所对应的项,只需要键入如下命令: + + >>> participant.pop('favorite_numbers') + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + + +正如你从输出中看到的,键值对所对应的'favorite_numbers'键已经被删除了。 + +此外,你还可以改变字典中已经存在的键所对应的值。键入: + + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + + +正如你所见,键`'country'`的值已经从`'Poland'`变为了`'Germany'`。:)兴奋吗?哈哈!你刚又学了另一个有趣的东西。 + +### 摘要 + +太棒了!你现在知道很多关于编程的东西了。在最后的部分你学习了: + +* **errors** - 你知道如何读并理解错误,如果Python不能理解你所给它的命令。 +* **variables** - 对象名称让你代码变得更简单更可读的 +* **lists** - 按照特定序列排序的存储着对象的列表 +* **dictionaries** - 存储着键值对的对象 + +为接下来的部分感到兴奋吗?:) + +## 比较事物 + +编程里经常会比较事物。什么是最容易比较的东西呢?当然是数字。让我们来看一看它是怎么工作的: + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + >>> 5 != 2 + True + + +我们给 Python 一些数字去比较。正如你所见的,Python 不仅可以比较数字,也可以比较函数的返回值。不错,是的吧? + +你知道为什么我们在判断相等时要把两个等号 `==` 放在一起吗? 我们使用一个等于符号 `=` 来给变量赋值。 你总是 **总是** 需要把两个 `==` 放在一起,如果你希望去检查两个东西是不是相同。 如果我们认为两个东西是不相等的。 我们使用符号 `! =`,如上面的示例中所示。 + +给Python两个更多的任务: + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +`>` 和 `<` 很简单, 但 `>=` and `<=` 表示什么啊? 阅读下面的说明: + +* x `>` y 表示: x 大于 y +* x `<` y 表示:x 小于 y +* x `< =` y 表示: x 小于或等于 y +* x `>=` y 表示:x 大于或等于 y + +棒极了!想要做一次吗?试试这个: + + >>> 6 > 2 and 2 < 3 + True + >>> 3 > 2 and 2 < 1 + False + >>> 3 > 2 or 2 < 1 + True + + +你可以给 Python 任意多的数字来比较,他会给你想要的答案!非常智能,对吗? + +* **and** -如果你使用 `and` 运算符,两个比较值都需要为真(True),这样整个命令才能为真 +* **or** - 如果你想使用 `or` 运算符,只要有一个比较值是真,那么整个命令就为真 + +你听说过“驴唇不对马嘴”这种说法吗?让我们试试它的 Python 版: + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +在这里你看到就像在这表达式中,Python 是不能比较数字 (`int`) 和字符串 (`str`)。 相反,它显示一个 **TypeError**,并告诉我们两个类型不能相互比较。 + +## 布尔逻辑 + +顺带提一句,你刚刚学习了一个 Python 新的类型。它被叫做**布尔**——而且这可能是最简单的类型。 + +只有两个布尔类型对象: - True - False + +但是为了 Python 能够理解,你需要写成 True(第一个字母大写,其他字母小写)。 **true, TRUE, tTUE都不会正常工作 —— 只有 True 是正确的**(同样适用于False) + +布尔也可以是变量!看这里: + + >>> a = True + >>> a + True + + +或者通过这种方式: + + >>> a = 2 > 5 + >>> a + False + + +练习有趣的布尔值,然后尝试下面的命令: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +祝贺你!布尔值是编程中最酷的功能,你刚刚学会了如何使用它们! + +# 保存它! + +到目前为止,我们所写的所有 Python 代码都是在命令行中,这限制了我们每次只能写一行代码。 正常的程序是被保存在文件里,并通过对应程序语言的**解释器**或者**编译器**处理后执行。 目前为止,我们已经试过在 Python **解释器**中一行一行的运行我们的程序。 我们接下来的几个任务需要不止一行代码,所以我们很快就会需要: + +* 退出 Python 解释器 +* 打开我们选择的代码编辑器 +* 将一些代码保存到一个新的 python 文件 +* 运行它! + +为了退出我们一直使用的 Python 解释器,只需要键入 exit() 函数: + + >>> exit() + $ + + +这将让你返回到命令提示符。 + +早些时候,我们在[代码编辑器][2]章节选择了一个代码编辑器。我们现在需要打开一个编辑器,然后写一些代码进入新文件: + + [2]: code_editor/README. md + + python + print('Hello, Django girls!') + + +> **注意**你应该注意到代码编辑器最酷的事情之一: 颜色! 在 Python 控制台中,一切都是相同的颜色,现在你应该看到 `打印` 函数和字符串的颜色不同。 这就所谓的"语法高亮",在编写代码时是非常有用的功能。 颜色会给你提示,如未闭合的字符串或关键字名称拼写错误 (如函数中的 `def` 关键字,我们会在下面看到) 。 这是我们使用代码编辑器的原因之一:) + +显然,你现在是一个相当熟练的python开发者,所以随便写一些你今天学到的代码吧。 + +现在我们需要保存文件,然后给它一个描述性的名字。 让我们命名这个文件 **python_intro.py** 然后保存它到您的桌面。 我们可以随意给文件起名字,但是要确保 **.py** 在文件名结尾。 **.py** 扩展名告诉操作系统,这是一个 **python可执行文件**,Python 可以运行它。 + +文件保存之后,就到了可以运行它的时候了!使用你在命令行章节学习到的技能,在终端**改变目录**到桌面。 + +在 Mac 上命令会看起来像这样: + + $ cd /Users//Desktop + + +在Linux,它会看起来像这样(“桌面”可能会被翻译成您所在的语言): + + $ cd /home//Desktop + + +并在 windows 上,它会看起来像这样: + + > cd C:\Users\\Desktop + + +如果你遇到麻烦了,尽管提问寻求帮助。 + +现在文件中输入这样的代码并使用 Python 执行: + + $ python3 python_intro.py + Hello, Django girls! + + +好吧!你刚刚运行了你保存在文件中的第一个 python 程序。感觉棒极了吗? + +你可以继续去学习编程中一些重要的工具: + +## If...elif...else + +很多代码只会在提供的条件被满足的时候运行。这就是为什么Python有**if 语句**. + +用以下代码替换 **python_intro.py** 中的内容: + + python + if 3 > 2: + + +如果我们保存这个,然后运行它,我们会看到一个类似这样的错误: + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +当条件 `3 > 2` 为真(或者 `True` ),Python 希望我们给它进一步的指示。 我们试着让 Python 打印 “it works!”。 更改您在 **python_intro.py** 文件中的代码变为这样: + + if 3 > 2: + print('It works!') + + +注意我们已经为下一行缩进了4个空格了吗? 这样做是为了让 Python 知道如果条件正确它将运行什么代码。 你可以使用一个空格,但是几乎所有的 Python 程序员都是用4个,使事情看上去很整洁。 单个 `tab` 也将算作 4 个空格。 + +保存它,然后再次运行它: + + $ python3 python_intro.py + It works! + + +### 如果条件不为真呢? + +在之前的例子里,代码只会在条件被满足的时候被运行。但是 Python 同样有 `elif` 和 `else` 语句: + + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') + + +这段代码在运行后会打印: + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +如果2是比5大,那么第二个命令会被执行。简单,对吧?在我们看看 `elif` 是怎么工作的: + + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') + + +然后运行: + + $ python3 python_intro.py + Hey Sonja! + + +看到发生什么了吗?如果前面的条件失败了,`elif` 允许你添加额外条件来判断接下来该怎么运行。 + +在 `if` 语句之后,你可以添加任意多的 `elif` 语句。例如: + + volume = 57 + if volume < 20: + print("It's kinda quiet.") + elif 20 <= volume < 40: + print("It's nice for background music") + elif 40 <= volume < 60: + print("Perfect, I can hear all the details") + elif 60 <= volume < 80: + print("Nice for parties") + elif 80 <= volume < 100: + print("A bit loud!") + else: + print("My ears are hurting!") + + +Python 遍历判断每个测试的条件,并打印: + + $ python3 python_intro.py + Perfect, I can hear all the details + + +### 摘要 + +在刚才的三个练习,你已经学习到了: + +* **比较事物** - 在Python里你可以比较东西通过使用`>`, `>=`, `==`, `<=`, `<` 和`and`, `or` 运算符。 +* **Boolean** - 一个只能有两个值中的一个的对象: `True` 或者 `False` +* **保存文件** - 保存代码到文件里,这样你可以执行更大的程序。 +* **if...elif...else** -让你只执行当某个条件满足后的代码。 + +现在是本章的最后一个部分了! + +## 你自己的函数! + +还记得你在Python里运行的函数`len()`?好消息,你会学习如何编写自己的函数了! + +一个函数就是一些 Python 应该运行的指令集。 每个Python函数都是以关键词 `def` 开始的,我们可以给定一个名字并能指定若干个参数。 让我们从一个简单的开始。 使用下面的替换**python_intro.py**中的代码: + + def hi(): + print('Hi there!') + print('How are you?') + + hi() + + +好吧,我们的第一个函数已经准备好了! + +你可以想知道为什么我们把函数的名称写在文件的底部。 这是因为Python读了文件,然后自顶向下的执行它。 所以为了使用我们的函数,我们必须要在底部重写它。 + +现在让我们运行这个,看看会发生什么: + + $ python3 python_intro.py + Hi there! + How are you? + + +那很简单!让我们建立我们第一个有参数的函数。我们使用前面的例子-一个函数打印“hi to the person running it” + + def hi(name): + + +正如你所见的,我们给我们的函数一个叫`name`的参数: + + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() + + +记住: `print` 函数是在 `if` 语句的缩进内的。这是因为我们要在仅满足条件时,才运行函数。让我们看看它是如何工作: + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' + + +哦!一个错误。 幸运的是,Python给我们一个有用的错误提示信息。 告诉我们函数 `hi()`(这是我们定义的)必须有一个参数(称之为`name`),我们调用函数的时候忘记传递它了。 让我们在文件的底部解决它: + + hi("Ola") + + +然后再次运行它: + + $ python3 python_intro.py + Hi Ola! + + +那如果我们改变名字了呢? + + hi("Sonja") + + +然后运行它: + + $ python3 python_intro.py + Hi Sonja! + + +现在,如果我们写了另一个名字会发生什么?(不是 Ola 或者 Sonja )试试看是不是和你想的是一样的。它应该打印成这样: + + Hi anonymous! + + +这太棒了,对吗? 这样我们不用在每次调用此方法跟不同的人打招呼的时候重复自己。 而这正是我们为什么需要(定义)函数 - 你永远不想重复你的代码! + +让我们做一些更智能的事情——如果有超过两个或者更多的名字,我们需要为每个都写一个判断,会比较难,对不对? + + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") + + +现在让我们调用代码: + + $ python3 python_intro.py + Hi Rachel! + + +祝贺你!你刚刚学习了如何写函数!:) + +## 循环 + +这是最后一部分。这真快,对吗?:) + +程序员不喜欢重复劳动。编程的核心是自动化,所以我们不希望手动的一行一行去调用打招呼函数,是吧?这时候循环就能派上用场了。 + +还记得列表吗?让我们做一个女孩的列表: + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + + +我们想要根据他们所有人的名字依次打招呼。我们有一个 `hi` 函数去实现这个,所以让我们在一个循环中使用它: + + for name in girls: + + +for 语句的声明和 if 语句声明类似,下面代码需要缩进。 + +这是文件中完整的代码: + + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('Next girl') + + +然后当我们去运行它: + + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl + + +正如你所看见的,所有你放在 `for` 中的语句都将会根据列表 `girls` 中的每个元素而重复执行。. + +你同样可以使用 `for` 来遍历使用 `range` 函数生成的数字: + + for i in range(1, 6): + print(i) + + +这将会打印: + + 1 + 2 + 3 + 4 + 5 + + +`range` 函数产生一个列表的数字,一个挨着一个(这些数字是由您提供的参数而产生的)。 + +请注意第二个参数将不会被包括在Python输出列表中(意味着`range(1,6)`从1到5计数,但是不包括数字6)。 这是因为"范围"是半开区间,意思是包含第一个值,但不包括最后一个。 + +## 摘要 + +就是这样,**你太厉害啦!** 这是一个棘手的章节,所以你应该为自己感到骄傲。我们为你取得这么多进展而感到骄傲! + +你可以简单做点其他事情—— 伸个懒腰,走动一会儿,放松下你的眼睛,再接着往下一章。:) + +![纸杯蛋糕][3] + + [3]: images/cupcake.png diff --git a/zh/python_introduction/images/cupcake.png b/zh/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/zh/python_introduction/images/cupcake.png differ diff --git a/zh/template_extending/README.md b/zh/template_extending/README.md new file mode 100755 index 00000000000..988d328e180 --- /dev/null +++ b/zh/template_extending/README.md @@ -0,0 +1,131 @@ +# 模板扩展 + +另一个有趣的事情Django已经为你做好了就是**模板扩展**。这是什么意思呢?它意味着你可以使用你的HTML相同代码为你网站不同的网页共享。 + +通过这种方法,当你想使用同样的信息或布局,或者你想改变某些模板内容时,你不必在每个文件中都重复着相同的代码。你仅仅只需要改变一个文件,而不是所有的。 + +## 创建一个基础模板 + +一个基础模板是最重要的模板,你扩展到你网站的每一页。 + +让我们创建一个`base.html`文件到`blog/templates/blog/`: + +``` + blog + └───templates + └───blog + base.html + post_list.html +``` + + +然后将它打开,从`post_list.html`中复制所有东西到`base.html`文件,就像这样: + +```html + {% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +
+
+
+ + +``` + + +然后在`base.html`中,替换你所有的 ``(所有的在`` 和 ``之间的内容)像这样: + +```html + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ +``` + + +用如下内容替换所有在 `{% for post in posts %}{% endfor %}`之间的代码: + +```html + {% block content %} + {% endblock %} +``` + + +这是什么意思呢? 你刚刚创建了一个`block(块)`,这个模板标签允许你在其中插入扩展自`base.html`的模板的HTML代码。 我们一会儿将给你展示这个如何使用。 + +现在保存它,然后再次打开你的`blog/templates/blog/post_list.html`。 删除一切body外的代码,然后删除 ``,此时文件会看起来像这样: + +```html + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} +``` + + +然后现在将这行加到文件的开始: + +```html + {% extends 'blog/base.html' %} +``` + + +{% raw %}这意味着我们在 `post_list.html`模板文件中扩展了 `base.html` 模板的内容。 还有一件事:将所有(除了我们刚刚加入的那行) 内容置于`{% block content %}`和 `{% endblock content %}`之间。。 像这样:{% endraw %} + +```html + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaksbr }}

+
+ {% endfor %} + {% endblock content %} +``` + + +好了,就是它了!检查你的网站还能正常工作:) + +> 如果你有任何错误 `TemplateDoesNotExists` 这意味着没有 `blog/base.html` 文件,你需要 `runserver` 运行在控制台,尝试去关掉它(通过按下Ctrl+C -Control和C按钮一切)然后重新运行`python manage.py runserver` 命令行。 diff --git a/zh/whats_next/README.md b/zh/whats_next/README.md new file mode 100755 index 00000000000..f08ef2cf4f4 --- /dev/null +++ b/zh/whats_next/README.md @@ -0,0 +1,40 @@ +# 接下来呢? + +祝贺你!**你简直太棒了**。我们很自豪!<3 + +### 现在要做什么? + +休息一下,放松。你刚做完非常多的事。 + +之后,请确保: + +* 在[Facebook][1]或者 [推特][2] 来关注 Django Girls 以了解最新情况 + + [1]: http://facebook.com/djangogirls + [2]: https://twitter.com/djangogirls + +### 你能推荐更进一步的资源吗? + +是啊!首先,继续尝试其他书籍,称作[Django Girls教程:扩展][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +稍后,你可以试试利用以下的资源。 他们非常值得推荐啊! +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django 1.8 book][11] + + [4]: https://docs.djangoproject.com/en/1.8/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: https://www.codecademy.com/en/tracks/python + [7]: https://www.codecademy.com/tracks/web + [8]: https://github.com/ggcarrots/django-carrots/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: https://twoscoopspress.com/products/two-scoops-of-django-1-8 +